1 //===- unittest/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "TestVisitor.h" 10 11 using namespace clang; 12 13 namespace { 14 15 class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> { 16 public: 17 DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {} 18 19 bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } 20 21 void setShouldVisitImplicitCode(bool NewValue) { 22 ShouldVisitImplicitCode = NewValue; 23 } 24 25 bool VisitDeclRefExpr(DeclRefExpr *Reference) { 26 Match(Reference->getNameInfo().getAsString(), Reference->getLocation()); 27 return true; 28 } 29 30 private: 31 bool ShouldVisitImplicitCode; 32 }; 33 34 TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) { 35 DeclRefExprVisitor Visitor; 36 Visitor.ExpectMatch("x", 2, 3); 37 EXPECT_TRUE(Visitor.runOver( 38 "void x(); template <void (*T)()> class X {};\nX<x> y;")); 39 } 40 41 TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) { 42 DeclRefExprVisitor Visitor; 43 Visitor.ExpectMatch("x", 2, 25); 44 Visitor.ExpectMatch("x", 2, 30); 45 EXPECT_TRUE(Visitor.runOver( 46 "int x[5];\n" 47 "void f() { for (int i : x) { x[0] = 1; } }", 48 DeclRefExprVisitor::Lang_CXX11)); 49 } 50 51 TEST(RecursiveASTVisitor, VisitsCallExpr) { 52 DeclRefExprVisitor Visitor; 53 Visitor.ExpectMatch("x", 1, 22); 54 EXPECT_TRUE(Visitor.runOver( 55 "void x(); void y() { x(); }")); 56 } 57 58 TEST(RecursiveASTVisitor, VisitsExplicitLambdaCaptureInit) { 59 DeclRefExprVisitor Visitor; 60 Visitor.ExpectMatch("i", 1, 20); 61 EXPECT_TRUE(Visitor.runOver( 62 "void f() { int i; [i]{}; }", 63 DeclRefExprVisitor::Lang_CXX11)); 64 } 65 66 TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) { 67 DeclRefExprVisitor Visitor; 68 Visitor.ExpectMatch("i", 1, 24); 69 EXPECT_TRUE(Visitor.runOver( 70 "void f() { int i; [=]{ i; }; }", 71 DeclRefExprVisitor::Lang_CXX11)); 72 } 73 74 TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) { 75 DeclRefExprVisitor Visitor; 76 Visitor.setShouldVisitImplicitCode(true); 77 // We're expecting "i" to be visited twice: once for the initialization expr 78 // for the captured variable "i" outside of the lambda body, and again for 79 // the use of "i" inside the lambda. 80 Visitor.ExpectMatch("i", 1, 20, /*Times=*/1); 81 Visitor.ExpectMatch("i", 1, 24, /*Times=*/1); 82 EXPECT_TRUE(Visitor.runOver( 83 "void f() { int i; [=]{ i; }; }", 84 DeclRefExprVisitor::Lang_CXX11)); 85 } 86 87 TEST(RecursiveASTVisitor, VisitsLambdaInitCaptureInit) { 88 DeclRefExprVisitor Visitor; 89 Visitor.ExpectMatch("i", 1, 24); 90 EXPECT_TRUE(Visitor.runOver( 91 "void f() { int i; [a = i + 1]{}; }", 92 DeclRefExprVisitor::Lang_CXX14)); 93 } 94 95 /* FIXME: According to Richard Smith this is a bug in the AST. 96 TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) { 97 DeclRefExprVisitor Visitor; 98 Visitor.ExpectMatch("x", 3, 43); 99 EXPECT_TRUE(Visitor.runOver( 100 "template <typename T> void x();\n" 101 "template <void (*T)()> class X {};\n" 102 "template <typename T> class Y : public X< x<T> > {};\n" 103 "Y<int> y;")); 104 } 105 */ 106 107 TEST(RecursiveASTVisitor, VisitsExtension) { 108 DeclRefExprVisitor Visitor; 109 Visitor.ExpectMatch("s", 1, 24); 110 EXPECT_TRUE(Visitor.runOver( 111 "int s = __extension__ (s);\n")); 112 } 113 114 TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) { 115 DeclRefExprVisitor Visitor; 116 Visitor.ExpectMatch("x", 3, 24); 117 EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n" 118 "void g() { \n" 119 " f([&](int x){ return x; }); \n" 120 "}", 121 DeclRefExprVisitor::Lang_OBJCXX11)); 122 } 123 124 } // end anonymous namespace 125