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