1 //===- unittest/Tooling/RecursiveASTVisitorTests/CXXMemberCall.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 using namespace clang;
13 
14 namespace {
15 
16 class CXXMemberCallVisitor
17   : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
18 public:
19   bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
20     Match(Call->getMethodDecl()->getQualifiedNameAsString(),
21           Call->getBeginLoc());
22     return true;
23   }
24 };
25 
26 TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
27   CXXMemberCallVisitor Visitor;
28   Visitor.ExpectMatch("Y::x", 3, 3);
29   EXPECT_TRUE(Visitor.runOver(
30     "struct Y { void x(); };\n"
31     "template<typename T> void y(T t) {\n"
32     "  t.x();\n"
33     "}\n"
34     "void foo() { y<Y>(Y()); }"));
35 }
36 
37 TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
38   CXXMemberCallVisitor Visitor;
39   Visitor.ExpectMatch("Y::x", 4, 5);
40   EXPECT_TRUE(Visitor.runOver(
41     "struct Y { void x(); };\n"
42     "template<typename T> struct Z {\n"
43     "  template<typename U> static void f() {\n"
44     "    T().x();\n"
45     "  }\n"
46     "};\n"
47     "void foo() { Z<Y>::f<int>(); }"));
48 }
49 
50 TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
51   CXXMemberCallVisitor Visitor;
52   Visitor.ExpectMatch("A::x", 5, 7);
53   EXPECT_TRUE(Visitor.runOver(
54     "template <typename T1> struct X {\n"
55     "  template <typename T2> struct Y {\n"
56     "    void f() {\n"
57     "      T2 y;\n"
58     "      y.x();\n"
59     "    }\n"
60     "  };\n"
61     "};\n"
62     "struct A { void x(); };\n"
63     "int main() {\n"
64     "  (new X<A>::Y<A>())->f();\n"
65     "}"));
66 }
67 
68 TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) {
69   CXXMemberCallVisitor Visitor;
70   Visitor.ExpectMatch("A::x", 6, 20);
71   EXPECT_TRUE(Visitor.runOver(
72     "template <typename T1> struct X {\n"
73     "  template <typename T2, bool B> struct Y { void g(); };\n"
74     "};\n"
75     "template <typename T1> template <typename T2>\n"
76     "struct X<T1>::Y<T2, true> {\n"
77     "  void f() { T2 y; y.x(); }\n"
78     "};\n"
79     "struct A { void x(); };\n"
80     "int main() {\n"
81     "  (new X<A>::Y<A, true>())->f();\n"
82     "}\n"));
83 }
84 
85 TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
86   CXXMemberCallVisitor Visitor;
87   Visitor.ExpectMatch("A::f", 4, 5);
88   EXPECT_TRUE(Visitor.runOver(
89     "struct A {\n"
90     "  void f() const {}\n"
91     "  template<class T> void g(const T& t) const {\n"
92     "    t.f();\n"
93     "  }\n"
94     "};\n"
95     "template void A::g(const A& a) const;\n"));
96 }
97 
98 } // end anonymous namespace
99