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