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