1 //===- unittest/Tooling/RecursiveASTVisitorTestCallVisitor.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 #include <stack> 12 13 using namespace clang; 14 15 namespace { 16 17 class CXXMemberCallVisitor 18 : public ExpectedLocationVisitor<CXXMemberCallVisitor> { 19 public: 20 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) { 21 Match(Call->getMethodDecl()->getQualifiedNameAsString(), 22 Call->getLocStart()); 23 return true; 24 } 25 }; 26 27 TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) { 28 CXXMemberCallVisitor Visitor; 29 Visitor.ExpectMatch("Y::x", 3, 3); 30 EXPECT_TRUE(Visitor.runOver( 31 "struct Y { void x(); };\n" 32 "template<typename T> void y(T t) {\n" 33 " t.x();\n" 34 "}\n" 35 "void foo() { y<Y>(Y()); }")); 36 } 37 38 TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) { 39 CXXMemberCallVisitor Visitor; 40 Visitor.ExpectMatch("Y::x", 4, 5); 41 EXPECT_TRUE(Visitor.runOver( 42 "struct Y { void x(); };\n" 43 "template<typename T> struct Z {\n" 44 " template<typename U> static void f() {\n" 45 " T().x();\n" 46 " }\n" 47 "};\n" 48 "void foo() { Z<Y>::f<int>(); }")); 49 } 50 51 TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) { 52 CXXMemberCallVisitor Visitor; 53 Visitor.ExpectMatch("A::x", 5, 7); 54 EXPECT_TRUE(Visitor.runOver( 55 "template <typename T1> struct X {\n" 56 " template <typename T2> struct Y {\n" 57 " void f() {\n" 58 " T2 y;\n" 59 " y.x();\n" 60 " }\n" 61 " };\n" 62 "};\n" 63 "struct A { void x(); };\n" 64 "int main() {\n" 65 " (new X<A>::Y<A>())->f();\n" 66 "}")); 67 } 68 69 TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) { 70 CXXMemberCallVisitor Visitor; 71 Visitor.ExpectMatch("A::x", 6, 20); 72 EXPECT_TRUE(Visitor.runOver( 73 "template <typename T1> struct X {\n" 74 " template <typename T2, bool B> struct Y { void g(); };\n" 75 "};\n" 76 "template <typename T1> template <typename T2>\n" 77 "struct X<T1>::Y<T2, true> {\n" 78 " void f() { T2 y; y.x(); }\n" 79 "};\n" 80 "struct A { void x(); };\n" 81 "int main() {\n" 82 " (new X<A>::Y<A, true>())->f();\n" 83 "}\n")); 84 } 85 86 TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) { 87 CXXMemberCallVisitor Visitor; 88 Visitor.ExpectMatch("A::f", 4, 5); 89 EXPECT_TRUE(Visitor.runOver( 90 "struct A {\n" 91 " void f() const {}\n" 92 " template<class T> void g(const T& t) const {\n" 93 " t.f();\n" 94 " }\n" 95 "};\n" 96 "template void A::g(const A& a) const;\n")); 97 } 98 99 class CXXOperatorCallExprTraverser 100 : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> { 101 public: 102 // Use Traverse, not Visit, to check that data recursion optimization isn't 103 // bypassing the call of this function. 104 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) { 105 Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc()); 106 return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>:: 107 TraverseCXXOperatorCallExpr(CE); 108 } 109 }; 110 111 TEST(RecursiveASTVisitor, TraversesOverloadedOperator) { 112 CXXOperatorCallExprTraverser Visitor; 113 Visitor.ExpectMatch("()", 4, 9); 114 EXPECT_TRUE(Visitor.runOver( 115 "struct A {\n" 116 " int operator()();\n" 117 "} a;\n" 118 "int k = a();\n")); 119 } 120 121 } // end anonymous namespace 122