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