1 //===- unittest/Tooling/RecursiveASTVisitorTest.cpp -----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "TestVisitor.h" 11 12 namespace clang { 13 14 class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> { 15 public: 16 bool VisitTypeLoc(TypeLoc TypeLocation) { 17 Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc()); 18 return true; 19 } 20 }; 21 22 class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> { 23 public: 24 bool VisitDeclRefExpr(DeclRefExpr *Reference) { 25 Match(Reference->getNameInfo().getAsString(), Reference->getLocation()); 26 return true; 27 } 28 }; 29 30 class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> { 31 public: 32 bool VisitVarDecl(VarDecl *Variable) { 33 Match(Variable->getNameAsString(), Variable->getLocStart()); 34 return true; 35 } 36 }; 37 38 class CXXMemberCallVisitor 39 : public ExpectedLocationVisitor<CXXMemberCallVisitor> { 40 public: 41 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) { 42 Match(Call->getMethodDecl()->getQualifiedNameAsString(), 43 Call->getLocStart()); 44 return true; 45 } 46 }; 47 48 class NamedDeclVisitor 49 : public ExpectedLocationVisitor<NamedDeclVisitor> { 50 public: 51 bool VisitNamedDecl(NamedDecl *Decl) { 52 std::string NameWithTemplateArgs; 53 llvm::raw_string_ostream OS(NameWithTemplateArgs); 54 Decl->getNameForDiagnostic(OS, 55 Decl->getASTContext().getPrintingPolicy(), 56 true); 57 Match(OS.str(), Decl->getLocation()); 58 return true; 59 } 60 }; 61 62 class CXXOperatorCallExprTraverser 63 : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> { 64 public: 65 // Use Traverse, not Visit, to check that data recursion optimization isn't 66 // bypassing the call of this function. 67 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) { 68 Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc()); 69 return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>:: 70 TraverseCXXOperatorCallExpr(CE); 71 } 72 }; 73 74 class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> { 75 public: 76 bool VisitParenExpr(ParenExpr *Parens) { 77 Match("", Parens->getExprLoc()); 78 return true; 79 } 80 }; 81 82 class TemplateArgumentLocTraverser 83 : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> { 84 public: 85 bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { 86 std::string ArgStr; 87 llvm::raw_string_ostream Stream(ArgStr); 88 const TemplateArgument &Arg = ArgLoc.getArgument(); 89 90 Arg.print(Context->getPrintingPolicy(), Stream); 91 Match(Stream.str(), ArgLoc.getLocation()); 92 return ExpectedLocationVisitor<TemplateArgumentLocTraverser>:: 93 TraverseTemplateArgumentLoc(ArgLoc); 94 } 95 }; 96 97 class CXXBoolLiteralExprVisitor 98 : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> { 99 public: 100 bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) { 101 if (BE->getValue()) 102 Match("true", BE->getLocation()); 103 else 104 Match("false", BE->getLocation()); 105 return true; 106 } 107 }; 108 109 TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) { 110 TypeLocVisitor Visitor; 111 Visitor.ExpectMatch("class X", 1, 30); 112 EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};")); 113 } 114 115 TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfForwardDeclaredClass) { 116 TypeLocVisitor Visitor; 117 Visitor.ExpectMatch("class X", 3, 18); 118 EXPECT_TRUE(Visitor.runOver( 119 "class Y;\n" 120 "class X {};\n" 121 "class Y : public X {};")); 122 } 123 124 TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersWithIncompleteInnerClass) { 125 TypeLocVisitor Visitor; 126 Visitor.ExpectMatch("class X", 2, 18); 127 EXPECT_TRUE(Visitor.runOver( 128 "class X {};\n" 129 "class Y : public X { class Z; };")); 130 } 131 132 TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfSelfReferentialType) { 133 TypeLocVisitor Visitor; 134 Visitor.ExpectMatch("X<class Y>", 2, 18); 135 EXPECT_TRUE(Visitor.runOver( 136 "template<typename T> class X {};\n" 137 "class Y : public X<Y> {};")); 138 } 139 140 TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) { 141 DeclRefExprVisitor Visitor; 142 Visitor.ExpectMatch("x", 2, 3); 143 EXPECT_TRUE(Visitor.runOver( 144 "void x(); template <void (*T)()> class X {};\nX<x> y;")); 145 } 146 147 TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) { 148 DeclRefExprVisitor Visitor; 149 Visitor.ExpectMatch("x", 2, 25); 150 Visitor.ExpectMatch("x", 2, 30); 151 EXPECT_TRUE(Visitor.runOver( 152 "int x[5];\n" 153 "void f() { for (int i : x) { x[0] = 1; } }")); 154 } 155 156 TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) { 157 VarDeclVisitor Visitor; 158 Visitor.ExpectMatch("i", 2, 17); 159 EXPECT_TRUE(Visitor.runOver( 160 "int x[5];\n" 161 "void f() { for (int i : x) {} }")); 162 } 163 164 TEST(RecursiveASTVisitor, VisitsCallExpr) { 165 DeclRefExprVisitor Visitor; 166 Visitor.ExpectMatch("x", 1, 22); 167 EXPECT_TRUE(Visitor.runOver( 168 "void x(); void y() { x(); }")); 169 } 170 171 TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) { 172 CXXMemberCallVisitor Visitor; 173 Visitor.ExpectMatch("Y::x", 3, 3); 174 EXPECT_TRUE(Visitor.runOver( 175 "struct Y { void x(); };\n" 176 "template<typename T> void y(T t) {\n" 177 " t.x();\n" 178 "}\n" 179 "void foo() { y<Y>(Y()); }")); 180 } 181 182 TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) { 183 CXXMemberCallVisitor Visitor; 184 Visitor.ExpectMatch("Y::x", 4, 5); 185 EXPECT_TRUE(Visitor.runOver( 186 "struct Y { void x(); };\n" 187 "template<typename T> struct Z {\n" 188 " template<typename U> static void f() {\n" 189 " T().x();\n" 190 " }\n" 191 "};\n" 192 "void foo() { Z<Y>::f<int>(); }")); 193 } 194 195 TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) { 196 CXXMemberCallVisitor Visitor; 197 Visitor.ExpectMatch("A::x", 5, 7); 198 EXPECT_TRUE(Visitor.runOver( 199 "template <typename T1> struct X {\n" 200 " template <typename T2> struct Y {\n" 201 " void f() {\n" 202 " T2 y;\n" 203 " y.x();\n" 204 " }\n" 205 " };\n" 206 "};\n" 207 "struct A { void x(); };\n" 208 "int main() {\n" 209 " (new X<A>::Y<A>())->f();\n" 210 "}")); 211 } 212 213 /* FIXME: According to Richard Smith this is a bug in the AST. 214 TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) { 215 DeclRefExprVisitor Visitor; 216 Visitor.ExpectMatch("x", 3, 43); 217 EXPECT_TRUE(Visitor.runOver( 218 "template <typename T> void x();\n" 219 "template <void (*T)()> class X {};\n" 220 "template <typename T> class Y : public X< x<T> > {};\n" 221 "Y<int> y;")); 222 } 223 */ 224 225 TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) { 226 CXXMemberCallVisitor Visitor; 227 Visitor.ExpectMatch("A::x", 6, 20); 228 EXPECT_TRUE(Visitor.runOver( 229 "template <typename T1> struct X {\n" 230 " template <typename T2, bool B> struct Y { void g(); };\n" 231 "};\n" 232 "template <typename T1> template <typename T2>\n" 233 "struct X<T1>::Y<T2, true> {\n" 234 " void f() { T2 y; y.x(); }\n" 235 "};\n" 236 "struct A { void x(); };\n" 237 "int main() {\n" 238 " (new X<A>::Y<A, true>())->f();\n" 239 "}\n")); 240 } 241 242 TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) { 243 CXXMemberCallVisitor Visitor; 244 Visitor.ExpectMatch("A::f", 4, 5); 245 EXPECT_TRUE(Visitor.runOver( 246 "struct A {\n" 247 " void f() const {}\n" 248 " template<class T> void g(const T& t) const {\n" 249 " t.f();\n" 250 " }\n" 251 "};\n" 252 "template void A::g(const A& a) const;\n")); 253 } 254 255 TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) { 256 // From cfe-commits/Week-of-Mon-20100830/033998.html 257 // Contrary to the approach suggested in that email, we visit all 258 // specializations when we visit the primary template. Visiting them when we 259 // visit the associated specialization is problematic for specializations of 260 // template members of class templates. 261 NamedDeclVisitor Visitor; 262 Visitor.ExpectMatch("A<bool>", 1, 26); 263 Visitor.ExpectMatch("A<char *>", 2, 26); 264 EXPECT_TRUE(Visitor.runOver( 265 "template <class T> class A {};\n" 266 "template <class T> class A<T*> {};\n" 267 "A<bool> ab;\n" 268 "A<char*> acp;\n")); 269 } 270 271 TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) { 272 NamedDeclVisitor Visitor; 273 Visitor.ExpectMatch("A<int>", 1, 29); 274 EXPECT_TRUE(Visitor.runOver( 275 "template<typename T> struct A;\n" 276 "A<int> *p;\n")); 277 } 278 279 TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) { 280 NamedDeclVisitor Visitor; 281 Visitor.ExpectMatch("A<int>::B<char>", 2, 31); 282 EXPECT_TRUE(Visitor.runOver( 283 "template<typename T> struct A {\n" 284 " template<typename U> struct B;\n" 285 "};\n" 286 "A<int>::B<char> *p;\n")); 287 } 288 289 TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) { 290 NamedDeclVisitor Visitor; 291 Visitor.ExpectMatch("A<int>", 1, 26); 292 EXPECT_TRUE(Visitor.runOver( 293 "template<typename T> int A();\n" 294 "int k = A<int>();\n")); 295 } 296 297 TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) { 298 NamedDeclVisitor Visitor; 299 Visitor.ExpectMatch("A<int>::B<char>", 2, 35); 300 EXPECT_TRUE(Visitor.runOver( 301 "template<typename T> struct A {\n" 302 " template<typename U> static int B();\n" 303 "};\n" 304 "int k = A<int>::B<char>();\n")); 305 } 306 307 TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) { 308 // From cfe-commits/Week-of-Mon-20100830/033977.html 309 NamedDeclVisitor Visitor; 310 Visitor.ExpectMatch("vector_iterator<int>", 2, 7); 311 EXPECT_TRUE(Visitor.runOver( 312 "template<typename Container>\n" 313 "class vector_iterator {\n" 314 " template <typename C> friend class vector_iterator;\n" 315 "};\n" 316 "vector_iterator<int> it_int;\n")); 317 } 318 319 TEST(RecursiveASTVisitor, TraversesOverloadedOperator) { 320 CXXOperatorCallExprTraverser Visitor; 321 Visitor.ExpectMatch("()", 4, 9); 322 EXPECT_TRUE(Visitor.runOver( 323 "struct A {\n" 324 " int operator()();\n" 325 "} a;\n" 326 "int k = a();\n")); 327 } 328 329 TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) { 330 ParenExprVisitor Visitor; 331 Visitor.ExpectMatch("", 1, 9); 332 EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n")); 333 } 334 335 TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) { 336 CXXBoolLiteralExprVisitor Visitor; 337 Visitor.ExpectMatch("true", 2, 19); 338 EXPECT_TRUE(Visitor.runOver( 339 "template<bool B> class X;\n" 340 "template<bool B = true> class Y;\n" 341 "template<bool B> class Y {};\n")); 342 } 343 344 TEST(RecursiveASTVisitor, VisitsClassTemplateTypeParmDefaultArgument) { 345 TypeLocVisitor Visitor; 346 Visitor.ExpectMatch("class X", 2, 23); 347 EXPECT_TRUE(Visitor.runOver( 348 "class X;\n" 349 "template<typename T = X> class Y;\n" 350 "template<typename T> class Y {};\n")); 351 } 352 353 TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) { 354 TemplateArgumentLocTraverser Visitor; 355 Visitor.ExpectMatch("X", 2, 40); 356 EXPECT_TRUE(Visitor.runOver( 357 "template<typename T> class X;\n" 358 "template<template <typename> class T = X> class Y;\n" 359 "template<template <typename> class T> class Y {};\n")); 360 } 361 362 // A visitor that visits implicit declarations and matches constructors. 363 class ImplicitCtorVisitor 364 : public ExpectedLocationVisitor<ImplicitCtorVisitor> { 365 public: 366 bool shouldVisitImplicitCode() const { return true; } 367 368 bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) { 369 if (Ctor->isImplicit()) { // Was not written in source code 370 if (const CXXRecordDecl* Class = Ctor->getParent()) { 371 Match(Class->getName(), Ctor->getLocation()); 372 } 373 } 374 return true; 375 } 376 }; 377 378 TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) { 379 ImplicitCtorVisitor Visitor; 380 Visitor.ExpectMatch("Simple", 2, 8); 381 // Note: Clang lazily instantiates implicit declarations, so we need 382 // to use them in order to force them to appear in the AST. 383 EXPECT_TRUE(Visitor.runOver( 384 "struct WithCtor { WithCtor(); }; \n" 385 "struct Simple { Simple(); WithCtor w; }; \n" 386 "int main() { Simple s; Simple t(s); }\n")); 387 } 388 389 /// \brief A visitor that optionally includes implicit code and matches 390 /// CXXConstructExpr. 391 /// 392 /// The name recorded for the match is the name of the class whose constructor 393 /// is invoked by the CXXConstructExpr, not the name of the class whose 394 /// constructor the CXXConstructExpr is contained in. 395 class ConstructExprVisitor 396 : public ExpectedLocationVisitor<ConstructExprVisitor> { 397 public: 398 ConstructExprVisitor() : ShouldVisitImplicitCode(false) {} 399 400 bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } 401 402 void setShouldVisitImplicitCode(bool NewValue) { 403 ShouldVisitImplicitCode = NewValue; 404 } 405 406 bool VisitCXXConstructExpr(CXXConstructExpr* Expr) { 407 if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) { 408 if (const CXXRecordDecl* Class = Ctor->getParent()) { 409 Match(Class->getName(), Expr->getLocation()); 410 } 411 } 412 return true; 413 } 414 415 private: 416 bool ShouldVisitImplicitCode; 417 }; 418 419 TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) { 420 ConstructExprVisitor Visitor; 421 Visitor.setShouldVisitImplicitCode(true); 422 Visitor.ExpectMatch("WithCtor", 2, 8); 423 // Simple has a constructor that implicitly initializes 'w'. Test 424 // that a visitor that visits implicit code visits that initialization. 425 // Note: Clang lazily instantiates implicit declarations, so we need 426 // to use them in order to force them to appear in the AST. 427 EXPECT_TRUE(Visitor.runOver( 428 "struct WithCtor { WithCtor(); }; \n" 429 "struct Simple { WithCtor w; }; \n" 430 "int main() { Simple s; }\n")); 431 } 432 433 // The same as CanVisitImplicitMemberInitializations, but checking that the 434 // visits are omitted when the visitor does not include implicit code. 435 TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) { 436 ConstructExprVisitor Visitor; 437 Visitor.setShouldVisitImplicitCode(false); 438 Visitor.DisallowMatch("WithCtor", 2, 8); 439 // Simple has a constructor that implicitly initializes 'w'. Test 440 // that a visitor that skips implicit code skips that initialization. 441 // Note: Clang lazily instantiates implicit declarations, so we need 442 // to use them in order to force them to appear in the AST. 443 EXPECT_TRUE(Visitor.runOver( 444 "struct WithCtor { WithCtor(); }; \n" 445 "struct Simple { WithCtor w; }; \n" 446 "int main() { Simple s; }\n")); 447 } 448 449 TEST(RecursiveASTVisitor, VisitsExtension) { 450 DeclRefExprVisitor Visitor; 451 Visitor.ExpectMatch("s", 1, 24); 452 EXPECT_TRUE(Visitor.runOver( 453 "int s = __extension__ (s);\n")); 454 } 455 456 TEST(RecursiveASTVisitor, VisitsCompoundLiteralType) { 457 TypeLocVisitor Visitor; 458 Visitor.ExpectMatch("struct S", 1, 26); 459 EXPECT_TRUE(Visitor.runOver( 460 "int f() { return (struct S { int a; }){.a = 0}.a; }", 461 TypeLocVisitor::Lang_C)); 462 } 463 464 } // end namespace clang 465