1//===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CXIndexDataConsumer.h"
10#include "CIndexDiagnostic.h"
11#include "CXFile.h"
12#include "CXTranslationUnit.h"
13#include "clang/AST/Attr.h"
14#include "clang/AST/DeclCXX.h"
15#include "clang/AST/DeclTemplate.h"
16#include "clang/AST/DeclVisitor.h"
17#include "clang/Frontend/ASTUnit.h"
18#include "llvm/ADT/STLExtras.h"
19
20using namespace clang;
21using namespace clang::index;
22using namespace cxindex;
23using namespace cxcursor;
24
25namespace {
26class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
27 CXIndexDataConsumer &DataConsumer;
28 SourceLocation DeclLoc;
29 const DeclContext *LexicalDC;
30
31public:
32 IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc,
33 const DeclContext *lexicalDC)
34 : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { }
35
36 bool VisitFunctionDecl(const FunctionDecl *D) {
37 DataConsumer.handleFunction(FD: D);
38 return true;
39 }
40
41 bool VisitVarDecl(const VarDecl *D) {
42 DataConsumer.handleVar(D);
43 return true;
44 }
45
46 bool VisitFieldDecl(const FieldDecl *D) {
47 DataConsumer.handleField(D);
48 return true;
49 }
50
51 bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
52 return true;
53 }
54
55 bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
56 DataConsumer.handleEnumerator(D);
57 return true;
58 }
59
60 bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
61 DataConsumer.handleTypedefName(D);
62 return true;
63 }
64
65 bool VisitTagDecl(const TagDecl *D) {
66 DataConsumer.handleTagDecl(D);
67 return true;
68 }
69
70 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
71 DataConsumer.handleObjCInterface(D);
72 return true;
73 }
74
75 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
76 DataConsumer.handleObjCProtocol(D);
77 return true;
78 }
79
80 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
81 DataConsumer.handleObjCImplementation(D);
82 return true;
83 }
84
85 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
86 DataConsumer.handleObjCCategory(D);
87 return true;
88 }
89
90 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
91 DataConsumer.handleObjCCategoryImpl(D);
92 return true;
93 }
94
95 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
96 if (isa<ObjCImplDecl>(Val: LexicalDC) && !D->isThisDeclarationADefinition())
97 DataConsumer.handleSynthesizedObjCMethod(D, Loc: DeclLoc, LexicalDC);
98 else
99 DataConsumer.handleObjCMethod(D, Loc: DeclLoc);
100 return true;
101 }
102
103 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
104 DataConsumer.handleObjCProperty(D);
105 return true;
106 }
107
108 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
109 DataConsumer.handleSynthesizedObjCProperty(D);
110 return true;
111 }
112
113 bool VisitNamespaceDecl(const NamespaceDecl *D) {
114 DataConsumer.handleNamespace(D);
115 return true;
116 }
117
118 bool VisitUsingDecl(const UsingDecl *D) {
119 return true;
120 }
121
122 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
123 return true;
124 }
125
126 bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
127 DataConsumer.handleClassTemplate(D);
128 return true;
129 }
130
131 bool VisitClassTemplateSpecializationDecl(const
132 ClassTemplateSpecializationDecl *D) {
133 DataConsumer.handleTagDecl(D);
134 return true;
135 }
136
137 bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
138 DataConsumer.handleFunctionTemplate(D);
139 return true;
140 }
141
142 bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
143 DataConsumer.handleTypeAliasTemplate(D);
144 return true;
145 }
146
147 bool VisitImportDecl(const ImportDecl *D) {
148 DataConsumer.importedModule(ImportD: D);
149 return true;
150 }
151
152 bool VisitConceptDecl(const ConceptDecl *D) {
153 DataConsumer.handleConcept(D);
154 return true;
155 }
156};
157
158CXSymbolRole getSymbolRole(SymbolRoleSet Role) {
159 // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole.
160 return CXSymbolRole(static_cast<uint32_t>(Role) & ((1 << 9) - 1));
161}
162}
163
164bool CXIndexDataConsumer::handleDeclOccurrence(
165 const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations,
166 SourceLocation Loc, ASTNodeInfo ASTNode) {
167 Loc = getASTContext().getSourceManager().getFileLoc(Loc);
168
169 if (Roles & (unsigned)SymbolRole::Reference) {
170 const NamedDecl *ND = dyn_cast<NamedDecl>(Val: D);
171 if (!ND)
172 return true;
173
174 if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(Val: ASTNode.OrigD)) {
175 if (!ObjCID->isThisDeclarationADefinition() &&
176 ObjCID->getLocation() == Loc) {
177 // The libclang API treats this as ObjCClassRef declaration.
178 IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID);
179 return true;
180 }
181 }
182 if (auto *ObjCPD = dyn_cast_or_null<ObjCProtocolDecl>(Val: ASTNode.OrigD)) {
183 if (!ObjCPD->isThisDeclarationADefinition() &&
184 ObjCPD->getLocation() == Loc) {
185 // The libclang API treats this as ObjCProtocolRef declaration.
186 IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCPD);
187 return true;
188 }
189 }
190
191 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct;
192 if (Roles & (unsigned)SymbolRole::Implicit) {
193 Kind = CXIdxEntityRef_Implicit;
194 }
195 CXSymbolRole CXRole = getSymbolRole(Role: Roles);
196
197 CXCursor Cursor;
198 if (ASTNode.OrigE) {
199 Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE,
200 cast<Decl>(Val: ASTNode.ContainerDC),
201 getCXTU());
202 } else {
203 if (ASTNode.OrigD) {
204 if (auto *OrigND = dyn_cast<NamedDecl>(Val: ASTNode.OrigD))
205 Cursor = getRefCursor(D: OrigND, Loc);
206 else
207 Cursor = MakeCXCursor(D: ASTNode.OrigD, TU: CXTU);
208 } else {
209 Cursor = getRefCursor(D: ND, Loc);
210 }
211 }
212 handleReference(D: ND, Loc, Cursor,
213 Parent: dyn_cast_or_null<NamedDecl>(Val: ASTNode.Parent),
214 DC: ASTNode.ContainerDC, E: ASTNode.OrigE, Kind, Role: CXRole);
215
216 } else {
217 const DeclContext *LexicalDC = ASTNode.ContainerDC;
218 if (!LexicalDC) {
219 for (const auto &SymRel : Relations) {
220 if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf)
221 LexicalDC = dyn_cast<DeclContext>(Val: SymRel.RelatedSymbol);
222 }
223 }
224 IndexingDeclVisitor(*this, Loc, LexicalDC).Visit(ASTNode.OrigD);
225 }
226
227 return !shouldAbort();
228}
229
230bool CXIndexDataConsumer::handleModuleOccurrence(const ImportDecl *ImportD,
231 const Module *Mod,
232 SymbolRoleSet Roles,
233 SourceLocation Loc) {
234 if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
235 IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
236 return !shouldAbort();
237}
238
239void CXIndexDataConsumer::finish() {
240 indexDiagnostics();
241}
242
243
244CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo(
245 const ObjCProtocolList &ProtList,
246 CXIndexDataConsumer &IdxCtx,
247 ScratchAlloc &SA) {
248 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
249 for (ObjCInterfaceDecl::protocol_iterator
250 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
251 SourceLocation Loc = *LI;
252 ObjCProtocolDecl *PD = *I;
253 ProtEntities.push_back(Elt: EntityInfo());
254 IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA);
255 CXIdxObjCProtocolRefInfo ProtInfo = { .protocol: nullptr,
256 .cursor: MakeCursorObjCProtocolRef(Proto: PD, Loc, TU: IdxCtx.CXTU),
257 .loc: IdxCtx.getIndexLoc(Loc) };
258 ProtInfos.push_back(Elt: ProtInfo);
259
260 if (IdxCtx.shouldSuppressRefs())
261 IdxCtx.markEntityOccurrenceInFile(PD, Loc);
262 }
263
264 for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
265 ProtInfos[i].protocol = &ProtEntities[i];
266
267 for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
268 Prots.push_back(Elt: &ProtInfos[i]);
269}
270
271
272IBOutletCollectionInfo::IBOutletCollectionInfo(
273 const IBOutletCollectionInfo &other)
274 : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) {
275
276 IBCollInfo.attrInfo = this;
277 IBCollInfo.classCursor = other.IBCollInfo.classCursor;
278 IBCollInfo.classLoc = other.IBCollInfo.classLoc;
279 if (other.IBCollInfo.objcClass) {
280 ClassInfo = other.ClassInfo;
281 IBCollInfo.objcClass = &ClassInfo;
282 } else
283 IBCollInfo.objcClass = nullptr;
284}
285
286AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
287 : SA(IdxCtx), ref_cnt(0) {
288
289 if (!D->hasAttrs())
290 return;
291
292 for (const auto *A : D->attrs()) {
293 CXCursor C = MakeCXCursor(A, D, IdxCtx.CXTU);
294 CXIdxLoc Loc = IdxCtx.getIndexLoc(A->getLocation());
295 switch (C.kind) {
296 default:
297 Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A));
298 break;
299 case CXCursor_IBActionAttr:
300 Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A));
301 break;
302 case CXCursor_IBOutletAttr:
303 Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A));
304 break;
305 case CXCursor_IBOutletCollectionAttr:
306 IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A));
307 break;
308 }
309 }
310
311 for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) {
312 IBOutletCollectionInfo &IBInfo = IBCollAttrs[i];
313 CXAttrs.push_back(Elt: &IBInfo);
314
315 const IBOutletCollectionAttr *
316 IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
317 SourceLocation InterfaceLocStart =
318 IBAttr->getInterfaceLoc()->getTypeLoc().getBeginLoc();
319 IBInfo.IBCollInfo.attrInfo = &IBInfo;
320 IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(Loc: InterfaceLocStart);
321 IBInfo.IBCollInfo.objcClass = nullptr;
322 IBInfo.IBCollInfo.classCursor = clang_getNullCursor();
323 QualType Ty = IBAttr->getInterface();
324 if (const ObjCObjectType *ObjectTy = Ty->getAs<ObjCObjectType>()) {
325 if (const ObjCInterfaceDecl *InterD = ObjectTy->getInterface()) {
326 IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA);
327 IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo;
328 IBInfo.IBCollInfo.classCursor =
329 MakeCursorObjCClassRef(Class: InterD, Loc: InterfaceLocStart, TU: IdxCtx.CXTU);
330 }
331 }
332 }
333
334 for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
335 CXAttrs.push_back(Elt: &Attrs[i]);
336}
337
338IntrusiveRefCntPtr<AttrListInfo>
339AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) {
340 ScratchAlloc SA(IdxCtx);
341 AttrListInfo *attrs = SA.allocate<AttrListInfo>();
342 return new (attrs) AttrListInfo(D, IdxCtx);
343}
344
345CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
346 CXIndexDataConsumer &IdxCtx,
347 ScratchAlloc &SA) {
348 for (const auto &Base : D->bases()) {
349 BaseEntities.push_back(Elt: EntityInfo());
350 const NamedDecl *BaseD = nullptr;
351 QualType T = Base.getType();
352 SourceLocation Loc = getBaseLoc(Base);
353
354 if (const TypedefType *TDT = T->getAs<TypedefType>()) {
355 BaseD = TDT->getDecl();
356 } else if (const TemplateSpecializationType *
357 TST = T->getAs<TemplateSpecializationType>()) {
358 BaseD = TST->getTemplateName().getAsTemplateDecl();
359 } else if (const RecordType *RT = T->getAs<RecordType>()) {
360 BaseD = RT->getDecl();
361 }
362
363 if (BaseD)
364 IdxCtx.getEntityInfo(D: BaseD, EntityInfo&: BaseEntities.back(), SA);
365 CXIdxBaseClassInfo BaseInfo = { .base: nullptr,
366 .cursor: MakeCursorCXXBaseSpecifier(B: &Base, TU: IdxCtx.CXTU),
367 .loc: IdxCtx.getIndexLoc(Loc) };
368 BaseInfos.push_back(Elt: BaseInfo);
369 }
370
371 for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) {
372 if (BaseEntities[i].name && BaseEntities[i].USR)
373 BaseInfos[i].base = &BaseEntities[i];
374 }
375
376 for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i)
377 CXBases.push_back(Elt: &BaseInfos[i]);
378}
379
380SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
381 const CXXBaseSpecifier &Base) const {
382 SourceLocation Loc = Base.getSourceRange().getBegin();
383 TypeLoc TL;
384 if (Base.getTypeSourceInfo())
385 TL = Base.getTypeSourceInfo()->getTypeLoc();
386 if (TL.isNull())
387 return Loc;
388
389 if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>())
390 TL = QL.getUnqualifiedLoc();
391
392 if (ElaboratedTypeLoc EL = TL.getAs<ElaboratedTypeLoc>())
393 return EL.getNamedTypeLoc().getBeginLoc();
394 if (DependentNameTypeLoc DL = TL.getAs<DependentNameTypeLoc>())
395 return DL.getNameLoc();
396 if (DependentTemplateSpecializationTypeLoc DTL =
397 TL.getAs<DependentTemplateSpecializationTypeLoc>())
398 return DTL.getTemplateNameLoc();
399
400 return Loc;
401}
402
403const char *ScratchAlloc::toCStr(StringRef Str) {
404 if (Str.empty())
405 return "";
406 if (Str.data()[Str.size()] == '\0')
407 return Str.data();
408 return copyCStr(Str);
409}
410
411const char *ScratchAlloc::copyCStr(StringRef Str) {
412 char *buf = IdxCtx.StrScratch.Allocate<char>(Num: Str.size() + 1);
413 llvm::uninitialized_copy(Src&: Str, Dst: buf);
414 buf[Str.size()] = '\0';
415 return buf;
416}
417
418void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
419 Ctx = &ctx;
420 cxtu::getASTUnit(TU: CXTU)->setASTContext(&ctx);
421}
422
423void CXIndexDataConsumer::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
424 cxtu::getASTUnit(TU: CXTU)->setPreprocessor(std::move(PP));
425}
426
427bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) {
428 assert(D);
429
430 if (!D->getParentFunctionOrMethod())
431 return false;
432
433 if (const NamedDecl *ND = dyn_cast<NamedDecl>(Val: D)) {
434 switch (ND->getFormalLinkage()) {
435 case Linkage::Invalid:
436 llvm_unreachable("Linkage hasn't been computed!");
437 case Linkage::None:
438 case Linkage::Internal:
439 return true;
440 case Linkage::VisibleNone:
441 case Linkage::UniqueExternal:
442 llvm_unreachable("Not a sema linkage");
443 case Linkage::Module:
444 case Linkage::External:
445 return false;
446 }
447 }
448
449 return true;
450}
451
452bool CXIndexDataConsumer::shouldAbort() {
453 if (!CB.abortQuery)
454 return false;
455 return CB.abortQuery(ClientData, nullptr);
456}
457
458void CXIndexDataConsumer::enteredMainFile(OptionalFileEntryRef File) {
459 if (File && CB.enteredMainFile) {
460 CXIdxClientFile idxFile =
461 CB.enteredMainFile(ClientData, cxfile::makeCXFile(FE: *File), nullptr);
462 FileMap[*File] = idxFile;
463 }
464}
465
466void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
467 StringRef filename,
468 OptionalFileEntryRef File,
469 bool isImport, bool isAngled,
470 bool isModuleImport) {
471 if (!CB.ppIncludedFile)
472 return;
473
474 const FileEntry *FE = File ? &File->getFileEntry() : nullptr;
475
476 ScratchAlloc SA(*this);
477 CXIdxIncludedFileInfo Info = { .hashLoc: getIndexLoc(Loc: hashLoc),
478 .filename: SA.toCStr(Str: filename),
479 .file: cxfile::makeCXFile(FE: File),
480 .isImport: isImport, .isAngled: isAngled, .isModuleImport: isModuleImport };
481 CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
482 FileMap[FE] = idxFile;
483}
484
485void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
486 if (!CB.importedASTFile)
487 return;
488
489 Module *Mod = ImportD->getImportedModule();
490 if (!Mod)
491 return;
492
493 // If the imported module is part of the top-level module that we're
494 // indexing, it doesn't correspond to an imported AST file.
495 // FIXME: This assumes that AST files and top-level modules directly
496 // correspond, which is unlikely to remain true forever.
497 if (Module *SrcMod = ImportD->getImportedOwningModule())
498 if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule())
499 return;
500
501 OptionalFileEntryRef FE = Mod->getASTFile();
502 CXIdxImportedASTFileInfo Info = {cxfile::makeCXFile(FE), Mod,
503 getIndexLoc(Loc: ImportD->getLocation()),
504 ImportD->isImplicit()};
505 CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
506 (void)astFile;
507}
508
509void CXIndexDataConsumer::importedPCH(FileEntryRef File) {
510 if (!CB.importedASTFile)
511 return;
512
513 CXIdxImportedASTFileInfo Info = {
514 .file: cxfile::makeCXFile(FE: File),
515 /*module=*/nullptr,
516 .loc: getIndexLoc(Loc: SourceLocation()),
517 /*isImplicit=*/false
518 };
519 CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
520 (void)astFile;
521}
522
523void CXIndexDataConsumer::startedTranslationUnit() {
524 CXIdxClientContainer idxCont = nullptr;
525 if (CB.startedTranslationUnit)
526 idxCont = CB.startedTranslationUnit(ClientData, nullptr);
527 addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
528}
529
530void CXIndexDataConsumer::indexDiagnostics() {
531 if (!hasDiagnosticCallback())
532 return;
533
534 CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(TU: getCXTU());
535 handleDiagnosticSet(CXDiagSet: DiagSet);
536}
537
538void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
539 if (!CB.diagnostic)
540 return;
541
542 CB.diagnostic(ClientData, CXDiagSet, nullptr);
543}
544
545bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
546 SourceLocation Loc, CXCursor Cursor,
547 DeclInfo &DInfo,
548 const DeclContext *LexicalDC,
549 const DeclContext *SemaDC) {
550 if (!CB.indexDeclaration || !D)
551 return false;
552 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
553 return false;
554
555 ScratchAlloc SA(*this);
556 getEntityInfo(D, EntityInfo&: DInfo.EntInfo, SA);
557 if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR)
558 || Loc.isInvalid())
559 return false;
560
561 if (!LexicalDC)
562 LexicalDC = D->getLexicalDeclContext();
563
564 if (shouldSuppressRefs())
565 markEntityOccurrenceInFile(D, Loc);
566
567 DInfo.entityInfo = &DInfo.EntInfo;
568 DInfo.cursor = Cursor;
569 DInfo.loc = getIndexLoc(Loc);
570 DInfo.isImplicit = D->isImplicit();
571
572 DInfo.attributes = DInfo.EntInfo.attributes;
573 DInfo.numAttributes = DInfo.EntInfo.numAttributes;
574
575 if (!SemaDC)
576 SemaDC = D->getDeclContext();
577 getContainerInfo(DC: SemaDC, ContInfo&: DInfo.SemanticContainer);
578 DInfo.semanticContainer = &DInfo.SemanticContainer;
579
580 if (LexicalDC == SemaDC) {
581 DInfo.lexicalContainer = &DInfo.SemanticContainer;
582 } else if (isTemplateImplicitInstantiation(D)) {
583 // Implicit instantiations have the lexical context of where they were
584 // instantiated first. We choose instead the semantic context because:
585 // 1) at the time that we see the instantiation we have not seen the
586 // function where it occurred yet.
587 // 2) the lexical context of the first instantiation is not useful
588 // information anyway.
589 DInfo.lexicalContainer = &DInfo.SemanticContainer;
590 } else {
591 getContainerInfo(DC: LexicalDC, ContInfo&: DInfo.LexicalContainer);
592 DInfo.lexicalContainer = &DInfo.LexicalContainer;
593 }
594
595 if (DInfo.isContainer) {
596 getContainerInfo(DC: getEntityContainer(D), ContInfo&: DInfo.DeclAsContainer);
597 DInfo.declAsContainer = &DInfo.DeclAsContainer;
598 }
599
600 CB.indexDeclaration(ClientData, &DInfo);
601 return true;
602}
603
604bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
605 SourceLocation Loc, CXCursor Cursor,
606 ObjCContainerDeclInfo &ContDInfo) {
607 ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
608 return handleDecl(D, Loc, Cursor, ContDInfo);
609}
610
611bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) {
612 bool isDef = D->isThisDeclarationADefinition();
613 bool isContainer = isDef;
614 bool isSkipped = false;
615 if (D->hasSkippedBody()) {
616 isSkipped = true;
617 isDef = true;
618 isContainer = false;
619 }
620
621 DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer);
622 if (isSkipped)
623 DInfo.flags |= CXIdxDeclFlag_Skipped;
624 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
625}
626
627bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
628 DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
629 /*isContainer=*/false);
630 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
631}
632
633bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
634 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
635 /*isContainer=*/false);
636 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
637}
638
639bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) {
640 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
641 /*isContainer=*/false);
642 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
643}
644
645bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) {
646 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: D))
647 return handleCXXRecordDecl(CXXRD, D);
648
649 DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
650 D->isThisDeclarationADefinition());
651 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
652}
653
654bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
655 DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
656 /*isContainer=*/false);
657 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
658}
659
660bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) {
661 // For @class forward declarations, suppress them the same way as references.
662 if (!D->isThisDeclarationADefinition()) {
663 if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, Loc: D->getLocation()))
664 return false; // already occurred.
665
666 // FIXME: This seems like the wrong definition for redeclaration.
667 bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
668 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration,
669 /*isImplementation=*/false);
670 return handleObjCContainer(D, Loc: D->getLocation(),
671 Cursor: MakeCursorObjCClassRef(D, D->getLocation(),
672 CXTU),
673 ContDInfo);
674 }
675
676 ScratchAlloc SA(*this);
677
678 CXIdxBaseClassInfo BaseClass;
679 EntityInfo BaseEntity;
680 BaseClass.cursor = clang_getNullCursor();
681 if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) {
682 getEntityInfo(SuperD, BaseEntity, SA);
683 SourceLocation SuperLoc = D->getSuperClassLoc();
684 BaseClass.base = &BaseEntity;
685 BaseClass.cursor = MakeCursorObjCSuperClassRef(Super: SuperD, Loc: SuperLoc, TU: CXTU);
686 BaseClass.loc = getIndexLoc(Loc: SuperLoc);
687
688 if (shouldSuppressRefs())
689 markEntityOccurrenceInFile(SuperD, SuperLoc);
690 }
691
692 ObjCProtocolList EmptyProtoList;
693 ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition()
694 ? D->getReferencedProtocols()
695 : EmptyProtoList,
696 *this, SA);
697
698 ObjCInterfaceDeclInfo InterInfo(D);
699 InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
700 InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo;
701 InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass
702 : nullptr;
703 InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo;
704
705 return handleObjCContainer(D, Loc: D->getLocation(), Cursor: getCursor(D), ContDInfo&: InterInfo);
706}
707
708bool CXIndexDataConsumer::handleObjCImplementation(
709 const ObjCImplementationDecl *D) {
710 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
711 /*isRedeclaration=*/true,
712 /*isImplementation=*/true);
713 return handleObjCContainer(D, Loc: D->getLocation(), Cursor: getCursor(D), ContDInfo);
714}
715
716bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
717 if (!D->isThisDeclarationADefinition()) {
718 if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, Loc: D->getLocation()))
719 return false; // already occurred.
720
721 // FIXME: This seems like the wrong definition for redeclaration.
722 bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
723 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true,
724 isRedeclaration,
725 /*isImplementation=*/false);
726 return handleObjCContainer(D, Loc: D->getLocation(),
727 Cursor: MakeCursorObjCProtocolRef(D, D->getLocation(),
728 CXTU),
729 ContDInfo);
730 }
731
732 ScratchAlloc SA(*this);
733 ObjCProtocolList EmptyProtoList;
734 ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition()
735 ? D->getReferencedProtocols()
736 : EmptyProtoList,
737 *this, SA);
738
739 ObjCProtocolDeclInfo ProtInfo(D);
740 ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo();
741
742 return handleObjCContainer(D, Loc: D->getLocation(), Cursor: getCursor(D), ContDInfo&: ProtInfo);
743}
744
745bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) {
746 ScratchAlloc SA(*this);
747
748 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
749 EntityInfo ClassEntity;
750 const ObjCInterfaceDecl *IFaceD = D->getClassInterface();
751 SourceLocation ClassLoc = D->getLocation();
752 SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc
753 : D->getCategoryNameLoc();
754 getEntityInfo(IFaceD, ClassEntity, SA);
755
756 if (shouldSuppressRefs())
757 markEntityOccurrenceInFile(IFaceD, ClassLoc);
758
759 ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA);
760
761 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
762 if (IFaceD) {
763 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
764 CatDInfo.ObjCCatDeclInfo.classCursor =
765 MakeCursorObjCClassRef(Class: IFaceD, Loc: ClassLoc, TU: CXTU);
766 } else {
767 CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
768 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
769 }
770 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(Loc: ClassLoc);
771 CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
772 CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo;
773
774 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
775}
776
777bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
778 ScratchAlloc SA(*this);
779
780 const ObjCCategoryDecl *CatD = D->getCategoryDecl();
781 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
782 EntityInfo ClassEntity;
783 const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface();
784 SourceLocation ClassLoc = D->getLocation();
785 SourceLocation CategoryLoc = D->getCategoryNameLoc();
786 getEntityInfo(IFaceD, ClassEntity, SA);
787
788 if (shouldSuppressRefs())
789 markEntityOccurrenceInFile(IFaceD, ClassLoc);
790
791 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
792 if (IFaceD) {
793 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
794 CatDInfo.ObjCCatDeclInfo.classCursor =
795 MakeCursorObjCClassRef(Class: IFaceD, Loc: ClassLoc, TU: CXTU);
796 } else {
797 CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
798 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
799 }
800 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(Loc: ClassLoc);
801 CatDInfo.ObjCCatDeclInfo.protocols = nullptr;
802
803 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
804}
805
806bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D,
807 SourceLocation Loc) {
808 bool isDef = D->isThisDeclarationADefinition();
809 bool isContainer = isDef;
810 bool isSkipped = false;
811 if (D->hasSkippedBody()) {
812 isSkipped = true;
813 isDef = true;
814 isContainer = false;
815 }
816
817 DeclInfo DInfo(!D->isCanonicalDecl(), isDef, isContainer);
818 if (isSkipped)
819 DInfo.flags |= CXIdxDeclFlag_Skipped;
820 return handleDecl(D, Loc, getCursor(D), DInfo);
821}
822
823bool CXIndexDataConsumer::handleSynthesizedObjCProperty(
824 const ObjCPropertyImplDecl *D) {
825 ObjCPropertyDecl *PD = D->getPropertyDecl();
826 auto *DC = D->getDeclContext();
827 return handleReference(D: PD, Loc: D->getLocation(), Cursor: getCursor(D),
828 Parent: dyn_cast<NamedDecl>(DC), DC: DC);
829}
830
831bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
832 SourceLocation Loc,
833 const DeclContext *LexicalDC) {
834 DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
835 /*isContainer=*/false);
836 return handleDecl(D, Loc, Cursor: getCursor(D), DInfo, LexicalDC, SemaDC: D->getDeclContext());
837}
838
839bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
840 ScratchAlloc SA(*this);
841
842 ObjCPropertyDeclInfo DInfo;
843 EntityInfo GetterEntity;
844 EntityInfo SetterEntity;
845
846 DInfo.ObjCPropDeclInfo.declInfo = &DInfo;
847
848 if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) {
849 getEntityInfo(Getter, GetterEntity, SA);
850 DInfo.ObjCPropDeclInfo.getter = &GetterEntity;
851 } else {
852 DInfo.ObjCPropDeclInfo.getter = nullptr;
853 }
854 if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) {
855 getEntityInfo(Setter, SetterEntity, SA);
856 DInfo.ObjCPropDeclInfo.setter = &SetterEntity;
857 } else {
858 DInfo.ObjCPropDeclInfo.setter = nullptr;
859 }
860
861 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
862}
863
864bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
865 DeclInfo DInfo(/*isRedeclaration=*/!D->isFirstDecl(),
866 /*isDefinition=*/true,
867 /*isContainer=*/true);
868 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
869}
870
871bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) {
872 return handleCXXRecordDecl(D->getTemplatedDecl(), D);
873}
874
875bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) {
876 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
877 /*isDefinition=*/D->isThisDeclarationADefinition(),
878 /*isContainer=*/D->isThisDeclarationADefinition());
879 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
880}
881
882bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
883 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
884 /*isDefinition=*/true, /*isContainer=*/false);
885 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
886}
887
888bool CXIndexDataConsumer::handleConcept(const ConceptDecl *D) {
889 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
890 /*isDefinition=*/true, /*isContainer=*/false);
891 return handleDecl(D, Loc: D->getLocation(), Cursor: getCursor(D), DInfo);
892}
893
894bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
895 CXCursor Cursor,
896 const NamedDecl *Parent,
897 const DeclContext *DC,
898 const Expr *E,
899 CXIdxEntityRefKind Kind,
900 CXSymbolRole Role) {
901 if (!CB.indexEntityReference)
902 return false;
903
904 if (!D || !DC)
905 return false;
906 if (Loc.isInvalid())
907 return false;
908 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
909 return false;
910 if (isNotFromSourceFile(Loc: D->getLocation()))
911 return false;
912 if (D->isImplicit() && shouldIgnoreIfImplicit(D))
913 return false;
914
915 if (shouldSuppressRefs()) {
916 if (markEntityOccurrenceInFile(D, Loc))
917 return false; // already occurred.
918 }
919
920 ScratchAlloc SA(*this);
921 EntityInfo RefEntity, ParentEntity;
922 getEntityInfo(D, EntityInfo&: RefEntity, SA);
923 if (!RefEntity.USR)
924 return false;
925
926 getEntityInfo(D: Parent, EntityInfo&: ParentEntity, SA);
927
928 ContainerInfo Container;
929 getContainerInfo(DC, ContInfo&: Container);
930
931 CXIdxEntityRefInfo Info = { .kind: Kind,
932 .cursor: Cursor,
933 .loc: getIndexLoc(Loc),
934 .referencedEntity: &RefEntity,
935 .parentEntity: Parent ? &ParentEntity : nullptr,
936 .container: &Container,
937 .role: Role };
938 CB.indexEntityReference(ClientData, &Info);
939 return true;
940}
941
942bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const {
943 if (Loc.isInvalid())
944 return true;
945 SourceManager &SM = Ctx->getSourceManager();
946 SourceLocation FileLoc = SM.getFileLoc(Loc);
947 FileID FID = SM.getFileID(SpellingLoc: FileLoc);
948 return SM.getFileEntryForID(FID) == nullptr;
949}
950
951void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC,
952 CXIdxClientContainer container) {
953 if (!DC)
954 return;
955
956 // Allow changing the container of a previously seen DeclContext so we
957 // can handle invalid user code, like a function re-definition.
958 if (container)
959 ContainerMap[DC] = container;
960 else
961 ContainerMap.erase(Val: DC);
962}
963
964CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const {
965 return D ? EntityMap.lookup(Val: D) : nullptr;
966}
967
968void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) {
969 if (!D)
970 return;
971 EntityMap[D] = client;
972}
973
974bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
975 const NamedDecl *OrigD) {
976 if (RD->isThisDeclarationADefinition()) {
977 ScratchAlloc SA(*this);
978 CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
979 /*isDefinition=*/RD->isThisDeclarationADefinition());
980 CXXBasesListInfo BaseList(RD, *this, SA);
981 CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
982 CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
983 CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
984
985 if (shouldSuppressRefs()) {
986 // Go through bases and mark them as referenced.
987 for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) {
988 const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i];
989 if (baseInfo->base) {
990 const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl;
991 SourceLocation
992 Loc = SourceLocation::getFromRawEncoding(Encoding: baseInfo->loc.int_data);
993 markEntityOccurrenceInFile(D: BaseD, Loc);
994 }
995 }
996 }
997
998 return handleDecl(D: OrigD, Loc: OrigD->getLocation(), Cursor: getCursor(OrigD), DInfo&: CXXDInfo);
999 }
1000
1001 DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
1002 /*isDefinition=*/RD->isThisDeclarationADefinition(),
1003 /*isContainer=*/RD->isThisDeclarationADefinition());
1004 return handleDecl(D: OrigD, Loc: OrigD->getLocation(), Cursor: getCursor(OrigD), DInfo);
1005}
1006
1007bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D,
1008 SourceLocation Loc) {
1009 if (!D || Loc.isInvalid())
1010 return true;
1011
1012 SourceManager &SM = Ctx->getSourceManager();
1013 D = getEntityDecl(D);
1014
1015 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc: SM.getFileLoc(Loc));
1016 FileID FID = LocInfo.first;
1017 if (FID.isInvalid())
1018 return true;
1019
1020 const FileEntry *FE = SM.getFileEntryForID(FID);
1021 if (!FE)
1022 return true;
1023 RefFileOccurrence RefOccur(FE, D);
1024 std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool>
1025 res = RefFileOccurrences.insert(V: RefOccur);
1026 return !res.second; // already in map
1027}
1028
1029const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const {
1030 assert(D);
1031 D = cast<NamedDecl>(D->getCanonicalDecl());
1032
1033 if (const ObjCImplementationDecl *
1034 ImplD = dyn_cast<ObjCImplementationDecl>(Val: D)) {
1035 return getEntityDecl(D: ImplD->getClassInterface());
1036
1037 } else if (const ObjCCategoryImplDecl *
1038 CatImplD = dyn_cast<ObjCCategoryImplDecl>(Val: D)) {
1039 return getEntityDecl(CatImplD->getCategoryDecl());
1040 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) {
1041 if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate())
1042 return getEntityDecl(TemplD);
1043 } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Val: D)) {
1044 if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate())
1045 return getEntityDecl(TemplD);
1046 }
1047
1048 return D;
1049}
1050
1051const DeclContext *
1052CXIndexDataConsumer::getEntityContainer(const Decl *D) const {
1053 const DeclContext *DC = dyn_cast<DeclContext>(Val: D);
1054 if (DC)
1055 return DC;
1056
1057 if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(Val: D)) {
1058 DC = ClassTempl->getTemplatedDecl();
1059 } else if (const FunctionTemplateDecl *
1060 FuncTempl = dyn_cast<FunctionTemplateDecl>(Val: D)) {
1061 DC = FuncTempl->getTemplatedDecl();
1062 }
1063
1064 return DC;
1065}
1066
1067CXIdxClientContainer
1068CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const {
1069 return DC ? ContainerMap.lookup(Val: DC) : nullptr;
1070}
1071
1072CXIdxClientFile CXIndexDataConsumer::getIndexFile(OptionalFileEntryRef File) {
1073 return File ? FileMap.lookup(Val: *File) : nullptr;
1074}
1075
1076CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const {
1077 CXIdxLoc idxLoc = { .ptr_data: {nullptr, nullptr}, .int_data: 0 };
1078 if (Loc.isInvalid())
1079 return idxLoc;
1080
1081 idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this);
1082 idxLoc.int_data = Loc.getRawEncoding();
1083 return idxLoc;
1084}
1085
1086void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
1087 CXIdxClientFile *indexFile, CXFile *file,
1088 unsigned *line, unsigned *column,
1089 unsigned *offset) {
1090 if (Loc.isInvalid())
1091 return;
1092
1093 SourceManager &SM = Ctx->getSourceManager();
1094 Loc = SM.getFileLoc(Loc);
1095
1096 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
1097 FileID FID = LocInfo.first;
1098 unsigned FileOffset = LocInfo.second;
1099
1100 if (FID.isInvalid())
1101 return;
1102
1103 OptionalFileEntryRef FE = SM.getFileEntryRefForID(FID);
1104 if (indexFile)
1105 *indexFile = getIndexFile(File: FE);
1106 if (file)
1107 *file = cxfile::makeCXFile(FE);
1108 if (line)
1109 *line = SM.getLineNumber(FID, FilePos: FileOffset);
1110 if (column)
1111 *column = SM.getColumnNumber(FID, FilePos: FileOffset);
1112 if (offset)
1113 *offset = FileOffset;
1114}
1115
1116static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L);
1117static CXIdxEntityCXXTemplateKind
1118getEntityKindFromSymbolProperties(SymbolPropertySet K);
1119static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
1120
1121void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
1122 EntityInfo &EntityInfo,
1123 ScratchAlloc &SA) {
1124 if (!D)
1125 return;
1126
1127 D = getEntityDecl(D);
1128 EntityInfo.cursor = getCursor(D);
1129 EntityInfo.Dcl = D;
1130 EntityInfo.IndexCtx = this;
1131
1132 SymbolInfo SymInfo = getSymbolInfo(D);
1133 EntityInfo.kind = getEntityKindFromSymbolKind(K: SymInfo.Kind, L: SymInfo.Lang);
1134 EntityInfo.templateKind = getEntityKindFromSymbolProperties(K: SymInfo.Properties);
1135 EntityInfo.lang = getEntityLangFromSymbolLang(L: SymInfo.Lang);
1136
1137 if (D->hasAttrs()) {
1138 EntityInfo.AttrList = AttrListInfo::create(D, *this);
1139 EntityInfo.attributes = EntityInfo.AttrList->getAttrs();
1140 EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
1141 }
1142
1143 if (EntityInfo.kind == CXIdxEntity_Unexposed)
1144 return;
1145
1146 if (IdentifierInfo *II = D->getIdentifier()) {
1147 EntityInfo.name = SA.toCStr(Str: II->getName());
1148
1149 } else if (isa<TagDecl>(Val: D) || isa<FieldDecl>(Val: D) || isa<NamespaceDecl>(Val: D)) {
1150 EntityInfo.name = nullptr; // anonymous tag/field/namespace.
1151
1152 } else {
1153 SmallString<256> StrBuf;
1154 {
1155 llvm::raw_svector_ostream OS(StrBuf);
1156 D->printName(OS);
1157 }
1158 EntityInfo.name = SA.copyCStr(Str: StrBuf.str());
1159 }
1160
1161 {
1162 SmallString<512> StrBuf;
1163 bool Ignore = getDeclCursorUSR(D, StrBuf);
1164 if (Ignore) {
1165 EntityInfo.USR = nullptr;
1166 } else {
1167 EntityInfo.USR = SA.copyCStr(Str: StrBuf.str());
1168 }
1169 }
1170}
1171
1172void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC,
1173 ContainerInfo &ContInfo) {
1174 ContInfo.cursor = getCursor(D: cast<Decl>(Val: DC));
1175 ContInfo.DC = DC;
1176 ContInfo.IndexCtx = this;
1177}
1178
1179CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
1180 if (const TypeDecl *TD = dyn_cast<TypeDecl>(Val: D))
1181 return MakeCursorTypeRef(Type: TD, Loc, TU: CXTU);
1182 if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(Val: D))
1183 return MakeCursorObjCClassRef(Class: ID, Loc, TU: CXTU);
1184 if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(Val: D))
1185 return MakeCursorObjCProtocolRef(Proto: PD, Loc, TU: CXTU);
1186 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(Val: D))
1187 return MakeCursorTemplateRef(Template, Loc, TU: CXTU);
1188 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Val: D))
1189 return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1190 if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(Val: D))
1191 return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1192 if (const FieldDecl *Field = dyn_cast<FieldDecl>(Val: D))
1193 return MakeCursorMemberRef(Field, Loc, TU: CXTU);
1194 if (const VarDecl *Var = dyn_cast<VarDecl>(Val: D))
1195 return MakeCursorVariableRef(Var, Loc, TU: CXTU);
1196
1197 return clang_getNullCursor();
1198}
1199
1200bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) {
1201 if (isa<ObjCInterfaceDecl>(Val: D))
1202 return false;
1203 if (isa<ObjCCategoryDecl>(Val: D))
1204 return false;
1205 if (isa<ObjCIvarDecl>(Val: D))
1206 return false;
1207 if (isa<ObjCMethodDecl>(Val: D))
1208 return false;
1209 if (isa<ImportDecl>(Val: D))
1210 return false;
1211 return true;
1212}
1213
1214bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) {
1215 if (const ClassTemplateSpecializationDecl *
1216 SD = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) {
1217 return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
1218 }
1219 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) {
1220 return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
1221 }
1222 return false;
1223}
1224
1225static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage Lang) {
1226 switch (K) {
1227 case SymbolKind::Unknown:
1228 case SymbolKind::Module:
1229 case SymbolKind::Macro:
1230 case SymbolKind::ClassProperty:
1231 case SymbolKind::Using:
1232 case SymbolKind::TemplateTypeParm:
1233 case SymbolKind::TemplateTemplateParm:
1234 case SymbolKind::NonTypeTemplateParm:
1235 return CXIdxEntity_Unexposed;
1236
1237 case SymbolKind::Enum: return CXIdxEntity_Enum;
1238 case SymbolKind::Struct: return CXIdxEntity_Struct;
1239 case SymbolKind::Union: return CXIdxEntity_Union;
1240 case SymbolKind::TypeAlias:
1241 if (Lang == SymbolLanguage::CXX)
1242 return CXIdxEntity_CXXTypeAlias;
1243 return CXIdxEntity_Typedef;
1244 case SymbolKind::Function: return CXIdxEntity_Function;
1245 case SymbolKind::Variable: return CXIdxEntity_Variable;
1246 case SymbolKind::Field:
1247 if (Lang == SymbolLanguage::ObjC)
1248 return CXIdxEntity_ObjCIvar;
1249 return CXIdxEntity_Field;
1250 case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant;
1251 case SymbolKind::Class:
1252 if (Lang == SymbolLanguage::ObjC)
1253 return CXIdxEntity_ObjCClass;
1254 return CXIdxEntity_CXXClass;
1255 case SymbolKind::Protocol:
1256 if (Lang == SymbolLanguage::ObjC)
1257 return CXIdxEntity_ObjCProtocol;
1258 return CXIdxEntity_CXXInterface;
1259 case SymbolKind::Extension: return CXIdxEntity_ObjCCategory;
1260 case SymbolKind::InstanceMethod:
1261 if (Lang == SymbolLanguage::ObjC)
1262 return CXIdxEntity_ObjCInstanceMethod;
1263 return CXIdxEntity_CXXInstanceMethod;
1264 case SymbolKind::ClassMethod: return CXIdxEntity_ObjCClassMethod;
1265 case SymbolKind::StaticMethod: return CXIdxEntity_CXXStaticMethod;
1266 case SymbolKind::InstanceProperty: return CXIdxEntity_ObjCProperty;
1267 case SymbolKind::StaticProperty: return CXIdxEntity_CXXStaticVariable;
1268 case SymbolKind::Namespace: return CXIdxEntity_CXXNamespace;
1269 case SymbolKind::NamespaceAlias: return CXIdxEntity_CXXNamespaceAlias;
1270 case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor;
1271 case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor;
1272 case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction;
1273 case SymbolKind::Parameter: return CXIdxEntity_Variable;
1274 case SymbolKind::Concept:
1275 return CXIdxEntity_CXXConcept;
1276 }
1277 llvm_unreachable("invalid symbol kind");
1278}
1279
1280static CXIdxEntityCXXTemplateKind
1281getEntityKindFromSymbolProperties(SymbolPropertySet K) {
1282 if (K & (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization)
1283 return CXIdxEntity_TemplatePartialSpecialization;
1284 if (K & (SymbolPropertySet)SymbolProperty::TemplateSpecialization)
1285 return CXIdxEntity_TemplateSpecialization;
1286 if (K & (SymbolPropertySet)SymbolProperty::Generic)
1287 return CXIdxEntity_Template;
1288 return CXIdxEntity_NonTemplate;
1289}
1290
1291static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
1292 switch (L) {
1293 case SymbolLanguage::C: return CXIdxEntityLang_C;
1294 case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
1295 case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
1296 case SymbolLanguage::Swift: return CXIdxEntityLang_Swift;
1297 }
1298 llvm_unreachable("invalid symbol language");
1299}
1300

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/tools/libclang/CXIndexDataConsumer.cpp