|  | //===- unittest/Tooling/RecursiveASTVisitorTestCallVisitor.cpp ------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "TestVisitor.h" | 
|  | #include <stack> | 
|  |  | 
|  | using namespace clang; | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class CXXMemberCallVisitor | 
|  | : public ExpectedLocationVisitor<CXXMemberCallVisitor> { | 
|  | public: | 
|  | bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) { | 
|  | Match(Call->getMethodDecl()->getQualifiedNameAsString(), | 
|  | Call->getLocStart()); | 
|  | return true; | 
|  | } | 
|  | }; | 
|  |  | 
|  | TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) { | 
|  | CXXMemberCallVisitor Visitor; | 
|  | Visitor.ExpectMatch("Y::x", 3, 3); | 
|  | EXPECT_TRUE(Visitor.runOver( | 
|  | "struct Y { void x(); };\n" | 
|  | "template<typename T> void y(T t) {\n" | 
|  | "  t.x();\n" | 
|  | "}\n" | 
|  | "void foo() { y<Y>(Y()); }")); | 
|  | } | 
|  |  | 
|  | TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) { | 
|  | CXXMemberCallVisitor Visitor; | 
|  | Visitor.ExpectMatch("Y::x", 4, 5); | 
|  | EXPECT_TRUE(Visitor.runOver( | 
|  | "struct Y { void x(); };\n" | 
|  | "template<typename T> struct Z {\n" | 
|  | "  template<typename U> static void f() {\n" | 
|  | "    T().x();\n" | 
|  | "  }\n" | 
|  | "};\n" | 
|  | "void foo() { Z<Y>::f<int>(); }")); | 
|  | } | 
|  |  | 
|  | TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) { | 
|  | CXXMemberCallVisitor Visitor; | 
|  | Visitor.ExpectMatch("A::x", 5, 7); | 
|  | EXPECT_TRUE(Visitor.runOver( | 
|  | "template <typename T1> struct X {\n" | 
|  | "  template <typename T2> struct Y {\n" | 
|  | "    void f() {\n" | 
|  | "      T2 y;\n" | 
|  | "      y.x();\n" | 
|  | "    }\n" | 
|  | "  };\n" | 
|  | "};\n" | 
|  | "struct A { void x(); };\n" | 
|  | "int main() {\n" | 
|  | "  (new X<A>::Y<A>())->f();\n" | 
|  | "}")); | 
|  | } | 
|  |  | 
|  | TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) { | 
|  | CXXMemberCallVisitor Visitor; | 
|  | Visitor.ExpectMatch("A::x", 6, 20); | 
|  | EXPECT_TRUE(Visitor.runOver( | 
|  | "template <typename T1> struct X {\n" | 
|  | "  template <typename T2, bool B> struct Y { void g(); };\n" | 
|  | "};\n" | 
|  | "template <typename T1> template <typename T2>\n" | 
|  | "struct X<T1>::Y<T2, true> {\n" | 
|  | "  void f() { T2 y; y.x(); }\n" | 
|  | "};\n" | 
|  | "struct A { void x(); };\n" | 
|  | "int main() {\n" | 
|  | "  (new X<A>::Y<A, true>())->f();\n" | 
|  | "}\n")); | 
|  | } | 
|  |  | 
|  | TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) { | 
|  | CXXMemberCallVisitor Visitor; | 
|  | Visitor.ExpectMatch("A::f", 4, 5); | 
|  | EXPECT_TRUE(Visitor.runOver( | 
|  | "struct A {\n" | 
|  | "  void f() const {}\n" | 
|  | "  template<class T> void g(const T& t) const {\n" | 
|  | "    t.f();\n" | 
|  | "  }\n" | 
|  | "};\n" | 
|  | "template void A::g(const A& a) const;\n")); | 
|  | } | 
|  |  | 
|  | class CXXOperatorCallExprTraverser | 
|  | : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> { | 
|  | public: | 
|  | // Use Traverse, not Visit, to check that data recursion optimization isn't | 
|  | // bypassing the call of this function. | 
|  | bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) { | 
|  | Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc()); | 
|  | return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>:: | 
|  | TraverseCXXOperatorCallExpr(CE); | 
|  | } | 
|  | }; | 
|  |  | 
|  | TEST(RecursiveASTVisitor, TraversesOverloadedOperator) { | 
|  | CXXOperatorCallExprTraverser Visitor; | 
|  | Visitor.ExpectMatch("()", 4, 9); | 
|  | EXPECT_TRUE(Visitor.runOver( | 
|  | "struct A {\n" | 
|  | "  int operator()();\n" | 
|  | "} a;\n" | 
|  | "int k = a();\n")); | 
|  | } | 
|  |  | 
|  | } // end anonymous namespace |