1//===- unittest/Introspection/IntrospectionTest.cpp ----------*- C++ -*---===//
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// Tests for AST location API introspection.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/ASTContext.h"
14#include "clang/ASTMatchers/ASTMatchFinder.h"
15#include "clang/ASTMatchers/ASTMatchers.h"
16#include "clang/Tooling/NodeIntrospection.h"
17#include "clang/Tooling/Tooling.h"
18#include "gmock/gmock-matchers.h"
19#include "gmock/gmock.h"
20#include "gtest/gtest.h"
21
22using namespace clang;
23using namespace clang::ast_matchers;
24using namespace clang::tooling;
25
26using ::testing::Pair;
27using ::testing::UnorderedElementsAre;
28
29template <typename T, typename MapType>
30std::vector<std::pair<std::string, T>>
31FormatExpected(const MapType &Accessors) {
32 std::vector<std::pair<std::string, T>> Result;
33 llvm::transform(llvm::make_filter_range(Accessors,
34 [](const auto &Accessor) {
35 return Accessor.first.isValid();
36 }),
37 std::back_inserter(Result), [](const auto &Accessor) {
38 return std::make_pair(
39 LocationCallFormatterCpp::format(Call: *Accessor.second),
40 Accessor.first);
41 });
42 return Result;
43}
44
45#define STRING_LOCATION_PAIR(INSTANCE, LOC) Pair(#LOC, INSTANCE->LOC)
46
47#define STRING_LOCATION_STDPAIR(INSTANCE, LOC) \
48 std::make_pair(std::string(#LOC), INSTANCE->LOC)
49
50/**
51 A test formatter for a hypothetical language which needs
52 neither casts nor '->'.
53*/
54class LocationCallFormatterSimple {
55public:
56 static void print(const LocationCall &Call, llvm::raw_ostream &OS) {
57 if (Call.isCast()) {
58 if (const LocationCall *On = Call.on())
59 print(Call: *On, OS);
60 return;
61 }
62 if (const LocationCall *On = Call.on()) {
63 print(Call: *On, OS);
64 OS << '.';
65 }
66 OS << Call.name() << "()";
67 }
68
69 static std::string format(const LocationCall &Call) {
70 std::string Result;
71 llvm::raw_string_ostream OS(Result);
72 print(Call, OS);
73 OS.flush();
74 return Result;
75 }
76};
77
78TEST(Introspection, SourceLocations_CallContainer) {
79 SourceLocationMap slm;
80 SharedLocationCall Prefix;
81 slm.insert(x: std::make_pair(
82 x: SourceLocation(),
83 y: llvm::makeIntrusiveRefCnt<LocationCall>(A&: Prefix, A: "getSourceRange")));
84 EXPECT_EQ(slm.size(), 1u);
85
86 auto callTypeLoc =
87 llvm::makeIntrusiveRefCnt<LocationCall>(A&: Prefix, A: "getTypeLoc");
88 slm.insert(x: std::make_pair(
89 x: SourceLocation(),
90 y: llvm::makeIntrusiveRefCnt<LocationCall>(A&: callTypeLoc, A: "getSourceRange")));
91 EXPECT_EQ(slm.size(), 2u);
92}
93
94TEST(Introspection, SourceLocations_CallContainer2) {
95 SourceRangeMap slm;
96 SharedLocationCall Prefix;
97 slm.insert(
98 x: std::make_pair(x: SourceRange(), y: llvm::makeIntrusiveRefCnt<LocationCall>(
99 A&: Prefix, A: "getCXXOperatorNameRange")));
100 EXPECT_EQ(slm.size(), 1u);
101
102 slm.insert(x: std::make_pair(
103 x: SourceRange(),
104 y: llvm::makeIntrusiveRefCnt<LocationCall>(A&: Prefix, A: "getSourceRange")));
105 EXPECT_EQ(slm.size(), 2u);
106}
107
108TEST(Introspection, SourceLocations_CallChainFormatting) {
109 SharedLocationCall Prefix;
110 auto chainedCall = llvm::makeIntrusiveRefCnt<LocationCall>(
111 A: llvm::makeIntrusiveRefCnt<LocationCall>(A&: Prefix, A: "getTypeLoc"),
112 A: "getSourceRange");
113 EXPECT_EQ(LocationCallFormatterCpp::format(*chainedCall),
114 "getTypeLoc().getSourceRange()");
115}
116
117TEST(Introspection, SourceLocations_Formatter) {
118 SharedLocationCall Prefix;
119 auto chainedCall = llvm::makeIntrusiveRefCnt<LocationCall>(
120 A: llvm::makeIntrusiveRefCnt<LocationCall>(
121 A: llvm::makeIntrusiveRefCnt<LocationCall>(
122 A: llvm::makeIntrusiveRefCnt<LocationCall>(
123 A&: Prefix, A: "getTypeSourceInfo", A: LocationCall::ReturnsPointer),
124 A: "getTypeLoc"),
125 A: "getAs<clang::TypeSpecTypeLoc>", A: LocationCall::IsCast),
126 A: "getNameLoc");
127
128 EXPECT_EQ("getTypeSourceInfo()->getTypeLoc().getAs<clang::TypeSpecTypeLoc>()."
129 "getNameLoc()",
130 LocationCallFormatterCpp::format(*chainedCall));
131 EXPECT_EQ("getTypeSourceInfo().getTypeLoc().getNameLoc()",
132 LocationCallFormatterSimple::format(*chainedCall));
133}
134
135TEST(Introspection, SourceLocations_Stmt) {
136 if (!NodeIntrospection::hasIntrospectionSupport())
137 GTEST_SKIP();
138 auto AST = buildASTFromCode(Code: "void foo() {} void bar() { foo(); }", FileName: "foo.cpp",
139 PCHContainerOps: std::make_shared<PCHContainerOperations>());
140 auto &Ctx = AST->getASTContext();
141 auto &TU = *Ctx.getTranslationUnitDecl();
142
143 auto BoundNodes = ast_matchers::match(
144 Matcher: decl(hasDescendant(
145 callExpr(callee(InnerMatcher: functionDecl(hasName(Name: "foo")))).bind(ID: "fooCall"))),
146 Node: TU, Context&: Ctx);
147
148 EXPECT_EQ(BoundNodes.size(), 1u);
149
150 auto *FooCall = BoundNodes[0].getNodeAs<CallExpr>(ID: "fooCall");
151
152 auto Result = NodeIntrospection::GetLocations(FooCall);
153
154 auto ExpectedLocations =
155 FormatExpected<SourceLocation>(Result.LocationAccessors);
156
157 EXPECT_THAT(
158 ExpectedLocations,
159 UnorderedElementsAre(STRING_LOCATION_PAIR(FooCall, getBeginLoc()),
160 STRING_LOCATION_PAIR(FooCall, getEndLoc()),
161 STRING_LOCATION_PAIR(FooCall, getExprLoc()),
162 STRING_LOCATION_PAIR(FooCall, getRParenLoc())));
163
164 auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors);
165
166 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(STRING_LOCATION_PAIR(
167 FooCall, getSourceRange())));
168}
169
170TEST(Introspection, SourceLocations_Decl) {
171 if (!NodeIntrospection::hasIntrospectionSupport())
172 GTEST_SKIP();
173 auto AST =
174 buildASTFromCode(Code: R"cpp(
175namespace ns1 {
176namespace ns2 {
177template <typename T, typename U> struct Foo {};
178template <typename T, typename U> struct Bar {
179 struct Nested {
180 template <typename A, typename B>
181 Foo<A, B> method(int i, bool b) const noexcept(true);
182 };
183};
184} // namespace ns2
185} // namespace ns1
186
187template <typename T, typename U>
188template <typename A, typename B>
189ns1::ns2::Foo<A, B> ns1::ns2::Bar<T, U>::Nested::method(int i, bool b) const
190 noexcept(true) {}
191)cpp",
192 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
193 auto &Ctx = AST->getASTContext();
194 auto &TU = *Ctx.getTranslationUnitDecl();
195
196 auto BoundNodes = ast_matchers::match(
197 Matcher: decl(hasDescendant(
198 cxxMethodDecl(hasName(Name: "method"), isDefinition()).bind(ID: "method"))),
199 Node: TU, Context&: Ctx);
200
201 EXPECT_EQ(BoundNodes.size(), 1u);
202
203 const auto *MethodDecl = BoundNodes[0].getNodeAs<CXXMethodDecl>(ID: "method");
204
205 auto Result = NodeIntrospection::GetLocations(MethodDecl);
206
207 auto ExpectedLocations =
208 FormatExpected<SourceLocation>(Result.LocationAccessors);
209
210 llvm::sort(ExpectedLocations);
211
212 // clang-format off
213 std::vector<std::pair<std::string, SourceLocation>> ActualLocations{
214STRING_LOCATION_STDPAIR(MethodDecl, getBeginLoc()),
215STRING_LOCATION_STDPAIR(MethodDecl, getBodyRBrace()),
216STRING_LOCATION_STDPAIR(MethodDecl, getEndLoc()),
217STRING_LOCATION_STDPAIR(MethodDecl, getInnerLocStart()),
218STRING_LOCATION_STDPAIR(MethodDecl, getLocation()),
219STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getBeginLoc()),
220STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getEndLoc()),
221STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getLoc()),
222STRING_LOCATION_STDPAIR(MethodDecl, getOuterLocStart()),
223STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getBeginLoc()),
224STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getEndLoc()),
225STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getLocalBeginLoc()),
226STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getLocalEndLoc()),
227STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getBeginLoc()),
228STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getEndLoc()),
229STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getLocalBeginLoc()),
230STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getLocalEndLoc()),
231STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getBeginLoc()),
232STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getEndLoc()),
233STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getLocalBeginLoc()),
234STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getLocalEndLoc()),
235STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getBeginLoc()),
236STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getEndLoc()),
237STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getLocalBeginLoc()),
238STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getLocalEndLoc()),
239STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
240STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
241STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
242STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getBeginLoc()),
243STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getEndLoc()),
244STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
245STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getBeginLoc()),
246STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getEndLoc()),
247STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getLParenLoc()),
248STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getLocalRangeBegin()),
249STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getLocalRangeEnd()),
250STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getRParenLoc()),
251STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
252STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
253STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
254STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
255STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
256STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getBeginLoc()),
257STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getEndLoc()),
258STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getLocalBeginLoc()),
259STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getLocalEndLoc()),
260STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getBeginLoc()),
261STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getEndLoc()),
262STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getLocalBeginLoc()),
263STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getLocalEndLoc()),
264STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getBeginLoc()),
265STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getEndLoc()),
266STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
267STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
268STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
269STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getNextTypeLoc().getBeginLoc()),
270STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getNextTypeLoc().getEndLoc()),
271STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
272STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
273STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
274STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
275STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
276STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
277STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
278STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getBeginLoc()),
279STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getEndLoc()),
280STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getLocalBeginLoc()),
281STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getLocalEndLoc()),
282STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getBeginLoc()),
283STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getEndLoc()),
284STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getLocalBeginLoc()),
285STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getLocalEndLoc()),
286STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
287STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()),
288STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
289STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
290STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
291STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getBeginLoc()),
292STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getEndLoc()),
293STRING_LOCATION_STDPAIR(MethodDecl, getTypeSpecEndLoc()),
294STRING_LOCATION_STDPAIR(MethodDecl, getTypeSpecStartLoc())
295 };
296 // clang-format on
297
298 EXPECT_EQ(ExpectedLocations, ActualLocations);
299
300 auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors);
301
302 llvm::sort(ExpectedRanges, [](const auto &LHS, const auto &RHS) {
303 return LHS.first < RHS.first;
304 });
305
306 // clang-format off
307 EXPECT_EQ(
308 llvm::ArrayRef(ExpectedRanges),
309 (ArrayRef<std::pair<std::string, SourceRange>>{
310STRING_LOCATION_STDPAIR(MethodDecl, getExceptionSpecSourceRange()),
311STRING_LOCATION_STDPAIR(MethodDecl, getNameInfo().getSourceRange()),
312STRING_LOCATION_STDPAIR(MethodDecl, getParametersSourceRange()),
313STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getLocalSourceRange()),
314STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getLocalSourceRange()),
315STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getLocalSourceRange()),
316STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getLocalSourceRange()),
317STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getPrefix().getSourceRange()),
318STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getPrefix().getSourceRange()),
319STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getSourceRange()),
320STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getLocalSourceRange()),
321STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getPrefix().getTypeLoc().getSourceRange()),
322STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getSourceRange()),
323STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getLocalSourceRange()),
324STRING_LOCATION_STDPAIR(MethodDecl, getQualifierLoc().getTypeLoc().getSourceRange()),
325STRING_LOCATION_STDPAIR(MethodDecl, getReturnTypeSourceRange()),
326STRING_LOCATION_STDPAIR(MethodDecl, getSourceRange()),
327STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getExceptionSpecRange()),
328STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getParensRange()),
329STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
330STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
331STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getLocalSourceRange()),
332STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getLocalSourceRange()),
333STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getSourceRange()),
334STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getSourceRange()),
335STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getLocalSourceRange()),
336STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getNextTypeLoc().getLocalSourceRange()),
337STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getNextTypeLoc().getSourceRange()),
338STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getAs<clang::FunctionTypeLoc>().getReturnLoc().getSourceRange()),
339STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getLocalSourceRange()),
340STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
341STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
342STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getLocalSourceRange()),
343STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getLocalSourceRange()),
344STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getPrefix().getSourceRange()),
345STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::ElaboratedTypeLoc>().getQualifierLoc().getSourceRange()),
346STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
347STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getLocalSourceRange()),
348STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getNextTypeLoc().getSourceRange()),
349STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()),
350STRING_LOCATION_STDPAIR(MethodDecl, getTypeSourceInfo()->getTypeLoc().getSourceRange())
351 }));
352 // clang-format on
353}
354
355TEST(Introspection, SourceLocations_NNS) {
356 if (!NodeIntrospection::hasIntrospectionSupport())
357 GTEST_SKIP();
358 auto AST =
359 buildASTFromCode(Code: R"cpp(
360namespace ns
361{
362 struct A {
363 void foo();
364};
365}
366void ns::A::foo() {}
367)cpp",
368 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
369 auto &Ctx = AST->getASTContext();
370 auto &TU = *Ctx.getTranslationUnitDecl();
371
372 auto BoundNodes = ast_matchers::match(
373 Matcher: decl(hasDescendant(nestedNameSpecifierLoc().bind(ID: "nns"))), Node: TU, Context&: Ctx);
374
375 EXPECT_EQ(BoundNodes.size(), 1u);
376
377 const auto *NNS = BoundNodes[0].getNodeAs<NestedNameSpecifierLoc>(ID: "nns");
378
379 auto Result = NodeIntrospection::GetLocations(*NNS);
380
381 auto ExpectedLocations =
382 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
383
384 llvm::sort(C&: ExpectedLocations);
385
386 EXPECT_EQ(
387 llvm::ArrayRef(ExpectedLocations),
388 (ArrayRef<std::pair<std::string, SourceLocation>>{
389 STRING_LOCATION_STDPAIR(NNS, getBeginLoc()),
390 STRING_LOCATION_STDPAIR(NNS, getEndLoc()),
391 STRING_LOCATION_STDPAIR(NNS, getLocalBeginLoc()),
392 STRING_LOCATION_STDPAIR(NNS, getLocalEndLoc()),
393 STRING_LOCATION_STDPAIR(NNS, getPrefix().getBeginLoc()),
394 STRING_LOCATION_STDPAIR(NNS, getPrefix().getEndLoc()),
395 STRING_LOCATION_STDPAIR(NNS, getPrefix().getLocalBeginLoc()),
396 STRING_LOCATION_STDPAIR(NNS, getPrefix().getLocalEndLoc()),
397 STRING_LOCATION_STDPAIR(
398 NNS, getTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
399 STRING_LOCATION_STDPAIR(NNS, getTypeLoc().getBeginLoc()),
400 STRING_LOCATION_STDPAIR(NNS, getTypeLoc().getEndLoc())}));
401
402 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
403
404 EXPECT_THAT(
405 ExpectedRanges,
406 UnorderedElementsAre(
407 STRING_LOCATION_PAIR(NNS, getPrefix().getLocalSourceRange()),
408 STRING_LOCATION_PAIR(NNS, getPrefix().getSourceRange()),
409 STRING_LOCATION_PAIR(NNS, getLocalSourceRange()),
410 STRING_LOCATION_PAIR(NNS, getSourceRange()),
411 STRING_LOCATION_PAIR(NNS, getTypeLoc().getSourceRange()),
412 STRING_LOCATION_PAIR(NNS, getTypeLoc().getLocalSourceRange())));
413}
414
415TEST(Introspection, SourceLocations_TA_Type) {
416 if (!NodeIntrospection::hasIntrospectionSupport())
417 GTEST_SKIP();
418 auto AST =
419 buildASTFromCode(Code: R"cpp(
420template<typename T>
421 struct A {
422 void foo();
423};
424
425void foo()
426{
427 A<int> a;
428}
429)cpp",
430 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
431 auto &Ctx = AST->getASTContext();
432 auto &TU = *Ctx.getTranslationUnitDecl();
433
434 auto BoundNodes = ast_matchers::match(
435 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
436
437 EXPECT_EQ(BoundNodes.size(), 1u);
438
439 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
440
441 auto Result = NodeIntrospection::GetLocations(*TA);
442
443 auto ExpectedLocations =
444 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
445
446 // clang-format off
447 EXPECT_THAT(ExpectedLocations,
448 UnorderedElementsAre(
449STRING_LOCATION_PAIR(TA, getLocation()),
450STRING_LOCATION_PAIR(TA,
451 getTypeSourceInfo()->getTypeLoc().getAs<clang::BuiltinTypeLoc>().getBuiltinLoc()),
452STRING_LOCATION_PAIR(TA,
453 getTypeSourceInfo()->getTypeLoc().getAs<clang::BuiltinTypeLoc>().getNameLoc()),
454STRING_LOCATION_PAIR(
455 TA, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
456STRING_LOCATION_PAIR(
457 TA, getTypeSourceInfo()->getTypeLoc().getEndLoc())
458 ));
459 // clang-format on
460
461 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
462
463 EXPECT_THAT(
464 ExpectedRanges,
465 UnorderedElementsAre(
466 STRING_LOCATION_PAIR(TA, getSourceRange()),
467 STRING_LOCATION_PAIR(
468 TA, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
469 STRING_LOCATION_PAIR(
470 TA, getTypeSourceInfo()->getTypeLoc().getLocalSourceRange())));
471}
472
473TEST(Introspection, SourceLocations_TA_Decl) {
474 if (!NodeIntrospection::hasIntrospectionSupport())
475 GTEST_SKIP();
476 auto AST =
477 buildASTFromCode(Code: R"cpp(
478template<void(*Ty)()>
479void test2() {}
480void doNothing() {}
481void test() {
482 test2<doNothing>();
483}
484)cpp",
485 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
486 auto &Ctx = AST->getASTContext();
487 auto &TU = *Ctx.getTranslationUnitDecl();
488
489 auto BoundNodes = ast_matchers::match(
490 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
491
492 EXPECT_EQ(BoundNodes.size(), 1u);
493
494 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
495
496 auto Result = NodeIntrospection::GetLocations(*TA);
497
498 auto ExpectedLocations =
499 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
500
501 EXPECT_THAT(ExpectedLocations,
502 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation())));
503
504 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
505
506 EXPECT_THAT(ExpectedRanges,
507 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange())));
508}
509
510TEST(Introspection, SourceLocations_TA_Nullptr) {
511 if (!NodeIntrospection::hasIntrospectionSupport())
512 GTEST_SKIP();
513 auto AST =
514 buildASTFromCode(Code: R"cpp(
515template<void(*Ty)()>
516void test2() {}
517void doNothing() {}
518void test() {
519 test2<nullptr>();
520}
521)cpp",
522 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
523 auto &Ctx = AST->getASTContext();
524 auto &TU = *Ctx.getTranslationUnitDecl();
525
526 auto BoundNodes = ast_matchers::match(
527 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
528
529 EXPECT_EQ(BoundNodes.size(), 1u);
530
531 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
532
533 auto Result = NodeIntrospection::GetLocations(*TA);
534
535 auto ExpectedLocations =
536 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
537
538 EXPECT_THAT(ExpectedLocations,
539 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation())));
540
541 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
542
543 EXPECT_THAT(ExpectedRanges,
544 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange())));
545}
546
547TEST(Introspection, SourceLocations_TA_Integral) {
548 if (!NodeIntrospection::hasIntrospectionSupport())
549 GTEST_SKIP();
550 auto AST =
551 buildASTFromCode(Code: R"cpp(
552template<int>
553void test2() {}
554void test() {
555 test2<42>();
556}
557)cpp",
558 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
559 auto &Ctx = AST->getASTContext();
560 auto &TU = *Ctx.getTranslationUnitDecl();
561
562 auto BoundNodes = ast_matchers::match(
563 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
564
565 EXPECT_EQ(BoundNodes.size(), 1u);
566
567 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
568
569 auto Result = NodeIntrospection::GetLocations(*TA);
570
571 auto ExpectedLocations =
572 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
573
574 EXPECT_THAT(ExpectedLocations,
575 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation())));
576
577 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
578
579 EXPECT_THAT(ExpectedRanges,
580 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange())));
581}
582
583TEST(Introspection, SourceLocations_TA_Template) {
584 if (!NodeIntrospection::hasIntrospectionSupport())
585 GTEST_SKIP();
586 auto AST =
587 buildASTFromCode(Code: R"cpp(
588template<typename T> class A;
589template <template <typename> class T> void foo();
590void bar()
591{
592 foo<A>();
593}
594)cpp",
595 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
596 auto &Ctx = AST->getASTContext();
597 auto &TU = *Ctx.getTranslationUnitDecl();
598
599 auto BoundNodes = ast_matchers::match(
600 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
601
602 EXPECT_EQ(BoundNodes.size(), 1u);
603
604 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
605
606 auto Result = NodeIntrospection::GetLocations(*TA);
607
608 auto ExpectedLocations =
609 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
610
611 EXPECT_THAT(
612 ExpectedLocations,
613 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation()),
614 STRING_LOCATION_PAIR(TA, getTemplateNameLoc())));
615
616 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
617
618 EXPECT_THAT(ExpectedRanges,
619 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange())));
620}
621
622TEST(Introspection, SourceLocations_TA_TemplateExpansion) {
623 if (!NodeIntrospection::hasIntrospectionSupport())
624 GTEST_SKIP();
625 auto AST = buildASTFromCodeWithArgs(
626 Code: R"cpp(
627template<template<typename> class ...> class B { };
628 template<template<typename> class ...T> class C {
629 B<T...> testTemplateExpansion;
630};
631)cpp",
632 Args: {"-fno-delayed-template-parsing"}, FileName: "foo.cpp", ToolName: "clang-tool",
633 PCHContainerOps: std::make_shared<PCHContainerOperations>());
634 auto &Ctx = AST->getASTContext();
635 auto &TU = *Ctx.getTranslationUnitDecl();
636
637 auto BoundNodes = ast_matchers::match(
638 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
639
640 EXPECT_EQ(BoundNodes.size(), 1u);
641
642 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
643
644 auto Result = NodeIntrospection::GetLocations(*TA);
645
646 auto ExpectedLocations =
647 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
648
649 EXPECT_THAT(
650 ExpectedLocations,
651 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation()),
652 STRING_LOCATION_PAIR(TA, getTemplateNameLoc()),
653 STRING_LOCATION_PAIR(TA, getTemplateEllipsisLoc())));
654
655 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
656
657 EXPECT_THAT(ExpectedRanges,
658 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange())));
659}
660
661TEST(Introspection, SourceLocations_TA_Expression) {
662 if (!NodeIntrospection::hasIntrospectionSupport())
663 GTEST_SKIP();
664 auto AST =
665 buildASTFromCode(Code: R"cpp(
666template<int, int = 0> class testExpr;
667template<int I> class testExpr<I> { };
668)cpp",
669 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
670 auto &Ctx = AST->getASTContext();
671 auto &TU = *Ctx.getTranslationUnitDecl();
672
673 auto BoundNodes = ast_matchers::match(
674 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
675
676 EXPECT_EQ(BoundNodes.size(), 1u);
677
678 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
679
680 auto Result = NodeIntrospection::GetLocations(*TA);
681
682 auto ExpectedLocations =
683 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
684
685 EXPECT_THAT(ExpectedLocations,
686 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getLocation())));
687
688 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
689
690 EXPECT_THAT(ExpectedRanges,
691 UnorderedElementsAre(STRING_LOCATION_PAIR(TA, getSourceRange())));
692}
693
694TEST(Introspection, SourceLocations_TA_Pack) {
695 if (!NodeIntrospection::hasIntrospectionSupport())
696 GTEST_SKIP();
697 auto AST = buildASTFromCodeWithArgs(
698 Code: R"cpp(
699template<typename... T> class A {};
700void foo()
701{
702 A<int> ai;
703}
704)cpp",
705 Args: {"-fno-delayed-template-parsing"}, FileName: "foo.cpp", ToolName: "clang-tool",
706 PCHContainerOps: std::make_shared<PCHContainerOperations>());
707 auto &Ctx = AST->getASTContext();
708 auto &TU = *Ctx.getTranslationUnitDecl();
709
710 auto BoundNodes = ast_matchers::match(
711 Matcher: decl(hasDescendant(templateArgumentLoc().bind(ID: "ta"))), Node: TU, Context&: Ctx);
712
713 EXPECT_EQ(BoundNodes.size(), 1u);
714
715 const auto *TA = BoundNodes[0].getNodeAs<TemplateArgumentLoc>(ID: "ta");
716
717 auto Result = NodeIntrospection::GetLocations(*TA);
718
719 auto ExpectedLocations =
720 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
721
722 // clang-format off
723 EXPECT_THAT(ExpectedLocations,
724 UnorderedElementsAre(
725STRING_LOCATION_PAIR(TA, getLocation()),
726STRING_LOCATION_PAIR(TA,
727 getTypeSourceInfo()->getTypeLoc().getAs<clang::BuiltinTypeLoc>().getBuiltinLoc()),
728STRING_LOCATION_PAIR(TA,
729 getTypeSourceInfo()->getTypeLoc().getAs<clang::BuiltinTypeLoc>().getNameLoc()),
730STRING_LOCATION_PAIR(
731 TA, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
732STRING_LOCATION_PAIR(
733 TA, getTypeSourceInfo()->getTypeLoc().getEndLoc())
734 ));
735 // clang-format on
736
737 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
738
739 EXPECT_THAT(
740 ExpectedRanges,
741 UnorderedElementsAre(
742 STRING_LOCATION_PAIR(TA, getSourceRange()),
743 STRING_LOCATION_PAIR(
744 TA, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
745 STRING_LOCATION_PAIR(
746 TA, getTypeSourceInfo()->getTypeLoc().getLocalSourceRange())));
747}
748
749TEST(Introspection, SourceLocations_CXXCtorInitializer_base) {
750 if (!NodeIntrospection::hasIntrospectionSupport())
751 GTEST_SKIP();
752 auto AST =
753 buildASTFromCode(Code: R"cpp(
754struct A {
755};
756
757struct B : A {
758 B() : A() {}
759};
760)cpp",
761 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
762 auto &Ctx = AST->getASTContext();
763 auto &TU = *Ctx.getTranslationUnitDecl();
764
765 auto BoundNodes = ast_matchers::match(
766 Matcher: decl(hasDescendant(cxxConstructorDecl(
767 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer().bind(ID: "init"))))),
768 Node: TU, Context&: Ctx);
769
770 EXPECT_EQ(BoundNodes.size(), 1u);
771
772 const auto *CtorInit = BoundNodes[0].getNodeAs<CXXCtorInitializer>(ID: "init");
773
774 auto Result = NodeIntrospection::GetLocations(Object: CtorInit);
775
776 auto ExpectedLocations =
777 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
778
779 // clang-format off
780 EXPECT_THAT(
781 ExpectedLocations,
782 UnorderedElementsAre(
783STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getBeginLoc()),
784STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getEndLoc()),
785STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
786STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
787STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getBeginLoc()),
788STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getEndLoc()),
789STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
790STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
791STRING_LOCATION_PAIR(CtorInit, getLParenLoc()),
792STRING_LOCATION_PAIR(CtorInit, getRParenLoc()),
793STRING_LOCATION_PAIR(CtorInit, getSourceLocation()),
794STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
795STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
796STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
797STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()),
798STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
799STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
800STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
801STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getEndLoc())
802 ));
803 // clang-format on
804
805 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
806
807 // clang-format off
808 EXPECT_THAT(
809 ExpectedRanges,
810 UnorderedElementsAre(
811STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getLocalSourceRange()),
812STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getSourceRange()),
813STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getSourceRange()),
814STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
815STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
816STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
817STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()),
818STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
819STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
820STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
821STRING_LOCATION_PAIR(CtorInit, getSourceRange())));
822 // clang-format on
823}
824
825TEST(Introspection, SourceLocations_CXXCtorInitializer_member) {
826 if (!NodeIntrospection::hasIntrospectionSupport())
827 GTEST_SKIP();
828 auto AST =
829 buildASTFromCode(Code: R"cpp(
830struct A {
831 int m_i;
832 A() : m_i(42) {}
833};
834)cpp",
835 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
836 auto &Ctx = AST->getASTContext();
837 auto &TU = *Ctx.getTranslationUnitDecl();
838
839 auto BoundNodes = ast_matchers::match(
840 Matcher: decl(hasDescendant(cxxConstructorDecl(
841 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer().bind(ID: "init"))))),
842 Node: TU, Context&: Ctx);
843
844 EXPECT_EQ(BoundNodes.size(), 1u);
845
846 const auto *CtorInit = BoundNodes[0].getNodeAs<CXXCtorInitializer>(ID: "init");
847
848 auto Result = NodeIntrospection::GetLocations(Object: CtorInit);
849
850 auto ExpectedLocations =
851 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
852
853 EXPECT_THAT(ExpectedLocations,
854 UnorderedElementsAre(
855 STRING_LOCATION_PAIR(CtorInit, getLParenLoc()),
856 STRING_LOCATION_PAIR(CtorInit, getMemberLocation()),
857 STRING_LOCATION_PAIR(CtorInit, getRParenLoc()),
858 STRING_LOCATION_PAIR(CtorInit, getSourceLocation())));
859
860 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
861
862 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(STRING_LOCATION_PAIR(
863 CtorInit, getSourceRange())));
864}
865
866TEST(Introspection, SourceLocations_CXXCtorInitializer_ctor) {
867 if (!NodeIntrospection::hasIntrospectionSupport())
868 GTEST_SKIP();
869 auto AST =
870 buildASTFromCode(Code: R"cpp(
871struct C {
872 C() : C(42) {}
873 C(int) {}
874};
875)cpp",
876 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
877 auto &Ctx = AST->getASTContext();
878 auto &TU = *Ctx.getTranslationUnitDecl();
879
880 auto BoundNodes = ast_matchers::match(
881 Matcher: decl(hasDescendant(cxxConstructorDecl(
882 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer().bind(ID: "init"))))),
883 Node: TU, Context&: Ctx);
884
885 EXPECT_EQ(BoundNodes.size(), 1u);
886
887 const auto *CtorInit = BoundNodes[0].getNodeAs<CXXCtorInitializer>(ID: "init");
888
889 auto Result = NodeIntrospection::GetLocations(Object: CtorInit);
890
891 auto ExpectedLocations =
892 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
893
894 // clang-format off
895 EXPECT_THAT(
896 ExpectedLocations,
897 UnorderedElementsAre(
898STRING_LOCATION_PAIR(CtorInit, getLParenLoc()),
899STRING_LOCATION_PAIR(CtorInit, getRParenLoc()),
900STRING_LOCATION_PAIR(CtorInit, getSourceLocation()),
901STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
902STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
903STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
904STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
905STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
906STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()),
907STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
908STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc())
909 ));
910 // clang-format on
911
912 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
913
914 // clang-format off
915 EXPECT_THAT(
916 ExpectedRanges,
917 UnorderedElementsAre(
918STRING_LOCATION_PAIR(CtorInit, getSourceRange()),
919STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
920STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
921STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
922STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
923STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange())
924 ));
925 // clang-format on
926}
927
928TEST(Introspection, SourceLocations_CXXCtorInitializer_pack) {
929 if (!NodeIntrospection::hasIntrospectionSupport())
930 GTEST_SKIP();
931 auto AST = buildASTFromCodeWithArgs(
932 Code: R"cpp(
933template<typename... T>
934struct Templ {
935};
936
937template<typename... T>
938struct D : Templ<T...> {
939 D(T... t) : Templ<T>(t)... {}
940};
941)cpp",
942 Args: {"-fno-delayed-template-parsing"}, FileName: "foo.cpp", ToolName: "clang-tool",
943 PCHContainerOps: std::make_shared<PCHContainerOperations>());
944 auto &Ctx = AST->getASTContext();
945 auto &TU = *Ctx.getTranslationUnitDecl();
946
947 auto BoundNodes = ast_matchers::match(
948 Matcher: decl(hasDescendant(cxxConstructorDecl(
949 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer().bind(ID: "init"))))),
950 Node: TU, Context&: Ctx);
951
952 EXPECT_EQ(BoundNodes.size(), 1u);
953
954 const auto *CtorInit = BoundNodes[0].getNodeAs<CXXCtorInitializer>(ID: "init");
955
956 auto Result = NodeIntrospection::GetLocations(Object: CtorInit);
957
958 auto ExpectedLocations =
959 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
960
961 llvm::sort(C&: ExpectedLocations);
962
963 // clang-format off
964 EXPECT_EQ(
965 llvm::ArrayRef(ExpectedLocations),
966 (ArrayRef<std::pair<std::string, SourceLocation>>{
967STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
968STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
969STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
970STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
971STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
972STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getBeginLoc()),
973STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getEndLoc()),
974STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
975STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
976STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
977STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getBeginLoc()),
978STRING_LOCATION_STDPAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getEndLoc()),
979STRING_LOCATION_STDPAIR(CtorInit, getEllipsisLoc()),
980STRING_LOCATION_STDPAIR(CtorInit, getLParenLoc()),
981STRING_LOCATION_STDPAIR(CtorInit, getMemberLocation()),
982STRING_LOCATION_STDPAIR(CtorInit, getRParenLoc()),
983STRING_LOCATION_STDPAIR(CtorInit, getSourceLocation()),
984STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
985STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
986STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
987STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
988STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
989STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
990STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
991STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
992STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
993STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
994STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
995STRING_LOCATION_STDPAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc())
996 }));
997 // clang-format on
998
999 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1000
1001 // clang-format off
1002 EXPECT_THAT(
1003 ExpectedRanges,
1004 UnorderedElementsAre(
1005STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
1006STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
1007STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getLocalSourceRange()),
1008STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
1009STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getSourceRange()),
1010STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
1011STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
1012STRING_LOCATION_PAIR(CtorInit, getBaseClassLoc().getNextTypeLoc().getSourceRange()),
1013STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()),
1014STRING_LOCATION_PAIR(CtorInit, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
1015STRING_LOCATION_PAIR(CtorInit, getSourceRange())
1016 ));
1017 // clang-format on
1018}
1019
1020TEST(Introspection, SourceLocations_CXXBaseSpecifier_plain) {
1021 if (!NodeIntrospection::hasIntrospectionSupport())
1022 GTEST_SKIP();
1023 auto AST =
1024 buildASTFromCode(Code: R"cpp(
1025class A {};
1026class B : A {};
1027)cpp",
1028 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1029 auto &Ctx = AST->getASTContext();
1030 auto &TU = *Ctx.getTranslationUnitDecl();
1031
1032 auto BoundNodes = ast_matchers::match(
1033 Matcher: decl(hasDescendant(cxxRecordDecl(hasDirectBase(
1034 BaseSpecMatcher: cxxBaseSpecifier(hasType(InnerMatcher: asString(Name: "A"))).bind(ID: "base"))))),
1035 Node: TU, Context&: Ctx);
1036
1037 EXPECT_EQ(BoundNodes.size(), 1u);
1038
1039 const auto *Base = BoundNodes[0].getNodeAs<CXXBaseSpecifier>(ID: "base");
1040
1041 auto Result = NodeIntrospection::GetLocations(Base);
1042
1043 auto ExpectedLocations =
1044 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1045
1046 // clang-format off
1047 EXPECT_THAT(ExpectedLocations,
1048 UnorderedElementsAre(
1049STRING_LOCATION_PAIR(Base, getBaseTypeLoc()),
1050STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
1051STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
1052STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
1053STRING_LOCATION_PAIR(Base, getBeginLoc()),
1054STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
1055STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()),
1056STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
1057STRING_LOCATION_PAIR(Base, getEndLoc()),
1058STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
1059STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc())
1060 ));
1061 // clang-format on
1062
1063 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1064
1065 // clang-format off
1066 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(
1067STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
1068STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
1069STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
1070STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()),
1071STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
1072STRING_LOCATION_PAIR(Base, getSourceRange())
1073 ));
1074 // clang-format on
1075}
1076
1077TEST(Introspection, SourceLocations_CXXBaseSpecifier_accessspec) {
1078 if (!NodeIntrospection::hasIntrospectionSupport())
1079 GTEST_SKIP();
1080 auto AST =
1081 buildASTFromCode(Code: R"cpp(
1082class A {};
1083class B : public A {};
1084)cpp",
1085 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1086 auto &Ctx = AST->getASTContext();
1087 auto &TU = *Ctx.getTranslationUnitDecl();
1088
1089 auto BoundNodes = ast_matchers::match(
1090 Matcher: decl(hasDescendant(cxxRecordDecl(hasDirectBase(
1091 BaseSpecMatcher: cxxBaseSpecifier(hasType(InnerMatcher: asString(Name: "A"))).bind(ID: "base"))))),
1092 Node: TU, Context&: Ctx);
1093
1094 EXPECT_EQ(BoundNodes.size(), 1u);
1095
1096 const auto *Base = BoundNodes[0].getNodeAs<CXXBaseSpecifier>(ID: "base");
1097
1098 auto Result = NodeIntrospection::GetLocations(Base);
1099
1100 auto ExpectedLocations =
1101 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1102
1103 // clang-format off
1104 EXPECT_THAT(ExpectedLocations,
1105 UnorderedElementsAre(
1106STRING_LOCATION_PAIR(Base, getBeginLoc()),
1107STRING_LOCATION_PAIR(Base, getBaseTypeLoc()),
1108STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
1109STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
1110STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
1111STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
1112STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()),
1113STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
1114STRING_LOCATION_PAIR(Base, getEndLoc()),
1115STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
1116STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc())
1117 ));
1118 // clang-format on
1119
1120 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1121
1122 // clang-format off
1123 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(
1124STRING_LOCATION_PAIR(Base, getSourceRange()),
1125STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
1126STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
1127STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
1128STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()),
1129STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getSourceRange())
1130 ));
1131 // clang-format on
1132}
1133
1134TEST(Introspection, SourceLocations_CXXBaseSpecifier_virtual) {
1135 if (!NodeIntrospection::hasIntrospectionSupport())
1136 GTEST_SKIP();
1137 auto AST =
1138 buildASTFromCode(Code: R"cpp(
1139class A {};
1140class B {};
1141class C : virtual B, A {};
1142)cpp",
1143 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1144 auto &Ctx = AST->getASTContext();
1145 auto &TU = *Ctx.getTranslationUnitDecl();
1146
1147 auto BoundNodes = ast_matchers::match(
1148 Matcher: decl(hasDescendant(cxxRecordDecl(hasDirectBase(
1149 BaseSpecMatcher: cxxBaseSpecifier(hasType(InnerMatcher: asString(Name: "A"))).bind(ID: "base"))))),
1150 Node: TU, Context&: Ctx);
1151
1152 EXPECT_EQ(BoundNodes.size(), 1u);
1153
1154 const auto *Base = BoundNodes[0].getNodeAs<CXXBaseSpecifier>(ID: "base");
1155
1156 auto Result = NodeIntrospection::GetLocations(Base);
1157
1158 auto ExpectedLocations =
1159 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1160
1161 // clang-format off
1162 EXPECT_THAT(ExpectedLocations,
1163 UnorderedElementsAre(
1164STRING_LOCATION_PAIR(Base, getBaseTypeLoc()),
1165STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
1166STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
1167STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
1168STRING_LOCATION_PAIR(Base, getBeginLoc()),
1169STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
1170STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()),
1171STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
1172STRING_LOCATION_PAIR(Base, getEndLoc()),
1173STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
1174STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc())
1175 ));
1176 // clang-format on
1177
1178 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1179
1180 // clang-format off
1181 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(
1182STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
1183STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
1184STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
1185STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()),
1186STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
1187STRING_LOCATION_PAIR(Base, getSourceRange())
1188 ));
1189 // clang-format on
1190}
1191
1192TEST(Introspection, SourceLocations_CXXBaseSpecifier_template_base) {
1193 if (!NodeIntrospection::hasIntrospectionSupport())
1194 GTEST_SKIP();
1195 auto AST =
1196 buildASTFromCode(Code: R"cpp(
1197template<typename T, typename U>
1198class A {};
1199class B : A<int, bool> {};
1200)cpp",
1201 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1202 auto &Ctx = AST->getASTContext();
1203 auto &TU = *Ctx.getTranslationUnitDecl();
1204
1205 auto BoundNodes =
1206 ast_matchers::match(Matcher: decl(hasDescendant(cxxRecordDecl(
1207 hasDirectBase(BaseSpecMatcher: cxxBaseSpecifier().bind(ID: "base"))))),
1208 Node: TU, Context&: Ctx);
1209
1210 EXPECT_EQ(BoundNodes.size(), 1u);
1211
1212 const auto *Base = BoundNodes[0].getNodeAs<CXXBaseSpecifier>(ID: "base");
1213
1214 auto Result = NodeIntrospection::GetLocations(Base);
1215
1216 auto ExpectedLocations =
1217 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1218
1219 // clang-format off
1220 EXPECT_THAT(ExpectedLocations,
1221 UnorderedElementsAre(
1222STRING_LOCATION_PAIR(Base, getBaseTypeLoc()),
1223STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getBeginLoc()),
1224STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getBeginLoc()),
1225STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getBeginLoc()),
1226STRING_LOCATION_PAIR(Base, getBeginLoc()),
1227STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
1228STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getTemplateNameLoc()),
1229STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
1230STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()),
1231STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getEndLoc()),
1232STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getEndLoc()),
1233STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
1234STRING_LOCATION_PAIR(Base, getEndLoc()),
1235STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc()),
1236STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getRAngleLoc())
1237 ));
1238 // clang-format on
1239
1240 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1241
1242 // clang-format off
1243 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(
1244STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getLocalSourceRange()),
1245STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getLocalSourceRange()),
1246STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::ElaboratedTypeLoc>().getNamedTypeLoc().getSourceRange()),
1247STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getNextTypeLoc().getSourceRange()),
1248STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
1249STRING_LOCATION_PAIR(Base, getSourceRange())
1250 ));
1251 // clang-format on
1252}
1253
1254TEST(Introspection, SourceLocations_CXXBaseSpecifier_pack) {
1255 if (!NodeIntrospection::hasIntrospectionSupport())
1256 GTEST_SKIP();
1257 auto AST = buildASTFromCodeWithArgs(
1258 Code: R"cpp(
1259template<typename... T>
1260struct Templ : T... {
1261};
1262)cpp",
1263 Args: {"-fno-delayed-template-parsing"}, FileName: "foo.cpp", ToolName: "clang-tool",
1264 PCHContainerOps: std::make_shared<PCHContainerOperations>());
1265 auto &Ctx = AST->getASTContext();
1266 auto &TU = *Ctx.getTranslationUnitDecl();
1267
1268 auto BoundNodes =
1269 ast_matchers::match(Matcher: decl(hasDescendant(cxxRecordDecl(
1270 hasDirectBase(BaseSpecMatcher: cxxBaseSpecifier().bind(ID: "base"))))),
1271 Node: TU, Context&: Ctx);
1272
1273 EXPECT_EQ(BoundNodes.size(), 1u);
1274
1275 const auto *Base = BoundNodes[0].getNodeAs<CXXBaseSpecifier>(ID: "base");
1276
1277 auto Result = NodeIntrospection::GetLocations(Base);
1278
1279 auto ExpectedLocations =
1280 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1281
1282 // clang-format off
1283 EXPECT_THAT(ExpectedLocations,
1284 UnorderedElementsAre(
1285STRING_LOCATION_PAIR(Base, getBaseTypeLoc()),
1286STRING_LOCATION_PAIR(Base, getEllipsisLoc()),
1287STRING_LOCATION_PAIR(Base, getBeginLoc()),
1288STRING_LOCATION_PAIR(Base, getEndLoc()),
1289STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getEndLoc()),
1290STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
1291STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getBeginLoc())
1292 ));
1293 // clang-format on
1294
1295 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1296
1297 // clang-format off
1298 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(
1299STRING_LOCATION_PAIR(Base, getSourceRange()),
1300STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getSourceRange()),
1301STRING_LOCATION_PAIR(Base, getTypeSourceInfo()->getTypeLoc().getLocalSourceRange())
1302 ));
1303 // clang-format on
1304}
1305
1306TEST(Introspection, SourceLocations_FunctionProtoTypeLoc) {
1307 if (!NodeIntrospection::hasIntrospectionSupport())
1308 GTEST_SKIP();
1309 auto AST =
1310 buildASTFromCode(Code: R"cpp(
1311int foo();
1312)cpp",
1313 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1314 auto &Ctx = AST->getASTContext();
1315 auto &TU = *Ctx.getTranslationUnitDecl();
1316
1317 auto BoundNodes = ast_matchers::match(
1318 Matcher: decl(hasDescendant(loc(InnerMatcher: functionProtoType()).bind(ID: "tl"))), Node: TU, Context&: Ctx);
1319
1320 EXPECT_EQ(BoundNodes.size(), 1u);
1321
1322 const auto *TL = BoundNodes[0].getNodeAs<TypeLoc>(ID: "tl");
1323 auto Result = NodeIntrospection::GetLocations(*TL);
1324
1325 auto ExpectedLocations =
1326 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1327
1328 llvm::sort(C&: ExpectedLocations);
1329
1330 // clang-format off
1331 EXPECT_EQ(
1332 llvm::ArrayRef(ExpectedLocations),
1333 (ArrayRef<std::pair<std::string, SourceLocation>>{
1334STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getLParenLoc()),
1335STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getLocalRangeBegin()),
1336STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getLocalRangeEnd()),
1337STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getRParenLoc()),
1338STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::BuiltinTypeLoc>().getBuiltinLoc()),
1339STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getReturnLoc().getAs<clang::BuiltinTypeLoc>().getNameLoc()),
1340STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getReturnLoc().getBeginLoc()),
1341STRING_LOCATION_STDPAIR(TL, getAs<clang::FunctionTypeLoc>().getReturnLoc().getEndLoc()),
1342STRING_LOCATION_STDPAIR(TL, getBeginLoc()),
1343STRING_LOCATION_STDPAIR(TL, getEndLoc()),
1344STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getAs<clang::BuiltinTypeLoc>().getBuiltinLoc()),
1345STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getAs<clang::BuiltinTypeLoc>().getNameLoc()),
1346STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getBeginLoc()),
1347STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getEndLoc())
1348 }));
1349 // clang-format on
1350
1351 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1352
1353 // clang-format off
1354 EXPECT_THAT(
1355 ExpectedRanges,
1356 UnorderedElementsAre(
1357STRING_LOCATION_PAIR(TL, getAs<clang::FunctionTypeLoc>().getParensRange()),
1358STRING_LOCATION_PAIR(TL, getAs<clang::FunctionTypeLoc>().getReturnLoc().getLocalSourceRange()),
1359STRING_LOCATION_PAIR(TL, getAs<clang::FunctionTypeLoc>().getReturnLoc().getSourceRange()),
1360STRING_LOCATION_PAIR(TL, getLocalSourceRange()),
1361STRING_LOCATION_PAIR(TL, getNextTypeLoc().getLocalSourceRange()),
1362STRING_LOCATION_PAIR(TL, getNextTypeLoc().getSourceRange()),
1363STRING_LOCATION_PAIR(TL, getSourceRange())
1364 ));
1365 // clang-format on
1366}
1367
1368TEST(Introspection, SourceLocations_PointerTypeLoc) {
1369 if (!NodeIntrospection::hasIntrospectionSupport())
1370 GTEST_SKIP();
1371 auto AST =
1372 buildASTFromCode(Code: R"cpp(
1373int* i;
1374)cpp",
1375 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1376 auto &Ctx = AST->getASTContext();
1377 auto &TU = *Ctx.getTranslationUnitDecl();
1378
1379 auto BoundNodes = ast_matchers::match(
1380 Matcher: decl(hasDescendant(
1381 varDecl(hasName(Name: "i"), hasDescendant(loc(InnerMatcher: pointerType()).bind(ID: "tl"))))),
1382 Node: TU, Context&: Ctx);
1383
1384 EXPECT_EQ(BoundNodes.size(), 1u);
1385
1386 const auto *TL = BoundNodes[0].getNodeAs<TypeLoc>(ID: "tl");
1387 auto Result = NodeIntrospection::GetLocations(*TL);
1388
1389 auto ExpectedLocations =
1390 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1391
1392 llvm::sort(C&: ExpectedLocations);
1393
1394 // clang-format off
1395 EXPECT_EQ(
1396 llvm::ArrayRef(ExpectedLocations),
1397 (ArrayRef<std::pair<std::string, SourceLocation>>{
1398STRING_LOCATION_STDPAIR(TL, getAs<clang::PointerTypeLoc>().getPointeeLoc().getAs<clang::BuiltinTypeLoc>().getBuiltinLoc()),
1399STRING_LOCATION_STDPAIR(TL, getAs<clang::PointerTypeLoc>().getPointeeLoc().getAs<clang::BuiltinTypeLoc>().getNameLoc()),
1400STRING_LOCATION_STDPAIR(TL, getAs<clang::PointerTypeLoc>().getPointeeLoc().getBeginLoc()),
1401STRING_LOCATION_STDPAIR(TL, getAs<clang::PointerTypeLoc>().getPointeeLoc().getEndLoc()),
1402STRING_LOCATION_STDPAIR(TL, getAs<clang::PointerTypeLoc>().getSigilLoc()),
1403STRING_LOCATION_STDPAIR(TL, getAs<clang::PointerTypeLoc>().getStarLoc()),
1404STRING_LOCATION_STDPAIR(TL, getBeginLoc()),
1405STRING_LOCATION_STDPAIR(TL, getEndLoc()),
1406STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getAs<clang::BuiltinTypeLoc>().getBuiltinLoc()),
1407STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getAs<clang::BuiltinTypeLoc>().getNameLoc()),
1408STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getBeginLoc()),
1409STRING_LOCATION_STDPAIR(TL, getNextTypeLoc().getEndLoc())
1410}));
1411 // clang-format on
1412
1413 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1414
1415 // clang-format off
1416 EXPECT_THAT(
1417 ExpectedRanges,
1418 UnorderedElementsAre(
1419STRING_LOCATION_PAIR(TL, getAs<clang::PointerTypeLoc>().getPointeeLoc().getLocalSourceRange()),
1420STRING_LOCATION_PAIR(TL, getAs<clang::PointerTypeLoc>().getPointeeLoc().getSourceRange()),
1421STRING_LOCATION_PAIR(TL, getLocalSourceRange()),
1422STRING_LOCATION_PAIR(TL, getNextTypeLoc().getLocalSourceRange()),
1423STRING_LOCATION_PAIR(TL, getNextTypeLoc().getSourceRange()),
1424STRING_LOCATION_PAIR(TL, getSourceRange())
1425 ));
1426 // clang-format on
1427}
1428
1429#ifndef _WIN32
1430// This test doesn't work on windows due to use of the typeof extension.
1431TEST(Introspection, SourceLocations_TypeOfTypeLoc) {
1432 if (!NodeIntrospection::hasIntrospectionSupport())
1433 GTEST_SKIP();
1434 auto AST =
1435 buildASTFromCode(Code: R"cpp(
1436typeof (static_cast<void *>(0)) i;
1437)cpp",
1438 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1439 auto &Ctx = AST->getASTContext();
1440 auto &TU = *Ctx.getTranslationUnitDecl();
1441
1442 auto BoundNodes = ast_matchers::match(
1443 Matcher: decl(hasDescendant(
1444 varDecl(hasName(Name: "i"), hasDescendant(loc(InnerMatcher: type()).bind(ID: "tl"))))),
1445 Node: TU, Context&: Ctx);
1446
1447 EXPECT_EQ(BoundNodes.size(), 1u);
1448
1449 const auto *TL = BoundNodes[0].getNodeAs<TypeLoc>(ID: "tl");
1450 auto Result = NodeIntrospection::GetLocations(*TL);
1451
1452 auto ExpectedLocations =
1453 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1454
1455 EXPECT_THAT(ExpectedLocations,
1456 UnorderedElementsAre(
1457 STRING_LOCATION_PAIR(TL, getBeginLoc()),
1458 STRING_LOCATION_PAIR(TL, getEndLoc()),
1459 STRING_LOCATION_PAIR(
1460 TL, getAs<clang::TypeOfExprTypeLoc>().getTypeofLoc()),
1461 STRING_LOCATION_PAIR(
1462 TL, getAs<clang::TypeOfExprTypeLoc>().getLParenLoc()),
1463 STRING_LOCATION_PAIR(
1464 TL, getAs<clang::TypeOfExprTypeLoc>().getRParenLoc())));
1465
1466 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1467
1468 EXPECT_THAT(ExpectedRanges,
1469 UnorderedElementsAre(
1470 STRING_LOCATION_PAIR(TL, getLocalSourceRange()),
1471 STRING_LOCATION_PAIR(TL, getSourceRange()),
1472 STRING_LOCATION_PAIR(
1473 TL, getAs<clang::TypeOfExprTypeLoc>().getParensRange())));
1474}
1475#endif
1476
1477TEST(Introspection, SourceLocations_DeclarationNameInfo_Dtor) {
1478 if (!NodeIntrospection::hasIntrospectionSupport())
1479 GTEST_SKIP();
1480 auto AST =
1481 buildASTFromCode(Code: R"cpp(
1482class Foo
1483{
1484 ~Foo() {}
1485};
1486)cpp",
1487 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1488 auto &Ctx = AST->getASTContext();
1489 auto &TU = *Ctx.getTranslationUnitDecl();
1490
1491 auto BoundNodes = ast_matchers::match(
1492 Matcher: decl(hasDescendant(cxxDestructorDecl(hasName(Name: "~Foo")).bind(ID: "dtor"))), Node: TU,
1493 Context&: Ctx);
1494
1495 EXPECT_EQ(BoundNodes.size(), 1u);
1496
1497 const auto *Dtor = BoundNodes[0].getNodeAs<CXXDestructorDecl>(ID: "dtor");
1498 auto NI = Dtor->getNameInfo();
1499 auto Result = NodeIntrospection::GetLocations(NI);
1500
1501 auto ExpectedLocations =
1502 FormatExpected<SourceLocation>(Result.LocationAccessors);
1503
1504 llvm::sort(ExpectedLocations);
1505
1506 // clang-format off
1507 EXPECT_EQ(
1508 llvm::ArrayRef(ExpectedLocations),
1509 (ArrayRef<std::pair<std::string, SourceLocation>>{
1510 STRING_LOCATION_STDPAIR((&NI), getBeginLoc()),
1511 STRING_LOCATION_STDPAIR((&NI), getEndLoc()),
1512 STRING_LOCATION_STDPAIR((&NI), getLoc()),
1513 STRING_LOCATION_STDPAIR((&NI),
1514getNamedTypeInfo()->getTypeLoc().getAs<clang::TypeSpecTypeLoc>().getNameLoc()),
1515 STRING_LOCATION_STDPAIR(
1516 (&NI), getNamedTypeInfo()->getTypeLoc().getBeginLoc()),
1517 STRING_LOCATION_STDPAIR(
1518 (&NI), getNamedTypeInfo()->getTypeLoc().getEndLoc())}));
1519 // clang-format on
1520
1521 auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors);
1522
1523 EXPECT_THAT(
1524 ExpectedRanges,
1525 UnorderedElementsAre(
1526 STRING_LOCATION_PAIR(
1527 (&NI), getNamedTypeInfo()->getTypeLoc().getLocalSourceRange()),
1528 STRING_LOCATION_PAIR(
1529 (&NI), getNamedTypeInfo()->getTypeLoc().getSourceRange()),
1530 STRING_LOCATION_PAIR((&NI), getSourceRange())));
1531}
1532
1533TEST(Introspection, SourceLocations_DeclarationNameInfo_CRef) {
1534 if (!NodeIntrospection::hasIntrospectionSupport())
1535 GTEST_SKIP();
1536
1537 auto AST = buildASTFromCodeWithArgs(
1538 Code: R"cpp(
1539template<typename T>
1540struct MyContainer
1541{
1542 template <typename U>
1543 void pushBack();
1544};
1545
1546template<typename T>
1547void foo()
1548{
1549 MyContainer<T> mc;
1550 mc.template pushBack<int>();
1551}
1552)cpp",
1553 Args: {"-fno-delayed-template-parsing"}, FileName: "foo.cpp", ToolName: "clang-tool",
1554 PCHContainerOps: std::make_shared<PCHContainerOperations>());
1555
1556 auto &Ctx = AST->getASTContext();
1557 auto &TU = *Ctx.getTranslationUnitDecl();
1558
1559 auto BoundNodes = ast_matchers::match(
1560 Matcher: decl(hasDescendant(cxxDependentScopeMemberExpr(hasMemberName(N: "pushBack")).bind(ID: "member"))), Node: TU,
1561 Context&: Ctx);
1562
1563 EXPECT_EQ(BoundNodes.size(), 1u);
1564
1565 const auto *Member = BoundNodes[0].getNodeAs<CXXDependentScopeMemberExpr>(ID: "member");
1566 auto Result = NodeIntrospection::GetLocations(Member);
1567
1568 auto ExpectedLocations =
1569 FormatExpected<SourceLocation>(Result.LocationAccessors);
1570
1571 llvm::sort(ExpectedLocations);
1572
1573 EXPECT_EQ(
1574 llvm::ArrayRef(ExpectedLocations),
1575 (ArrayRef<std::pair<std::string, SourceLocation>>{
1576 STRING_LOCATION_STDPAIR(Member, getBeginLoc()),
1577 STRING_LOCATION_STDPAIR(Member, getEndLoc()),
1578 STRING_LOCATION_STDPAIR(Member, getExprLoc()),
1579 STRING_LOCATION_STDPAIR(Member, getLAngleLoc()),
1580 STRING_LOCATION_STDPAIR(Member, getMemberLoc()),
1581 STRING_LOCATION_STDPAIR(Member, getMemberNameInfo().getBeginLoc()),
1582 STRING_LOCATION_STDPAIR(Member, getMemberNameInfo().getEndLoc()),
1583 STRING_LOCATION_STDPAIR(Member, getMemberNameInfo().getLoc()),
1584 STRING_LOCATION_STDPAIR(Member, getOperatorLoc()),
1585 STRING_LOCATION_STDPAIR(Member, getRAngleLoc()),
1586 STRING_LOCATION_STDPAIR(Member, getTemplateKeywordLoc())}));
1587
1588 auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors);
1589
1590 EXPECT_THAT(
1591 ExpectedRanges,
1592 UnorderedElementsAre(
1593 STRING_LOCATION_PAIR(Member, getMemberNameInfo().getSourceRange()),
1594 STRING_LOCATION_PAIR(Member, getSourceRange())
1595 ));
1596}
1597
1598TEST(Introspection, SourceLocations_DeclarationNameInfo_ConvOp) {
1599 if (!NodeIntrospection::hasIntrospectionSupport())
1600 GTEST_SKIP();
1601 auto AST =
1602 buildASTFromCode(Code: R"cpp(
1603class Foo
1604{
1605 bool operator==(const Foo&) const { return false; }
1606};
1607)cpp",
1608 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1609 auto &Ctx = AST->getASTContext();
1610 auto &TU = *Ctx.getTranslationUnitDecl();
1611
1612 auto BoundNodes = ast_matchers::match(
1613 Matcher: decl(hasDescendant(cxxMethodDecl().bind(ID: "opeq"))), Node: TU, Context&: Ctx);
1614
1615 EXPECT_EQ(BoundNodes.size(), 1u);
1616
1617 const auto *Opeq = BoundNodes[0].getNodeAs<CXXMethodDecl>(ID: "opeq");
1618 auto NI = Opeq->getNameInfo();
1619 auto Result = NodeIntrospection::GetLocations(NI);
1620
1621 auto ExpectedLocations =
1622 FormatExpected<SourceLocation>(Result.LocationAccessors);
1623
1624 llvm::sort(ExpectedLocations);
1625
1626 EXPECT_EQ(llvm::ArrayRef(ExpectedLocations),
1627 (ArrayRef<std::pair<std::string, SourceLocation>>{
1628 STRING_LOCATION_STDPAIR((&NI), getBeginLoc()),
1629 STRING_LOCATION_STDPAIR((&NI), getEndLoc()),
1630 STRING_LOCATION_STDPAIR((&NI), getLoc())}));
1631
1632 auto ExpectedRanges = FormatExpected<SourceRange>(Result.RangeAccessors);
1633
1634 EXPECT_THAT(ExpectedRanges,
1635 UnorderedElementsAre(
1636 STRING_LOCATION_PAIR((&NI), getSourceRange()),
1637 STRING_LOCATION_PAIR((&NI), getCXXOperatorNameRange())));
1638}
1639
1640TEST(Introspection, SourceLocations_DeclarationNameInfo_LitOp) {
1641 if (!NodeIntrospection::hasIntrospectionSupport())
1642 GTEST_SKIP();
1643 auto AST =
1644 buildASTFromCode(Code: R"cpp(
1645long double operator"" _identity ( long double val )
1646{
1647 return val;
1648}
1649)cpp",
1650 FileName: "foo.cpp", PCHContainerOps: std::make_shared<PCHContainerOperations>());
1651 auto &Ctx = AST->getASTContext();
1652 auto &TU = *Ctx.getTranslationUnitDecl();
1653
1654 auto BoundNodes = ast_matchers::match(
1655 Matcher: decl(hasDescendant(functionDecl().bind(ID: "litop"))), Node: TU, Context&: Ctx);
1656
1657 EXPECT_EQ(BoundNodes.size(), 1u);
1658
1659 const auto *LitOp = BoundNodes[0].getNodeAs<FunctionDecl>(ID: "litop");
1660 auto NI = LitOp->getNameInfo();
1661 auto Result = NodeIntrospection::GetLocations(NI);
1662
1663 auto ExpectedLocations =
1664 FormatExpected<SourceLocation>(Accessors: Result.LocationAccessors);
1665
1666 llvm::sort(C&: ExpectedLocations);
1667
1668 EXPECT_EQ(llvm::ArrayRef(ExpectedLocations),
1669 (ArrayRef<std::pair<std::string, SourceLocation>>{
1670 STRING_LOCATION_STDPAIR((&NI), getBeginLoc()),
1671 STRING_LOCATION_STDPAIR((&NI), getCXXLiteralOperatorNameLoc()),
1672 STRING_LOCATION_STDPAIR((&NI), getEndLoc()),
1673 STRING_LOCATION_STDPAIR((&NI), getLoc())}));
1674
1675 auto ExpectedRanges = FormatExpected<SourceRange>(Accessors: Result.RangeAccessors);
1676
1677 EXPECT_THAT(ExpectedRanges, UnorderedElementsAre(STRING_LOCATION_PAIR(
1678 (&NI), getSourceRange())));
1679}
1680

source code of clang/unittests/Introspection/IntrospectionTest.cpp