1 | //===--- FindTarget.cpp - What does an AST node refer to? -----------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "FindTarget.h" |
10 | #include "AST.h" |
11 | #include "support/Logger.h" |
12 | #include "clang/AST/ASTConcept.h" |
13 | #include "clang/AST/ASTTypeTraits.h" |
14 | #include "clang/AST/Decl.h" |
15 | #include "clang/AST/DeclBase.h" |
16 | #include "clang/AST/DeclCXX.h" |
17 | #include "clang/AST/DeclTemplate.h" |
18 | #include "clang/AST/DeclVisitor.h" |
19 | #include "clang/AST/DeclarationName.h" |
20 | #include "clang/AST/Expr.h" |
21 | #include "clang/AST/ExprCXX.h" |
22 | #include "clang/AST/ExprConcepts.h" |
23 | #include "clang/AST/ExprObjC.h" |
24 | #include "clang/AST/NestedNameSpecifier.h" |
25 | #include "clang/AST/PrettyPrinter.h" |
26 | #include "clang/AST/RecursiveASTVisitor.h" |
27 | #include "clang/AST/StmtVisitor.h" |
28 | #include "clang/AST/TemplateBase.h" |
29 | #include "clang/AST/Type.h" |
30 | #include "clang/AST/TypeLoc.h" |
31 | #include "clang/AST/TypeLocVisitor.h" |
32 | #include "clang/AST/TypeVisitor.h" |
33 | #include "clang/Basic/LangOptions.h" |
34 | #include "clang/Basic/SourceLocation.h" |
35 | #include "clang/Basic/SourceManager.h" |
36 | #include "clang/Basic/Specifiers.h" |
37 | #include "clang/Sema/HeuristicResolver.h" |
38 | #include "llvm/ADT/STLExtras.h" |
39 | #include "llvm/ADT/SmallVector.h" |
40 | #include "llvm/ADT/StringExtras.h" |
41 | #include "llvm/Support/Casting.h" |
42 | #include "llvm/Support/Compiler.h" |
43 | #include "llvm/Support/raw_ostream.h" |
44 | #include <iterator> |
45 | #include <string> |
46 | #include <utility> |
47 | #include <vector> |
48 | |
49 | namespace clang { |
50 | namespace clangd { |
51 | namespace { |
52 | |
53 | LLVM_ATTRIBUTE_UNUSED std::string nodeToString(const DynTypedNode &N) { |
54 | std::string S = std::string(N.getNodeKind().asStringRef()); |
55 | { |
56 | llvm::raw_string_ostream OS(S); |
57 | OS << ": " ; |
58 | N.print(OS, PP: PrintingPolicy(LangOptions())); |
59 | } |
60 | std::replace(first: S.begin(), last: S.end(), old_value: '\n', new_value: ' '); |
61 | return S; |
62 | } |
63 | |
64 | const NamedDecl *getTemplatePattern(const NamedDecl *D) { |
65 | if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(Val: D)) { |
66 | if (const auto *Result = CRD->getTemplateInstantiationPattern()) |
67 | return Result; |
68 | // getTemplateInstantiationPattern returns null if the Specialization is |
69 | // incomplete (e.g. the type didn't need to be complete), fall back to the |
70 | // primary template. |
71 | if (CRD->getTemplateSpecializationKind() == TSK_Undeclared) |
72 | if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: CRD)) |
73 | return Spec->getSpecializedTemplate()->getTemplatedDecl(); |
74 | } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) { |
75 | return FD->getTemplateInstantiationPattern(); |
76 | } else if (auto *VD = dyn_cast<VarDecl>(Val: D)) { |
77 | // Hmm: getTIP returns its arg if it's not an instantiation?! |
78 | VarDecl *T = VD->getTemplateInstantiationPattern(); |
79 | return (T == D) ? nullptr : T; |
80 | } else if (const auto *ED = dyn_cast<EnumDecl>(Val: D)) { |
81 | return ED->getInstantiatedFromMemberEnum(); |
82 | } else if (isa<FieldDecl>(Val: D) || isa<TypedefNameDecl>(Val: D)) { |
83 | if (const auto *Parent = llvm::dyn_cast<NamedDecl>(D->getDeclContext())) |
84 | if (const DeclContext *ParentPat = |
85 | dyn_cast_or_null<DeclContext>(getTemplatePattern(Parent))) |
86 | for (const NamedDecl *BaseND : ParentPat->lookup(Name: D->getDeclName())) |
87 | if (!BaseND->isImplicit() && BaseND->getKind() == D->getKind()) |
88 | return BaseND; |
89 | } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(Val: D)) { |
90 | if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) { |
91 | if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { |
92 | for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) |
93 | return BaseECD; |
94 | } |
95 | } |
96 | } |
97 | return nullptr; |
98 | } |
99 | |
100 | // Returns true if the `TypedefNameDecl` should not be reported. |
101 | bool shouldSkipTypedef(const TypedefNameDecl *TD) { |
102 | // These should be treated as keywords rather than decls - the typedef is an |
103 | // odd implementation detail. |
104 | if (TD == TD->getASTContext().getObjCInstanceTypeDecl() || |
105 | TD == TD->getASTContext().getObjCIdDecl()) |
106 | return true; |
107 | return false; |
108 | } |
109 | |
110 | // TargetFinder locates the entities that an AST node refers to. |
111 | // |
112 | // Typically this is (possibly) one declaration and (possibly) one type, but |
113 | // may be more: |
114 | // - for ambiguous nodes like OverloadExpr |
115 | // - if we want to include e.g. both typedefs and the underlying type |
116 | // |
117 | // This is organized as a set of mutually recursive helpers for particular node |
118 | // types, but for most nodes this is a short walk rather than a deep traversal. |
119 | // |
120 | // It's tempting to do e.g. typedef resolution as a second normalization step, |
121 | // after finding the 'primary' decl etc. But we do this monolithically instead |
122 | // because: |
123 | // - normalization may require these traversals again (e.g. unwrapping a |
124 | // typedef reveals a decltype which must be traversed) |
125 | // - it doesn't simplify that much, e.g. the first stage must still be able |
126 | // to yield multiple decls to handle OverloadExpr |
127 | // - there are cases where it's required for correctness. e.g: |
128 | // template<class X> using pvec = vector<x*>; pvec<int> x; |
129 | // There's no Decl `pvec<int>`, we must choose `pvec<X>` or `vector<int*>` |
130 | // and both are lossy. We must know upfront what the caller ultimately wants. |
131 | struct TargetFinder { |
132 | using RelSet = DeclRelationSet; |
133 | using Rel = DeclRelation; |
134 | |
135 | private: |
136 | const HeuristicResolver *Resolver; |
137 | llvm::SmallDenseMap<const NamedDecl *, |
138 | std::pair<RelSet, /*InsertionOrder*/ size_t>> |
139 | Decls; |
140 | llvm::SmallDenseMap<const Decl *, RelSet> Seen; |
141 | RelSet Flags; |
142 | |
143 | template <typename T> void debug(T &Node, RelSet Flags) { |
144 | dlog("visit [{0}] {1}" , Flags, nodeToString(DynTypedNode::create(Node))); |
145 | } |
146 | |
147 | void report(const NamedDecl *D, RelSet Flags) { |
148 | dlog("--> [{0}] {1}" , Flags, nodeToString(DynTypedNode::create(*D))); |
149 | auto It = Decls.try_emplace(Key: D, Args: std::make_pair(x&: Flags, y: Decls.size())); |
150 | // If already exists, update the flags. |
151 | if (!It.second) |
152 | It.first->second.first |= Flags; |
153 | } |
154 | |
155 | public: |
156 | TargetFinder(const HeuristicResolver *Resolver) : Resolver(Resolver) {} |
157 | |
158 | llvm::SmallVector<std::pair<const NamedDecl *, RelSet>, 1> takeDecls() const { |
159 | using ValTy = std::pair<const NamedDecl *, RelSet>; |
160 | llvm::SmallVector<ValTy, 1> Result; |
161 | Result.resize(N: Decls.size()); |
162 | for (const auto &Elem : Decls) |
163 | Result[Elem.second.second] = {Elem.first, Elem.second.first}; |
164 | return Result; |
165 | } |
166 | |
167 | void add(const Decl *Dcl, RelSet Flags) { |
168 | const NamedDecl *D = llvm::dyn_cast_or_null<NamedDecl>(Val: Dcl); |
169 | if (!D) |
170 | return; |
171 | debug(Node: *D, Flags); |
172 | |
173 | // Avoid recursion (which can arise in the presence of heuristic |
174 | // resolution of dependent names) by exiting early if we have |
175 | // already seen this decl with all flags in Flags. |
176 | auto Res = Seen.try_emplace(D); |
177 | if (!Res.second && Res.first->second.contains(Flags)) |
178 | return; |
179 | Res.first->second |= Flags; |
180 | |
181 | if (const UsingDirectiveDecl *UDD = llvm::dyn_cast<UsingDirectiveDecl>(Val: D)) |
182 | D = UDD->getNominatedNamespaceAsWritten(); |
183 | |
184 | if (const TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(Val: D)) { |
185 | add(T: TND->getUnderlyingType(), Flags: Flags | Rel::Underlying); |
186 | Flags |= Rel::Alias; // continue with the alias. |
187 | } else if (const UsingDecl *UD = dyn_cast<UsingDecl>(Val: D)) { |
188 | // no Underlying as this is a non-renaming alias. |
189 | for (const UsingShadowDecl *S : UD->shadows()) |
190 | add(S->getUnderlyingDecl(), Flags); |
191 | Flags |= Rel::Alias; // continue with the alias. |
192 | } else if (const UsingEnumDecl *UED = dyn_cast<UsingEnumDecl>(Val: D)) { |
193 | // UsingEnumDecl is not an alias at all, just a reference. |
194 | D = UED->getEnumDecl(); |
195 | } else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(Val: D)) { |
196 | add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); |
197 | Flags |= Rel::Alias; // continue with the alias |
198 | } else if (const UnresolvedUsingValueDecl *UUVD = |
199 | dyn_cast<UnresolvedUsingValueDecl>(Val: D)) { |
200 | if (Resolver) { |
201 | for (const NamedDecl *Target : Resolver->resolveUsingValueDecl(UUVD)) { |
202 | add(Target, Flags); // no Underlying as this is a non-renaming alias |
203 | } |
204 | } |
205 | Flags |= Rel::Alias; // continue with the alias |
206 | } else if (isa<UnresolvedUsingTypenameDecl>(Val: D)) { |
207 | // FIXME: improve common dependent scope using name lookup in primary |
208 | // templates. |
209 | Flags |= Rel::Alias; |
210 | } else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(Val: D)) { |
211 | // Include the introducing UsingDecl, but don't traverse it. This may end |
212 | // up including *all* shadows, which we don't want. |
213 | // Don't apply this logic to UsingEnumDecl, which can't easily be |
214 | // conflated with the aliases it introduces. |
215 | if (llvm::isa<UsingDecl>(Val: USD->getIntroducer())) |
216 | report(USD->getIntroducer(), Flags | Rel::Alias); |
217 | // Shadow decls are synthetic and not themselves interesting. |
218 | // Record the underlying decl instead, if allowed. |
219 | D = USD->getTargetDecl(); |
220 | } else if (const auto *DG = dyn_cast<CXXDeductionGuideDecl>(Val: D)) { |
221 | D = DG->getDeducedTemplate(); |
222 | } else if (const ObjCImplementationDecl *IID = |
223 | dyn_cast<ObjCImplementationDecl>(Val: D)) { |
224 | // Treat ObjC{Interface,Implementation}Decl as if they were a decl/def |
225 | // pair as long as the interface isn't implicit. |
226 | if (const auto *CID = IID->getClassInterface()) |
227 | if (const auto *DD = CID->getDefinition()) |
228 | if (!DD->isImplicitInterfaceDecl()) |
229 | D = DD; |
230 | } else if (const ObjCCategoryImplDecl *CID = |
231 | dyn_cast<ObjCCategoryImplDecl>(Val: D)) { |
232 | // Treat ObjC{Category,CategoryImpl}Decl as if they were a decl/def pair. |
233 | D = CID->getCategoryDecl(); |
234 | } |
235 | if (!D) |
236 | return; |
237 | |
238 | if (const Decl *Pat = getTemplatePattern(D)) { |
239 | assert(Pat != D); |
240 | add(Dcl: Pat, Flags: Flags | Rel::TemplatePattern); |
241 | // Now continue with the instantiation. |
242 | Flags |= Rel::TemplateInstantiation; |
243 | } |
244 | |
245 | report(D, Flags); |
246 | } |
247 | |
248 | void add(const Stmt *S, RelSet Flags) { |
249 | if (!S) |
250 | return; |
251 | debug(Node: *S, Flags); |
252 | struct Visitor : public ConstStmtVisitor<Visitor> { |
253 | TargetFinder &Outer; |
254 | RelSet Flags; |
255 | Visitor(TargetFinder &Outer, RelSet Flags) : Outer(Outer), Flags(Flags) {} |
256 | |
257 | void VisitCallExpr(const CallExpr *CE) { |
258 | Outer.add(Dcl: CE->getCalleeDecl(), Flags); |
259 | } |
260 | void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) { |
261 | Outer.add(CR: E->getConceptReference(), Flags); |
262 | } |
263 | void VisitDeclRefExpr(const DeclRefExpr *DRE) { |
264 | const Decl *D = DRE->getDecl(); |
265 | // UsingShadowDecl allows us to record the UsingDecl. |
266 | // getFoundDecl() returns the wrong thing in other cases (templates). |
267 | if (auto *USD = llvm::dyn_cast<UsingShadowDecl>(Val: DRE->getFoundDecl())) |
268 | D = USD; |
269 | Outer.add(Dcl: D, Flags); |
270 | } |
271 | void VisitMemberExpr(const MemberExpr *ME) { |
272 | const Decl *D = ME->getMemberDecl(); |
273 | if (auto *USD = |
274 | llvm::dyn_cast<UsingShadowDecl>(Val: ME->getFoundDecl().getDecl())) |
275 | D = USD; |
276 | Outer.add(Dcl: D, Flags); |
277 | } |
278 | void VisitOverloadExpr(const OverloadExpr *OE) { |
279 | for (auto *D : OE->decls()) |
280 | Outer.add(D, Flags); |
281 | } |
282 | void VisitSizeOfPackExpr(const SizeOfPackExpr *SE) { |
283 | Outer.add(SE->getPack(), Flags); |
284 | } |
285 | void VisitCXXConstructExpr(const CXXConstructExpr *CCE) { |
286 | Outer.add(CCE->getConstructor(), Flags); |
287 | } |
288 | void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) { |
289 | for (const DesignatedInitExpr::Designator &D : |
290 | llvm::reverse(C: DIE->designators())) |
291 | if (D.isFieldDesignator()) { |
292 | Outer.add(D.getFieldDecl(), Flags); |
293 | // We don't know which designator was intended, we assume the outer. |
294 | break; |
295 | } |
296 | } |
297 | void VisitGotoStmt(const GotoStmt *Goto) { |
298 | if (auto *LabelDecl = Goto->getLabel()) |
299 | Outer.add(LabelDecl, Flags); |
300 | } |
301 | void VisitLabelStmt(const LabelStmt *Label) { |
302 | if (auto *LabelDecl = Label->getDecl()) |
303 | Outer.add(LabelDecl, Flags); |
304 | } |
305 | void |
306 | VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { |
307 | if (Outer.Resolver) { |
308 | for (const NamedDecl *D : Outer.Resolver->resolveMemberExpr(ME: E)) { |
309 | Outer.add(D, Flags); |
310 | } |
311 | } |
312 | } |
313 | void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { |
314 | if (Outer.Resolver) { |
315 | for (const NamedDecl *D : Outer.Resolver->resolveDeclRefExpr(RE: E)) { |
316 | Outer.add(D, Flags); |
317 | } |
318 | } |
319 | } |
320 | void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) { |
321 | Outer.add(OIRE->getDecl(), Flags); |
322 | } |
323 | void VisitObjCMessageExpr(const ObjCMessageExpr *OME) { |
324 | Outer.add(OME->getMethodDecl(), Flags); |
325 | } |
326 | void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) { |
327 | if (OPRE->isExplicitProperty()) |
328 | Outer.add(OPRE->getExplicitProperty(), Flags); |
329 | else { |
330 | if (OPRE->isMessagingGetter()) |
331 | Outer.add(OPRE->getImplicitPropertyGetter(), Flags); |
332 | if (OPRE->isMessagingSetter()) |
333 | Outer.add(OPRE->getImplicitPropertySetter(), Flags); |
334 | } |
335 | } |
336 | void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) { |
337 | Outer.add(OPE->getProtocol(), Flags); |
338 | } |
339 | void VisitOpaqueValueExpr(const OpaqueValueExpr *OVE) { |
340 | Outer.add(Arg: OVE->getSourceExpr(), Flags); |
341 | } |
342 | void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) { |
343 | Outer.add(POE->getSyntacticForm(), Flags); |
344 | } |
345 | void VisitCXXNewExpr(const CXXNewExpr *CNE) { |
346 | Outer.add(CNE->getOperatorNew(), Flags); |
347 | } |
348 | void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE) { |
349 | Outer.add(CDE->getOperatorDelete(), Flags); |
350 | } |
351 | void |
352 | VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) { |
353 | Outer.add(RBO->getDecomposedForm().InnerBinOp, Flags); |
354 | } |
355 | }; |
356 | Visitor(*this, Flags).Visit(S); |
357 | } |
358 | |
359 | void add(QualType T, RelSet Flags) { |
360 | if (T.isNull()) |
361 | return; |
362 | debug(Node&: T, Flags); |
363 | struct Visitor : public TypeVisitor<Visitor> { |
364 | TargetFinder &Outer; |
365 | RelSet Flags; |
366 | Visitor(TargetFinder &Outer, RelSet Flags) : Outer(Outer), Flags(Flags) {} |
367 | |
368 | void VisitTagType(const TagType *TT) { |
369 | Outer.add(TT->getAsTagDecl(), Flags); |
370 | } |
371 | |
372 | void VisitElaboratedType(const ElaboratedType *ET) { |
373 | Outer.add(T: ET->desugar(), Flags); |
374 | } |
375 | |
376 | void VisitUsingType(const UsingType *ET) { |
377 | Outer.add(ET->getFoundDecl(), Flags); |
378 | } |
379 | |
380 | void VisitInjectedClassNameType(const InjectedClassNameType *ICNT) { |
381 | Outer.add(ICNT->getDecl(), Flags); |
382 | } |
383 | |
384 | void VisitDecltypeType(const DecltypeType *DTT) { |
385 | Outer.add(T: DTT->getUnderlyingType(), Flags: Flags | Rel::Underlying); |
386 | } |
387 | void VisitDeducedType(const DeducedType *DT) { |
388 | // FIXME: In practice this doesn't work: the AutoType you find inside |
389 | // TypeLoc never has a deduced type. https://llvm.org/PR42914 |
390 | Outer.add(T: DT->getDeducedType(), Flags); |
391 | } |
392 | void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) { |
393 | Outer.add(UUT->getDecl(), Flags); |
394 | } |
395 | void VisitDeducedTemplateSpecializationType( |
396 | const DeducedTemplateSpecializationType *DTST) { |
397 | if (const auto *USD = DTST->getTemplateName().getAsUsingShadowDecl()) |
398 | Outer.add(USD, Flags); |
399 | |
400 | // FIXME: This is a workaround for https://llvm.org/PR42914, |
401 | // which is causing DTST->getDeducedType() to be empty. We |
402 | // fall back to the template pattern and miss the instantiation |
403 | // even when it's known in principle. Once that bug is fixed, |
404 | // the following code can be removed (the existing handling in |
405 | // VisitDeducedType() is sufficient). |
406 | if (auto *TD = DTST->getTemplateName().getAsTemplateDecl()) |
407 | Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); |
408 | } |
409 | void VisitDependentNameType(const DependentNameType *DNT) { |
410 | if (Outer.Resolver) { |
411 | for (const NamedDecl *ND : |
412 | Outer.Resolver->resolveDependentNameType(DNT)) { |
413 | Outer.add(ND, Flags); |
414 | } |
415 | } |
416 | } |
417 | void VisitDependentTemplateSpecializationType( |
418 | const DependentTemplateSpecializationType *DTST) { |
419 | if (Outer.Resolver) { |
420 | for (const NamedDecl *ND : |
421 | Outer.Resolver->resolveTemplateSpecializationType(DTST)) { |
422 | Outer.add(ND, Flags); |
423 | } |
424 | } |
425 | } |
426 | void VisitTypedefType(const TypedefType *TT) { |
427 | if (shouldSkipTypedef(TD: TT->getDecl())) |
428 | return; |
429 | Outer.add(TT->getDecl(), Flags); |
430 | } |
431 | void |
432 | VisitTemplateSpecializationType(const TemplateSpecializationType *TST) { |
433 | // Have to handle these case-by-case. |
434 | |
435 | if (const auto *UTN = TST->getTemplateName().getAsUsingShadowDecl()) |
436 | Outer.add(UTN, Flags); |
437 | |
438 | // templated type aliases: there's no specialized/instantiated using |
439 | // decl to point to. So try to find a decl for the underlying type |
440 | // (after substitution), and failing that point to the (templated) using |
441 | // decl. |
442 | if (TST->isTypeAlias()) { |
443 | Outer.add(T: TST->getAliasedType(), Flags: Flags | Rel::Underlying); |
444 | // Don't *traverse* the alias, which would result in traversing the |
445 | // template of the underlying type. |
446 | |
447 | TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl(); |
448 | // Builtin templates e.g. __make_integer_seq, __type_pack_element |
449 | // are such that they don't have alias *decls*. Even then, we still |
450 | // traverse their desugared *types* so that instantiated decls are |
451 | // collected. |
452 | if (llvm::isa<BuiltinTemplateDecl>(Val: TD)) |
453 | return; |
454 | Outer.report(D: TD->getTemplatedDecl(), |
455 | Flags: Flags | Rel::Alias | Rel::TemplatePattern); |
456 | } |
457 | // specializations of template template parameters aren't instantiated |
458 | // into decls, so they must refer to the parameter itself. |
459 | else if (const auto *Parm = |
460 | llvm::dyn_cast_or_null<TemplateTemplateParmDecl>( |
461 | Val: TST->getTemplateName().getAsTemplateDecl())) |
462 | Outer.add(Parm, Flags); |
463 | // class template specializations have a (specialized) CXXRecordDecl. |
464 | else if (const CXXRecordDecl *RD = TST->getAsCXXRecordDecl()) |
465 | Outer.add(RD, Flags); // add(Decl) will despecialize if needed. |
466 | else { |
467 | // fallback: the (un-specialized) declaration from primary template. |
468 | if (auto *TD = TST->getTemplateName().getAsTemplateDecl()) |
469 | Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); |
470 | } |
471 | } |
472 | void |
473 | VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT) { |
474 | Outer.add(T: STTPT->getReplacementType(), Flags); |
475 | } |
476 | void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT) { |
477 | Outer.add(TTPT->getDecl(), Flags); |
478 | } |
479 | void VisitObjCInterfaceType(const ObjCInterfaceType *OIT) { |
480 | Outer.add(OIT->getDecl(), Flags); |
481 | } |
482 | }; |
483 | Visitor(*this, Flags).Visit(T: T.getTypePtr()); |
484 | } |
485 | |
486 | void add(const NestedNameSpecifier *NNS, RelSet Flags) { |
487 | if (!NNS) |
488 | return; |
489 | debug(Node: *NNS, Flags); |
490 | switch (NNS->getKind()) { |
491 | case NestedNameSpecifier::Namespace: |
492 | add(NNS->getAsNamespace(), Flags); |
493 | return; |
494 | case NestedNameSpecifier::NamespaceAlias: |
495 | add(NNS->getAsNamespaceAlias(), Flags); |
496 | return; |
497 | case NestedNameSpecifier::Identifier: |
498 | if (Resolver) { |
499 | add(T: Resolver->resolveNestedNameSpecifierToType(NNS), Flags); |
500 | } |
501 | return; |
502 | case NestedNameSpecifier::TypeSpec: |
503 | case NestedNameSpecifier::TypeSpecWithTemplate: |
504 | add(T: QualType(NNS->getAsType(), 0), Flags); |
505 | return; |
506 | case NestedNameSpecifier::Global: |
507 | // This should be TUDecl, but we can't get a pointer to it! |
508 | return; |
509 | case NestedNameSpecifier::Super: |
510 | add(NNS->getAsRecordDecl(), Flags); |
511 | return; |
512 | } |
513 | llvm_unreachable("unhandled NestedNameSpecifier::SpecifierKind" ); |
514 | } |
515 | |
516 | void add(const CXXCtorInitializer *CCI, RelSet Flags) { |
517 | if (!CCI) |
518 | return; |
519 | debug(Node: *CCI, Flags); |
520 | |
521 | if (CCI->isAnyMemberInitializer()) |
522 | add(CCI->getAnyMember(), Flags); |
523 | // Constructor calls contain a TypeLoc node, so we don't handle them here. |
524 | } |
525 | |
526 | void add(const TemplateArgument &Arg, RelSet Flags) { |
527 | // Only used for template template arguments. |
528 | // For type and non-type template arguments, SelectionTree |
529 | // will hit a more specific node (e.g. a TypeLoc or a |
530 | // DeclRefExpr). |
531 | if (Arg.getKind() == TemplateArgument::Template || |
532 | Arg.getKind() == TemplateArgument::TemplateExpansion) { |
533 | if (TemplateDecl *TD = |
534 | Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) { |
535 | report(TD, Flags); |
536 | } |
537 | if (const auto *USD = |
538 | Arg.getAsTemplateOrTemplatePattern().getAsUsingShadowDecl()) |
539 | add(USD, Flags); |
540 | } |
541 | } |
542 | |
543 | void add(const ConceptReference *CR, RelSet Flags) { |
544 | add(CR->getNamedConcept(), Flags); |
545 | } |
546 | }; |
547 | |
548 | } // namespace |
549 | |
550 | llvm::SmallVector<std::pair<const NamedDecl *, DeclRelationSet>, 1> |
551 | allTargetDecls(const DynTypedNode &N, const HeuristicResolver *Resolver) { |
552 | dlog("allTargetDecls({0})" , nodeToString(N)); |
553 | TargetFinder Finder(Resolver); |
554 | DeclRelationSet Flags; |
555 | if (const Decl *D = N.get<Decl>()) |
556 | Finder.add(Dcl: D, Flags); |
557 | else if (const Stmt *S = N.get<Stmt>()) |
558 | Finder.add(S, Flags); |
559 | else if (const NestedNameSpecifierLoc *NNSL = N.get<NestedNameSpecifierLoc>()) |
560 | Finder.add(NNS: NNSL->getNestedNameSpecifier(), Flags); |
561 | else if (const NestedNameSpecifier *NNS = N.get<NestedNameSpecifier>()) |
562 | Finder.add(NNS, Flags); |
563 | else if (const TypeLoc *TL = N.get<TypeLoc>()) |
564 | Finder.add(T: TL->getType(), Flags); |
565 | else if (const QualType *QT = N.get<QualType>()) |
566 | Finder.add(T: *QT, Flags); |
567 | else if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) |
568 | Finder.add(CCI, Flags); |
569 | else if (const TemplateArgumentLoc *TAL = N.get<TemplateArgumentLoc>()) |
570 | Finder.add(Arg: TAL->getArgument(), Flags); |
571 | else if (const CXXBaseSpecifier *CBS = N.get<CXXBaseSpecifier>()) |
572 | Finder.add(T: CBS->getTypeSourceInfo()->getType(), Flags); |
573 | else if (const ObjCProtocolLoc *PL = N.get<ObjCProtocolLoc>()) |
574 | Finder.add(PL->getProtocol(), Flags); |
575 | else if (const ConceptReference *CR = N.get<ConceptReference>()) |
576 | Finder.add(CR, Flags); |
577 | return Finder.takeDecls(); |
578 | } |
579 | |
580 | llvm::SmallVector<const NamedDecl *, 1> |
581 | targetDecl(const DynTypedNode &N, DeclRelationSet Mask, |
582 | const HeuristicResolver *Resolver) { |
583 | llvm::SmallVector<const NamedDecl *, 1> Result; |
584 | for (const auto &Entry : allTargetDecls(N, Resolver)) { |
585 | if (!(Entry.second & ~Mask)) |
586 | Result.push_back(Elt: Entry.first); |
587 | } |
588 | return Result; |
589 | } |
590 | |
591 | llvm::SmallVector<const NamedDecl *, 1> |
592 | explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask, |
593 | const HeuristicResolver *Resolver) { |
594 | assert(!(Mask & (DeclRelation::TemplatePattern | |
595 | DeclRelation::TemplateInstantiation)) && |
596 | "explicitReferenceTargets handles templates on its own" ); |
597 | auto Decls = allTargetDecls(N, Resolver); |
598 | |
599 | // We prefer to return template instantiation, but fallback to template |
600 | // pattern if instantiation is not available. |
601 | Mask |= DeclRelation::TemplatePattern | DeclRelation::TemplateInstantiation; |
602 | |
603 | llvm::SmallVector<const NamedDecl *, 1> TemplatePatterns; |
604 | llvm::SmallVector<const NamedDecl *, 1> Targets; |
605 | bool SeenTemplateInstantiations = false; |
606 | for (auto &D : Decls) { |
607 | if (D.second & ~Mask) |
608 | continue; |
609 | if (D.second & DeclRelation::TemplatePattern) { |
610 | TemplatePatterns.push_back(Elt: D.first); |
611 | continue; |
612 | } |
613 | if (D.second & DeclRelation::TemplateInstantiation) |
614 | SeenTemplateInstantiations = true; |
615 | Targets.push_back(Elt: D.first); |
616 | } |
617 | if (!SeenTemplateInstantiations) |
618 | Targets.insert(I: Targets.end(), From: TemplatePatterns.begin(), |
619 | To: TemplatePatterns.end()); |
620 | return Targets; |
621 | } |
622 | |
623 | namespace { |
624 | llvm::SmallVector<ReferenceLoc> refInDecl(const Decl *D, |
625 | const HeuristicResolver *Resolver) { |
626 | struct Visitor : ConstDeclVisitor<Visitor> { |
627 | Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {} |
628 | |
629 | const HeuristicResolver *Resolver; |
630 | llvm::SmallVector<ReferenceLoc> Refs; |
631 | |
632 | void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { |
633 | // We want to keep it as non-declaration references, as the |
634 | // "using namespace" declaration doesn't have a name. |
635 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: D->getQualifierLoc(), |
636 | .NameLoc: D->getIdentLocation(), |
637 | /*IsDecl=*/false, |
638 | .Targets: {D->getNominatedNamespaceAsWritten()}}); |
639 | } |
640 | |
641 | void VisitUsingDecl(const UsingDecl *D) { |
642 | // "using ns::identifier;" is a non-declaration reference. |
643 | Refs.push_back(Elt: ReferenceLoc{ |
644 | D->getQualifierLoc(), D->getLocation(), /*IsDecl=*/false, |
645 | explicitReferenceTargets(N: DynTypedNode::create(Node: *D), |
646 | Mask: DeclRelation::Underlying, Resolver)}); |
647 | } |
648 | |
649 | void VisitUsingEnumDecl(const UsingEnumDecl *D) { |
650 | // "using enum ns::E" is a non-declaration reference. |
651 | // The reference is covered by the embedded typeloc. |
652 | // Don't use the default VisitNamedDecl, which would report a declaration. |
653 | } |
654 | |
655 | void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { |
656 | // For namespace alias, "namespace Foo = Target;", we add two references. |
657 | // Add a declaration reference for Foo. |
658 | VisitNamedDecl(D); |
659 | // Add a non-declaration reference for Target. |
660 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: D->getQualifierLoc(), |
661 | .NameLoc: D->getTargetNameLoc(), |
662 | /*IsDecl=*/false, |
663 | .Targets: {D->getAliasedNamespace()}}); |
664 | } |
665 | |
666 | void VisitNamedDecl(const NamedDecl *ND) { |
667 | // We choose to ignore {Class, Function, Var, TypeAlias}TemplateDecls. As |
668 | // as their underlying decls, covering the same range, will be visited. |
669 | if (llvm::isa<ClassTemplateDecl>(Val: ND) || |
670 | llvm::isa<FunctionTemplateDecl>(Val: ND) || |
671 | llvm::isa<VarTemplateDecl>(Val: ND) || |
672 | llvm::isa<TypeAliasTemplateDecl>(Val: ND)) |
673 | return; |
674 | // FIXME: decide on how to surface destructors when we need them. |
675 | if (llvm::isa<CXXDestructorDecl>(Val: ND)) |
676 | return; |
677 | // Filter anonymous decls, name location will point outside the name token |
678 | // and the clients are not prepared to handle that. |
679 | if (ND->getDeclName().isIdentifier() && |
680 | !ND->getDeclName().getAsIdentifierInfo()) |
681 | return; |
682 | Refs.push_back(Elt: ReferenceLoc{getQualifierLoc(ND: *ND), |
683 | ND->getLocation(), |
684 | /*IsDecl=*/true, |
685 | {ND}}); |
686 | } |
687 | |
688 | void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *DG) { |
689 | // The class template name in a deduction guide targets the class |
690 | // template. |
691 | Refs.push_back(Elt: ReferenceLoc{DG->getQualifierLoc(), |
692 | DG->getNameInfo().getLoc(), |
693 | /*IsDecl=*/false, |
694 | {DG->getDeducedTemplate()}}); |
695 | } |
696 | |
697 | void VisitObjCMethodDecl(const ObjCMethodDecl *OMD) { |
698 | // The name may have several tokens, we can only report the first. |
699 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
700 | .NameLoc: OMD->getSelectorStartLoc(), |
701 | /*IsDecl=*/true, |
702 | {OMD}}); |
703 | } |
704 | |
705 | void VisitObjCCategoryDecl(const ObjCCategoryDecl *OCD) { |
706 | // getLocation is the extended class's location, not the category's. |
707 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
708 | OCD->getLocation(), |
709 | /*IsDecl=*/false, |
710 | {OCD->getClassInterface()}}); |
711 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
712 | .NameLoc: OCD->getCategoryNameLoc(), |
713 | /*IsDecl=*/true, |
714 | {OCD}}); |
715 | } |
716 | |
717 | void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *OCID) { |
718 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
719 | OCID->getLocation(), |
720 | /*IsDecl=*/false, |
721 | {OCID->getClassInterface()}}); |
722 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
723 | .NameLoc: OCID->getCategoryNameLoc(), |
724 | /*IsDecl=*/false, |
725 | {OCID->getCategoryDecl()}}); |
726 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
727 | .NameLoc: OCID->getCategoryNameLoc(), |
728 | /*IsDecl=*/true, |
729 | {OCID}}); |
730 | } |
731 | |
732 | void VisitObjCImplementationDecl(const ObjCImplementationDecl *OIMD) { |
733 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
734 | OIMD->getLocation(), |
735 | /*IsDecl=*/false, |
736 | {OIMD->getClassInterface()}}); |
737 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
738 | OIMD->getLocation(), |
739 | /*IsDecl=*/true, |
740 | {OIMD}}); |
741 | } |
742 | }; |
743 | |
744 | Visitor V{Resolver}; |
745 | V.Visit(D); |
746 | return V.Refs; |
747 | } |
748 | |
749 | llvm::SmallVector<ReferenceLoc> refInStmt(const Stmt *S, |
750 | const HeuristicResolver *Resolver) { |
751 | struct Visitor : ConstStmtVisitor<Visitor> { |
752 | Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {} |
753 | |
754 | const HeuristicResolver *Resolver; |
755 | // FIXME: handle more complicated cases: more ObjC, designated initializers. |
756 | llvm::SmallVector<ReferenceLoc> Refs; |
757 | |
758 | void VisitDeclRefExpr(const DeclRefExpr *E) { |
759 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: E->getQualifierLoc(), |
760 | .NameLoc: E->getNameInfo().getLoc(), |
761 | /*IsDecl=*/false, |
762 | .Targets: {E->getFoundDecl()}}); |
763 | } |
764 | |
765 | void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { |
766 | Refs.push_back(Elt: ReferenceLoc{ |
767 | .Qualifier: E->getQualifierLoc(), .NameLoc: E->getNameInfo().getLoc(), /*IsDecl=*/false, |
768 | .Targets: explicitReferenceTargets(N: DynTypedNode::create(Node: *E), Mask: {}, Resolver)}); |
769 | } |
770 | |
771 | void VisitMemberExpr(const MemberExpr *E) { |
772 | // Skip destructor calls to avoid duplication: TypeLoc within will be |
773 | // visited separately. |
774 | if (llvm::isa<CXXDestructorDecl>(Val: E->getFoundDecl().getDecl())) |
775 | return; |
776 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: E->getQualifierLoc(), |
777 | .NameLoc: E->getMemberNameInfo().getLoc(), |
778 | /*IsDecl=*/false, |
779 | .Targets: {E->getFoundDecl()}}); |
780 | } |
781 | |
782 | void |
783 | VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { |
784 | Refs.push_back(Elt: ReferenceLoc{ |
785 | .Qualifier: E->getQualifierLoc(), .NameLoc: E->getMemberNameInfo().getLoc(), |
786 | /*IsDecl=*/false, |
787 | .Targets: explicitReferenceTargets(N: DynTypedNode::create(Node: *E), Mask: {}, Resolver)}); |
788 | } |
789 | |
790 | void VisitOverloadExpr(const OverloadExpr *E) { |
791 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: E->getQualifierLoc(), |
792 | .NameLoc: E->getNameInfo().getLoc(), |
793 | /*IsDecl=*/false, |
794 | .Targets: llvm::SmallVector<const NamedDecl *, 1>( |
795 | E->decls().begin(), E->decls().end())}); |
796 | } |
797 | |
798 | void VisitSizeOfPackExpr(const SizeOfPackExpr *E) { |
799 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
800 | .NameLoc: E->getPackLoc(), |
801 | /*IsDecl=*/false, |
802 | .Targets: {E->getPack()}}); |
803 | } |
804 | |
805 | void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) { |
806 | Refs.push_back(Elt: ReferenceLoc{ |
807 | .Qualifier: NestedNameSpecifierLoc(), .NameLoc: E->getLocation(), |
808 | /*IsDecl=*/false, |
809 | // Select the getter, setter, or @property depending on the call. |
810 | .Targets: explicitReferenceTargets(N: DynTypedNode::create(Node: *E), Mask: {}, Resolver)}); |
811 | } |
812 | |
813 | void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) { |
814 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
815 | .NameLoc: OIRE->getLocation(), |
816 | /*IsDecl=*/false, |
817 | {OIRE->getDecl()}}); |
818 | } |
819 | |
820 | void VisitObjCMessageExpr(const ObjCMessageExpr *E) { |
821 | // The name may have several tokens, we can only report the first. |
822 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
823 | .NameLoc: E->getSelectorStartLoc(), |
824 | /*IsDecl=*/false, |
825 | {E->getMethodDecl()}}); |
826 | } |
827 | |
828 | void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) { |
829 | for (const DesignatedInitExpr::Designator &D : DIE->designators()) { |
830 | if (!D.isFieldDesignator()) |
831 | continue; |
832 | |
833 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
834 | .NameLoc: D.getFieldLoc(), |
835 | /*IsDecl=*/false, |
836 | {D.getFieldDecl()}}); |
837 | } |
838 | } |
839 | |
840 | void VisitGotoStmt(const GotoStmt *GS) { |
841 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
842 | .NameLoc: GS->getLabelLoc(), |
843 | /*IsDecl=*/false, |
844 | {GS->getLabel()}}); |
845 | } |
846 | |
847 | void VisitLabelStmt(const LabelStmt *LS) { |
848 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
849 | .NameLoc: LS->getIdentLoc(), |
850 | /*IsDecl=*/true, |
851 | {LS->getDecl()}}); |
852 | } |
853 | }; |
854 | |
855 | Visitor V{Resolver}; |
856 | V.Visit(S); |
857 | return V.Refs; |
858 | } |
859 | |
860 | llvm::SmallVector<ReferenceLoc> |
861 | refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) { |
862 | struct Visitor : TypeLocVisitor<Visitor> { |
863 | Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {} |
864 | |
865 | const HeuristicResolver *Resolver; |
866 | llvm::SmallVector<ReferenceLoc> Refs; |
867 | |
868 | void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) { |
869 | // We only know about qualifier, rest if filled by inner locations. |
870 | size_t InitialSize = Refs.size(); |
871 | Visit(TyLoc: L.getNamedTypeLoc().getUnqualifiedLoc()); |
872 | size_t NewSize = Refs.size(); |
873 | // Add qualifier for the newly-added refs. |
874 | for (unsigned I = InitialSize; I < NewSize; ++I) { |
875 | ReferenceLoc *Ref = &Refs[I]; |
876 | // Fill in the qualifier. |
877 | assert(!Ref->Qualifier.hasQualifier() && "qualifier already set" ); |
878 | Ref->Qualifier = L.getQualifierLoc(); |
879 | } |
880 | } |
881 | |
882 | void VisitUsingTypeLoc(UsingTypeLoc L) { |
883 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
884 | L.getLocalSourceRange().getBegin(), |
885 | /*IsDecl=*/false, |
886 | {L.getFoundDecl()}}); |
887 | } |
888 | |
889 | void VisitTagTypeLoc(TagTypeLoc L) { |
890 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
891 | L.getNameLoc(), |
892 | /*IsDecl=*/false, |
893 | {L.getDecl()}}); |
894 | } |
895 | |
896 | void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) { |
897 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
898 | L.getNameLoc(), |
899 | /*IsDecl=*/false, |
900 | {L.getDecl()}}); |
901 | } |
902 | |
903 | void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) { |
904 | // We must ensure template type aliases are included in results if they |
905 | // were written in the source code, e.g. in |
906 | // template <class T> using valias = vector<T>; |
907 | // ^valias<int> x; |
908 | // 'explicitReferenceTargets' will return: |
909 | // 1. valias with mask 'Alias'. |
910 | // 2. 'vector<int>' with mask 'Underlying'. |
911 | // we want to return only #1 in this case. |
912 | Refs.push_back(Elt: ReferenceLoc{ |
913 | NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false, |
914 | explicitReferenceTargets(DynTypedNode::create(L.getType()), |
915 | DeclRelation::Alias, Resolver)}); |
916 | } |
917 | void VisitDeducedTemplateSpecializationTypeLoc( |
918 | DeducedTemplateSpecializationTypeLoc L) { |
919 | Refs.push_back(Elt: ReferenceLoc{ |
920 | NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false, |
921 | explicitReferenceTargets(DynTypedNode::create(L.getType()), |
922 | DeclRelation::Alias, Resolver)}); |
923 | } |
924 | |
925 | void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { |
926 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
927 | TL.getNameLoc(), |
928 | /*IsDecl=*/false, |
929 | {TL.getDecl()}}); |
930 | } |
931 | |
932 | void VisitDependentTemplateSpecializationTypeLoc( |
933 | DependentTemplateSpecializationTypeLoc L) { |
934 | Refs.push_back( |
935 | Elt: ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(), |
936 | /*IsDecl=*/false, |
937 | explicitReferenceTargets( |
938 | DynTypedNode::create(L.getType()), {}, Resolver)}); |
939 | } |
940 | |
941 | void VisitDependentNameTypeLoc(DependentNameTypeLoc L) { |
942 | Refs.push_back( |
943 | Elt: ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), |
944 | /*IsDecl=*/false, |
945 | explicitReferenceTargets( |
946 | DynTypedNode::create(L.getType()), {}, Resolver)}); |
947 | } |
948 | |
949 | void VisitTypedefTypeLoc(TypedefTypeLoc L) { |
950 | if (shouldSkipTypedef(TD: L.getTypedefNameDecl())) |
951 | return; |
952 | Refs.push_back(Elt: ReferenceLoc{NestedNameSpecifierLoc(), |
953 | L.getNameLoc(), |
954 | /*IsDecl=*/false, |
955 | {L.getTypedefNameDecl()}}); |
956 | } |
957 | |
958 | void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) { |
959 | Refs.push_back(Elt: ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
960 | .NameLoc: L.getNameLoc(), |
961 | /*IsDecl=*/false, |
962 | {L.getIFaceDecl()}}); |
963 | } |
964 | }; |
965 | |
966 | Visitor V{Resolver}; |
967 | V.Visit(TyLoc: L.getUnqualifiedLoc()); |
968 | return V.Refs; |
969 | } |
970 | |
971 | class ExplicitReferenceCollector |
972 | : public RecursiveASTVisitor<ExplicitReferenceCollector> { |
973 | public: |
974 | ExplicitReferenceCollector(llvm::function_ref<void(ReferenceLoc)> Out, |
975 | const HeuristicResolver *Resolver) |
976 | : Out(Out), Resolver(Resolver) { |
977 | assert(Out); |
978 | } |
979 | |
980 | bool VisitTypeLoc(TypeLoc TTL) { |
981 | if (TypeLocsToSkip.count(V: TTL.getBeginLoc())) |
982 | return true; |
983 | visitNode(N: DynTypedNode::create(Node: TTL)); |
984 | return true; |
985 | } |
986 | |
987 | bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc L) { |
988 | // ElaboratedTypeLoc will reports information for its inner type loc. |
989 | // Otherwise we loose information about inner types loc's qualifier. |
990 | TypeLoc Inner = L.getNamedTypeLoc().getUnqualifiedLoc(); |
991 | if (L.getBeginLoc() == Inner.getBeginLoc()) |
992 | return RecursiveASTVisitor::TraverseTypeLoc(TL: Inner); |
993 | else |
994 | TypeLocsToSkip.insert(V: Inner.getBeginLoc()); |
995 | return RecursiveASTVisitor::TraverseElaboratedTypeLoc(L); |
996 | } |
997 | |
998 | bool VisitStmt(Stmt *S) { |
999 | visitNode(N: DynTypedNode::create(Node: *S)); |
1000 | return true; |
1001 | } |
1002 | |
1003 | bool TraverseOpaqueValueExpr(OpaqueValueExpr *OVE) { |
1004 | visitNode(N: DynTypedNode::create(Node: *OVE)); |
1005 | // Not clear why the source expression is skipped by default... |
1006 | // FIXME: can we just make RecursiveASTVisitor do this? |
1007 | return RecursiveASTVisitor::TraverseStmt(OVE->getSourceExpr()); |
1008 | } |
1009 | |
1010 | bool TraversePseudoObjectExpr(PseudoObjectExpr *POE) { |
1011 | visitNode(N: DynTypedNode::create(Node: *POE)); |
1012 | // Traverse only the syntactic form to find the *written* references. |
1013 | // (The semantic form also contains lots of duplication) |
1014 | return RecursiveASTVisitor::TraverseStmt(POE->getSyntacticForm()); |
1015 | } |
1016 | |
1017 | // We re-define Traverse*, since there's no corresponding Visit*. |
1018 | // TemplateArgumentLoc is the only way to get locations for references to |
1019 | // template template parameters. |
1020 | bool TraverseTemplateArgumentLoc(TemplateArgumentLoc A) { |
1021 | switch (A.getArgument().getKind()) { |
1022 | case TemplateArgument::Template: |
1023 | case TemplateArgument::TemplateExpansion: |
1024 | reportReference(Ref: ReferenceLoc{.Qualifier: A.getTemplateQualifierLoc(), |
1025 | .NameLoc: A.getTemplateNameLoc(), |
1026 | /*IsDecl=*/false, |
1027 | {A.getArgument() |
1028 | .getAsTemplateOrTemplatePattern() |
1029 | .getAsTemplateDecl()}}, |
1030 | N: DynTypedNode::create(Node: A.getArgument())); |
1031 | break; |
1032 | case TemplateArgument::Declaration: |
1033 | break; // FIXME: can this actually happen in TemplateArgumentLoc? |
1034 | case TemplateArgument::Integral: |
1035 | case TemplateArgument::Null: |
1036 | case TemplateArgument::NullPtr: |
1037 | break; // no references. |
1038 | case TemplateArgument::Pack: |
1039 | case TemplateArgument::Type: |
1040 | case TemplateArgument::Expression: |
1041 | case TemplateArgument::StructuralValue: |
1042 | break; // Handled by VisitType and VisitExpression. |
1043 | }; |
1044 | return RecursiveASTVisitor::TraverseTemplateArgumentLoc(ArgLoc: A); |
1045 | } |
1046 | |
1047 | bool VisitDecl(Decl *D) { |
1048 | visitNode(N: DynTypedNode::create(Node: *D)); |
1049 | return true; |
1050 | } |
1051 | |
1052 | // We have to use Traverse* because there is no corresponding Visit*. |
1053 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc L) { |
1054 | if (!L.getNestedNameSpecifier()) |
1055 | return true; |
1056 | visitNode(N: DynTypedNode::create(Node: L)); |
1057 | // Inner type is missing information about its qualifier, skip it. |
1058 | if (auto TL = L.getTypeLoc()) |
1059 | TypeLocsToSkip.insert(V: TL.getBeginLoc()); |
1060 | return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS: L); |
1061 | } |
1062 | |
1063 | bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) { |
1064 | visitNode(N: DynTypedNode::create(Node: ProtocolLoc)); |
1065 | return true; |
1066 | } |
1067 | |
1068 | bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { |
1069 | visitNode(N: DynTypedNode::create(Node: *Init)); |
1070 | return RecursiveASTVisitor::TraverseConstructorInitializer(Init); |
1071 | } |
1072 | |
1073 | bool VisitConceptReference(const ConceptReference *CR) { |
1074 | visitNode(N: DynTypedNode::create(Node: *CR)); |
1075 | return true; |
1076 | } |
1077 | |
1078 | private: |
1079 | /// Obtain information about a reference directly defined in \p N. Does not |
1080 | /// recurse into child nodes, e.g. do not expect references for constructor |
1081 | /// initializers |
1082 | /// |
1083 | /// Any of the fields in the returned structure can be empty, but not all of |
1084 | /// them, e.g. |
1085 | /// - for implicitly generated nodes (e.g. MemberExpr from range-based-for), |
1086 | /// source location information may be missing, |
1087 | /// - for dependent code, targets may be empty. |
1088 | /// |
1089 | /// (!) For the purposes of this function declarations are not considered to |
1090 | /// be references. However, declarations can have references inside them, |
1091 | /// e.g. 'namespace foo = std' references namespace 'std' and this |
1092 | /// function will return the corresponding reference. |
1093 | llvm::SmallVector<ReferenceLoc> explicitReference(DynTypedNode N) { |
1094 | if (auto *D = N.get<Decl>()) |
1095 | return refInDecl(D, Resolver); |
1096 | if (auto *S = N.get<Stmt>()) |
1097 | return refInStmt(S, Resolver); |
1098 | if (auto *NNSL = N.get<NestedNameSpecifierLoc>()) { |
1099 | // (!) 'DeclRelation::Alias' ensures we do not loose namespace aliases. |
1100 | return {ReferenceLoc{ |
1101 | .Qualifier: NNSL->getPrefix(), .NameLoc: NNSL->getLocalBeginLoc(), .IsDecl: false, |
1102 | .Targets: explicitReferenceTargets( |
1103 | N: DynTypedNode::create(Node: *NNSL->getNestedNameSpecifier()), |
1104 | Mask: DeclRelation::Alias, Resolver)}}; |
1105 | } |
1106 | if (const TypeLoc *TL = N.get<TypeLoc>()) |
1107 | return refInTypeLoc(L: *TL, Resolver); |
1108 | if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) { |
1109 | // Other type initializers (e.g. base initializer) are handled by visiting |
1110 | // the typeLoc. |
1111 | if (CCI->isAnyMemberInitializer()) { |
1112 | return {ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
1113 | .NameLoc: CCI->getMemberLocation(), |
1114 | /*IsDecl=*/false, |
1115 | {CCI->getAnyMember()}}}; |
1116 | } |
1117 | } |
1118 | if (const ObjCProtocolLoc *PL = N.get<ObjCProtocolLoc>()) |
1119 | return {ReferenceLoc{.Qualifier: NestedNameSpecifierLoc(), |
1120 | .NameLoc: PL->getLocation(), |
1121 | /*IsDecl=*/false, |
1122 | {PL->getProtocol()}}}; |
1123 | if (const ConceptReference *CR = N.get<ConceptReference>()) |
1124 | return {ReferenceLoc{.Qualifier: CR->getNestedNameSpecifierLoc(), |
1125 | .NameLoc: CR->getConceptNameLoc(), |
1126 | /*IsDecl=*/false, |
1127 | {CR->getNamedConcept()}}}; |
1128 | |
1129 | // We do not have location information for other nodes (QualType, etc) |
1130 | return {}; |
1131 | } |
1132 | |
1133 | void visitNode(DynTypedNode N) { |
1134 | for (auto &R : explicitReference(N)) |
1135 | reportReference(Ref: std::move(R), N); |
1136 | } |
1137 | |
1138 | void reportReference(ReferenceLoc &&Ref, DynTypedNode N) { |
1139 | // Strip null targets that can arise from invalid code. |
1140 | // (This avoids having to check for null everywhere we insert) |
1141 | llvm::erase(C&: Ref.Targets, V: nullptr); |
1142 | // Our promise is to return only references from the source code. If we lack |
1143 | // location information, skip these nodes. |
1144 | // Normally this should not happen in practice, unless there are bugs in the |
1145 | // traversals or users started the traversal at an implicit node. |
1146 | if (Ref.NameLoc.isInvalid()) { |
1147 | dlog("invalid location at node {0}" , nodeToString(N)); |
1148 | return; |
1149 | } |
1150 | Out(Ref); |
1151 | } |
1152 | |
1153 | llvm::function_ref<void(ReferenceLoc)> Out; |
1154 | const HeuristicResolver *Resolver; |
1155 | /// TypeLocs starting at these locations must be skipped, see |
1156 | /// TraverseElaboratedTypeSpecifierLoc for details. |
1157 | llvm::DenseSet<SourceLocation> TypeLocsToSkip; |
1158 | }; |
1159 | } // namespace |
1160 | |
1161 | void findExplicitReferences(const Stmt *S, |
1162 | llvm::function_ref<void(ReferenceLoc)> Out, |
1163 | const HeuristicResolver *Resolver) { |
1164 | assert(S); |
1165 | ExplicitReferenceCollector(Out, Resolver).TraverseStmt(S: const_cast<Stmt *>(S)); |
1166 | } |
1167 | void findExplicitReferences(const Decl *D, |
1168 | llvm::function_ref<void(ReferenceLoc)> Out, |
1169 | const HeuristicResolver *Resolver) { |
1170 | assert(D); |
1171 | ExplicitReferenceCollector(Out, Resolver).TraverseDecl(D: const_cast<Decl *>(D)); |
1172 | } |
1173 | void findExplicitReferences(const ASTContext &AST, |
1174 | llvm::function_ref<void(ReferenceLoc)> Out, |
1175 | const HeuristicResolver *Resolver) { |
1176 | ExplicitReferenceCollector(Out, Resolver) |
1177 | .TraverseAST(AST&: const_cast<ASTContext &>(AST)); |
1178 | } |
1179 | |
1180 | llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, DeclRelation R) { |
1181 | switch (R) { |
1182 | #define REL_CASE(X) \ |
1183 | case DeclRelation::X: \ |
1184 | return OS << #X; |
1185 | REL_CASE(Alias); |
1186 | REL_CASE(Underlying); |
1187 | REL_CASE(TemplateInstantiation); |
1188 | REL_CASE(TemplatePattern); |
1189 | #undef REL_CASE |
1190 | } |
1191 | llvm_unreachable("Unhandled DeclRelation enum" ); |
1192 | } |
1193 | llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, DeclRelationSet RS) { |
1194 | const char *Sep = "" ; |
1195 | for (unsigned I = 0; I < RS.S.size(); ++I) { |
1196 | if (RS.S.test(position: I)) { |
1197 | OS << Sep << static_cast<DeclRelation>(I); |
1198 | Sep = "|" ; |
1199 | } |
1200 | } |
1201 | return OS; |
1202 | } |
1203 | |
1204 | llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R) { |
1205 | // note we cannot print R.NameLoc without a source manager. |
1206 | OS << "targets = {" ; |
1207 | llvm::SmallVector<std::string> Targets; |
1208 | for (const NamedDecl *T : R.Targets) { |
1209 | llvm::raw_string_ostream Target(Targets.emplace_back()); |
1210 | Target << printQualifiedName(ND: *T) << printTemplateSpecializationArgs(ND: *T); |
1211 | } |
1212 | llvm::sort(C&: Targets); |
1213 | OS << llvm::join(R&: Targets, Separator: ", " ); |
1214 | OS << "}" ; |
1215 | if (R.Qualifier) { |
1216 | OS << ", qualifier = '" ; |
1217 | R.Qualifier.getNestedNameSpecifier()->print(OS, |
1218 | Policy: PrintingPolicy(LangOptions())); |
1219 | OS << "'" ; |
1220 | } |
1221 | if (R.IsDecl) |
1222 | OS << ", decl" ; |
1223 | return OS; |
1224 | } |
1225 | |
1226 | } // namespace clangd |
1227 | } // namespace clang |
1228 | |