Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clangd/FindTarget.cpp @ 221:79ff65ed7e25
LLVM12 Original
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Jun 2021 19:15:29 +0900 |
parents | 0572611fdcc8 |
children | 5f17cb93ff66 |
comparison
equal
deleted
inserted
replaced
220:42394fc6a535 | 221:79ff65ed7e25 |
---|---|
6 // | 6 // |
7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
8 | 8 |
9 #include "FindTarget.h" | 9 #include "FindTarget.h" |
10 #include "AST.h" | 10 #include "AST.h" |
11 #include "HeuristicResolver.h" | |
11 #include "support/Logger.h" | 12 #include "support/Logger.h" |
12 #include "clang/AST/ASTTypeTraits.h" | 13 #include "clang/AST/ASTTypeTraits.h" |
13 #include "clang/AST/Decl.h" | 14 #include "clang/AST/Decl.h" |
15 #include "clang/AST/DeclBase.h" | |
14 #include "clang/AST/DeclCXX.h" | 16 #include "clang/AST/DeclCXX.h" |
15 #include "clang/AST/DeclTemplate.h" | 17 #include "clang/AST/DeclTemplate.h" |
16 #include "clang/AST/DeclVisitor.h" | 18 #include "clang/AST/DeclVisitor.h" |
17 #include "clang/AST/DeclarationName.h" | 19 #include "clang/AST/DeclarationName.h" |
18 #include "clang/AST/Expr.h" | 20 #include "clang/AST/Expr.h" |
42 #include <vector> | 44 #include <vector> |
43 | 45 |
44 namespace clang { | 46 namespace clang { |
45 namespace clangd { | 47 namespace clangd { |
46 namespace { | 48 namespace { |
47 using ast_type_traits::DynTypedNode; | 49 |
48 | 50 LLVM_ATTRIBUTE_UNUSED std::string nodeToString(const DynTypedNode &N) { |
49 LLVM_ATTRIBUTE_UNUSED std::string | |
50 nodeToString(const ast_type_traits::DynTypedNode &N) { | |
51 std::string S = std::string(N.getNodeKind().asStringRef()); | 51 std::string S = std::string(N.getNodeKind().asStringRef()); |
52 { | 52 { |
53 llvm::raw_string_ostream OS(S); | 53 llvm::raw_string_ostream OS(S); |
54 OS << ": "; | 54 OS << ": "; |
55 N.print(OS, PrintingPolicy(LangOptions())); | 55 N.print(OS, PrintingPolicy(LangOptions())); |
56 } | 56 } |
57 std::replace(S.begin(), S.end(), '\n', ' '); | 57 std::replace(S.begin(), S.end(), '\n', ' '); |
58 return S; | 58 return S; |
59 } | |
60 | |
61 // Given a dependent type and a member name, heuristically resolve the | |
62 // name to one or more declarations. | |
63 // The current heuristic is simply to look up the name in the primary | |
64 // template. This is a heuristic because the template could potentially | |
65 // have specializations that declare different members. | |
66 // Multiple declarations could be returned if the name is overloaded | |
67 // (e.g. an overloaded method in the primary template). | |
68 // This heuristic will give the desired answer in many cases, e.g. | |
69 // for a call to vector<T>::size(). | |
70 // The name to look up is provided in the form of a factory that takes | |
71 // an ASTContext, because an ASTContext may be needed to obtain the | |
72 // name (e.g. if it's an operator name), but the caller may not have | |
73 // access to an ASTContext. | |
74 std::vector<const NamedDecl *> getMembersReferencedViaDependentName( | |
75 const Type *T, | |
76 llvm::function_ref<DeclarationName(ASTContext &)> NameFactory, | |
77 bool IsNonstaticMember) { | |
78 if (!T) | |
79 return {}; | |
80 if (auto *ET = T->getAs<EnumType>()) { | |
81 auto Result = | |
82 ET->getDecl()->lookup(NameFactory(ET->getDecl()->getASTContext())); | |
83 return {Result.begin(), Result.end()}; | |
84 } | |
85 if (auto *ICNT = T->getAs<InjectedClassNameType>()) { | |
86 T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); | |
87 } | |
88 auto *TST = T->getAs<TemplateSpecializationType>(); | |
89 if (!TST) | |
90 return {}; | |
91 const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>( | |
92 TST->getTemplateName().getAsTemplateDecl()); | |
93 if (!TD) | |
94 return {}; | |
95 CXXRecordDecl *RD = TD->getTemplatedDecl(); | |
96 if (!RD->hasDefinition()) | |
97 return {}; | |
98 RD = RD->getDefinition(); | |
99 DeclarationName Name = NameFactory(RD->getASTContext()); | |
100 return RD->lookupDependentName(Name, [=](const NamedDecl *D) { | |
101 return IsNonstaticMember ? D->isCXXInstanceMember() | |
102 : !D->isCXXInstanceMember(); | |
103 }); | |
104 } | |
105 | |
106 // Given the type T of a dependent expression that appears of the LHS of a "->", | |
107 // heuristically find a corresponding pointee type in whose scope we could look | |
108 // up the name appearing on the RHS. | |
109 const Type *getPointeeType(const Type *T) { | |
110 if (!T) | |
111 return nullptr; | |
112 | |
113 if (T->isPointerType()) { | |
114 return T->getAs<PointerType>()->getPointeeType().getTypePtrOrNull(); | |
115 } | |
116 | |
117 // Try to handle smart pointer types. | |
118 | |
119 // Look up operator-> in the primary template. If we find one, it's probably a | |
120 // smart pointer type. | |
121 auto ArrowOps = getMembersReferencedViaDependentName( | |
122 T, | |
123 [](ASTContext &Ctx) { | |
124 return Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow); | |
125 }, | |
126 /*IsNonStaticMember=*/true); | |
127 if (ArrowOps.empty()) | |
128 return nullptr; | |
129 | |
130 // Getting the return type of the found operator-> method decl isn't useful, | |
131 // because we discarded template arguments to perform lookup in the primary | |
132 // template scope, so the return type would just have the form U* where U is a | |
133 // template parameter type. | |
134 // Instead, just handle the common case where the smart pointer type has the | |
135 // form of SmartPtr<X, ...>, and assume X is the pointee type. | |
136 auto *TST = T->getAs<TemplateSpecializationType>(); | |
137 if (!TST) | |
138 return nullptr; | |
139 if (TST->getNumArgs() == 0) | |
140 return nullptr; | |
141 const TemplateArgument &FirstArg = TST->getArg(0); | |
142 if (FirstArg.getKind() != TemplateArgument::Type) | |
143 return nullptr; | |
144 return FirstArg.getAsType().getTypePtrOrNull(); | |
145 } | 59 } |
146 | 60 |
147 const NamedDecl *getTemplatePattern(const NamedDecl *D) { | 61 const NamedDecl *getTemplatePattern(const NamedDecl *D) { |
148 if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { | 62 if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { |
149 if (const auto *Result = CRD->getTemplateInstantiationPattern()) | 63 if (const auto *Result = CRD->getTemplateInstantiationPattern()) |
201 // template<class X> using pvec = vector<x*>; pvec<int> x; | 115 // template<class X> using pvec = vector<x*>; pvec<int> x; |
202 // There's no Decl `pvec<int>`, we must choose `pvec<X>` or `vector<int*>` | 116 // There's no Decl `pvec<int>`, we must choose `pvec<X>` or `vector<int*>` |
203 // and both are lossy. We must know upfront what the caller ultimately wants. | 117 // and both are lossy. We must know upfront what the caller ultimately wants. |
204 // | 118 // |
205 // FIXME: improve common dependent scope using name lookup in primary templates. | 119 // FIXME: improve common dependent scope using name lookup in primary templates. |
206 // e.g. template<typename T> int foo() { return std::vector<T>().size(); } | 120 // We currently handle several dependent constructs, but some others remain to |
207 // formally size() is unresolved, but the primary template is a good guess. | 121 // be handled: |
208 // This affects: | |
209 // - DependentTemplateSpecializationType, | |
210 // - DependentNameType | |
211 // - UnresolvedUsingValueDecl | |
212 // - UnresolvedUsingTypenameDecl | 122 // - UnresolvedUsingTypenameDecl |
213 struct TargetFinder { | 123 struct TargetFinder { |
214 using RelSet = DeclRelationSet; | 124 using RelSet = DeclRelationSet; |
215 using Rel = DeclRelation; | 125 using Rel = DeclRelation; |
216 | 126 |
217 private: | 127 private: |
128 const HeuristicResolver *Resolver; | |
218 llvm::SmallDenseMap<const NamedDecl *, | 129 llvm::SmallDenseMap<const NamedDecl *, |
219 std::pair<RelSet, /*InsertionOrder*/ size_t>> | 130 std::pair<RelSet, /*InsertionOrder*/ size_t>> |
220 Decls; | 131 Decls; |
132 llvm::SmallDenseMap<const Decl *, RelSet> Seen; | |
221 RelSet Flags; | 133 RelSet Flags; |
222 | 134 |
223 template <typename T> void debug(T &Node, RelSet Flags) { | 135 template <typename T> void debug(T &Node, RelSet Flags) { |
224 dlog("visit [{0}] {1}", Flags, | 136 dlog("visit [{0}] {1}", Flags, nodeToString(DynTypedNode::create(Node))); |
225 nodeToString(ast_type_traits::DynTypedNode::create(Node))); | |
226 } | 137 } |
227 | 138 |
228 void report(const NamedDecl *D, RelSet Flags) { | 139 void report(const NamedDecl *D, RelSet Flags) { |
229 dlog("--> [{0}] {1}", Flags, | 140 dlog("--> [{0}] {1}", Flags, nodeToString(DynTypedNode::create(*D))); |
230 nodeToString(ast_type_traits::DynTypedNode::create(*D))); | |
231 auto It = Decls.try_emplace(D, std::make_pair(Flags, Decls.size())); | 141 auto It = Decls.try_emplace(D, std::make_pair(Flags, Decls.size())); |
232 // If already exists, update the flags. | 142 // If already exists, update the flags. |
233 if (!It.second) | 143 if (!It.second) |
234 It.first->second.first |= Flags; | 144 It.first->second.first |= Flags; |
235 } | 145 } |
236 | 146 |
237 public: | 147 public: |
148 TargetFinder(const HeuristicResolver *Resolver) : Resolver(Resolver) {} | |
149 | |
238 llvm::SmallVector<std::pair<const NamedDecl *, RelSet>, 1> takeDecls() const { | 150 llvm::SmallVector<std::pair<const NamedDecl *, RelSet>, 1> takeDecls() const { |
239 using ValTy = std::pair<const NamedDecl *, RelSet>; | 151 using ValTy = std::pair<const NamedDecl *, RelSet>; |
240 llvm::SmallVector<ValTy, 1> Result; | 152 llvm::SmallVector<ValTy, 1> Result; |
241 Result.resize(Decls.size()); | 153 Result.resize(Decls.size()); |
242 for (const auto &Elem : Decls) | 154 for (const auto &Elem : Decls) |
247 void add(const Decl *Dcl, RelSet Flags) { | 159 void add(const Decl *Dcl, RelSet Flags) { |
248 const NamedDecl *D = llvm::dyn_cast_or_null<NamedDecl>(Dcl); | 160 const NamedDecl *D = llvm::dyn_cast_or_null<NamedDecl>(Dcl); |
249 if (!D) | 161 if (!D) |
250 return; | 162 return; |
251 debug(*D, Flags); | 163 debug(*D, Flags); |
164 | |
165 // Avoid recursion (which can arise in the presence of heuristic | |
166 // resolution of dependent names) by exiting early if we have | |
167 // already seen this decl with all flags in Flags. | |
168 auto Res = Seen.try_emplace(D); | |
169 if (!Res.second && Res.first->second.contains(Flags)) | |
170 return; | |
171 Res.first->second |= Flags; | |
172 | |
252 if (const UsingDirectiveDecl *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D)) | 173 if (const UsingDirectiveDecl *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D)) |
253 D = UDD->getNominatedNamespaceAsWritten(); | 174 D = UDD->getNominatedNamespaceAsWritten(); |
254 | 175 |
255 if (const TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) { | 176 if (const TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) { |
256 add(TND->getUnderlyingType(), Flags | Rel::Underlying); | 177 add(TND->getUnderlyingType(), Flags | Rel::Underlying); |
257 Flags |= Rel::Alias; // continue with the alias. | 178 Flags |= Rel::Alias; // continue with the alias. |
258 } else if (const UsingDecl *UD = dyn_cast<UsingDecl>(D)) { | 179 } else if (const UsingDecl *UD = dyn_cast<UsingDecl>(D)) { |
180 // no Underlying as this is a non-renaming alias. | |
259 for (const UsingShadowDecl *S : UD->shadows()) | 181 for (const UsingShadowDecl *S : UD->shadows()) |
260 add(S->getUnderlyingDecl(), Flags | Rel::Underlying); | 182 add(S->getUnderlyingDecl(), Flags); |
261 Flags |= Rel::Alias; // continue with the alias. | 183 Flags |= Rel::Alias; // continue with the alias. |
262 } else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) { | 184 } else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) { |
263 add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); | 185 add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); |
186 Flags |= Rel::Alias; // continue with the alias | |
187 } else if (const UnresolvedUsingValueDecl *UUVD = | |
188 dyn_cast<UnresolvedUsingValueDecl>(D)) { | |
189 if (Resolver) { | |
190 for (const NamedDecl *Target : Resolver->resolveUsingValueDecl(UUVD)) { | |
191 add(Target, Flags); // no Underlying as this is a non-renaming alias | |
192 } | |
193 } | |
264 Flags |= Rel::Alias; // continue with the alias | 194 Flags |= Rel::Alias; // continue with the alias |
265 } else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { | 195 } else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { |
266 // Include the using decl, but don't traverse it. This may end up | 196 // Include the using decl, but don't traverse it. This may end up |
267 // including *all* shadows, which we don't want. | 197 // including *all* shadows, which we don't want. |
268 report(USD->getUsingDecl(), Flags | Rel::Alias); | 198 report(USD->getUsingDecl(), Flags | Rel::Alias); |
269 // Shadow decls are synthetic and not themselves interesting. | 199 // Shadow decls are synthetic and not themselves interesting. |
270 // Record the underlying decl instead, if allowed. | 200 // Record the underlying decl instead, if allowed. |
271 D = USD->getTargetDecl(); | 201 D = USD->getTargetDecl(); |
272 Flags |= Rel::Underlying; // continue with the underlying decl. | 202 } else if (const auto *DG = dyn_cast<CXXDeductionGuideDecl>(D)) { |
273 } | 203 D = DG->getDeducedTemplate(); |
204 } else if (const ObjCImplementationDecl *IID = | |
205 dyn_cast<ObjCImplementationDecl>(D)) { | |
206 // Treat ObjC{Interface,Implementation}Decl as if they were a decl/def | |
207 // pair as long as the interface isn't implicit. | |
208 if (const auto *CID = IID->getClassInterface()) | |
209 if (const auto *DD = CID->getDefinition()) | |
210 if (!DD->isImplicitInterfaceDecl()) | |
211 D = DD; | |
212 } else if (const ObjCCategoryImplDecl *CID = | |
213 dyn_cast<ObjCCategoryImplDecl>(D)) { | |
214 // Treat ObjC{Category,CategoryImpl}Decl as if they were a decl/def pair. | |
215 D = CID->getCategoryDecl(); | |
216 } | |
217 if (!D) | |
218 return; | |
274 | 219 |
275 if (const Decl *Pat = getTemplatePattern(D)) { | 220 if (const Decl *Pat = getTemplatePattern(D)) { |
276 assert(Pat != D); | 221 assert(Pat != D); |
277 add(Pat, Flags | Rel::TemplatePattern); | 222 add(Pat, Flags | Rel::TemplatePattern); |
278 // Now continue with the instantiation. | 223 // Now continue with the instantiation. |
339 if (auto *LabelDecl = Label->getDecl()) | 284 if (auto *LabelDecl = Label->getDecl()) |
340 Outer.add(LabelDecl, Flags); | 285 Outer.add(LabelDecl, Flags); |
341 } | 286 } |
342 void | 287 void |
343 VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { | 288 VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { |
344 const Type *BaseType = E->getBaseType().getTypePtrOrNull(); | 289 if (Outer.Resolver) { |
345 if (E->isArrow()) { | 290 for (const NamedDecl *D : Outer.Resolver->resolveMemberExpr(E)) { |
346 BaseType = getPointeeType(BaseType); | 291 Outer.add(D, Flags); |
292 } | |
347 } | 293 } |
348 for (const NamedDecl *D : getMembersReferencedViaDependentName( | |
349 BaseType, [E](ASTContext &) { return E->getMember(); }, | |
350 /*IsNonstaticMember=*/true)) { | |
351 Outer.add(D, Flags); | |
352 } | |
353 } | 294 } |
354 void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { | 295 void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { |
355 for (const NamedDecl *D : getMembersReferencedViaDependentName( | 296 if (Outer.Resolver) { |
356 E->getQualifier()->getAsType(), | 297 for (const NamedDecl *D : Outer.Resolver->resolveDeclRefExpr(E)) { |
357 [E](ASTContext &) { return E->getDeclName(); }, | 298 Outer.add(D, Flags); |
358 /*IsNonstaticMember=*/false)) { | 299 } |
359 Outer.add(D, Flags); | |
360 } | 300 } |
361 } | 301 } |
362 void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) { | 302 void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) { |
363 Outer.add(OIRE->getDecl(), Flags); | 303 Outer.add(OIRE->getDecl(), Flags); |
364 } | 304 } |
381 void VisitOpaqueValueExpr(const OpaqueValueExpr *OVE) { | 321 void VisitOpaqueValueExpr(const OpaqueValueExpr *OVE) { |
382 Outer.add(OVE->getSourceExpr(), Flags); | 322 Outer.add(OVE->getSourceExpr(), Flags); |
383 } | 323 } |
384 void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) { | 324 void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) { |
385 Outer.add(POE->getSyntacticForm(), Flags); | 325 Outer.add(POE->getSyntacticForm(), Flags); |
326 } | |
327 void VisitCXXNewExpr(const CXXNewExpr *CNE) { | |
328 Outer.add(CNE->getOperatorNew(), Flags); | |
329 } | |
330 void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE) { | |
331 Outer.add(CDE->getOperatorDelete(), Flags); | |
386 } | 332 } |
387 }; | 333 }; |
388 Visitor(*this, Flags).Visit(S); | 334 Visitor(*this, Flags).Visit(S); |
389 } | 335 } |
390 | 336 |
425 // even when it's known in principle. Once that bug is fixed, | 371 // even when it's known in principle. Once that bug is fixed, |
426 // this method can be removed (the existing handling in | 372 // this method can be removed (the existing handling in |
427 // VisitDeducedType() is sufficient). | 373 // VisitDeducedType() is sufficient). |
428 if (auto *TD = DTST->getTemplateName().getAsTemplateDecl()) | 374 if (auto *TD = DTST->getTemplateName().getAsTemplateDecl()) |
429 Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); | 375 Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); |
376 } | |
377 void VisitDependentNameType(const DependentNameType *DNT) { | |
378 if (Outer.Resolver) { | |
379 for (const NamedDecl *ND : | |
380 Outer.Resolver->resolveDependentNameType(DNT)) { | |
381 Outer.add(ND, Flags); | |
382 } | |
383 } | |
384 } | |
385 void VisitDependentTemplateSpecializationType( | |
386 const DependentTemplateSpecializationType *DTST) { | |
387 if (Outer.Resolver) { | |
388 for (const NamedDecl *ND : | |
389 Outer.Resolver->resolveTemplateSpecializationType(DTST)) { | |
390 Outer.add(ND, Flags); | |
391 } | |
392 } | |
430 } | 393 } |
431 void VisitTypedefType(const TypedefType *TT) { | 394 void VisitTypedefType(const TypedefType *TT) { |
432 Outer.add(TT->getDecl(), Flags); | 395 Outer.add(TT->getDecl(), Flags); |
433 } | 396 } |
434 void | 397 void |
467 } | 430 } |
468 void VisitObjCInterfaceType(const ObjCInterfaceType *OIT) { | 431 void VisitObjCInterfaceType(const ObjCInterfaceType *OIT) { |
469 Outer.add(OIT->getDecl(), Flags); | 432 Outer.add(OIT->getDecl(), Flags); |
470 } | 433 } |
471 void VisitObjCObjectType(const ObjCObjectType *OOT) { | 434 void VisitObjCObjectType(const ObjCObjectType *OOT) { |
472 // FIXME: ObjCObjectTypeLoc has no children for the protocol list, so | 435 // Make all of the protocols targets since there's no child nodes for |
473 // there is no node in id<Foo> that refers to ObjCProtocolDecl Foo. | 436 // protocols. This isn't needed for the base type, which *does* have a |
474 if (OOT->isObjCQualifiedId() && OOT->getNumProtocols() == 1) | 437 // child `ObjCInterfaceTypeLoc`. This structure is a hack, but it works |
475 Outer.add(OOT->getProtocol(0), Flags); | 438 // well for go-to-definition. |
439 unsigned NumProtocols = OOT->getNumProtocols(); | |
440 for (unsigned I = 0; I < NumProtocols; I++) | |
441 Outer.add(OOT->getProtocol(I), Flags); | |
476 } | 442 } |
477 }; | 443 }; |
478 Visitor(*this, Flags).Visit(T.getTypePtr()); | 444 Visitor(*this, Flags).Visit(T.getTypePtr()); |
479 } | 445 } |
480 | 446 |
481 void add(const NestedNameSpecifier *NNS, RelSet Flags) { | 447 void add(const NestedNameSpecifier *NNS, RelSet Flags) { |
482 if (!NNS) | 448 if (!NNS) |
483 return; | 449 return; |
484 debug(*NNS, Flags); | 450 debug(*NNS, Flags); |
485 switch (NNS->getKind()) { | 451 switch (NNS->getKind()) { |
486 case NestedNameSpecifier::Identifier: | |
487 return; | |
488 case NestedNameSpecifier::Namespace: | 452 case NestedNameSpecifier::Namespace: |
489 add(NNS->getAsNamespace(), Flags); | 453 add(NNS->getAsNamespace(), Flags); |
490 return; | 454 return; |
491 case NestedNameSpecifier::NamespaceAlias: | 455 case NestedNameSpecifier::NamespaceAlias: |
492 add(NNS->getAsNamespaceAlias(), Flags); | 456 add(NNS->getAsNamespaceAlias(), Flags); |
457 return; | |
458 case NestedNameSpecifier::Identifier: | |
459 if (Resolver) { | |
460 add(QualType(Resolver->resolveNestedNameSpecifierToType(NNS), 0), | |
461 Flags); | |
462 } | |
493 return; | 463 return; |
494 case NestedNameSpecifier::TypeSpec: | 464 case NestedNameSpecifier::TypeSpec: |
495 case NestedNameSpecifier::TypeSpecWithTemplate: | 465 case NestedNameSpecifier::TypeSpecWithTemplate: |
496 add(QualType(NNS->getAsType(), 0), Flags); | 466 add(QualType(NNS->getAsType(), 0), Flags); |
497 return; | 467 return; |
512 | 482 |
513 if (CCI->isAnyMemberInitializer()) | 483 if (CCI->isAnyMemberInitializer()) |
514 add(CCI->getAnyMember(), Flags); | 484 add(CCI->getAnyMember(), Flags); |
515 // Constructor calls contain a TypeLoc node, so we don't handle them here. | 485 // Constructor calls contain a TypeLoc node, so we don't handle them here. |
516 } | 486 } |
487 | |
488 void add(const TemplateArgument &Arg, RelSet Flags) { | |
489 // Only used for template template arguments. | |
490 // For type and non-type template arguments, SelectionTree | |
491 // will hit a more specific node (e.g. a TypeLoc or a | |
492 // DeclRefExpr). | |
493 if (Arg.getKind() == TemplateArgument::Template || | |
494 Arg.getKind() == TemplateArgument::TemplateExpansion) { | |
495 if (TemplateDecl *TD = Arg.getAsTemplate().getAsTemplateDecl()) { | |
496 report(TD, Flags); | |
497 } | |
498 } | |
499 } | |
517 }; | 500 }; |
518 | 501 |
519 } // namespace | 502 } // namespace |
520 | 503 |
521 llvm::SmallVector<std::pair<const NamedDecl *, DeclRelationSet>, 1> | 504 llvm::SmallVector<std::pair<const NamedDecl *, DeclRelationSet>, 1> |
522 allTargetDecls(const ast_type_traits::DynTypedNode &N) { | 505 allTargetDecls(const DynTypedNode &N, const HeuristicResolver *Resolver) { |
523 dlog("allTargetDecls({0})", nodeToString(N)); | 506 dlog("allTargetDecls({0})", nodeToString(N)); |
524 TargetFinder Finder; | 507 TargetFinder Finder(Resolver); |
525 DeclRelationSet Flags; | 508 DeclRelationSet Flags; |
526 if (const Decl *D = N.get<Decl>()) | 509 if (const Decl *D = N.get<Decl>()) |
527 Finder.add(D, Flags); | 510 Finder.add(D, Flags); |
528 else if (const Stmt *S = N.get<Stmt>()) | 511 else if (const Stmt *S = N.get<Stmt>()) |
529 Finder.add(S, Flags); | 512 Finder.add(S, Flags); |
535 Finder.add(TL->getType(), Flags); | 518 Finder.add(TL->getType(), Flags); |
536 else if (const QualType *QT = N.get<QualType>()) | 519 else if (const QualType *QT = N.get<QualType>()) |
537 Finder.add(*QT, Flags); | 520 Finder.add(*QT, Flags); |
538 else if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) | 521 else if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) |
539 Finder.add(CCI, Flags); | 522 Finder.add(CCI, Flags); |
540 | 523 else if (const TemplateArgumentLoc *TAL = N.get<TemplateArgumentLoc>()) |
524 Finder.add(TAL->getArgument(), Flags); | |
525 else if (const CXXBaseSpecifier *CBS = N.get<CXXBaseSpecifier>()) | |
526 Finder.add(CBS->getTypeSourceInfo()->getType(), Flags); | |
541 return Finder.takeDecls(); | 527 return Finder.takeDecls(); |
542 } | 528 } |
543 | 529 |
544 llvm::SmallVector<const NamedDecl *, 1> | 530 llvm::SmallVector<const NamedDecl *, 1> |
545 targetDecl(const ast_type_traits::DynTypedNode &N, DeclRelationSet Mask) { | 531 targetDecl(const DynTypedNode &N, DeclRelationSet Mask, |
532 const HeuristicResolver *Resolver) { | |
546 llvm::SmallVector<const NamedDecl *, 1> Result; | 533 llvm::SmallVector<const NamedDecl *, 1> Result; |
547 for (const auto &Entry : allTargetDecls(N)) { | 534 for (const auto &Entry : allTargetDecls(N, Resolver)) { |
548 if (!(Entry.second & ~Mask)) | 535 if (!(Entry.second & ~Mask)) |
549 Result.push_back(Entry.first); | 536 Result.push_back(Entry.first); |
550 } | 537 } |
551 return Result; | 538 return Result; |
552 } | 539 } |
553 | 540 |
554 llvm::SmallVector<const NamedDecl *, 1> | 541 llvm::SmallVector<const NamedDecl *, 1> |
555 explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask) { | 542 explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask, |
543 const HeuristicResolver *Resolver) { | |
556 assert(!(Mask & (DeclRelation::TemplatePattern | | 544 assert(!(Mask & (DeclRelation::TemplatePattern | |
557 DeclRelation::TemplateInstantiation)) && | 545 DeclRelation::TemplateInstantiation)) && |
558 "explicitReferenceTargets handles templates on its own"); | 546 "explicitReferenceTargets handles templates on its own"); |
559 auto Decls = allTargetDecls(N); | 547 auto Decls = allTargetDecls(N, Resolver); |
560 | 548 |
561 // We prefer to return template instantiation, but fallback to template | 549 // We prefer to return template instantiation, but fallback to template |
562 // pattern if instantiation is not available. | 550 // pattern if instantiation is not available. |
563 Mask |= DeclRelation::TemplatePattern | DeclRelation::TemplateInstantiation; | 551 Mask |= DeclRelation::TemplatePattern | DeclRelation::TemplateInstantiation; |
564 | 552 |
581 TemplatePatterns.end()); | 569 TemplatePatterns.end()); |
582 return Targets; | 570 return Targets; |
583 } | 571 } |
584 | 572 |
585 namespace { | 573 namespace { |
586 llvm::SmallVector<ReferenceLoc, 2> refInDecl(const Decl *D) { | 574 llvm::SmallVector<ReferenceLoc> refInDecl(const Decl *D, |
575 const HeuristicResolver *Resolver) { | |
587 struct Visitor : ConstDeclVisitor<Visitor> { | 576 struct Visitor : ConstDeclVisitor<Visitor> { |
588 llvm::SmallVector<ReferenceLoc, 2> Refs; | 577 Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {} |
578 | |
579 const HeuristicResolver *Resolver; | |
580 llvm::SmallVector<ReferenceLoc> Refs; | |
589 | 581 |
590 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { | 582 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { |
591 // We want to keep it as non-declaration references, as the | 583 // We want to keep it as non-declaration references, as the |
592 // "using namespace" declaration doesn't have a name. | 584 // "using namespace" declaration doesn't have a name. |
593 Refs.push_back(ReferenceLoc{D->getQualifierLoc(), | 585 Refs.push_back(ReferenceLoc{D->getQualifierLoc(), |
596 {D->getNominatedNamespaceAsWritten()}}); | 588 {D->getNominatedNamespaceAsWritten()}}); |
597 } | 589 } |
598 | 590 |
599 void VisitUsingDecl(const UsingDecl *D) { | 591 void VisitUsingDecl(const UsingDecl *D) { |
600 // "using ns::identifier;" is a non-declaration reference. | 592 // "using ns::identifier;" is a non-declaration reference. |
601 Refs.push_back( | 593 Refs.push_back(ReferenceLoc{ |
602 ReferenceLoc{D->getQualifierLoc(), D->getLocation(), /*IsDecl=*/false, | 594 D->getQualifierLoc(), D->getLocation(), /*IsDecl=*/false, |
603 explicitReferenceTargets(DynTypedNode::create(*D), | 595 explicitReferenceTargets(DynTypedNode::create(*D), |
604 DeclRelation::Underlying)}); | 596 DeclRelation::Underlying, Resolver)}); |
605 } | 597 } |
606 | 598 |
607 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { | 599 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { |
608 // For namespace alias, "namespace Foo = Target;", we add two references. | 600 // For namespace alias, "namespace Foo = Target;", we add two references. |
609 // Add a declaration reference for Foo. | 601 // Add a declaration reference for Foo. |
634 Refs.push_back(ReferenceLoc{getQualifierLoc(*ND), | 626 Refs.push_back(ReferenceLoc{getQualifierLoc(*ND), |
635 ND->getLocation(), | 627 ND->getLocation(), |
636 /*IsDecl=*/true, | 628 /*IsDecl=*/true, |
637 {ND}}); | 629 {ND}}); |
638 } | 630 } |
631 | |
632 void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *DG) { | |
633 // The class template name in a deduction guide targets the class | |
634 // template. | |
635 Refs.push_back(ReferenceLoc{DG->getQualifierLoc(), | |
636 DG->getNameInfo().getLoc(), | |
637 /*IsDecl=*/false, | |
638 {DG->getDeducedTemplate()}}); | |
639 } | |
640 | |
641 void VisitObjCMethodDecl(const ObjCMethodDecl *OMD) { | |
642 // The name may have several tokens, we can only report the first. | |
643 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
644 OMD->getSelectorStartLoc(), | |
645 /*IsDecl=*/true, | |
646 {OMD}}); | |
647 } | |
648 | |
649 void visitProtocolList( | |
650 llvm::iterator_range<ObjCProtocolList::iterator> Protocols, | |
651 llvm::iterator_range<const SourceLocation *> Locations) { | |
652 for (const auto &P : llvm::zip(Protocols, Locations)) { | |
653 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
654 std::get<1>(P), | |
655 /*IsDecl=*/false, | |
656 {std::get<0>(P)}}); | |
657 } | |
658 } | |
659 | |
660 void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *OID) { | |
661 if (OID->isThisDeclarationADefinition()) | |
662 visitProtocolList(OID->protocols(), OID->protocol_locs()); | |
663 Base::VisitObjCInterfaceDecl(OID); // Visit the interface's name. | |
664 } | |
665 | |
666 void VisitObjCCategoryDecl(const ObjCCategoryDecl *OCD) { | |
667 visitProtocolList(OCD->protocols(), OCD->protocol_locs()); | |
668 // getLocation is the extended class's location, not the category's. | |
669 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
670 OCD->getLocation(), | |
671 /*IsDecl=*/false, | |
672 {OCD->getClassInterface()}}); | |
673 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
674 OCD->getCategoryNameLoc(), | |
675 /*IsDecl=*/true, | |
676 {OCD}}); | |
677 } | |
678 | |
679 void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *OCID) { | |
680 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
681 OCID->getLocation(), | |
682 /*IsDecl=*/false, | |
683 {OCID->getClassInterface()}}); | |
684 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
685 OCID->getCategoryNameLoc(), | |
686 /*IsDecl=*/true, | |
687 {OCID->getCategoryDecl()}}); | |
688 } | |
689 | |
690 void VisitObjCProtocolDecl(const ObjCProtocolDecl *OPD) { | |
691 if (OPD->isThisDeclarationADefinition()) | |
692 visitProtocolList(OPD->protocols(), OPD->protocol_locs()); | |
693 Base::VisitObjCProtocolDecl(OPD); // Visit the protocol's name. | |
694 } | |
639 }; | 695 }; |
640 | 696 |
641 Visitor V; | 697 Visitor V{Resolver}; |
642 V.Visit(D); | 698 V.Visit(D); |
643 return V.Refs; | 699 return V.Refs; |
644 } | 700 } |
645 | 701 |
646 llvm::SmallVector<ReferenceLoc, 2> refInStmt(const Stmt *S) { | 702 llvm::SmallVector<ReferenceLoc> refInStmt(const Stmt *S, |
703 const HeuristicResolver *Resolver) { | |
647 struct Visitor : ConstStmtVisitor<Visitor> { | 704 struct Visitor : ConstStmtVisitor<Visitor> { |
705 Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {} | |
706 | |
707 const HeuristicResolver *Resolver; | |
648 // FIXME: handle more complicated cases: more ObjC, designated initializers. | 708 // FIXME: handle more complicated cases: more ObjC, designated initializers. |
649 llvm::SmallVector<ReferenceLoc, 2> Refs; | 709 llvm::SmallVector<ReferenceLoc> Refs; |
650 | 710 |
651 void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) { | 711 void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) { |
652 Refs.push_back(ReferenceLoc{E->getNestedNameSpecifierLoc(), | 712 Refs.push_back(ReferenceLoc{E->getNestedNameSpecifierLoc(), |
653 E->getConceptNameLoc(), | 713 E->getConceptNameLoc(), |
654 /*IsDecl=*/false, | 714 /*IsDecl=*/false, |
663 } | 723 } |
664 | 724 |
665 void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { | 725 void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { |
666 Refs.push_back(ReferenceLoc{ | 726 Refs.push_back(ReferenceLoc{ |
667 E->getQualifierLoc(), E->getNameInfo().getLoc(), /*IsDecl=*/false, | 727 E->getQualifierLoc(), E->getNameInfo().getLoc(), /*IsDecl=*/false, |
668 explicitReferenceTargets(DynTypedNode::create(*E), {})}); | 728 explicitReferenceTargets(DynTypedNode::create(*E), {}, Resolver)}); |
669 } | 729 } |
670 | 730 |
671 void VisitMemberExpr(const MemberExpr *E) { | 731 void VisitMemberExpr(const MemberExpr *E) { |
672 // Skip destructor calls to avoid duplication: TypeLoc within will be | 732 // Skip destructor calls to avoid duplication: TypeLoc within will be |
673 // visited separately. | 733 // visited separately. |
674 if (llvm::dyn_cast<CXXDestructorDecl>(E->getFoundDecl().getDecl())) | 734 if (llvm::isa<CXXDestructorDecl>(E->getFoundDecl().getDecl())) |
675 return; | 735 return; |
676 Refs.push_back(ReferenceLoc{E->getQualifierLoc(), | 736 Refs.push_back(ReferenceLoc{E->getQualifierLoc(), |
677 E->getMemberNameInfo().getLoc(), | 737 E->getMemberNameInfo().getLoc(), |
678 /*IsDecl=*/false, | 738 /*IsDecl=*/false, |
679 {E->getFoundDecl()}}); | 739 {E->getFoundDecl()}}); |
680 } | 740 } |
681 | 741 |
682 void | 742 void |
683 VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { | 743 VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { |
684 Refs.push_back( | 744 Refs.push_back(ReferenceLoc{ |
685 ReferenceLoc{E->getQualifierLoc(), E->getMemberNameInfo().getLoc(), | 745 E->getQualifierLoc(), E->getMemberNameInfo().getLoc(), |
686 /*IsDecl=*/false, | 746 /*IsDecl=*/false, |
687 explicitReferenceTargets(DynTypedNode::create(*E), {})}); | 747 explicitReferenceTargets(DynTypedNode::create(*E), {}, Resolver)}); |
688 } | 748 } |
689 | 749 |
690 void VisitOverloadExpr(const OverloadExpr *E) { | 750 void VisitOverloadExpr(const OverloadExpr *E) { |
691 Refs.push_back(ReferenceLoc{E->getQualifierLoc(), | 751 Refs.push_back(ReferenceLoc{E->getQualifierLoc(), |
692 E->getNameInfo().getLoc(), | 752 E->getNameInfo().getLoc(), |
705 void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) { | 765 void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) { |
706 Refs.push_back(ReferenceLoc{ | 766 Refs.push_back(ReferenceLoc{ |
707 NestedNameSpecifierLoc(), E->getLocation(), | 767 NestedNameSpecifierLoc(), E->getLocation(), |
708 /*IsDecl=*/false, | 768 /*IsDecl=*/false, |
709 // Select the getter, setter, or @property depending on the call. | 769 // Select the getter, setter, or @property depending on the call. |
710 explicitReferenceTargets(DynTypedNode::create(*E), {})}); | 770 explicitReferenceTargets(DynTypedNode::create(*E), {}, Resolver)}); |
771 } | |
772 | |
773 void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) { | |
774 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
775 OIRE->getLocation(), | |
776 /*IsDecl=*/false, | |
777 {OIRE->getDecl()}}); | |
778 } | |
779 | |
780 void VisitObjCMessageExpr(const ObjCMessageExpr *E) { | |
781 // The name may have several tokens, we can only report the first. | |
782 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
783 E->getSelectorStartLoc(), | |
784 /*IsDecl=*/false, | |
785 {E->getMethodDecl()}}); | |
711 } | 786 } |
712 | 787 |
713 void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) { | 788 void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) { |
714 for (const DesignatedInitExpr::Designator &D : DIE->designators()) { | 789 for (const DesignatedInitExpr::Designator &D : DIE->designators()) { |
715 if (!D.isFieldDesignator()) | 790 if (!D.isFieldDesignator()) |
716 continue; | 791 continue; |
717 | 792 |
718 llvm::SmallVector<const NamedDecl *, 1> Targets; | 793 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), |
719 if (D.getField()) | 794 D.getFieldLoc(), |
720 Targets.push_back(D.getField()); | 795 /*IsDecl=*/false, |
721 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), D.getFieldLoc(), | 796 {D.getField()}}); |
722 /*IsDecl=*/false, std::move(Targets)}); | |
723 } | 797 } |
724 } | 798 } |
725 | 799 |
726 void VisitGotoStmt(const GotoStmt *GS) { | 800 void VisitGotoStmt(const GotoStmt *GS) { |
727 llvm::SmallVector<const NamedDecl *, 1> Targets; | 801 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), |
728 if (const auto *L = GS->getLabel()) | 802 GS->getLabelLoc(), |
729 Targets.push_back(L); | 803 /*IsDecl=*/false, |
730 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), GS->getLabelLoc(), | 804 {GS->getLabel()}}); |
731 /*IsDecl=*/false, std::move(Targets)}); | |
732 } | 805 } |
733 | 806 |
734 void VisitLabelStmt(const LabelStmt *LS) { | 807 void VisitLabelStmt(const LabelStmt *LS) { |
735 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | 808 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), |
736 LS->getIdentLoc(), | 809 LS->getIdentLoc(), |
737 /*IsDecl=*/true, | 810 /*IsDecl=*/true, |
738 {LS->getDecl()}}); | 811 {LS->getDecl()}}); |
739 } | 812 } |
740 }; | 813 }; |
741 | 814 |
742 Visitor V; | 815 Visitor V{Resolver}; |
743 V.Visit(S); | 816 V.Visit(S); |
744 return V.Refs; | 817 return V.Refs; |
745 } | 818 } |
746 | 819 |
747 llvm::SmallVector<ReferenceLoc, 2> refInTypeLoc(TypeLoc L) { | 820 llvm::SmallVector<ReferenceLoc> |
821 refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) { | |
748 struct Visitor : TypeLocVisitor<Visitor> { | 822 struct Visitor : TypeLocVisitor<Visitor> { |
749 llvm::Optional<ReferenceLoc> Ref; | 823 Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {} |
824 | |
825 const HeuristicResolver *Resolver; | |
826 llvm::SmallVector<ReferenceLoc> Refs; | |
750 | 827 |
751 void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) { | 828 void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) { |
752 // We only know about qualifier, rest if filled by inner locations. | 829 // We only know about qualifier, rest if filled by inner locations. |
830 size_t InitialSize = Refs.size(); | |
753 Visit(L.getNamedTypeLoc().getUnqualifiedLoc()); | 831 Visit(L.getNamedTypeLoc().getUnqualifiedLoc()); |
754 // Fill in the qualifier. | 832 size_t NewSize = Refs.size(); |
755 if (!Ref) | 833 // Add qualifier for the newly-added refs. |
756 return; | 834 for (unsigned I = InitialSize; I < NewSize; ++I) { |
757 assert(!Ref->Qualifier.hasQualifier() && "qualifier already set"); | 835 ReferenceLoc *Ref = &Refs[I]; |
758 Ref->Qualifier = L.getQualifierLoc(); | 836 // Fill in the qualifier. |
837 assert(!Ref->Qualifier.hasQualifier() && "qualifier already set"); | |
838 Ref->Qualifier = L.getQualifierLoc(); | |
839 } | |
759 } | 840 } |
760 | 841 |
761 void VisitTagTypeLoc(TagTypeLoc L) { | 842 void VisitTagTypeLoc(TagTypeLoc L) { |
762 Ref = ReferenceLoc{NestedNameSpecifierLoc(), | 843 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), |
763 L.getNameLoc(), | 844 L.getNameLoc(), |
764 /*IsDecl=*/false, | 845 /*IsDecl=*/false, |
765 {L.getDecl()}}; | 846 {L.getDecl()}}); |
766 } | 847 } |
767 | 848 |
768 void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) { | 849 void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) { |
769 Ref = ReferenceLoc{NestedNameSpecifierLoc(), | 850 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), |
770 L.getNameLoc(), | 851 L.getNameLoc(), |
771 /*IsDecl=*/false, | 852 /*IsDecl=*/false, |
772 {L.getDecl()}}; | 853 {L.getDecl()}}); |
773 } | 854 } |
774 | 855 |
775 void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) { | 856 void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) { |
776 // We must ensure template type aliases are included in results if they | 857 // We must ensure template type aliases are included in results if they |
777 // were written in the source code, e.g. in | 858 // were written in the source code, e.g. in |
779 // ^valias<int> x; | 860 // ^valias<int> x; |
780 // 'explicitReferenceTargets' will return: | 861 // 'explicitReferenceTargets' will return: |
781 // 1. valias with mask 'Alias'. | 862 // 1. valias with mask 'Alias'. |
782 // 2. 'vector<int>' with mask 'Underlying'. | 863 // 2. 'vector<int>' with mask 'Underlying'. |
783 // we want to return only #1 in this case. | 864 // we want to return only #1 in this case. |
784 Ref = ReferenceLoc{ | 865 Refs.push_back(ReferenceLoc{ |
785 NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false, | 866 NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false, |
786 explicitReferenceTargets(DynTypedNode::create(L.getType()), | 867 explicitReferenceTargets(DynTypedNode::create(L.getType()), |
787 DeclRelation::Alias)}; | 868 DeclRelation::Alias, Resolver)}); |
788 } | 869 } |
789 void VisitDeducedTemplateSpecializationTypeLoc( | 870 void VisitDeducedTemplateSpecializationTypeLoc( |
790 DeducedTemplateSpecializationTypeLoc L) { | 871 DeducedTemplateSpecializationTypeLoc L) { |
791 Ref = ReferenceLoc{ | 872 Refs.push_back(ReferenceLoc{ |
792 NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false, | 873 NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false, |
793 explicitReferenceTargets(DynTypedNode::create(L.getType()), | 874 explicitReferenceTargets(DynTypedNode::create(L.getType()), |
794 DeclRelation::Alias)}; | 875 DeclRelation::Alias, Resolver)}); |
795 } | 876 } |
796 | 877 |
797 void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { | 878 void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { |
798 Ref = ReferenceLoc{NestedNameSpecifierLoc(), | 879 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), |
799 TL.getNameLoc(), | 880 TL.getNameLoc(), |
800 /*IsDecl=*/false, | 881 /*IsDecl=*/false, |
801 {TL.getDecl()}}; | 882 {TL.getDecl()}}); |
802 } | 883 } |
803 | 884 |
804 void VisitDependentTemplateSpecializationTypeLoc( | 885 void VisitDependentTemplateSpecializationTypeLoc( |
805 DependentTemplateSpecializationTypeLoc L) { | 886 DependentTemplateSpecializationTypeLoc L) { |
806 Ref = ReferenceLoc{ | 887 Refs.push_back( |
807 L.getQualifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false, | 888 ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(), |
808 explicitReferenceTargets(DynTypedNode::create(L.getType()), {})}; | 889 /*IsDecl=*/false, |
890 explicitReferenceTargets( | |
891 DynTypedNode::create(L.getType()), {}, Resolver)}); | |
809 } | 892 } |
810 | 893 |
811 void VisitDependentNameTypeLoc(DependentNameTypeLoc L) { | 894 void VisitDependentNameTypeLoc(DependentNameTypeLoc L) { |
812 Ref = ReferenceLoc{ | 895 Refs.push_back( |
813 L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false, | 896 ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), |
814 explicitReferenceTargets(DynTypedNode::create(L.getType()), {})}; | 897 /*IsDecl=*/false, |
898 explicitReferenceTargets( | |
899 DynTypedNode::create(L.getType()), {}, Resolver)}); | |
815 } | 900 } |
816 | 901 |
817 void VisitTypedefTypeLoc(TypedefTypeLoc L) { | 902 void VisitTypedefTypeLoc(TypedefTypeLoc L) { |
818 Ref = ReferenceLoc{NestedNameSpecifierLoc(), | 903 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), |
819 L.getNameLoc(), | 904 L.getNameLoc(), |
820 /*IsDecl=*/false, | 905 /*IsDecl=*/false, |
821 {L.getTypedefNameDecl()}}; | 906 {L.getTypedefNameDecl()}}); |
907 } | |
908 | |
909 void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) { | |
910 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
911 L.getNameLoc(), | |
912 /*IsDecl=*/false, | |
913 {L.getIFaceDecl()}}); | |
914 } | |
915 | |
916 void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc L) { | |
917 unsigned NumProtocols = L.getNumProtocols(); | |
918 for (unsigned I = 0; I < NumProtocols; I++) { | |
919 Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), | |
920 L.getProtocolLoc(I), | |
921 /*IsDecl=*/false, | |
922 {L.getProtocol(I)}}); | |
923 } | |
822 } | 924 } |
823 }; | 925 }; |
824 | 926 |
825 Visitor V; | 927 Visitor V{Resolver}; |
826 V.Visit(L.getUnqualifiedLoc()); | 928 V.Visit(L.getUnqualifiedLoc()); |
827 if (!V.Ref) | 929 return V.Refs; |
828 return {}; | |
829 return {*V.Ref}; | |
830 } | 930 } |
831 | 931 |
832 class ExplicitReferenceCollector | 932 class ExplicitReferenceCollector |
833 : public RecursiveASTVisitor<ExplicitReferenceCollector> { | 933 : public RecursiveASTVisitor<ExplicitReferenceCollector> { |
834 public: | 934 public: |
835 ExplicitReferenceCollector(llvm::function_ref<void(ReferenceLoc)> Out) | 935 ExplicitReferenceCollector(llvm::function_ref<void(ReferenceLoc)> Out, |
836 : Out(Out) { | 936 const HeuristicResolver *Resolver) |
937 : Out(Out), Resolver(Resolver) { | |
837 assert(Out); | 938 assert(Out); |
838 } | 939 } |
839 | 940 |
840 bool VisitTypeLoc(TypeLoc TTL) { | 941 bool VisitTypeLoc(TypeLoc TTL) { |
841 if (TypeLocsToSkip.count(TTL.getBeginLoc().getRawEncoding())) | 942 if (TypeLocsToSkip.count(TTL.getBeginLoc())) |
842 return true; | 943 return true; |
843 visitNode(DynTypedNode::create(TTL)); | 944 visitNode(DynTypedNode::create(TTL)); |
844 return true; | 945 return true; |
845 } | 946 } |
846 | 947 |
847 bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc L) { | 948 bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc L) { |
848 // ElaboratedTypeLoc will reports information for its inner type loc. | 949 // ElaboratedTypeLoc will reports information for its inner type loc. |
849 // Otherwise we loose information about inner types loc's qualifier. | 950 // Otherwise we loose information about inner types loc's qualifier. |
850 TypeLoc Inner = L.getNamedTypeLoc().getUnqualifiedLoc(); | 951 TypeLoc Inner = L.getNamedTypeLoc().getUnqualifiedLoc(); |
851 TypeLocsToSkip.insert(Inner.getBeginLoc().getRawEncoding()); | 952 TypeLocsToSkip.insert(Inner.getBeginLoc()); |
852 return RecursiveASTVisitor::TraverseElaboratedTypeLoc(L); | 953 return RecursiveASTVisitor::TraverseElaboratedTypeLoc(L); |
853 } | 954 } |
854 | 955 |
855 bool VisitStmt(Stmt *S) { | 956 bool VisitStmt(Stmt *S) { |
856 visitNode(DynTypedNode::create(*S)); | 957 visitNode(DynTypedNode::create(*S)); |
873 | 974 |
874 // We re-define Traverse*, since there's no corresponding Visit*. | 975 // We re-define Traverse*, since there's no corresponding Visit*. |
875 // TemplateArgumentLoc is the only way to get locations for references to | 976 // TemplateArgumentLoc is the only way to get locations for references to |
876 // template template parameters. | 977 // template template parameters. |
877 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc A) { | 978 bool TraverseTemplateArgumentLoc(TemplateArgumentLoc A) { |
878 llvm::SmallVector<const NamedDecl *, 1> Targets; | |
879 switch (A.getArgument().getKind()) { | 979 switch (A.getArgument().getKind()) { |
880 case TemplateArgument::Template: | 980 case TemplateArgument::Template: |
881 case TemplateArgument::TemplateExpansion: | 981 case TemplateArgument::TemplateExpansion: |
882 if (const auto *D = A.getArgument() | |
883 .getAsTemplateOrTemplatePattern() | |
884 .getAsTemplateDecl()) | |
885 Targets.push_back(D); | |
886 reportReference(ReferenceLoc{A.getTemplateQualifierLoc(), | 982 reportReference(ReferenceLoc{A.getTemplateQualifierLoc(), |
887 A.getTemplateNameLoc(), | 983 A.getTemplateNameLoc(), |
888 /*IsDecl=*/false, Targets}, | 984 /*IsDecl=*/false, |
985 {A.getArgument() | |
986 .getAsTemplateOrTemplatePattern() | |
987 .getAsTemplateDecl()}}, | |
889 DynTypedNode::create(A.getArgument())); | 988 DynTypedNode::create(A.getArgument())); |
890 break; | 989 break; |
891 case TemplateArgument::Declaration: | 990 case TemplateArgument::Declaration: |
892 break; // FIXME: can this actually happen in TemplateArgumentLoc? | 991 break; // FIXME: can this actually happen in TemplateArgumentLoc? |
893 case TemplateArgument::Integral: | 992 case TemplateArgument::Integral: |
912 if (!L.getNestedNameSpecifier()) | 1011 if (!L.getNestedNameSpecifier()) |
913 return true; | 1012 return true; |
914 visitNode(DynTypedNode::create(L)); | 1013 visitNode(DynTypedNode::create(L)); |
915 // Inner type is missing information about its qualifier, skip it. | 1014 // Inner type is missing information about its qualifier, skip it. |
916 if (auto TL = L.getTypeLoc()) | 1015 if (auto TL = L.getTypeLoc()) |
917 TypeLocsToSkip.insert(TL.getBeginLoc().getRawEncoding()); | 1016 TypeLocsToSkip.insert(TL.getBeginLoc()); |
918 return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(L); | 1017 return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(L); |
919 } | 1018 } |
920 | 1019 |
921 bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { | 1020 bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { |
922 visitNode(DynTypedNode::create(*Init)); | 1021 visitNode(DynTypedNode::create(*Init)); |
936 /// | 1035 /// |
937 /// (!) For the purposes of this function declarations are not considered to | 1036 /// (!) For the purposes of this function declarations are not considered to |
938 /// be references. However, declarations can have references inside them, | 1037 /// be references. However, declarations can have references inside them, |
939 /// e.g. 'namespace foo = std' references namespace 'std' and this | 1038 /// e.g. 'namespace foo = std' references namespace 'std' and this |
940 /// function will return the corresponding reference. | 1039 /// function will return the corresponding reference. |
941 llvm::SmallVector<ReferenceLoc, 2> explicitReference(DynTypedNode N) { | 1040 llvm::SmallVector<ReferenceLoc> explicitReference(DynTypedNode N) { |
942 if (auto *D = N.get<Decl>()) | 1041 if (auto *D = N.get<Decl>()) |
943 return refInDecl(D); | 1042 return refInDecl(D, Resolver); |
944 if (auto *S = N.get<Stmt>()) | 1043 if (auto *S = N.get<Stmt>()) |
945 return refInStmt(S); | 1044 return refInStmt(S, Resolver); |
946 if (auto *NNSL = N.get<NestedNameSpecifierLoc>()) { | 1045 if (auto *NNSL = N.get<NestedNameSpecifierLoc>()) { |
947 // (!) 'DeclRelation::Alias' ensures we do not loose namespace aliases. | 1046 // (!) 'DeclRelation::Alias' ensures we do not loose namespace aliases. |
948 return {ReferenceLoc{ | 1047 return {ReferenceLoc{ |
949 NNSL->getPrefix(), NNSL->getLocalBeginLoc(), false, | 1048 NNSL->getPrefix(), NNSL->getLocalBeginLoc(), false, |
950 explicitReferenceTargets( | 1049 explicitReferenceTargets( |
951 DynTypedNode::create(*NNSL->getNestedNameSpecifier()), | 1050 DynTypedNode::create(*NNSL->getNestedNameSpecifier()), |
952 DeclRelation::Alias)}}; | 1051 DeclRelation::Alias, Resolver)}}; |
953 } | 1052 } |
954 if (const TypeLoc *TL = N.get<TypeLoc>()) | 1053 if (const TypeLoc *TL = N.get<TypeLoc>()) |
955 return refInTypeLoc(*TL); | 1054 return refInTypeLoc(*TL, Resolver); |
956 if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) { | 1055 if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) { |
957 // Other type initializers (e.g. base initializer) are handled by visiting | 1056 // Other type initializers (e.g. base initializer) are handled by visiting |
958 // the typeLoc. | 1057 // the typeLoc. |
959 if (CCI->isAnyMemberInitializer()) { | 1058 if (CCI->isAnyMemberInitializer()) { |
960 return {ReferenceLoc{NestedNameSpecifierLoc(), | 1059 return {ReferenceLoc{NestedNameSpecifierLoc(), |
966 // We do not have location information for other nodes (QualType, etc) | 1065 // We do not have location information for other nodes (QualType, etc) |
967 return {}; | 1066 return {}; |
968 } | 1067 } |
969 | 1068 |
970 void visitNode(DynTypedNode N) { | 1069 void visitNode(DynTypedNode N) { |
971 for (const auto &R : explicitReference(N)) | 1070 for (auto &R : explicitReference(N)) |
972 reportReference(R, N); | 1071 reportReference(std::move(R), N); |
973 } | 1072 } |
974 | 1073 |
975 void reportReference(const ReferenceLoc &Ref, DynTypedNode N) { | 1074 void reportReference(ReferenceLoc &&Ref, DynTypedNode N) { |
1075 // Strip null targets that can arise from invalid code. | |
1076 // (This avoids having to check for null everywhere we insert) | |
1077 llvm::erase_value(Ref.Targets, nullptr); | |
976 // Our promise is to return only references from the source code. If we lack | 1078 // Our promise is to return only references from the source code. If we lack |
977 // location information, skip these nodes. | 1079 // location information, skip these nodes. |
978 // Normally this should not happen in practice, unless there are bugs in the | 1080 // Normally this should not happen in practice, unless there are bugs in the |
979 // traversals or users started the traversal at an implicit node. | 1081 // traversals or users started the traversal at an implicit node. |
980 if (Ref.NameLoc.isInvalid()) { | 1082 if (Ref.NameLoc.isInvalid()) { |
983 } | 1085 } |
984 Out(Ref); | 1086 Out(Ref); |
985 } | 1087 } |
986 | 1088 |
987 llvm::function_ref<void(ReferenceLoc)> Out; | 1089 llvm::function_ref<void(ReferenceLoc)> Out; |
1090 const HeuristicResolver *Resolver; | |
988 /// TypeLocs starting at these locations must be skipped, see | 1091 /// TypeLocs starting at these locations must be skipped, see |
989 /// TraverseElaboratedTypeSpecifierLoc for details. | 1092 /// TraverseElaboratedTypeSpecifierLoc for details. |
990 llvm::DenseSet</*SourceLocation*/ unsigned> TypeLocsToSkip; | 1093 llvm::DenseSet<SourceLocation> TypeLocsToSkip; |
991 }; | 1094 }; |
992 } // namespace | 1095 } // namespace |
993 | 1096 |
994 void findExplicitReferences(const Stmt *S, | 1097 void findExplicitReferences(const Stmt *S, |
995 llvm::function_ref<void(ReferenceLoc)> Out) { | 1098 llvm::function_ref<void(ReferenceLoc)> Out, |
1099 const HeuristicResolver *Resolver) { | |
996 assert(S); | 1100 assert(S); |
997 ExplicitReferenceCollector(Out).TraverseStmt(const_cast<Stmt *>(S)); | 1101 ExplicitReferenceCollector(Out, Resolver).TraverseStmt(const_cast<Stmt *>(S)); |
998 } | 1102 } |
999 void findExplicitReferences(const Decl *D, | 1103 void findExplicitReferences(const Decl *D, |
1000 llvm::function_ref<void(ReferenceLoc)> Out) { | 1104 llvm::function_ref<void(ReferenceLoc)> Out, |
1105 const HeuristicResolver *Resolver) { | |
1001 assert(D); | 1106 assert(D); |
1002 ExplicitReferenceCollector(Out).TraverseDecl(const_cast<Decl *>(D)); | 1107 ExplicitReferenceCollector(Out, Resolver).TraverseDecl(const_cast<Decl *>(D)); |
1003 } | 1108 } |
1004 void findExplicitReferences(const ASTContext &AST, | 1109 void findExplicitReferences(const ASTContext &AST, |
1005 llvm::function_ref<void(ReferenceLoc)> Out) { | 1110 llvm::function_ref<void(ReferenceLoc)> Out, |
1006 ExplicitReferenceCollector(Out).TraverseAST(const_cast<ASTContext &>(AST)); | 1111 const HeuristicResolver *Resolver) { |
1112 ExplicitReferenceCollector(Out, Resolver) | |
1113 .TraverseAST(const_cast<ASTContext &>(AST)); | |
1007 } | 1114 } |
1008 | 1115 |
1009 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, DeclRelation R) { | 1116 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, DeclRelation R) { |
1010 switch (R) { | 1117 switch (R) { |
1011 #define REL_CASE(X) \ | 1118 #define REL_CASE(X) \ |