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(Name: Call->getMethodDecl()->getQualifiedNameAsString(), |
19 | Location: 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 | |