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 handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false,
28 cast<Decl>(D->getDeclContext()), Roles, Relations,
29 nullptr, nullptr, D->getDeclContext());
32 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
34 ArrayRef<SymbolRelation> Relations,
35 const DeclContext *DC) {
37 DC = D->getDeclContext();
38 return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
40 nullptr, nullptr, DC);
43 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
44 const NamedDecl *Parent,
45 const DeclContext *DC,
47 ArrayRef<SymbolRelation> Relations,
50 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
53 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
56 return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
60 bool IndexingContext::importedModule(const ImportDecl *ImportD) {
62 auto IdLocs = ImportD->getIdentifierLocs();
66 Loc = ImportD->getLocation();
67 SourceManager &SM = Ctx->getSourceManager();
68 Loc = SM.getFileLoc(Loc);
74 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
79 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
80 if (Invalid || !SEntry.isFile())
83 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
84 switch (IndexOpts.SystemSymbolFilter) {
85 case IndexingOptions::SystemSymbolFilterKind::None:
87 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
88 case IndexingOptions::SystemSymbolFilterKind::All:
93 SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
94 if (ImportD->isImplicit())
95 Roles |= (unsigned)SymbolRole::Implicit;
97 return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
100 bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
103 if (isa<TemplateTemplateParmDecl>(D))
106 if (isa<ObjCTypeParamDecl>(D))
109 if (!D->getParentFunctionOrMethod())
112 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
113 switch (ND->getFormalLinkage()) {
115 case VisibleNoLinkage:
116 case InternalLinkage:
118 case UniqueExternalLinkage:
119 llvm_unreachable("Not a sema linkage");
120 case ExternalLinkage:
128 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
129 TemplateSpecializationKind TKind = TSK_Undeclared;
130 if (const ClassTemplateSpecializationDecl *
131 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
132 TKind = SD->getSpecializationKind();
133 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
134 TKind = FD->getTemplateSpecializationKind();
135 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
136 TKind = VD->getTemplateSpecializationKind();
140 case TSK_ExplicitSpecialization:
142 case TSK_ImplicitInstantiation:
143 case TSK_ExplicitInstantiationDeclaration:
144 case TSK_ExplicitInstantiationDefinition:
147 llvm_unreachable("invalid TemplateSpecializationKind");
150 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
151 if (isa<ObjCInterfaceDecl>(D))
153 if (isa<ObjCCategoryDecl>(D))
155 if (isa<ObjCIvarDecl>(D))
157 if (isa<ObjCMethodDecl>(D))
159 if (isa<ImportDecl>(D))
164 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
165 if (const ClassTemplateSpecializationDecl *
166 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
167 return SD->getTemplateInstantiationPattern();
168 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
169 return FD->getTemplateInstantiationPattern();
170 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
171 return VD->getTemplateInstantiationPattern();
176 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
177 if (auto VD = dyn_cast<VarDecl>(D))
178 return VD->isThisDeclarationADefinition(Ctx);
180 if (auto FD = dyn_cast<FunctionDecl>(D))
181 return FD->isThisDeclarationADefinition();
183 if (auto TD = dyn_cast<TagDecl>(D))
184 return TD->isThisDeclarationADefinition();
186 if (auto MD = dyn_cast<ObjCMethodDecl>(D))
187 return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
189 if (isa<TypedefNameDecl>(D) ||
190 isa<EnumConstantDecl>(D) ||
192 isa<MSPropertyDecl>(D) ||
193 isa<ObjCImplDecl>(D) ||
194 isa<ObjCPropertyImplDecl>(D))
200 static const Decl *adjustParent(const Decl *Parent) {
203 for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
204 if (isa<TranslationUnitDecl>(Parent))
206 if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
208 if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
209 if (NS->isAnonymousNamespace())
211 } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
212 if (RD->isAnonymousStructOrUnion())
214 } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
215 if (FD->getDeclName().isEmpty())
222 static const Decl *getCanonicalDecl(const Decl *D) {
223 D = D->getCanonicalDecl();
224 if (auto TD = dyn_cast<TemplateDecl>(D)) {
225 D = TD->getTemplatedDecl();
226 assert(D->isCanonicalDecl());
232 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
233 bool IsRef, const Decl *Parent,
235 ArrayRef<SymbolRelation> Relations,
238 const DeclContext *ContainerDC) {
239 if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
241 if (!isa<NamedDecl>(D) ||
242 (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
243 !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
246 SourceManager &SM = Ctx->getSourceManager();
247 Loc = SM.getFileLoc(Loc);
253 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
257 bool Invalid = false;
258 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
259 if (Invalid || !SEntry.isFile())
262 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
263 switch (IndexOpts.SystemSymbolFilter) {
264 case IndexingOptions::SystemSymbolFilterKind::None:
266 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
270 case IndexingOptions::SystemSymbolFilterKind::All:
275 if (isTemplateImplicitInstantiation(D)) {
278 D = adjustTemplateImplicitInstantiation(D);
281 assert(!isTemplateImplicitInstantiation(D));
288 Roles |= (unsigned)SymbolRole::Reference;
289 else if (isDeclADefinition(D, ContainerDC, *Ctx))
290 Roles |= (unsigned)SymbolRole::Definition;
292 Roles |= (unsigned)SymbolRole::Declaration;
294 D = getCanonicalDecl(D);
295 Parent = adjustParent(Parent);
297 Parent = getCanonicalDecl(Parent);
299 SmallVector<SymbolRelation, 6> FinalRelations;
300 FinalRelations.reserve(Relations.size()+1);
302 auto addRelation = [&](SymbolRelation Rel) {
303 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
304 [&](SymbolRelation Elem)->bool {
305 return Elem.RelatedSymbol == Rel.RelatedSymbol;
307 if (It != FinalRelations.end()) {
308 It->Roles |= Rel.Roles;
310 FinalRelations.push_back(Rel);
315 if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) {
316 addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent});
318 for (auto &Rel : Relations) {
319 addRelation(SymbolRelation(Rel.Roles,
320 Rel.RelatedSymbol->getCanonicalDecl()));
323 IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
324 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,