]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Index / IndexingContext.cpp
1 //===- IndexingContext.cpp - Indexing context data ------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "IndexingContext.h"
11 #include "clang/Basic/SourceLocation.h"
12 #include "clang/Index/IndexDataConsumer.h"
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/DeclTemplate.h"
15 #include "clang/AST/DeclObjC.h"
16 #include "clang/Basic/SourceManager.h"
17
18 using namespace clang;
19 using namespace index;
20
21 static bool isGeneratedDecl(const Decl *D) {
22   if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
23     return attr->getGeneratedDeclaration();
24   }
25   return false;
26 }
27
28 bool IndexingContext::shouldIndex(const Decl *D) {
29   return !isGeneratedDecl(D);
30 }
31
32 const LangOptions &IndexingContext::getLangOpts() const {
33   return Ctx->getLangOpts();
34 }
35
36 bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
37   return IndexOpts.IndexFunctionLocals;
38 }
39
40 bool IndexingContext::shouldIndexImplicitInstantiation() const {
41   return IndexOpts.IndexImplicitInstantiation;
42 }
43
44 bool IndexingContext::handleDecl(const Decl *D,
45                                  SymbolRoleSet Roles,
46                                  ArrayRef<SymbolRelation> Relations) {
47   return handleDecl(D, D->getLocation(), Roles, Relations);
48 }
49
50 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
51                                  SymbolRoleSet Roles,
52                                  ArrayRef<SymbolRelation> Relations,
53                                  const DeclContext *DC) {
54   if (!DC)
55     DC = D->getDeclContext();
56
57   const Decl *OrigD = D;
58   if (isa<ObjCPropertyImplDecl>(D)) {
59     D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
60   }
61   return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
62                               Roles, Relations,
63                               nullptr, OrigD, DC);
64 }
65
66 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
67                                       const NamedDecl *Parent,
68                                       const DeclContext *DC,
69                                       SymbolRoleSet Roles,
70                                       ArrayRef<SymbolRelation> Relations,
71                                       const Expr *RefE,
72                                       const Decl *RefD) {
73   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
74     return true;
75
76   if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
77     return true;
78
79   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
80                               RefE, RefD, DC);
81 }
82
83 static void reportModuleReferences(const Module *Mod,
84                                    ArrayRef<SourceLocation> IdLocs,
85                                    const ImportDecl *ImportD,
86                                    IndexDataConsumer &DataConsumer) {
87   if (!Mod)
88     return;
89   reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
90                          DataConsumer);
91   DataConsumer.handleModuleOccurence(ImportD, Mod,
92                                      (SymbolRoleSet)SymbolRole::Reference,
93                                      IdLocs.back());
94 }
95
96 bool IndexingContext::importedModule(const ImportDecl *ImportD) {
97   if (ImportD->isInvalidDecl())
98     return true;
99
100   SourceLocation Loc;
101   auto IdLocs = ImportD->getIdentifierLocs();
102   if (!IdLocs.empty())
103     Loc = IdLocs.back();
104   else
105     Loc = ImportD->getLocation();
106
107   SourceManager &SM = Ctx->getSourceManager();
108   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
109   if (FID.isInvalid())
110     return true;
111
112   bool Invalid = false;
113   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
114   if (Invalid || !SEntry.isFile())
115     return true;
116
117   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
118     switch (IndexOpts.SystemSymbolFilter) {
119     case IndexingOptions::SystemSymbolFilterKind::None:
120       return true;
121     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
122     case IndexingOptions::SystemSymbolFilterKind::All:
123       break;
124     }
125   }
126
127   const Module *Mod = ImportD->getImportedModule();
128   if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
129     reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
130                            DataConsumer);
131   }
132
133   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
134   if (ImportD->isImplicit())
135     Roles |= (unsigned)SymbolRole::Implicit;
136
137   return DataConsumer.handleModuleOccurence(ImportD, Mod, Roles, Loc);
138 }
139
140 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
141   TemplateSpecializationKind TKind = TSK_Undeclared;
142   if (const ClassTemplateSpecializationDecl *
143       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
144     TKind = SD->getSpecializationKind();
145   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
146     TKind = FD->getTemplateSpecializationKind();
147   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
148     TKind = VD->getTemplateSpecializationKind();
149   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
150     if (RD->getInstantiatedFromMemberClass())
151       TKind = RD->getTemplateSpecializationKind();
152   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
153     if (ED->getInstantiatedFromMemberEnum())
154       TKind = ED->getTemplateSpecializationKind();
155   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
156              isa<EnumConstantDecl>(D)) {
157     if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
158       return isTemplateImplicitInstantiation(Parent);
159   }
160   switch (TKind) {
161     case TSK_Undeclared:
162     case TSK_ExplicitSpecialization:
163       return false;
164     case TSK_ImplicitInstantiation:
165     case TSK_ExplicitInstantiationDeclaration:
166     case TSK_ExplicitInstantiationDefinition:
167       return true;
168   }
169   llvm_unreachable("invalid TemplateSpecializationKind");
170 }
171
172 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
173   if (isa<ObjCInterfaceDecl>(D))
174     return false;
175   if (isa<ObjCCategoryDecl>(D))
176     return false;
177   if (isa<ObjCIvarDecl>(D))
178     return false;
179   if (isa<ObjCMethodDecl>(D))
180     return false;
181   if (isa<ImportDecl>(D))
182     return false;
183   return true;
184 }
185
186 static const CXXRecordDecl *
187 getDeclContextForTemplateInstationPattern(const Decl *D) {
188   if (const auto *CTSD =
189           dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
190     return CTSD->getTemplateInstantiationPattern();
191   else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
192     return RD->getInstantiatedFromMemberClass();
193   return nullptr;
194 }
195
196 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
197   if (const ClassTemplateSpecializationDecl *
198       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
199     return SD->getTemplateInstantiationPattern();
200   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
201     return FD->getTemplateInstantiationPattern();
202   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
203     return VD->getTemplateInstantiationPattern();
204   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
205     return RD->getInstantiatedFromMemberClass();
206   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
207     return ED->getInstantiatedFromMemberEnum();
208   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
209     const auto *ND = cast<NamedDecl>(D);
210     if (const CXXRecordDecl *Pattern =
211             getDeclContextForTemplateInstationPattern(ND)) {
212       for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
213         if (BaseND->isImplicit())
214           continue;
215         if (BaseND->getKind() == ND->getKind())
216           return BaseND;
217       }
218     }
219   } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
220     if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
221       if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
222         for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
223           return BaseECD;
224       }
225     }
226   }
227   return nullptr;
228 }
229
230 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
231   if (auto VD = dyn_cast<VarDecl>(D))
232     return VD->isThisDeclarationADefinition(Ctx);
233
234   if (auto FD = dyn_cast<FunctionDecl>(D))
235     return FD->isThisDeclarationADefinition();
236
237   if (auto TD = dyn_cast<TagDecl>(D))
238     return TD->isThisDeclarationADefinition();
239
240   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
241     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
242
243   if (isa<TypedefNameDecl>(D) ||
244       isa<EnumConstantDecl>(D) ||
245       isa<FieldDecl>(D) ||
246       isa<MSPropertyDecl>(D) ||
247       isa<ObjCImplDecl>(D) ||
248       isa<ObjCPropertyImplDecl>(D))
249     return true;
250
251   return false;
252 }
253
254 /// Whether the given NamedDecl should be skipped because it has no name.
255 static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
256   return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
257           !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
258 }
259
260 static const Decl *adjustParent(const Decl *Parent) {
261   if (!Parent)
262     return nullptr;
263   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
264     if (isa<TranslationUnitDecl>(Parent))
265       return nullptr;
266     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
267       continue;
268     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
269       if (NS->isAnonymousNamespace())
270         continue;
271     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
272       if (RD->isAnonymousStructOrUnion())
273         continue;
274     } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
275       if (shouldSkipNamelessDecl(ND))
276         continue;
277     }
278     return Parent;
279   }
280 }
281
282 static const Decl *getCanonicalDecl(const Decl *D) {
283   D = D->getCanonicalDecl();
284   if (auto TD = dyn_cast<TemplateDecl>(D)) {
285     if (auto TTD = TD->getTemplatedDecl()) {
286       D = TTD;
287       assert(D->isCanonicalDecl());
288     }
289   }
290
291   return D;
292 }
293
294 static bool shouldReportOccurrenceForSystemDeclOnlyMode(
295     bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
296   if (!IsRef)
297     return true;
298
299   auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
300     bool accept = false;
301     applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
302       switch (r) {
303       case SymbolRole::RelationChildOf:
304       case SymbolRole::RelationBaseOf:
305       case SymbolRole::RelationOverrideOf:
306       case SymbolRole::RelationExtendedBy:
307       case SymbolRole::RelationAccessorOf:
308       case SymbolRole::RelationIBTypeOf:
309         accept = true;
310         return false;
311       case SymbolRole::Declaration:
312       case SymbolRole::Definition:
313       case SymbolRole::Reference:
314       case SymbolRole::Read:
315       case SymbolRole::Write:
316       case SymbolRole::Call:
317       case SymbolRole::Dynamic:
318       case SymbolRole::AddressOf:
319       case SymbolRole::Implicit:
320       case SymbolRole::Undefinition:
321       case SymbolRole::RelationReceivedBy:
322       case SymbolRole::RelationCalledBy:
323       case SymbolRole::RelationContainedBy:
324       case SymbolRole::RelationSpecializationOf:
325         return true;
326       }
327       llvm_unreachable("Unsupported SymbolRole value!");
328     });
329     return accept;
330   };
331
332   for (auto &Rel : Relations) {
333     if (acceptForRelation(Rel.Roles))
334       return true;
335   }
336
337   return false;
338 }
339
340 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
341                                            bool IsRef, const Decl *Parent,
342                                            SymbolRoleSet Roles,
343                                            ArrayRef<SymbolRelation> Relations,
344                                            const Expr *OrigE,
345                                            const Decl *OrigD,
346                                            const DeclContext *ContainerDC) {
347   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
348     return true;
349   if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
350     return true;
351
352   SourceManager &SM = Ctx->getSourceManager();
353   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
354   if (FID.isInvalid())
355     return true;
356
357   bool Invalid = false;
358   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
359   if (Invalid || !SEntry.isFile())
360     return true;
361
362   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
363     switch (IndexOpts.SystemSymbolFilter) {
364     case IndexingOptions::SystemSymbolFilterKind::None:
365       return true;
366     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
367       if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
368         return true;
369       break;
370     case IndexingOptions::SystemSymbolFilterKind::All:
371       break;
372     }
373   }
374
375   if (!OrigD)
376     OrigD = D;
377
378   if (isTemplateImplicitInstantiation(D)) {
379     if (!IsRef)
380       return true;
381     D = adjustTemplateImplicitInstantiation(D);
382     if (!D)
383       return true;
384     assert(!isTemplateImplicitInstantiation(D));
385   }
386
387   if (IsRef)
388     Roles |= (unsigned)SymbolRole::Reference;
389   else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
390     Roles |= (unsigned)SymbolRole::Definition;
391   else
392     Roles |= (unsigned)SymbolRole::Declaration;
393
394   D = getCanonicalDecl(D);
395   Parent = adjustParent(Parent);
396   if (Parent)
397     Parent = getCanonicalDecl(Parent);
398
399   SmallVector<SymbolRelation, 6> FinalRelations;
400   FinalRelations.reserve(Relations.size()+1);
401
402   auto addRelation = [&](SymbolRelation Rel) {
403     auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
404                 [&](SymbolRelation Elem)->bool {
405                   return Elem.RelatedSymbol == Rel.RelatedSymbol;
406                 });
407     if (It != FinalRelations.end()) {
408       It->Roles |= Rel.Roles;
409     } else {
410       FinalRelations.push_back(Rel);
411     }
412     Roles |= Rel.Roles;
413   };
414
415   if (Parent) {
416     if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
417       addRelation(SymbolRelation{
418         (unsigned)SymbolRole::RelationContainedBy,
419         Parent
420       });
421     } else {
422       addRelation(SymbolRelation{
423         (unsigned)SymbolRole::RelationChildOf,
424         Parent
425       });
426     }
427   }
428
429   for (auto &Rel : Relations) {
430     addRelation(SymbolRelation(Rel.Roles,
431                                Rel.RelatedSymbol->getCanonicalDecl()));
432   }
433
434   IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
435   return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node);
436 }
437
438 void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
439                                          SourceLocation Loc,
440                                          const MacroInfo &MI) {
441   SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
442   DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
443 }
444
445 void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
446                                            SourceLocation Loc,
447                                            const MacroInfo &MI) {
448   SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
449   DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
450 }
451
452 void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
453                                            SourceLocation Loc,
454                                            const MacroInfo &MI) {
455   SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
456   DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc);
457 }