1 //===- IndexingContext.cpp - Indexing context data ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "IndexingContext.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"
17 using namespace clang;
18 using namespace index;
20 bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
21 return IndexOpts.IndexFunctionLocals;
24 bool IndexingContext::handleDecl(const Decl *D,
26 ArrayRef<SymbolRelation> Relations) {
27 return handleDecl(D, D->getLocation(), Roles, Relations);
30 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
32 ArrayRef<SymbolRelation> Relations,
33 const DeclContext *DC) {
35 DC = D->getDeclContext();
37 const Decl *OrigD = D;
38 if (isa<ObjCPropertyImplDecl>(D)) {
39 D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
41 return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
46 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
47 const NamedDecl *Parent,
48 const DeclContext *DC,
50 ArrayRef<SymbolRelation> Relations,
53 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
56 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
59 return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
63 bool IndexingContext::importedModule(const ImportDecl *ImportD) {
65 auto IdLocs = ImportD->getIdentifierLocs();
69 Loc = ImportD->getLocation();
70 SourceManager &SM = Ctx->getSourceManager();
71 Loc = SM.getFileLoc(Loc);
77 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
82 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
83 if (Invalid || !SEntry.isFile())
86 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
87 switch (IndexOpts.SystemSymbolFilter) {
88 case IndexingOptions::SystemSymbolFilterKind::None:
90 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
91 case IndexingOptions::SystemSymbolFilterKind::All:
96 SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
97 if (ImportD->isImplicit())
98 Roles |= (unsigned)SymbolRole::Implicit;
100 return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
103 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
104 TemplateSpecializationKind TKind = TSK_Undeclared;
105 if (const ClassTemplateSpecializationDecl *
106 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
107 TKind = SD->getSpecializationKind();
108 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
109 TKind = FD->getTemplateSpecializationKind();
110 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
111 TKind = VD->getTemplateSpecializationKind();
115 case TSK_ExplicitSpecialization:
117 case TSK_ImplicitInstantiation:
118 case TSK_ExplicitInstantiationDeclaration:
119 case TSK_ExplicitInstantiationDefinition:
122 llvm_unreachable("invalid TemplateSpecializationKind");
125 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
126 if (isa<ObjCInterfaceDecl>(D))
128 if (isa<ObjCCategoryDecl>(D))
130 if (isa<ObjCIvarDecl>(D))
132 if (isa<ObjCMethodDecl>(D))
134 if (isa<ImportDecl>(D))
139 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
140 if (const ClassTemplateSpecializationDecl *
141 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
142 return SD->getTemplateInstantiationPattern();
143 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
144 return FD->getTemplateInstantiationPattern();
145 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
146 return VD->getTemplateInstantiationPattern();
151 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
152 if (auto VD = dyn_cast<VarDecl>(D))
153 return VD->isThisDeclarationADefinition(Ctx);
155 if (auto FD = dyn_cast<FunctionDecl>(D))
156 return FD->isThisDeclarationADefinition();
158 if (auto TD = dyn_cast<TagDecl>(D))
159 return TD->isThisDeclarationADefinition();
161 if (auto MD = dyn_cast<ObjCMethodDecl>(D))
162 return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
164 if (isa<TypedefNameDecl>(D) ||
165 isa<EnumConstantDecl>(D) ||
167 isa<MSPropertyDecl>(D) ||
168 isa<ObjCImplDecl>(D) ||
169 isa<ObjCPropertyImplDecl>(D))
175 static const Decl *adjustParent(const Decl *Parent) {
178 for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
179 if (isa<TranslationUnitDecl>(Parent))
181 if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
183 if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
184 if (NS->isAnonymousNamespace())
186 } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
187 if (RD->isAnonymousStructOrUnion())
189 } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
190 if (FD->getDeclName().isEmpty())
197 static const Decl *getCanonicalDecl(const Decl *D) {
198 D = D->getCanonicalDecl();
199 if (auto TD = dyn_cast<TemplateDecl>(D)) {
200 D = TD->getTemplatedDecl();
201 assert(D->isCanonicalDecl());
207 static bool shouldReportOccurrenceForSystemDeclOnlyMode(
208 bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
212 auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
214 applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
216 case SymbolRole::RelationChildOf:
217 case SymbolRole::RelationBaseOf:
218 case SymbolRole::RelationOverrideOf:
219 case SymbolRole::RelationExtendedBy:
220 case SymbolRole::RelationAccessorOf:
221 case SymbolRole::RelationIBTypeOf:
224 case SymbolRole::Declaration:
225 case SymbolRole::Definition:
226 case SymbolRole::Reference:
227 case SymbolRole::Read:
228 case SymbolRole::Write:
229 case SymbolRole::Call:
230 case SymbolRole::Dynamic:
231 case SymbolRole::AddressOf:
232 case SymbolRole::Implicit:
233 case SymbolRole::RelationReceivedBy:
234 case SymbolRole::RelationCalledBy:
235 case SymbolRole::RelationContainedBy:
238 llvm_unreachable("Unsupported SymbolRole value!");
243 for (auto &Rel : Relations) {
244 if (acceptForRelation(Rel.Roles))
251 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
252 bool IsRef, const Decl *Parent,
254 ArrayRef<SymbolRelation> Relations,
257 const DeclContext *ContainerDC) {
258 if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
260 if (!isa<NamedDecl>(D) ||
261 (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
262 !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
265 SourceManager &SM = Ctx->getSourceManager();
266 Loc = SM.getFileLoc(Loc);
272 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
276 bool Invalid = false;
277 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
278 if (Invalid || !SEntry.isFile())
281 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
282 switch (IndexOpts.SystemSymbolFilter) {
283 case IndexingOptions::SystemSymbolFilterKind::None:
285 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
286 if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
289 case IndexingOptions::SystemSymbolFilterKind::All:
294 if (isTemplateImplicitInstantiation(D)) {
297 D = adjustTemplateImplicitInstantiation(D);
300 assert(!isTemplateImplicitInstantiation(D));
307 Roles |= (unsigned)SymbolRole::Reference;
308 else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
309 Roles |= (unsigned)SymbolRole::Definition;
311 Roles |= (unsigned)SymbolRole::Declaration;
313 D = getCanonicalDecl(D);
314 Parent = adjustParent(Parent);
316 Parent = getCanonicalDecl(Parent);
318 SmallVector<SymbolRelation, 6> FinalRelations;
319 FinalRelations.reserve(Relations.size()+1);
321 auto addRelation = [&](SymbolRelation Rel) {
322 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
323 [&](SymbolRelation Elem)->bool {
324 return Elem.RelatedSymbol == Rel.RelatedSymbol;
326 if (It != FinalRelations.end()) {
327 It->Roles |= Rel.Roles;
329 FinalRelations.push_back(Rel);
335 if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
336 addRelation(SymbolRelation{
337 (unsigned)SymbolRole::RelationContainedBy,
341 addRelation(SymbolRelation{
342 (unsigned)SymbolRole::RelationChildOf,
348 for (auto &Rel : Relations) {
349 addRelation(SymbolRelation(Rel.Roles,
350 Rel.RelatedSymbol->getCanonicalDecl()));
353 IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
354 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,