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