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