blob: 709a23657b07844d6507ec0a89799afab10062f7 [file] [log] [blame]
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +00001//===- IndexingContext.cpp - Indexing context data ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
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"
16
17using namespace clang;
18using namespace index;
19
Argyrios Kyrtzidis6e5ca5b2017-04-21 05:42:46 +000020static bool isGeneratedDecl(const Decl *D) {
21 if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
22 return attr->getGeneratedDeclaration();
23 }
24 return false;
25}
26
27bool IndexingContext::shouldIndex(const Decl *D) {
28 return !isGeneratedDecl(D);
29}
30
Alex Lorenza352ba02017-04-24 14:04:58 +000031const LangOptions &IndexingContext::getLangOpts() const {
32 return Ctx->getLangOpts();
33}
34
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000035bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
36 return IndexOpts.IndexFunctionLocals;
37}
38
39bool IndexingContext::handleDecl(const Decl *D,
40 SymbolRoleSet Roles,
41 ArrayRef<SymbolRelation> Relations) {
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +000042 return handleDecl(D, D->getLocation(), Roles, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000043}
44
45bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
46 SymbolRoleSet Roles,
47 ArrayRef<SymbolRelation> Relations,
48 const DeclContext *DC) {
49 if (!DC)
50 DC = D->getDeclContext();
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +000051
52 const Decl *OrigD = D;
53 if (isa<ObjCPropertyImplDecl>(D)) {
54 D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
55 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000056 return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
57 Roles, Relations,
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +000058 nullptr, OrigD, DC);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000059}
60
61bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
62 const NamedDecl *Parent,
63 const DeclContext *DC,
64 SymbolRoleSet Roles,
65 ArrayRef<SymbolRelation> Relations,
66 const Expr *RefE,
67 const Decl *RefD) {
Argyrios Kyrtzidis6d1a15b22017-02-26 05:37:56 +000068 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000069 return true;
70
71 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
72 return true;
73
74 return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
75 RefE, RefD, DC);
76}
77
78bool IndexingContext::importedModule(const ImportDecl *ImportD) {
Argyrios Kyrtzidis113387e2016-02-29 07:56:07 +000079 SourceLocation Loc;
80 auto IdLocs = ImportD->getIdentifierLocs();
81 if (!IdLocs.empty())
82 Loc = IdLocs.front();
83 else
84 Loc = ImportD->getLocation();
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000085 SourceManager &SM = Ctx->getSourceManager();
86 Loc = SM.getFileLoc(Loc);
87 if (Loc.isInvalid())
88 return true;
89
90 FileID FID;
91 unsigned Offset;
92 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
93 if (FID.isInvalid())
94 return true;
95
96 bool Invalid = false;
97 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
98 if (Invalid || !SEntry.isFile())
99 return true;
100
101 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
102 switch (IndexOpts.SystemSymbolFilter) {
103 case IndexingOptions::SystemSymbolFilterKind::None:
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000104 return true;
Ben Langmuir6aed6b42016-07-14 18:51:55 +0000105 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000106 case IndexingOptions::SystemSymbolFilterKind::All:
107 break;
108 }
109 }
110
Ben Langmuir6aed6b42016-07-14 18:51:55 +0000111 SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000112 if (ImportD->isImplicit())
113 Roles |= (unsigned)SymbolRole::Implicit;
114
115 return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
116}
117
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000118bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
119 TemplateSpecializationKind TKind = TSK_Undeclared;
120 if (const ClassTemplateSpecializationDecl *
121 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
122 TKind = SD->getSpecializationKind();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000123 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000124 TKind = FD->getTemplateSpecializationKind();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000125 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
126 TKind = VD->getTemplateSpecializationKind();
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000127 }
128 switch (TKind) {
129 case TSK_Undeclared:
130 case TSK_ExplicitSpecialization:
131 return false;
132 case TSK_ImplicitInstantiation:
133 case TSK_ExplicitInstantiationDeclaration:
134 case TSK_ExplicitInstantiationDefinition:
135 return true;
136 }
Saleem Abdulrasool9b0ac332016-02-15 00:36:52 +0000137 llvm_unreachable("invalid TemplateSpecializationKind");
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000138}
139
140bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
141 if (isa<ObjCInterfaceDecl>(D))
142 return false;
143 if (isa<ObjCCategoryDecl>(D))
144 return false;
145 if (isa<ObjCIvarDecl>(D))
146 return false;
147 if (isa<ObjCMethodDecl>(D))
148 return false;
149 if (isa<ImportDecl>(D))
150 return false;
151 return true;
152}
153
154static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
155 if (const ClassTemplateSpecializationDecl *
156 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
157 return SD->getTemplateInstantiationPattern();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000158 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000159 return FD->getTemplateInstantiationPattern();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000160 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
161 return VD->getTemplateInstantiationPattern();
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000162 }
163 return nullptr;
164}
165
Argyrios Kyrtzidis66c49f72016-03-31 20:18:22 +0000166static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000167 if (auto VD = dyn_cast<VarDecl>(D))
168 return VD->isThisDeclarationADefinition(Ctx);
169
170 if (auto FD = dyn_cast<FunctionDecl>(D))
171 return FD->isThisDeclarationADefinition();
172
173 if (auto TD = dyn_cast<TagDecl>(D))
174 return TD->isThisDeclarationADefinition();
175
176 if (auto MD = dyn_cast<ObjCMethodDecl>(D))
Argyrios Kyrtzidis66c49f72016-03-31 20:18:22 +0000177 return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000178
179 if (isa<TypedefNameDecl>(D) ||
180 isa<EnumConstantDecl>(D) ||
181 isa<FieldDecl>(D) ||
182 isa<MSPropertyDecl>(D) ||
183 isa<ObjCImplDecl>(D) ||
184 isa<ObjCPropertyImplDecl>(D))
185 return true;
186
187 return false;
188}
189
190static const Decl *adjustParent(const Decl *Parent) {
191 if (!Parent)
192 return nullptr;
193 for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
194 if (isa<TranslationUnitDecl>(Parent))
195 return nullptr;
196 if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
197 continue;
198 if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
199 if (NS->isAnonymousNamespace())
200 continue;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000201 } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
202 if (RD->isAnonymousStructOrUnion())
203 continue;
204 } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
205 if (FD->getDeclName().isEmpty())
206 continue;
207 }
208 return Parent;
209 }
210}
211
212static const Decl *getCanonicalDecl(const Decl *D) {
213 D = D->getCanonicalDecl();
214 if (auto TD = dyn_cast<TemplateDecl>(D)) {
215 D = TD->getTemplatedDecl();
216 assert(D->isCanonicalDecl());
217 }
218
219 return D;
220}
221
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000222static bool shouldReportOccurrenceForSystemDeclOnlyMode(
223 bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
224 if (!IsRef)
225 return true;
226
227 auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
228 bool accept = false;
229 applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
230 switch (r) {
231 case SymbolRole::RelationChildOf:
232 case SymbolRole::RelationBaseOf:
233 case SymbolRole::RelationOverrideOf:
234 case SymbolRole::RelationExtendedBy:
235 case SymbolRole::RelationAccessorOf:
236 case SymbolRole::RelationIBTypeOf:
237 accept = true;
238 return false;
239 case SymbolRole::Declaration:
240 case SymbolRole::Definition:
241 case SymbolRole::Reference:
242 case SymbolRole::Read:
243 case SymbolRole::Write:
244 case SymbolRole::Call:
245 case SymbolRole::Dynamic:
246 case SymbolRole::AddressOf:
247 case SymbolRole::Implicit:
248 case SymbolRole::RelationReceivedBy:
249 case SymbolRole::RelationCalledBy:
250 case SymbolRole::RelationContainedBy:
Alex Lorenzf6071c32017-04-20 10:43:22 +0000251 case SymbolRole::RelationSpecializationOf:
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000252 return true;
253 }
Simon Pilgrimdfbf0492017-03-24 16:59:14 +0000254 llvm_unreachable("Unsupported SymbolRole value!");
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000255 });
256 return accept;
257 };
258
259 for (auto &Rel : Relations) {
260 if (acceptForRelation(Rel.Roles))
261 return true;
262 }
263
264 return false;
265}
266
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000267bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
268 bool IsRef, const Decl *Parent,
269 SymbolRoleSet Roles,
270 ArrayRef<SymbolRelation> Relations,
271 const Expr *OrigE,
272 const Decl *OrigD,
273 const DeclContext *ContainerDC) {
274 if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
275 return true;
276 if (!isa<NamedDecl>(D) ||
277 (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
278 !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
279 return true;
280
281 SourceManager &SM = Ctx->getSourceManager();
282 Loc = SM.getFileLoc(Loc);
283 if (Loc.isInvalid())
284 return true;
285
286 FileID FID;
287 unsigned Offset;
288 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
289 if (FID.isInvalid())
290 return true;
291
292 bool Invalid = false;
293 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
294 if (Invalid || !SEntry.isFile())
295 return true;
296
297 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
298 switch (IndexOpts.SystemSymbolFilter) {
299 case IndexingOptions::SystemSymbolFilterKind::None:
300 return true;
301 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000302 if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000303 return true;
304 break;
305 case IndexingOptions::SystemSymbolFilterKind::All:
306 break;
307 }
308 }
309
310 if (isTemplateImplicitInstantiation(D)) {
311 if (!IsRef)
312 return true;
313 D = adjustTemplateImplicitInstantiation(D);
314 if (!D)
315 return true;
316 assert(!isTemplateImplicitInstantiation(D));
317 }
318
319 if (!OrigD)
320 OrigD = D;
321
322 if (IsRef)
323 Roles |= (unsigned)SymbolRole::Reference;
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000324 else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000325 Roles |= (unsigned)SymbolRole::Definition;
326 else
327 Roles |= (unsigned)SymbolRole::Declaration;
328
329 D = getCanonicalDecl(D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000330 Parent = adjustParent(Parent);
331 if (Parent)
332 Parent = getCanonicalDecl(Parent);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000333
334 SmallVector<SymbolRelation, 6> FinalRelations;
335 FinalRelations.reserve(Relations.size()+1);
336
337 auto addRelation = [&](SymbolRelation Rel) {
338 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
339 [&](SymbolRelation Elem)->bool {
340 return Elem.RelatedSymbol == Rel.RelatedSymbol;
341 });
342 if (It != FinalRelations.end()) {
343 It->Roles |= Rel.Roles;
344 } else {
345 FinalRelations.push_back(Rel);
346 }
347 Roles |= Rel.Roles;
348 };
349
Argyrios Kyrtzidisdf60aa82017-01-11 20:51:10 +0000350 if (Parent) {
Argyrios Kyrtzidis6d1a15b22017-02-26 05:37:56 +0000351 if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000352 addRelation(SymbolRelation{
353 (unsigned)SymbolRole::RelationContainedBy,
354 Parent
355 });
Argyrios Kyrtzidis6d1a15b22017-02-26 05:37:56 +0000356 } else {
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000357 addRelation(SymbolRelation{
358 (unsigned)SymbolRole::RelationChildOf,
359 Parent
360 });
Argyrios Kyrtzidisdf60aa82017-01-11 20:51:10 +0000361 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000362 }
Argyrios Kyrtzidisdf60aa82017-01-11 20:51:10 +0000363
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000364 for (auto &Rel : Relations) {
365 addRelation(SymbolRelation(Rel.Roles,
366 Rel.RelatedSymbol->getCanonicalDecl()));
367 }
368
369 IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
370 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
371 Node);
372}