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 12namespace clang { 13 14class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> { 15public: 16 bool VisitTypeLoc(TypeLoc TypeLocation) { 17 Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc()); 18 return true; 19 } 20}; 21 22class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> { 23public: 24 bool VisitDeclRefExpr(DeclRefExpr *Reference) { 25 Match(Reference->getNameInfo().getAsString(), Reference->getLocation()); 26 return true; 27 } 28}; 29 30class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> { 31public: 32 bool VisitVarDecl(VarDecl *Variable) { 33 Match(Variable->getNameAsString(), Variable->getLocStart()); 34 return true; 35 } 36}; 37 38class CXXMemberCallVisitor 39 : public ExpectedLocationVisitor<CXXMemberCallVisitor> { 40public: 41 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) { 42 Match(Call->getMethodDecl()->getQualifiedNameAsString(), 43 Call->getLocStart()); 44 return true; 45 } 46}; 47 48class NamedDeclVisitor 49 : public ExpectedLocationVisitor<NamedDeclVisitor> { 50public: 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 62class CXXOperatorCallExprTraverser 63 : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> { 64public: 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 74class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> { 75public: 76 bool VisitParenExpr(ParenExpr *Parens) { 77 Match("", Parens->getExprLoc()); 78 return true; 79 } 80}; 81 82class TemplateArgumentLocTraverser 83 : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> { 84public: 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 97class CXXBoolLiteralExprVisitor 98 : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> { 99public: 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 109TEST(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 115TEST(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 124TEST(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 132TEST(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 140TEST(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 147TEST(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 156TEST(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 164TEST(RecursiveASTVisitor, VisitsCallExpr) { 165 DeclRefExprVisitor Visitor; 166 Visitor.ExpectMatch("x", 1, 22); 167 EXPECT_TRUE(Visitor.runOver( 168 "void x(); void y() { x(); }")); 169} 170 171TEST(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 182TEST(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 195TEST(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. 214TEST(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 225TEST(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 242TEST(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 255TEST(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 271TEST(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 279TEST(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 289TEST(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 297TEST(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 307TEST(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 319TEST(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 329TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) { 330 ParenExprVisitor Visitor; 331 Visitor.ExpectMatch("", 1, 9); 332 EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n")); 333} 334 335TEST(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 344TEST(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 353TEST(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. 363class ImplicitCtorVisitor 364 : public ExpectedLocationVisitor<ImplicitCtorVisitor> { 365public: 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 378TEST(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. 395class ConstructExprVisitor 396 : public ExpectedLocationVisitor<ConstructExprVisitor> { 397public: 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 419TEST(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. 435TEST(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 449TEST(RecursiveASTVisitor, VisitsExtension) { 450 DeclRefExprVisitor Visitor; 451 Visitor.ExpectMatch("s", 1, 24); 452 EXPECT_TRUE(Visitor.runOver( 453 "int s = __extension__ (s);\n")); 454} 455 456TEST(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