blob: 97b3e10450d66e20ea271f6f7feaef17a91a1fed [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
Sam McCallcc026eb2018-04-09 14:12:51 +000086 SourceManager &SM = Ctx->getSourceManager();
87 FileID FID = SM.getFileID(SM.getFileLoc(Loc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000088 if (FID.isInvalid())
89 return true;
90
91 bool Invalid = false;
92 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
93 if (Invalid || !SEntry.isFile())
94 return true;
95
96 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
97 switch (IndexOpts.SystemSymbolFilter) {
98 case IndexingOptions::SystemSymbolFilterKind::None:
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000099 return true;
Ben Langmuir6aed6b42016-07-14 18:51:55 +0000100 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000101 case IndexingOptions::SystemSymbolFilterKind::All:
102 break;
103 }
104 }
105
Ben Langmuir6aed6b42016-07-14 18:51:55 +0000106 SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000107 if (ImportD->isImplicit())
108 Roles |= (unsigned)SymbolRole::Implicit;
109
Sam McCallcc026eb2018-04-09 14:12:51 +0000110 return DataConsumer.handleModuleOccurence(ImportD, Roles, Loc);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000111}
112
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000113bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
114 TemplateSpecializationKind TKind = TSK_Undeclared;
115 if (const ClassTemplateSpecializationDecl *
116 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
117 TKind = SD->getSpecializationKind();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000118 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000119 TKind = FD->getTemplateSpecializationKind();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000120 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
121 TKind = VD->getTemplateSpecializationKind();
Alex Lorenz2109d432017-05-23 16:23:28 +0000122 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
123 if (RD->getInstantiatedFromMemberClass())
124 TKind = RD->getTemplateSpecializationKind();
Alex Lorenz9d605202017-05-23 16:35:50 +0000125 } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
126 if (ED->getInstantiatedFromMemberEnum())
127 TKind = ED->getTemplateSpecializationKind();
Alex Lorenz4bbce512017-05-23 16:47:01 +0000128 } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
129 isa<EnumConstantDecl>(D)) {
Alex Lorenz73e27a62017-05-23 16:25:06 +0000130 if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
131 return isTemplateImplicitInstantiation(Parent);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000132 }
133 switch (TKind) {
134 case TSK_Undeclared:
135 case TSK_ExplicitSpecialization:
136 return false;
137 case TSK_ImplicitInstantiation:
138 case TSK_ExplicitInstantiationDeclaration:
139 case TSK_ExplicitInstantiationDefinition:
140 return true;
141 }
Saleem Abdulrasool9b0ac332016-02-15 00:36:52 +0000142 llvm_unreachable("invalid TemplateSpecializationKind");
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000143}
144
145bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
146 if (isa<ObjCInterfaceDecl>(D))
147 return false;
148 if (isa<ObjCCategoryDecl>(D))
149 return false;
150 if (isa<ObjCIvarDecl>(D))
151 return false;
152 if (isa<ObjCMethodDecl>(D))
153 return false;
154 if (isa<ImportDecl>(D))
155 return false;
156 return true;
157}
158
Alex Lorenz73e27a62017-05-23 16:25:06 +0000159static const CXXRecordDecl *
160getDeclContextForTemplateInstationPattern(const Decl *D) {
161 if (const auto *CTSD =
162 dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
163 return CTSD->getTemplateInstantiationPattern();
164 else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
165 return RD->getInstantiatedFromMemberClass();
166 return nullptr;
167}
168
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000169static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
170 if (const ClassTemplateSpecializationDecl *
171 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
172 return SD->getTemplateInstantiationPattern();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000173 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000174 return FD->getTemplateInstantiationPattern();
Argyrios Kyrtzidis9d8ab722016-11-07 21:20:15 +0000175 } else if (auto *VD = dyn_cast<VarDecl>(D)) {
176 return VD->getTemplateInstantiationPattern();
Alex Lorenz2109d432017-05-23 16:23:28 +0000177 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
178 return RD->getInstantiatedFromMemberClass();
Alex Lorenz9d605202017-05-23 16:35:50 +0000179 } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
180 return ED->getInstantiatedFromMemberEnum();
Alex Lorenzfcbae3a2017-05-23 16:27:42 +0000181 } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
182 const auto *ND = cast<NamedDecl>(D);
Alex Lorenz73e27a62017-05-23 16:25:06 +0000183 if (const CXXRecordDecl *Pattern =
Alex Lorenzfcbae3a2017-05-23 16:27:42 +0000184 getDeclContextForTemplateInstationPattern(ND)) {
185 for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
186 if (BaseND->isImplicit())
Alex Lorenz048c8a92017-05-15 14:26:22 +0000187 continue;
Alex Lorenzfcbae3a2017-05-23 16:27:42 +0000188 if (BaseND->getKind() == ND->getKind())
189 return BaseND;
Alex Lorenz048c8a92017-05-15 14:26:22 +0000190 }
191 }
Alex Lorenz4bbce512017-05-23 16:47:01 +0000192 } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
193 if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
194 if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
195 for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
196 return BaseECD;
197 }
198 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000199 }
200 return nullptr;
201}
202
Argyrios Kyrtzidis66c49f72016-03-31 20:18:22 +0000203static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000204 if (auto VD = dyn_cast<VarDecl>(D))
205 return VD->isThisDeclarationADefinition(Ctx);
206
207 if (auto FD = dyn_cast<FunctionDecl>(D))
208 return FD->isThisDeclarationADefinition();
209
210 if (auto TD = dyn_cast<TagDecl>(D))
211 return TD->isThisDeclarationADefinition();
212
213 if (auto MD = dyn_cast<ObjCMethodDecl>(D))
Argyrios Kyrtzidis66c49f72016-03-31 20:18:22 +0000214 return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000215
216 if (isa<TypedefNameDecl>(D) ||
217 isa<EnumConstantDecl>(D) ||
218 isa<FieldDecl>(D) ||
219 isa<MSPropertyDecl>(D) ||
220 isa<ObjCImplDecl>(D) ||
221 isa<ObjCPropertyImplDecl>(D))
222 return true;
223
224 return false;
225}
226
Ben Langmuirda467ed2017-07-12 22:05:30 +0000227/// Whether the given NamedDecl should be skipped because it has no name.
228static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
Argyrios Kyrtzidis47827622017-08-15 17:20:37 +0000229 return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
230 !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
Ben Langmuirda467ed2017-07-12 22:05:30 +0000231}
232
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000233static const Decl *adjustParent(const Decl *Parent) {
234 if (!Parent)
235 return nullptr;
236 for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
237 if (isa<TranslationUnitDecl>(Parent))
238 return nullptr;
239 if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
240 continue;
241 if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
242 if (NS->isAnonymousNamespace())
243 continue;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000244 } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
245 if (RD->isAnonymousStructOrUnion())
246 continue;
Ben Langmuirda467ed2017-07-12 22:05:30 +0000247 } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
248 if (shouldSkipNamelessDecl(ND))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000249 continue;
250 }
251 return Parent;
252 }
253}
254
255static const Decl *getCanonicalDecl(const Decl *D) {
256 D = D->getCanonicalDecl();
257 if (auto TD = dyn_cast<TemplateDecl>(D)) {
Krasimir Georgieve62dd8b2017-07-18 07:20:53 +0000258 if (auto TTD = TD->getTemplatedDecl()) {
259 D = TTD;
260 assert(D->isCanonicalDecl());
261 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000262 }
263
264 return D;
265}
266
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000267static bool shouldReportOccurrenceForSystemDeclOnlyMode(
268 bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
269 if (!IsRef)
270 return true;
271
272 auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
273 bool accept = false;
274 applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
275 switch (r) {
276 case SymbolRole::RelationChildOf:
277 case SymbolRole::RelationBaseOf:
278 case SymbolRole::RelationOverrideOf:
279 case SymbolRole::RelationExtendedBy:
280 case SymbolRole::RelationAccessorOf:
281 case SymbolRole::RelationIBTypeOf:
282 accept = true;
283 return false;
284 case SymbolRole::Declaration:
285 case SymbolRole::Definition:
286 case SymbolRole::Reference:
287 case SymbolRole::Read:
288 case SymbolRole::Write:
289 case SymbolRole::Call:
290 case SymbolRole::Dynamic:
291 case SymbolRole::AddressOf:
292 case SymbolRole::Implicit:
293 case SymbolRole::RelationReceivedBy:
294 case SymbolRole::RelationCalledBy:
295 case SymbolRole::RelationContainedBy:
Alex Lorenzf6071c32017-04-20 10:43:22 +0000296 case SymbolRole::RelationSpecializationOf:
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000297 return true;
298 }
Simon Pilgrimdfbf0492017-03-24 16:59:14 +0000299 llvm_unreachable("Unsupported SymbolRole value!");
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000300 });
301 return accept;
302 };
303
304 for (auto &Rel : Relations) {
305 if (acceptForRelation(Rel.Roles))
306 return true;
307 }
308
309 return false;
310}
311
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000312bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
313 bool IsRef, const Decl *Parent,
314 SymbolRoleSet Roles,
315 ArrayRef<SymbolRelation> Relations,
316 const Expr *OrigE,
317 const Decl *OrigD,
318 const DeclContext *ContainerDC) {
319 if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
320 return true;
Ben Langmuirda467ed2017-07-12 22:05:30 +0000321 if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000322 return true;
323
324 SourceManager &SM = Ctx->getSourceManager();
Sam McCallcc026eb2018-04-09 14:12:51 +0000325 FileID FID = SM.getFileID(SM.getFileLoc(Loc));
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000326 if (FID.isInvalid())
327 return true;
328
329 bool Invalid = false;
330 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
331 if (Invalid || !SEntry.isFile())
332 return true;
333
334 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
335 switch (IndexOpts.SystemSymbolFilter) {
336 case IndexingOptions::SystemSymbolFilterKind::None:
337 return true;
338 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
Argyrios Kyrtzidisa9876ca2017-03-23 16:34:47 +0000339 if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000340 return true;
341 break;
342 case IndexingOptions::SystemSymbolFilterKind::All:
343 break;
344 }
345 }
346
347 if (isTemplateImplicitInstantiation(D)) {
348 if (!IsRef)
349 return true;
350 D = adjustTemplateImplicitInstantiation(D);
351 if (!D)
352 return true;
353 assert(!isTemplateImplicitInstantiation(D));
354 }
355
356 if (!OrigD)
357 OrigD = D;
358
359 if (IsRef)
360 Roles |= (unsigned)SymbolRole::Reference;
Argyrios Kyrtzidis74790482017-02-17 04:49:41 +0000361 else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000362 Roles |= (unsigned)SymbolRole::Definition;
363 else
364 Roles |= (unsigned)SymbolRole::Declaration;
365
366 D = getCanonicalDecl(D);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000367 Parent = adjustParent(Parent);
368 if (Parent)
369 Parent = getCanonicalDecl(Parent);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000370
371 SmallVector<SymbolRelation, 6> FinalRelations;
372 FinalRelations.reserve(Relations.size()+1);
373
374 auto addRelation = [&](SymbolRelation Rel) {
375 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
376 [&](SymbolRelation Elem)->bool {
377 return Elem.RelatedSymbol == Rel.RelatedSymbol;
378 });
379 if (It != FinalRelations.end()) {
380 It->Roles |= Rel.Roles;
381 } else {
382 FinalRelations.push_back(Rel);
383 }
384 Roles |= Rel.Roles;
385 };
386
Argyrios Kyrtzidisdf60aa82017-01-11 20:51:10 +0000387 if (Parent) {
Argyrios Kyrtzidis6d1a15b22017-02-26 05:37:56 +0000388 if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000389 addRelation(SymbolRelation{
390 (unsigned)SymbolRole::RelationContainedBy,
391 Parent
392 });
Argyrios Kyrtzidis6d1a15b22017-02-26 05:37:56 +0000393 } else {
Argyrios Kyrtzidisde0f5082017-01-11 21:01:07 +0000394 addRelation(SymbolRelation{
395 (unsigned)SymbolRole::RelationChildOf,
396 Parent
397 });
Argyrios Kyrtzidisdf60aa82017-01-11 20:51:10 +0000398 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000399 }
Argyrios Kyrtzidisdf60aa82017-01-11 20:51:10 +0000400
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000401 for (auto &Rel : Relations) {
402 addRelation(SymbolRelation(Rel.Roles,
403 Rel.RelatedSymbol->getCanonicalDecl()));
404 }
405
Sam McCallcc026eb2018-04-09 14:12:51 +0000406 IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
407 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000408}