3535#include " llvm/Support/Compiler.h"
3636#include " llvm/Support/raw_ostream.h"
3737#include < utility>
38+ #include < vector>
3839
3940namespace clang {
4041namespace clangd {
@@ -134,6 +135,35 @@ const Type *getPointeeType(const Type *T) {
134135 return FirstArg.getAsType ().getTypePtrOrNull ();
135136}
136137
138+ const NamedDecl *getTemplatePattern (const NamedDecl *D) {
139+ if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
140+ return CRD->getTemplateInstantiationPattern ();
141+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
142+ return FD->getTemplateInstantiationPattern ();
143+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
144+ // Hmm: getTIP returns its arg if it's not an instantiation?!
145+ VarDecl *T = VD->getTemplateInstantiationPattern ();
146+ return (T == D) ? nullptr : T;
147+ } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
148+ return ED->getInstantiatedFromMemberEnum ();
149+ } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
150+ if (const auto *Parent = llvm::dyn_cast<NamedDecl>(D->getDeclContext ()))
151+ if (const DeclContext *ParentPat =
152+ dyn_cast_or_null<DeclContext>(getTemplatePattern (Parent)))
153+ for (const NamedDecl *BaseND : ParentPat->lookup (D->getDeclName ()))
154+ if (!BaseND->isImplicit () && BaseND->getKind () == D->getKind ())
155+ return BaseND;
156+ } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
157+ if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext ())) {
158+ if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum ()) {
159+ for (const NamedDecl *BaseECD : Pattern->lookup (ECD->getDeclName ()))
160+ return BaseECD;
161+ }
162+ }
163+ }
164+ return nullptr ;
165+ }
166+
137167// TargetFinder locates the entities that an AST node refers to.
138168//
139169// Typically this is (possibly) one declaration and (possibly) one type, but
@@ -167,37 +197,12 @@ const Type *getPointeeType(const Type *T) {
167197struct TargetFinder {
168198 using RelSet = DeclRelationSet;
169199 using Rel = DeclRelation;
170- llvm::SmallDenseMap<const NamedDecl *, RelSet> Decls;
171- RelSet Flags;
172200
173- static const NamedDecl *getTemplatePattern (const NamedDecl *D) {
174- if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
175- return CRD->getTemplateInstantiationPattern ();
176- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
177- return FD->getTemplateInstantiationPattern ();
178- } else if (auto *VD = dyn_cast<VarDecl>(D)) {
179- // Hmm: getTIP returns its arg if it's not an instantiation?!
180- VarDecl *T = VD->getTemplateInstantiationPattern ();
181- return (T == D) ? nullptr : T;
182- } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
183- return ED->getInstantiatedFromMemberEnum ();
184- } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
185- if (const auto *Parent = llvm::dyn_cast<NamedDecl>(D->getDeclContext ()))
186- if (const DeclContext *ParentPat =
187- dyn_cast_or_null<DeclContext>(getTemplatePattern (Parent)))
188- for (const NamedDecl *BaseND : ParentPat->lookup (D->getDeclName ()))
189- if (!BaseND->isImplicit () && BaseND->getKind () == D->getKind ())
190- return BaseND;
191- } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
192- if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext ())) {
193- if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum ()) {
194- for (const NamedDecl *BaseECD : Pattern->lookup (ECD->getDeclName ()))
195- return BaseECD;
196- }
197- }
198- }
199- return nullptr ;
200- }
201+ private:
202+ llvm::SmallDenseMap<const NamedDecl *,
203+ std::pair<RelSet, /* InsertionOrder*/ size_t >>
204+ Decls;
205+ RelSet Flags;
201206
202207 template <typename T> void debug (T &Node, RelSet Flags) {
203208 dlog (" visit [{0}] {1}" , Flags,
@@ -207,10 +212,22 @@ struct TargetFinder {
207212 void report (const NamedDecl *D, RelSet Flags) {
208213 dlog (" --> [{0}] {1}" , Flags,
209214 nodeToString (ast_type_traits::DynTypedNode::create (*D)));
210- Decls[D] |= Flags;
215+ auto It = Decls.try_emplace (D, std::make_pair (Flags, Decls.size ()));
216+ // If already exists, update the flags.
217+ if (!It.second )
218+ It.first ->second .first |= Flags;
211219 }
212220
213221public:
222+ llvm::SmallVector<std::pair<const NamedDecl *, RelSet>, 1 > takeDecls () const {
223+ using ValTy = std::pair<const NamedDecl *, RelSet>;
224+ llvm::SmallVector<ValTy, 1 > Result;
225+ Result.resize (Decls.size ());
226+ for (const auto &Elem : Decls)
227+ Result[Elem.second .second ] = {Elem.first , Elem.second .first };
228+ return Result;
229+ }
230+
214231 void add (const Decl *Dcl, RelSet Flags) {
215232 const NamedDecl *D = llvm::dyn_cast<NamedDecl>(Dcl);
216233 if (!D)
@@ -485,7 +502,7 @@ allTargetDecls(const ast_type_traits::DynTypedNode &N) {
485502 else if (const CXXCtorInitializer *CCI = N.get <CXXCtorInitializer>())
486503 Finder.add (CCI, Flags);
487504
488- return { Finder.Decls . begin (), Finder. Decls . end ()} ;
505+ return Finder.takeDecls () ;
489506}
490507
491508llvm::SmallVector<const NamedDecl *, 1 >
0 commit comments