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