xref: /aosp_15_r20/external/clang/lib/Index/IndexingContext.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- IndexingContext.cpp - Indexing context data ------------------------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li 
10*67e74705SXin Li #include "IndexingContext.h"
11*67e74705SXin Li #include "clang/Index/IndexDataConsumer.h"
12*67e74705SXin Li #include "clang/AST/ASTContext.h"
13*67e74705SXin Li #include "clang/AST/DeclTemplate.h"
14*67e74705SXin Li #include "clang/AST/DeclObjC.h"
15*67e74705SXin Li #include "clang/Basic/SourceManager.h"
16*67e74705SXin Li 
17*67e74705SXin Li using namespace clang;
18*67e74705SXin Li using namespace index;
19*67e74705SXin Li 
shouldIndexFunctionLocalSymbols() const20*67e74705SXin Li bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
21*67e74705SXin Li   return IndexOpts.IndexFunctionLocals;
22*67e74705SXin Li }
23*67e74705SXin Li 
handleDecl(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations)24*67e74705SXin Li bool IndexingContext::handleDecl(const Decl *D,
25*67e74705SXin Li                                  SymbolRoleSet Roles,
26*67e74705SXin Li                                  ArrayRef<SymbolRelation> Relations) {
27*67e74705SXin Li   return handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false,
28*67e74705SXin Li                               cast<Decl>(D->getDeclContext()), Roles, Relations,
29*67e74705SXin Li                               nullptr, nullptr, D->getDeclContext());
30*67e74705SXin Li }
31*67e74705SXin Li 
handleDecl(const Decl * D,SourceLocation Loc,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const DeclContext * DC)32*67e74705SXin Li bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
33*67e74705SXin Li                                  SymbolRoleSet Roles,
34*67e74705SXin Li                                  ArrayRef<SymbolRelation> Relations,
35*67e74705SXin Li                                  const DeclContext *DC) {
36*67e74705SXin Li   if (!DC)
37*67e74705SXin Li     DC = D->getDeclContext();
38*67e74705SXin Li   return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
39*67e74705SXin Li                               Roles, Relations,
40*67e74705SXin Li                               nullptr, nullptr, DC);
41*67e74705SXin Li }
42*67e74705SXin Li 
handleReference(const NamedDecl * D,SourceLocation Loc,const NamedDecl * Parent,const DeclContext * DC,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const Expr * RefE,const Decl * RefD)43*67e74705SXin Li bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
44*67e74705SXin Li                                       const NamedDecl *Parent,
45*67e74705SXin Li                                       const DeclContext *DC,
46*67e74705SXin Li                                       SymbolRoleSet Roles,
47*67e74705SXin Li                                       ArrayRef<SymbolRelation> Relations,
48*67e74705SXin Li                                       const Expr *RefE,
49*67e74705SXin Li                                       const Decl *RefD) {
50*67e74705SXin Li   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
51*67e74705SXin Li     return true;
52*67e74705SXin Li 
53*67e74705SXin Li   if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
54*67e74705SXin Li     return true;
55*67e74705SXin Li 
56*67e74705SXin Li   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
57*67e74705SXin Li                               RefE, RefD, DC);
58*67e74705SXin Li }
59*67e74705SXin Li 
importedModule(const ImportDecl * ImportD)60*67e74705SXin Li bool IndexingContext::importedModule(const ImportDecl *ImportD) {
61*67e74705SXin Li   SourceLocation Loc;
62*67e74705SXin Li   auto IdLocs = ImportD->getIdentifierLocs();
63*67e74705SXin Li   if (!IdLocs.empty())
64*67e74705SXin Li     Loc = IdLocs.front();
65*67e74705SXin Li   else
66*67e74705SXin Li     Loc = ImportD->getLocation();
67*67e74705SXin Li   SourceManager &SM = Ctx->getSourceManager();
68*67e74705SXin Li   Loc = SM.getFileLoc(Loc);
69*67e74705SXin Li   if (Loc.isInvalid())
70*67e74705SXin Li     return true;
71*67e74705SXin Li 
72*67e74705SXin Li   FileID FID;
73*67e74705SXin Li   unsigned Offset;
74*67e74705SXin Li   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
75*67e74705SXin Li   if (FID.isInvalid())
76*67e74705SXin Li     return true;
77*67e74705SXin Li 
78*67e74705SXin Li   bool Invalid = false;
79*67e74705SXin Li   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
80*67e74705SXin Li   if (Invalid || !SEntry.isFile())
81*67e74705SXin Li     return true;
82*67e74705SXin Li 
83*67e74705SXin Li   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
84*67e74705SXin Li     switch (IndexOpts.SystemSymbolFilter) {
85*67e74705SXin Li     case IndexingOptions::SystemSymbolFilterKind::None:
86*67e74705SXin Li       return true;
87*67e74705SXin Li     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
88*67e74705SXin Li     case IndexingOptions::SystemSymbolFilterKind::All:
89*67e74705SXin Li       break;
90*67e74705SXin Li     }
91*67e74705SXin Li   }
92*67e74705SXin Li 
93*67e74705SXin Li   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
94*67e74705SXin Li   if (ImportD->isImplicit())
95*67e74705SXin Li     Roles |= (unsigned)SymbolRole::Implicit;
96*67e74705SXin Li 
97*67e74705SXin Li   return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
98*67e74705SXin Li }
99*67e74705SXin Li 
isFunctionLocalDecl(const Decl * D)100*67e74705SXin Li bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
101*67e74705SXin Li   assert(D);
102*67e74705SXin Li 
103*67e74705SXin Li   if (isa<TemplateTemplateParmDecl>(D))
104*67e74705SXin Li     return true;
105*67e74705SXin Li 
106*67e74705SXin Li   if (isa<ObjCTypeParamDecl>(D))
107*67e74705SXin Li     return true;
108*67e74705SXin Li 
109*67e74705SXin Li   if (!D->getParentFunctionOrMethod())
110*67e74705SXin Li     return false;
111*67e74705SXin Li 
112*67e74705SXin Li   if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
113*67e74705SXin Li     switch (ND->getFormalLinkage()) {
114*67e74705SXin Li     case NoLinkage:
115*67e74705SXin Li     case VisibleNoLinkage:
116*67e74705SXin Li     case InternalLinkage:
117*67e74705SXin Li       return true;
118*67e74705SXin Li     case UniqueExternalLinkage:
119*67e74705SXin Li       llvm_unreachable("Not a sema linkage");
120*67e74705SXin Li     case ExternalLinkage:
121*67e74705SXin Li       return false;
122*67e74705SXin Li     }
123*67e74705SXin Li   }
124*67e74705SXin Li 
125*67e74705SXin Li   return true;
126*67e74705SXin Li }
127*67e74705SXin Li 
isTemplateImplicitInstantiation(const Decl * D)128*67e74705SXin Li bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
129*67e74705SXin Li   TemplateSpecializationKind TKind = TSK_Undeclared;
130*67e74705SXin Li   if (const ClassTemplateSpecializationDecl *
131*67e74705SXin Li       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
132*67e74705SXin Li     TKind = SD->getSpecializationKind();
133*67e74705SXin Li   }
134*67e74705SXin Li   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
135*67e74705SXin Li     TKind = FD->getTemplateSpecializationKind();
136*67e74705SXin Li   }
137*67e74705SXin Li   switch (TKind) {
138*67e74705SXin Li     case TSK_Undeclared:
139*67e74705SXin Li     case TSK_ExplicitSpecialization:
140*67e74705SXin Li       return false;
141*67e74705SXin Li     case TSK_ImplicitInstantiation:
142*67e74705SXin Li     case TSK_ExplicitInstantiationDeclaration:
143*67e74705SXin Li     case TSK_ExplicitInstantiationDefinition:
144*67e74705SXin Li       return true;
145*67e74705SXin Li   }
146*67e74705SXin Li   llvm_unreachable("invalid TemplateSpecializationKind");
147*67e74705SXin Li }
148*67e74705SXin Li 
shouldIgnoreIfImplicit(const Decl * D)149*67e74705SXin Li bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
150*67e74705SXin Li   if (isa<ObjCInterfaceDecl>(D))
151*67e74705SXin Li     return false;
152*67e74705SXin Li   if (isa<ObjCCategoryDecl>(D))
153*67e74705SXin Li     return false;
154*67e74705SXin Li   if (isa<ObjCIvarDecl>(D))
155*67e74705SXin Li     return false;
156*67e74705SXin Li   if (isa<ObjCMethodDecl>(D))
157*67e74705SXin Li     return false;
158*67e74705SXin Li   if (isa<ImportDecl>(D))
159*67e74705SXin Li     return false;
160*67e74705SXin Li   return true;
161*67e74705SXin Li }
162*67e74705SXin Li 
adjustTemplateImplicitInstantiation(const Decl * D)163*67e74705SXin Li static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
164*67e74705SXin Li   if (const ClassTemplateSpecializationDecl *
165*67e74705SXin Li       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
166*67e74705SXin Li     return SD->getTemplateInstantiationPattern();
167*67e74705SXin Li   }
168*67e74705SXin Li   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
169*67e74705SXin Li     return FD->getTemplateInstantiationPattern();
170*67e74705SXin Li   }
171*67e74705SXin Li   return nullptr;
172*67e74705SXin Li }
173*67e74705SXin Li 
isDeclADefinition(const Decl * D,const DeclContext * ContainerDC,ASTContext & Ctx)174*67e74705SXin Li static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
175*67e74705SXin Li   if (auto VD = dyn_cast<VarDecl>(D))
176*67e74705SXin Li     return VD->isThisDeclarationADefinition(Ctx);
177*67e74705SXin Li 
178*67e74705SXin Li   if (auto FD = dyn_cast<FunctionDecl>(D))
179*67e74705SXin Li     return FD->isThisDeclarationADefinition();
180*67e74705SXin Li 
181*67e74705SXin Li   if (auto TD = dyn_cast<TagDecl>(D))
182*67e74705SXin Li     return TD->isThisDeclarationADefinition();
183*67e74705SXin Li 
184*67e74705SXin Li   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
185*67e74705SXin Li     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
186*67e74705SXin Li 
187*67e74705SXin Li   if (isa<TypedefNameDecl>(D) ||
188*67e74705SXin Li       isa<EnumConstantDecl>(D) ||
189*67e74705SXin Li       isa<FieldDecl>(D) ||
190*67e74705SXin Li       isa<MSPropertyDecl>(D) ||
191*67e74705SXin Li       isa<ObjCImplDecl>(D) ||
192*67e74705SXin Li       isa<ObjCPropertyImplDecl>(D))
193*67e74705SXin Li     return true;
194*67e74705SXin Li 
195*67e74705SXin Li   return false;
196*67e74705SXin Li }
197*67e74705SXin Li 
adjustParent(const Decl * Parent)198*67e74705SXin Li static const Decl *adjustParent(const Decl *Parent) {
199*67e74705SXin Li   if (!Parent)
200*67e74705SXin Li     return nullptr;
201*67e74705SXin Li   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
202*67e74705SXin Li     if (isa<TranslationUnitDecl>(Parent))
203*67e74705SXin Li       return nullptr;
204*67e74705SXin Li     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
205*67e74705SXin Li       continue;
206*67e74705SXin Li     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
207*67e74705SXin Li       if (NS->isAnonymousNamespace())
208*67e74705SXin Li         continue;
209*67e74705SXin Li     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
210*67e74705SXin Li       if (RD->isAnonymousStructOrUnion())
211*67e74705SXin Li         continue;
212*67e74705SXin Li     } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
213*67e74705SXin Li       if (FD->getDeclName().isEmpty())
214*67e74705SXin Li         continue;
215*67e74705SXin Li     }
216*67e74705SXin Li     return Parent;
217*67e74705SXin Li   }
218*67e74705SXin Li }
219*67e74705SXin Li 
getCanonicalDecl(const Decl * D)220*67e74705SXin Li static const Decl *getCanonicalDecl(const Decl *D) {
221*67e74705SXin Li   D = D->getCanonicalDecl();
222*67e74705SXin Li   if (auto TD = dyn_cast<TemplateDecl>(D)) {
223*67e74705SXin Li     D = TD->getTemplatedDecl();
224*67e74705SXin Li     assert(D->isCanonicalDecl());
225*67e74705SXin Li   }
226*67e74705SXin Li 
227*67e74705SXin Li   return D;
228*67e74705SXin Li }
229*67e74705SXin Li 
handleDeclOccurrence(const Decl * D,SourceLocation Loc,bool IsRef,const Decl * Parent,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const Expr * OrigE,const Decl * OrigD,const DeclContext * ContainerDC)230*67e74705SXin Li bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
231*67e74705SXin Li                                            bool IsRef, const Decl *Parent,
232*67e74705SXin Li                                            SymbolRoleSet Roles,
233*67e74705SXin Li                                            ArrayRef<SymbolRelation> Relations,
234*67e74705SXin Li                                            const Expr *OrigE,
235*67e74705SXin Li                                            const Decl *OrigD,
236*67e74705SXin Li                                            const DeclContext *ContainerDC) {
237*67e74705SXin Li   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
238*67e74705SXin Li     return true;
239*67e74705SXin Li   if (!isa<NamedDecl>(D) ||
240*67e74705SXin Li       (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
241*67e74705SXin Li        !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
242*67e74705SXin Li     return true;
243*67e74705SXin Li 
244*67e74705SXin Li   SourceManager &SM = Ctx->getSourceManager();
245*67e74705SXin Li   Loc = SM.getFileLoc(Loc);
246*67e74705SXin Li   if (Loc.isInvalid())
247*67e74705SXin Li     return true;
248*67e74705SXin Li 
249*67e74705SXin Li   FileID FID;
250*67e74705SXin Li   unsigned Offset;
251*67e74705SXin Li   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
252*67e74705SXin Li   if (FID.isInvalid())
253*67e74705SXin Li     return true;
254*67e74705SXin Li 
255*67e74705SXin Li   bool Invalid = false;
256*67e74705SXin Li   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
257*67e74705SXin Li   if (Invalid || !SEntry.isFile())
258*67e74705SXin Li     return true;
259*67e74705SXin Li 
260*67e74705SXin Li   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
261*67e74705SXin Li     switch (IndexOpts.SystemSymbolFilter) {
262*67e74705SXin Li     case IndexingOptions::SystemSymbolFilterKind::None:
263*67e74705SXin Li       return true;
264*67e74705SXin Li     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
265*67e74705SXin Li       if (IsRef)
266*67e74705SXin Li         return true;
267*67e74705SXin Li       break;
268*67e74705SXin Li     case IndexingOptions::SystemSymbolFilterKind::All:
269*67e74705SXin Li       break;
270*67e74705SXin Li     }
271*67e74705SXin Li   }
272*67e74705SXin Li 
273*67e74705SXin Li   if (isTemplateImplicitInstantiation(D)) {
274*67e74705SXin Li     if (!IsRef)
275*67e74705SXin Li       return true;
276*67e74705SXin Li     D = adjustTemplateImplicitInstantiation(D);
277*67e74705SXin Li     if (!D)
278*67e74705SXin Li       return true;
279*67e74705SXin Li     assert(!isTemplateImplicitInstantiation(D));
280*67e74705SXin Li   }
281*67e74705SXin Li 
282*67e74705SXin Li   if (!OrigD)
283*67e74705SXin Li     OrigD = D;
284*67e74705SXin Li 
285*67e74705SXin Li   if (IsRef)
286*67e74705SXin Li     Roles |= (unsigned)SymbolRole::Reference;
287*67e74705SXin Li   else if (isDeclADefinition(D, ContainerDC, *Ctx))
288*67e74705SXin Li     Roles |= (unsigned)SymbolRole::Definition;
289*67e74705SXin Li   else
290*67e74705SXin Li     Roles |= (unsigned)SymbolRole::Declaration;
291*67e74705SXin Li 
292*67e74705SXin Li   D = getCanonicalDecl(D);
293*67e74705SXin Li   if (D->isImplicit() && !isa<ObjCMethodDecl>(D) &&
294*67e74705SXin Li       !(isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->getBuiltinID())) {
295*67e74705SXin Li     // operator new declarations will link to the implicit one as canonical.
296*67e74705SXin Li     return true;
297*67e74705SXin Li   }
298*67e74705SXin Li   Parent = adjustParent(Parent);
299*67e74705SXin Li   if (Parent)
300*67e74705SXin Li     Parent = getCanonicalDecl(Parent);
301*67e74705SXin Li   assert((!Parent || !Parent->isImplicit() ||
302*67e74705SXin Li           (isa<FunctionDecl>(Parent) &&
303*67e74705SXin Li            cast<FunctionDecl>(Parent)->getBuiltinID()) ||
304*67e74705SXin Li           isa<ObjCInterfaceDecl>(Parent) || isa<ObjCMethodDecl>(Parent)) &&
305*67e74705SXin Li          "unexpected implicit parent!");
306*67e74705SXin Li 
307*67e74705SXin Li   SmallVector<SymbolRelation, 6> FinalRelations;
308*67e74705SXin Li   FinalRelations.reserve(Relations.size()+1);
309*67e74705SXin Li 
310*67e74705SXin Li   auto addRelation = [&](SymbolRelation Rel) {
311*67e74705SXin Li     auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
312*67e74705SXin Li                 [&](SymbolRelation Elem)->bool {
313*67e74705SXin Li                   return Elem.RelatedSymbol == Rel.RelatedSymbol;
314*67e74705SXin Li                 });
315*67e74705SXin Li     if (It != FinalRelations.end()) {
316*67e74705SXin Li       It->Roles |= Rel.Roles;
317*67e74705SXin Li     } else {
318*67e74705SXin Li       FinalRelations.push_back(Rel);
319*67e74705SXin Li     }
320*67e74705SXin Li     Roles |= Rel.Roles;
321*67e74705SXin Li   };
322*67e74705SXin Li 
323*67e74705SXin Li   if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) {
324*67e74705SXin Li     addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent});
325*67e74705SXin Li   }
326*67e74705SXin Li   for (auto &Rel : Relations) {
327*67e74705SXin Li     addRelation(SymbolRelation(Rel.Roles,
328*67e74705SXin Li                                Rel.RelatedSymbol->getCanonicalDecl()));
329*67e74705SXin Li   }
330*67e74705SXin Li 
331*67e74705SXin Li   IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
332*67e74705SXin Li   return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
333*67e74705SXin Li                                           Node);
334*67e74705SXin Li }
335