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:
VisitCXXMemberCallExpr(CXXMemberCallExpr * Call)20   bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
21     Match(Call->getMethodDecl()->getQualifiedNameAsString(),
22           Call->getLocStart());
23     return true;
24   }
25 };
26 
TEST(RecursiveASTVisitor,VisitsCallInTemplateInstantiation)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 
TEST(RecursiveASTVisitor,VisitsCallInNestedFunctionTemplateInstantiation)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 
TEST(RecursiveASTVisitor,VisitsCallInNestedClassTemplateInstantiation)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 
TEST(RecursiveASTVisitor,VisitsCallInPartialTemplateSpecialization)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 
TEST(RecursiveASTVisitor,VisitsExplicitTemplateSpecialization)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.
TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * CE)104   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
105     Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
106     return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
107         TraverseCXXOperatorCallExpr(CE);
108   }
109 };
110 
TEST(RecursiveASTVisitor,TraversesOverloadedOperator)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