xref: /llvm-project/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp (revision 4e600751d2f7e8e7b85a71b7128b68444bdde91b)
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