Clang Project

clang_source_code/tools/libclang/CXIndexDataConsumer.cpp
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 "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
18using namespace clang;
19using namespace clang::index;
20using namespace cxindex;
21using namespace cxcursor;
22
23namespace {
24class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitorbool> {
25  CXIndexDataConsumer &DataConsumer;
26  SourceLocation DeclLoc;
27  const DeclContext *LexicalDC;
28
29public:
30  IndexingDeclVisitor(CXIndexDataConsumer &dataConsumerSourceLocation 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(DDeclLocLexicalDC);
96    else
97      DataConsumer.handleObjCMethod(DDeclLoc);
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
151CXSymbolRole getSymbolRole(SymbolRoleSet Role) {
152  // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole.
153  return CXSymbolRole(static_cast<uint32_t>(Role) & ((1 << 9) - 1));
154}
155}
156
157bool CXIndexDataConsumer::handleDeclOccurence(
158    const Decl *DSymbolRoleSet RolesArrayRef<SymbolRelationRelations,
159    SourceLocation LocASTNodeInfo 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        // The libclang API treats this as ObjCClassRef declaration.
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        // The libclang API treats this as ObjCProtocolRef declaration.
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.OrigDCXTU);
201      } else {
202        Cursor = getRefCursor(NDLoc);
203      }
204    }
205    handleReference(NDLocCursor,
206                    dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
207                    ASTNode.ContainerDCASTNode.OrigEKindCXRole);
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(*thisLocLexicalDC).Visit(ASTNode.OrigD);
218  }
219
220  return !shouldAbort();
221}
222
223bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
224                                                const Module *Mod,
225                                                SymbolRoleSet Roles,
226                                                SourceLocation Loc) {
227  if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
228    IndexingDeclVisitor(*thisSourceLocation(), nullptr).Visit(ImportD);
229  return !shouldAbort();
230}
231
232void CXIndexDataConsumer::finish() {
233  indexDiagnostics();
234}
235
236
237CXIndexDataConsumer::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(PDLocIdxCtx.CXTU),
250                                IdxCtx.getIndexLoc(Loc) };
251    ProtInfos.push_back(ProtInfo);
252
253    if (IdxCtx.shouldSuppressRefs())
254      IdxCtx.markEntityOccurrenceInFile(PDLoc);
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
265IBOutletCollectionInfo::IBOutletCollectionInfo(
266                                          const IBOutletCollectionInfo &other)
267  : AttrInfo(CXIdxAttr_IBOutletCollectionother.cursorother.locother.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
279AttrListInfo::AttrListInfo(const Decl *DCXIndexDataConsumer &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 = 0e = 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(InterDIBInfo.ClassInfoSA);
320        IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo;
321        IBInfo.IBCollInfo.classCursor =
322            MakeCursorObjCClassRef(InterDInterfaceLocStartIdxCtx.CXTU);
323      }
324    }
325  }
326
327  for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
328    CXAttrs.push_back(&Attrs[i]);
329}
330
331IntrusiveRefCntPtr<AttrListInfo>
332AttrListInfo::create(const Decl *DCXIndexDataConsumer &IdxCtx) {
333  ScratchAlloc SA(IdxCtx);
334  AttrListInfo *attrs = SA.allocate<AttrListInfo>();
335  return new (attrs) AttrListInfo(D, IdxCtx);
336}
337
338CXIndexDataConsumer::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 = 0e = 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
373SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
374                                           const CXXBaseSpecifier &Baseconst {
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
396const 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
404const 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
411void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
412  Ctx = &ctx;
413  cxtu::getASTUnit(CXTU)->setASTContext(&ctx);
414}
415
416void CXIndexDataConsumer::setPreprocessor(std::shared_ptr<PreprocessorPP) {
417  cxtu::getASTUnit(CXTU)->setPreprocessor(std::move(PP));
418}
419
420bool 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
444bool CXIndexDataConsumer::shouldAbort() {
445  if (!CB.abortQuery)
446    return false;
447  return CB.abortQuery(ClientDatanullptr);
448}
449
450void 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
460void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
461                                     StringRef filename,
462                                     const FileEntry *File,
463                                     bool isImportbool 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
478void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
479  if (!CB.importedASTFile)
480    return;
481
482  Module *Mod = ImportD->getImportedModule();
483  if (!Mod)
484    return;
485
486  // If the imported module is part of the top-level module that we're
487  // indexing, it doesn't correspond to an imported AST file.
488  // FIXME: This assumes that AST files and top-level modules directly
489  // correspond, which is unlikely to remain true forever.
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
505void 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                                    /*module=*/nullptr,
513                                    getIndexLoc(SourceLocation()),
514                                    /*isImplicit=*/false
515                                  };
516  CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
517  (void)astFile;
518}
519
520void CXIndexDataConsumer::startedTranslationUnit() {
521  CXIdxClientContainer idxCont = nullptr;
522  if (CB.startedTranslationUnit)
523    idxCont = CB.startedTranslationUnit(ClientDatanullptr);
524  addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
525}
526
527void CXIndexDataConsumer::indexDiagnostics() {
528  if (!hasDiagnosticCallback())
529    return;
530
531  CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU());
532  handleDiagnosticSet(DiagSet);
533}
534
535void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
536  if (!CB.diagnostic)
537    return;
538
539  CB.diagnostic(ClientDataCXDiagSetnullptr);
540}
541
542bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
543                                 SourceLocation LocCXCursor 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(DDInfo.EntInfoSA);
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(DLoc);
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(SemaDCDInfo.SemanticContainer);
575  DInfo.semanticContainer = &DInfo.SemanticContainer;
576
577  if (LexicalDC == SemaDC) {
578    DInfo.lexicalContainer = &DInfo.SemanticContainer;
579  } else if (isTemplateImplicitInstantiation(D)) {
580    // Implicit instantiations have the lexical context of where they were
581    // instantiated first. We choose instead the semantic context because:
582    // 1) at the time that we see the instantiation we have not seen the
583    //   function where it occurred yet.
584    // 2) the lexical context of the first instantiation is not useful
585    //   information anyway.
586    DInfo.lexicalContainer = &DInfo.SemanticContainer;
587  } else {
588    getContainerInfo(LexicalDCDInfo.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
601bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
602                                          SourceLocation LocCXCursor Cursor,
603                                          ObjCContainerDeclInfo &ContDInfo) {
604  ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
605  return handleDecl(DLocCursorContDInfo);
606}
607
608bool 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(), isDefisContainer);
619  if (isSkipped)
620    DInfo.flags |= CXIdxDeclFlag_Skipped;
621  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
622}
623
624bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
625  DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
626                 /*isContainer=*/false);
627  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
628}
629
630bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
631  DeclInfo DInfo(/*isRedeclaration=*/false/*isDefinition=*/true,
632                 /*isContainer=*/false);
633  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
634}
635
636bool CXIndexDataConsumer::handleMSProperty(const MSPropertyDecl *D) {
637  DeclInfo DInfo(/*isRedeclaration=*/false/*isDefinition=*/true,
638                 /*isContainer=*/false);
639  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
640}
641
642bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) {
643  DeclInfo DInfo(/*isRedeclaration=*/false/*isDefinition=*/true,
644                 /*isContainer=*/false);
645  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
646}
647
648bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) {
649  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D))
650    return handleCXXRecordDecl(CXXRDD);
651
652  DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
653                 D->isThisDeclarationADefinition());
654  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
655}
656
657bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
658  DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
659                 /*isContainer=*/false);
660  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
661}
662
663bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) {
664  // For @class forward declarations, suppress them the same way as references.
665  if (!D->isThisDeclarationADefinition()) {
666    if (shouldSuppressRefs() && markEntityOccurrenceInFile(DD->getLocation()))
667      return false// already occurred.
668
669    // FIXME: This seems like the wrong definition for redeclaration.
670    bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
671    ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/trueisRedeclaration,
672                                    /*isImplementation=*/false);
673    return handleObjCContainer(DD->getLocation(),
674                               MakeCursorObjCClassRef(DD->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(SuperDBaseEntitySA);
686    SourceLocation SuperLoc = D->getSuperClassLoc();
687    BaseClass.base = &BaseEntity;
688    BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperDSuperLocCXTU);
689    BaseClass.loc = getIndexLoc(SuperLoc);
690
691    if (shouldSuppressRefs())
692      markEntityOccurrenceInFile(SuperDSuperLoc);
693  }
694  
695  ObjCProtocolList EmptyProtoList;
696  ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition() 
697                                  ? D->getReferencedProtocols()
698                                  : EmptyProtoList
699                                *thisSA);
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(DD->getLocation(), getCursor(D), InterInfo);
709}
710
711bool CXIndexDataConsumer::handleObjCImplementation(
712                                              const ObjCImplementationDecl *D) {
713  ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
714                      /*isRedeclaration=*/true,
715                      /*isImplementation=*/true);
716  return handleObjCContainer(DD->getLocation(), getCursor(D), ContDInfo);
717}
718
719bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
720  if (!D->isThisDeclarationADefinition()) {
721    if (shouldSuppressRefs() && markEntityOccurrenceInFile(DD->getLocation()))
722      return false// already occurred.
723    
724    // FIXME: This seems like the wrong definition for redeclaration.
725    bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
726    ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true,
727                                    isRedeclaration,
728                                    /*isImplementation=*/false);
729    return handleObjCContainer(DD->getLocation(), 
730                               MakeCursorObjCProtocolRef(DD->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                                    *thisSA);
741  
742  ObjCProtocolDeclInfo ProtInfo(D);
743  ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo();
744
745  return handleObjCContainer(DD->getLocation(), getCursor(D), ProtInfo);
746}
747
748bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) {
749  ScratchAlloc SA(*this);
750
751  ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
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(IFaceDClassEntitySA);
758
759  if (shouldSuppressRefs())
760    markEntityOccurrenceInFile(IFaceDClassLoc);
761
762  ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *thisSA);
763  
764  CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
765  if (IFaceD) {
766    CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
767    CatDInfo.ObjCCatDeclInfo.classCursor =
768        MakeCursorObjCClassRef(IFaceDClassLocCXTU);
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(DCategoryLocgetCursor(D), CatDInfo);
778}
779
780bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
781  ScratchAlloc SA(*this);
782
783  const ObjCCategoryDecl *CatD = D->getCategoryDecl();
784  ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
785  EntityInfo ClassEntity;
786  const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface();
787  SourceLocation ClassLoc = D->getLocation();
788  SourceLocation CategoryLoc = D->getCategoryNameLoc();
789  getEntityInfo(IFaceDClassEntitySA);
790
791  if (shouldSuppressRefs())
792    markEntityOccurrenceInFile(IFaceDClassLoc);
793
794  CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
795  if (IFaceD) {
796    CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
797    CatDInfo.ObjCCatDeclInfo.classCursor =
798        MakeCursorObjCClassRef(IFaceDClassLocCXTU);
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(DCategoryLocgetCursor(D), CatDInfo);
807}
808
809bool 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(), isDefisContainer);
821  if (isSkipped)
822    DInfo.flags |= CXIdxDeclFlag_Skipped;
823  return handleDecl(DLocgetCursor(D), DInfo);
824}
825
826bool 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
834bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
835                                                  SourceLocation Loc,
836                                                 const DeclContext *LexicalDC) {
837  DeclInfo DInfo(/*isRedeclaration=*/true/*isDefinition=*/true,
838                 /*isContainer=*/false);
839  return handleDecl(DLocgetCursor(D), DInfoLexicalDCD->getDeclContext());
840}
841
842bool 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(GetterGetterEntitySA);
853    DInfo.ObjCPropDeclInfo.getter = &GetterEntity;
854  } else {
855    DInfo.ObjCPropDeclInfo.getter = nullptr;
856  }
857  if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) {
858    getEntityInfo(SetterSetterEntitySA);
859    DInfo.ObjCPropDeclInfo.setter = &SetterEntity;
860  } else {
861    DInfo.ObjCPropDeclInfo.setter = nullptr;
862  }
863
864  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
865}
866
867bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
868  DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
869                 /*isDefinition=*/true,
870                 /*isContainer=*/true);
871  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
872}
873
874bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) {
875  return handleCXXRecordDecl(D->getTemplatedDecl(), D);
876}
877
878bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) {
879  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
880                 /*isDefinition=*/D->isThisDeclarationADefinition(),
881                 /*isContainer=*/D->isThisDeclarationADefinition());
882  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
883}
884
885bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
886  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
887                 /*isDefinition=*/true/*isContainer=*/false);
888  return handleDecl(DD->getLocation(), getCursor(D), DInfo);
889}
890
891bool CXIndexDataConsumer::handleReference(const NamedDecl *DSourceLocation 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(DLoc);
902  return handleReference(DLocCursorParentDCEKindRole);
903}
904
905bool CXIndexDataConsumer::handleReference(const NamedDecl *DSourceLocation 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(DLoc))
928      return false// already occurred.
929  }
930
931  ScratchAlloc SA(*this);
932  EntityInfo RefEntityParentEntity;
933  getEntityInfo(DRefEntitySA);
934  if (!RefEntity.USR)
935    return false;
936
937  getEntityInfo(ParentParentEntitySA);
938
939  ContainerInfo Container;
940  getContainerInfo(DCContainer);
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
953bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Locconst {
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
962void 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  // Allow changing the container of a previously seen DeclContext so we
974  // can handle invalid user code, like a function re-definition.
975  if (container)
976    I->second = container;
977  else
978    ContainerMap.erase(I);
979}
980
981CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *Dconst {
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
990void CXIndexDataConsumer::setClientEntity(const Decl *DCXIdxClientEntity client) {
991  if (!D)
992    return;
993  EntityMap[D] = client;
994}
995
996bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
997                                          const NamedDecl *OrigD) {
998  if (RD->isThisDeclarationADefinition()) {
999    ScratchAlloc SA(*this);
1000    CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
1001                           /*isDefinition=*/RD->isThisDeclarationADefinition());
1002    CXXBasesListInfo BaseList(RD, *thisSA);
1003    CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
1004    CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
1005    CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
1006
1007    if (shouldSuppressRefs()) {
1008      // Go through bases and mark them as referenced.
1009      for (unsigned i = 0e = 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(BaseDLoc);
1016        }
1017      }
1018    }
1019
1020    return handleDecl(OrigDOrigD->getLocation(), getCursor(OrigD), CXXDInfo);
1021  }
1022
1023  DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
1024                 /*isDefinition=*/RD->isThisDeclarationADefinition(),
1025                 /*isContainer=*/RD->isThisDeclarationADefinition());
1026  return handleDecl(OrigDOrigD->getLocation(), getCursor(OrigD), DInfo);
1027}
1028
1029bool 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<FileIDunsignedLocInfo = 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(FED);
1046  std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool>
1047  res = RefFileOccurrences.insert(RefOccur);
1048  return !res.second; // already in map
1049}
1050
1051const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *Dconst {
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
1073const DeclContext *
1074CXIndexDataConsumer::getEntityContainer(const Decl *Dconst {
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
1089CXIdxClientContainer
1090CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DCconst {
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
1101CXIdxClientFile 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
1112CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Locconst {
1113  CXIdxLoc idxLoc =  { {nullptrnullptr}, 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
1122void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
1123                                   CXIdxClientFile *indexFileCXFile *file,
1124                                   unsigned *lineunsigned *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<FileIDunsignedLocInfo = 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(FIDFileOffset);
1146  if (column)
1147    *column = SM.getColumnNumber(FIDFileOffset);
1148  if (offset)
1149    *offset = FileOffset;
1150}
1151
1152static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind KSymbolLanguage L);
1153static CXIdxEntityCXXTemplateKind
1154getEntityKindFromSymbolProperties(SymbolPropertySet K);
1155static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
1156
1157void 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.KindSymInfo.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// anonymous tag/field/namespace.
1187
1188  } else {
1189    SmallString<256StrBuf;
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<512StrBuf;
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
1208void 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
1215CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *DSourceLocation Loc) {
1216  if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
1217    return MakeCursorTypeRef(TDLocCXTU);
1218  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
1219    return MakeCursorObjCClassRef(IDLocCXTU);
1220  if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
1221    return MakeCursorObjCProtocolRef(PDLocCXTU);
1222  if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
1223    return MakeCursorTemplateRef(TemplateLocCXTU);
1224  if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
1225    return MakeCursorNamespaceRef(NamespaceLocCXTU);
1226  if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
1227    return MakeCursorNamespaceRef(NamespaceLocCXTU);
1228  if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
1229    return MakeCursorMemberRef(FieldLocCXTU);
1230  if (const VarDecl *Var = dyn_cast<VarDecl>(D))
1231    return MakeCursorVariableRef(VarLocCXTU);
1232  
1233  return clang_getNullCursor();
1234}
1235
1236bool 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
1250bool 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
1261static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind KSymbolLanguage 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::Enumreturn CXIdxEntity_Enum;
1271  case SymbolKind::Structreturn CXIdxEntity_Struct;
1272  case SymbolKind::Unionreturn CXIdxEntity_Union;
1273  case SymbolKind::TypeAlias:
1274    if (Lang == SymbolLanguage::CXX)
1275      return CXIdxEntity_CXXTypeAlias;
1276    return CXIdxEntity_Typedef;
1277  case SymbolKind::Functionreturn CXIdxEntity_Function;
1278  case SymbolKind::Variablereturn CXIdxEntity_Variable;
1279  case SymbolKind::Field:
1280    if (Lang == SymbolLanguage::ObjC)
1281      return CXIdxEntity_ObjCIvar;
1282    return CXIdxEntity_Field;
1283  case SymbolKind::EnumConstantreturn 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::Extensionreturn CXIdxEntity_ObjCCategory;
1293  case SymbolKind::InstanceMethod:
1294    if (Lang == SymbolLanguage::ObjC)
1295      return CXIdxEntity_ObjCInstanceMethod;
1296    return CXIdxEntity_CXXInstanceMethod;
1297  case SymbolKind::ClassMethodreturn CXIdxEntity_ObjCClassMethod;
1298  case SymbolKind::StaticMethodreturn CXIdxEntity_CXXStaticMethod;
1299  case SymbolKind::InstancePropertyreturn CXIdxEntity_ObjCProperty;
1300  case SymbolKind::StaticPropertyreturn CXIdxEntity_CXXStaticVariable;
1301  case SymbolKind::Namespacereturn CXIdxEntity_CXXNamespace;
1302  case SymbolKind::NamespaceAliasreturn CXIdxEntity_CXXNamespaceAlias;
1303  case SymbolKind::Constructorreturn CXIdxEntity_CXXConstructor;
1304  case SymbolKind::Destructorreturn CXIdxEntity_CXXDestructor;
1305  case SymbolKind::ConversionFunctionreturn CXIdxEntity_CXXConversionFunction;
1306  case SymbolKind::Parameterreturn CXIdxEntity_Variable;
1307  }
1308  llvm_unreachable("invalid symbol kind");
1309}
1310
1311static CXIdxEntityCXXTemplateKind
1312getEntityKindFromSymbolProperties(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
1322static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
1323  switch (L) {
1324  case SymbolLanguage::Creturn CXIdxEntityLang_C;
1325  case SymbolLanguage::ObjCreturn CXIdxEntityLang_ObjC;
1326  case SymbolLanguage::CXXreturn CXIdxEntityLang_CXX;
1327  case SymbolLanguage::Swiftreturn CXIdxEntityLang_Swift;
1328  }
1329  llvm_unreachable("invalid symbol language");
1330}
1331
clang::cxindex::CXIndexDataConsumer::handleDeclOccurence
clang::cxindex::CXIndexDataConsumer::handleModuleOccurence
clang::cxindex::CXIndexDataConsumer::finish
clang::cxindex::AttrListInfo::create
clang::cxindex::CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc
clang::cxindex::ScratchAlloc::toCStr
clang::cxindex::ScratchAlloc::copyCStr
clang::cxindex::CXIndexDataConsumer::setASTContext
clang::cxindex::CXIndexDataConsumer::setPreprocessor
clang::cxindex::CXIndexDataConsumer::isFunctionLocalDecl
clang::cxindex::CXIndexDataConsumer::shouldAbort
clang::cxindex::CXIndexDataConsumer::enteredMainFile
clang::cxindex::CXIndexDataConsumer::ppIncludedFile
clang::cxindex::CXIndexDataConsumer::importedModule
clang::cxindex::CXIndexDataConsumer::importedPCH
clang::cxindex::CXIndexDataConsumer::startedTranslationUnit
clang::cxindex::CXIndexDataConsumer::indexDiagnostics
clang::cxindex::CXIndexDataConsumer::handleDiagnosticSet
clang::cxindex::CXIndexDataConsumer::handleDecl
clang::cxindex::CXIndexDataConsumer::handleObjCContainer
clang::cxindex::CXIndexDataConsumer::handleFunction
clang::cxindex::CXIndexDataConsumer::handleVar
clang::cxindex::CXIndexDataConsumer::handleField
clang::cxindex::CXIndexDataConsumer::handleMSProperty
clang::cxindex::CXIndexDataConsumer::handleEnumerator
clang::cxindex::CXIndexDataConsumer::handleTagDecl
clang::cxindex::CXIndexDataConsumer::handleTypedefName
clang::cxindex::CXIndexDataConsumer::handleObjCInterface
clang::cxindex::CXIndexDataConsumer::handleObjCImplementation
clang::cxindex::CXIndexDataConsumer::handleObjCProtocol
clang::cxindex::CXIndexDataConsumer::handleObjCCategory
clang::cxindex::CXIndexDataConsumer::handleObjCCategoryImpl
clang::cxindex::CXIndexDataConsumer::handleObjCMethod
clang::cxindex::CXIndexDataConsumer::handleSynthesizedObjCProperty
clang::cxindex::CXIndexDataConsumer::handleSynthesizedObjCMethod
clang::cxindex::CXIndexDataConsumer::handleObjCProperty
clang::cxindex::CXIndexDataConsumer::handleNamespace
clang::cxindex::CXIndexDataConsumer::handleClassTemplate
clang::cxindex::CXIndexDataConsumer::handleFunctionTemplate
clang::cxindex::CXIndexDataConsumer::handleTypeAliasTemplate
clang::cxindex::CXIndexDataConsumer::handleReference
clang::cxindex::CXIndexDataConsumer::handleReference
clang::cxindex::CXIndexDataConsumer::isNotFromSourceFile
clang::cxindex::CXIndexDataConsumer::addContainerInMap
clang::cxindex::CXIndexDataConsumer::getClientEntity
clang::cxindex::CXIndexDataConsumer::setClientEntity
clang::cxindex::CXIndexDataConsumer::handleCXXRecordDecl
clang::cxindex::CXIndexDataConsumer::markEntityOccurrenceInFile
clang::cxindex::CXIndexDataConsumer::getEntityDecl
clang::cxindex::CXIndexDataConsumer::getEntityContainer
clang::cxindex::CXIndexDataConsumer::getClientContainerForDC
clang::cxindex::CXIndexDataConsumer::getIndexFile
clang::cxindex::CXIndexDataConsumer::getIndexLoc
clang::cxindex::CXIndexDataConsumer::translateLoc
clang::cxindex::CXIndexDataConsumer::getEntityInfo
clang::cxindex::CXIndexDataConsumer::getContainerInfo
clang::cxindex::CXIndexDataConsumer::getRefCursor
clang::cxindex::CXIndexDataConsumer::shouldIgnoreIfImplicit
clang::cxindex::CXIndexDataConsumer::isTemplateImplicitInstantiation