1 //===- unittest/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp --------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "TestVisitor.h" 10 11 using namespace clang; 12 13 namespace { 14 15 class CXXMemberCallVisitor : public ExpectedLocationVisitor { 16 public: 17 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) override { 18 Match(Call->getMethodDecl()->getQualifiedNameAsString(), 19 Call->getBeginLoc()); 20 return true; 21 } 22 }; 23 24 TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) { 25 CXXMemberCallVisitor Visitor; 26 Visitor.ExpectMatch("Y::x", 3, 3); 27 EXPECT_TRUE(Visitor.runOver( 28 "struct Y { void x(); };\n" 29 "template<typename T> void y(T t) {\n" 30 " t.x();\n" 31 "}\n" 32 "void foo() { y<Y>(Y()); }")); 33 } 34 35 TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) { 36 CXXMemberCallVisitor Visitor; 37 Visitor.ExpectMatch("Y::x", 4, 5); 38 EXPECT_TRUE(Visitor.runOver( 39 "struct Y { void x(); };\n" 40 "template<typename T> struct Z {\n" 41 " template<typename U> static void f() {\n" 42 " T().x();\n" 43 " }\n" 44 "};\n" 45 "void foo() { Z<Y>::f<int>(); }")); 46 } 47 48 TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) { 49 CXXMemberCallVisitor Visitor; 50 Visitor.ExpectMatch("A::x", 5, 7); 51 EXPECT_TRUE(Visitor.runOver( 52 "template <typename T1> struct X {\n" 53 " template <typename T2> struct Y {\n" 54 " void f() {\n" 55 " T2 y;\n" 56 " y.x();\n" 57 " }\n" 58 " };\n" 59 "};\n" 60 "struct A { void x(); };\n" 61 "int main() {\n" 62 " (new X<A>::Y<A>())->f();\n" 63 "}")); 64 } 65 66 TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) { 67 CXXMemberCallVisitor Visitor; 68 Visitor.ExpectMatch("A::x", 6, 20); 69 EXPECT_TRUE(Visitor.runOver( 70 "template <typename T1> struct X {\n" 71 " template <typename T2, bool B> struct Y { void g(); };\n" 72 "};\n" 73 "template <typename T1> template <typename T2>\n" 74 "struct X<T1>::Y<T2, true> {\n" 75 " void f() { T2 y; y.x(); }\n" 76 "};\n" 77 "struct A { void x(); };\n" 78 "int main() {\n" 79 " (new X<A>::Y<A, true>())->f();\n" 80 "}\n")); 81 } 82 83 TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) { 84 CXXMemberCallVisitor Visitor; 85 Visitor.ExpectMatch("A::f", 4, 5); 86 EXPECT_TRUE(Visitor.runOver( 87 "struct A {\n" 88 " void f() const {}\n" 89 " template<class T> void g(const T& t) const {\n" 90 " t.f();\n" 91 " }\n" 92 "};\n" 93 "template void A::g(const A& a) const;\n")); 94 } 95 96 } // end anonymous namespace 97