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<IndexingDeclVisitor, bool> {
25  CXIndexDataConsumer &DataConsumer;
26  SourceLocation DeclLoc;
27  const DeclContext *LexicalDC;
28
29public:
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  bool VisitConceptDecl(const ConceptDecl *D) {
151    DataConsumer.handleConcept(D);
152    return true;
153  }
154};
155
156CXSymbolRole getSymbolRole(SymbolRoleSet Role) {
157  // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole.
158  return CXSymbolRole(static_cast<uint32_t>(Role) & ((1 << 9) - 1));
159}
160}
161
162bool CXIndexDataConsumer::handleDeclOccurrence(
163    const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations,
164    SourceLocation Loc, ASTNodeInfo ASTNode) {
165  Loc = getASTContext().getSourceManager().getFileLoc(Loc);
166
167  if (Roles & (unsigned)SymbolRole::Reference) {
168    const NamedDecl *ND = dyn_cast<NamedDecl>(D);
169    if (!ND)
170      return true;
171
172    if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(ASTNode.OrigD)) {
173      if (!ObjCID->isThisDeclarationADefinition() &&
174          ObjCID->getLocation() == Loc) {
175        // The libclang API treats this as ObjCClassRef declaration.
176        IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID);
177        return true;
178      }
179    }
180    if (auto *ObjCPD = dyn_cast_or_null<ObjCProtocolDecl>(ASTNode.OrigD)) {
181      if (!ObjCPD->isThisDeclarationADefinition() &&
182          ObjCPD->getLocation() == Loc) {
183        // The libclang API treats this as ObjCProtocolRef declaration.
184        IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCPD);
185        return true;
186      }
187    }
188
189    CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct;
190    if (Roles & (unsigned)SymbolRole::Implicit) {
191      Kind = CXIdxEntityRef_Implicit;
192    }
193    CXSymbolRole CXRole = getSymbolRole(Roles);
194
195    CXCursor Cursor;
196    if (ASTNode.OrigE) {
197      Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE,
198                                      cast<Decl>(ASTNode.ContainerDC),
199                                      getCXTU());
200    } else {
201      if (ASTNode.OrigD) {
202        if (auto *OrigND = dyn_cast<NamedDecl>(ASTNode.OrigD))
203          Cursor = getRefCursor(OrigND, Loc);
204        else
205          Cursor = MakeCXCursor(ASTNode.OrigD, CXTU);
206      } else {
207        Cursor = getRefCursor(ND, Loc);
208      }
209    }
210    handleReference(ND, Loc, Cursor,
211                    dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
212                    ASTNode.ContainerDC, ASTNode.OrigE, Kind, CXRole);
213
214  } else {
215    const DeclContext *LexicalDC = ASTNode.ContainerDC;
216    if (!LexicalDC) {
217      for (const auto &SymRel : Relations) {
218        if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf)
219          LexicalDC = dyn_cast<DeclContext>(SymRel.RelatedSymbol);
220      }
221    }
222    IndexingDeclVisitor(*this, Loc, LexicalDC).Visit(ASTNode.OrigD);
223  }
224
225  return !shouldAbort();
226}
227
228bool CXIndexDataConsumer::handleModuleOccurrence(const ImportDecl *ImportD,
229                                                 const Module *Mod,
230                                                 SymbolRoleSet Roles,
231                                                 SourceLocation Loc) {
232  if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
233    IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
234  return !shouldAbort();
235}
236
237void CXIndexDataConsumer::finish() {
238  indexDiagnostics();
239}
240
241
242CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo(
243                                    const ObjCProtocolList &ProtList,
244                                    CXIndexDataConsumer &IdxCtx,
245                                    ScratchAlloc &SA) {
246  ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
247  for (ObjCInterfaceDecl::protocol_iterator
248         I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
249    SourceLocation Loc = *LI;
250    ObjCProtocolDecl *PD = *I;
251    ProtEntities.push_back(EntityInfo());
252    IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA);
253    CXIdxObjCProtocolRefInfo ProtInfo = { nullptr,
254                                MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU),
255                                IdxCtx.getIndexLoc(Loc) };
256    ProtInfos.push_back(ProtInfo);
257
258    if (IdxCtx.shouldSuppressRefs())
259      IdxCtx.markEntityOccurrenceInFile(PD, Loc);
260  }
261
262  for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
263    ProtInfos[i].protocol = &ProtEntities[i];
264
265  for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
266    Prots.push_back(&ProtInfos[i]);
267}
268
269
270IBOutletCollectionInfo::IBOutletCollectionInfo(
271                                          const IBOutletCollectionInfo &other)
272  : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) {
273
274  IBCollInfo.attrInfo = this;
275  IBCollInfo.classCursor = other.IBCollInfo.classCursor;
276  IBCollInfo.classLoc = other.IBCollInfo.classLoc;
277  if (other.IBCollInfo.objcClass) {
278    ClassInfo = other.ClassInfo;
279    IBCollInfo.objcClass = &ClassInfo;
280  } else
281    IBCollInfo.objcClass = nullptr;
282}
283
284AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
285  : SA(IdxCtx), ref_cnt(0) {
286
287  if (!D->hasAttrs())
288    return;
289
290  for (const auto *A : D->attrs()) {
291    CXCursor C = MakeCXCursor(A, D, IdxCtx.CXTU);
292    CXIdxLoc Loc =  IdxCtx.getIndexLoc(A->getLocation());
293    switch (C.kind) {
294    default:
295      Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A));
296      break;
297    case CXCursor_IBActionAttr:
298      Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A));
299      break;
300    case CXCursor_IBOutletAttr:
301      Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A));
302      break;
303    case CXCursor_IBOutletCollectionAttr:
304      IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A));
305      break;
306    }
307  }
308
309  for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) {
310    IBOutletCollectionInfo &IBInfo = IBCollAttrs[i];
311    CXAttrs.push_back(&IBInfo);
312
313    const IBOutletCollectionAttr *
314      IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
315    SourceLocation InterfaceLocStart =
316        IBAttr->getInterfaceLoc()->getTypeLoc().getBeginLoc();
317    IBInfo.IBCollInfo.attrInfo = &IBInfo;
318    IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(InterfaceLocStart);
319    IBInfo.IBCollInfo.objcClass = nullptr;
320    IBInfo.IBCollInfo.classCursor = clang_getNullCursor();
321    QualType Ty = IBAttr->getInterface();
322    if (const ObjCObjectType *ObjectTy = Ty->getAs<ObjCObjectType>()) {
323      if (const ObjCInterfaceDecl *InterD = ObjectTy->getInterface()) {
324        IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA);
325        IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo;
326        IBInfo.IBCollInfo.classCursor =
327            MakeCursorObjCClassRef(InterD, InterfaceLocStart, IdxCtx.CXTU);
328      }
329    }
330  }
331
332  for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
333    CXAttrs.push_back(&Attrs[i]);
334}
335
336IntrusiveRefCntPtr<AttrListInfo>
337AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) {
338  ScratchAlloc SA(IdxCtx);
339  AttrListInfo *attrs = SA.allocate<AttrListInfo>();
340  return new (attrs) AttrListInfo(D, IdxCtx);
341}
342
343CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
344                                   CXIndexDataConsumer &IdxCtx,
345                                   ScratchAlloc &SA) {
346  for (const auto &Base : D->bases()) {
347    BaseEntities.push_back(EntityInfo());
348    const NamedDecl *BaseD = nullptr;
349    QualType T = Base.getType();
350    SourceLocation Loc = getBaseLoc(Base);
351
352    if (const TypedefType *TDT = T->getAs<TypedefType>()) {
353      BaseD = TDT->getDecl();
354    } else if (const TemplateSpecializationType *
355          TST = T->getAs<TemplateSpecializationType>()) {
356      BaseD = TST->getTemplateName().getAsTemplateDecl();
357    } else if (const RecordType *RT = T->getAs<RecordType>()) {
358      BaseD = RT->getDecl();
359    }
360
361    if (BaseD)
362      IdxCtx.getEntityInfo(BaseD, BaseEntities.back(), SA);
363    CXIdxBaseClassInfo BaseInfo = { nullptr,
364                         MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU),
365                         IdxCtx.getIndexLoc(Loc) };
366    BaseInfos.push_back(BaseInfo);
367  }
368
369  for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) {
370    if (BaseEntities[i].name && BaseEntities[i].USR)
371      BaseInfos[i].base = &BaseEntities[i];
372  }
373
374  for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i)
375    CXBases.push_back(&BaseInfos[i]);
376}
377
378SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
379                                           const CXXBaseSpecifier &Base) const {
380  SourceLocation Loc = Base.getSourceRange().getBegin();
381  TypeLoc TL;
382  if (Base.getTypeSourceInfo())
383    TL = Base.getTypeSourceInfo()->getTypeLoc();
384  if (TL.isNull())
385    return Loc;
386
387  if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>())
388    TL = QL.getUnqualifiedLoc();
389
390  if (ElaboratedTypeLoc EL = TL.getAs<ElaboratedTypeLoc>())
391    return EL.getNamedTypeLoc().getBeginLoc();
392  if (DependentNameTypeLoc DL = TL.getAs<DependentNameTypeLoc>())
393    return DL.getNameLoc();
394  if (DependentTemplateSpecializationTypeLoc DTL =
395          TL.getAs<DependentTemplateSpecializationTypeLoc>())
396    return DTL.getTemplateNameLoc();
397
398  return Loc;
399}
400
401const char *ScratchAlloc::toCStr(StringRef Str) {
402  if (Str.empty())
403    return "";
404  if (Str.data()[Str.size()] == '\0')
405    return Str.data();
406  return copyCStr(Str);
407}
408
409const char *ScratchAlloc::copyCStr(StringRef Str) {
410  char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1);
411  std::uninitialized_copy(Str.begin(), Str.end(), buf);
412  buf[Str.size()] = '\0';
413  return buf;
414}
415
416void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
417  Ctx = &ctx;
418  cxtu::getASTUnit(CXTU)->setASTContext(&ctx);
419}
420
421void CXIndexDataConsumer::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
422  cxtu::getASTUnit(CXTU)->setPreprocessor(std::move(PP));
423}
424
425bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) {
426  assert(D);
427
428  if (!D->getParentFunctionOrMethod())
429    return false;
430
431  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
432    switch (ND->getFormalLinkage()) {
433    case NoLinkage:
434    case InternalLinkage:
435      return true;
436    case VisibleNoLinkage:
437    case ModuleInternalLinkage:
438    case UniqueExternalLinkage:
439      llvm_unreachable("Not a sema linkage");
440    case ModuleLinkage:
441    case ExternalLinkage:
442      return false;
443    }
444  }
445
446  return true;
447}
448
449bool CXIndexDataConsumer::shouldAbort() {
450  if (!CB.abortQuery)
451    return false;
452  return CB.abortQuery(ClientData, nullptr);
453}
454
455void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) {
456  if (File && CB.enteredMainFile) {
457    CXIdxClientFile idxFile =
458      CB.enteredMainFile(ClientData,
459                         static_cast<CXFile>(const_cast<FileEntry *>(File)),
460                         nullptr);
461    FileMap[File] = idxFile;
462  }
463}
464
465void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
466                                         StringRef filename,
467                                         OptionalFileEntryRef File,
468                                         bool isImport, bool isAngled,
469                                         bool isModuleImport) {
470  if (!CB.ppIncludedFile)
471    return;
472
473  const FileEntry *FE = File ? &File->getFileEntry() : nullptr;
474
475  ScratchAlloc SA(*this);
476  CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
477                                 SA.toCStr(filename),
478                                 static_cast<CXFile>(
479                                   const_cast<FileEntry *>(FE)),
480                                 isImport, isAngled, isModuleImport };
481  CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
482  FileMap[FE] = idxFile;
483}
484
485void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
486  if (!CB.importedASTFile)
487    return;
488
489  Module *Mod = ImportD->getImportedModule();
490  if (!Mod)
491    return;
492
493  // If the imported module is part of the top-level module that we're
494  // indexing, it doesn't correspond to an imported AST file.
495  // FIXME: This assumes that AST files and top-level modules directly
496  // correspond, which is unlikely to remain true forever.
497  if (Module *SrcMod = ImportD->getImportedOwningModule())
498    if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule())
499      return;
500
501  FileEntry *FE = nullptr;
502  if (auto File = Mod->getASTFile())
503    FE = const_cast<FileEntry *>(&File->getFileEntry());
504  CXIdxImportedASTFileInfo Info = {static_cast<CXFile>(FE), Mod,
505                                   getIndexLoc(ImportD->getLocation()),
506                                   ImportD->isImplicit()};
507  CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
508  (void)astFile;
509}
510
511void CXIndexDataConsumer::importedPCH(const FileEntry *File) {
512  if (!CB.importedASTFile)
513    return;
514
515  CXIdxImportedASTFileInfo Info = {
516                                    static_cast<CXFile>(
517                                      const_cast<FileEntry *>(File)),
518                                    /*module=*/nullptr,
519                                    getIndexLoc(SourceLocation()),
520                                    /*isImplicit=*/false
521                                  };
522  CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
523  (void)astFile;
524}
525
526void CXIndexDataConsumer::startedTranslationUnit() {
527  CXIdxClientContainer idxCont = nullptr;
528  if (CB.startedTranslationUnit)
529    idxCont = CB.startedTranslationUnit(ClientData, nullptr);
530  addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
531}
532
533void CXIndexDataConsumer::indexDiagnostics() {
534  if (!hasDiagnosticCallback())
535    return;
536
537  CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU());
538  handleDiagnosticSet(DiagSet);
539}
540
541void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
542  if (!CB.diagnostic)
543    return;
544
545  CB.diagnostic(ClientData, CXDiagSet, nullptr);
546}
547
548bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
549                                 SourceLocation Loc, CXCursor Cursor,
550                                 DeclInfo &DInfo,
551                                 const DeclContext *LexicalDC,
552                                 const DeclContext *SemaDC) {
553  if (!CB.indexDeclaration || !D)
554    return false;
555  if (D->isImplicit() && shouldIgnoreIfImplicit(D))
556    return false;
557
558  ScratchAlloc SA(*this);
559  getEntityInfo(D, DInfo.EntInfo, SA);
560  if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR)
561      || Loc.isInvalid())
562    return false;
563
564  if (!LexicalDC)
565    LexicalDC = D->getLexicalDeclContext();
566
567  if (shouldSuppressRefs())
568    markEntityOccurrenceInFile(D, Loc);
569
570  DInfo.entityInfo = &DInfo.EntInfo;
571  DInfo.cursor = Cursor;
572  DInfo.loc = getIndexLoc(Loc);
573  DInfo.isImplicit = D->isImplicit();
574
575  DInfo.attributes = DInfo.EntInfo.attributes;
576  DInfo.numAttributes = DInfo.EntInfo.numAttributes;
577
578  if (!SemaDC)
579    SemaDC = D->getDeclContext();
580  getContainerInfo(SemaDC, DInfo.SemanticContainer);
581  DInfo.semanticContainer = &DInfo.SemanticContainer;
582
583  if (LexicalDC == SemaDC) {
584    DInfo.lexicalContainer = &DInfo.SemanticContainer;
585  } else if (isTemplateImplicitInstantiation(D)) {
586    // Implicit instantiations have the lexical context of where they were
587    // instantiated first. We choose instead the semantic context because:
588    // 1) at the time that we see the instantiation we have not seen the
589    //   function where it occurred yet.
590    // 2) the lexical context of the first instantiation is not useful
591    //   information anyway.
592    DInfo.lexicalContainer = &DInfo.SemanticContainer;
593  } else {
594    getContainerInfo(LexicalDC, DInfo.LexicalContainer);
595    DInfo.lexicalContainer = &DInfo.LexicalContainer;
596  }
597
598  if (DInfo.isContainer) {
599    getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer);
600    DInfo.declAsContainer = &DInfo.DeclAsContainer;
601  }
602
603  CB.indexDeclaration(ClientData, &DInfo);
604  return true;
605}
606
607bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
608                                          SourceLocation Loc, CXCursor Cursor,
609                                          ObjCContainerDeclInfo &ContDInfo) {
610  ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
611  return handleDecl(D, Loc, Cursor, ContDInfo);
612}
613
614bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) {
615  bool isDef = D->isThisDeclarationADefinition();
616  bool isContainer = isDef;
617  bool isSkipped = false;
618  if (D->hasSkippedBody()) {
619    isSkipped = true;
620    isDef = true;
621    isContainer = false;
622  }
623
624  DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer);
625  if (isSkipped)
626    DInfo.flags |= CXIdxDeclFlag_Skipped;
627  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
628}
629
630bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
631  DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
632                 /*isContainer=*/false);
633  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
634}
635
636bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
637  DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
638                 /*isContainer=*/false);
639  return handleDecl(D, D->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(D, D->getLocation(), getCursor(D), DInfo);
646}
647
648bool 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
657bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
658  DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
659                 /*isContainer=*/false);
660  return handleDecl(D, D->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(D, D->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=*/true, isRedeclaration,
672                                    /*isImplementation=*/false);
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
711bool CXIndexDataConsumer::handleObjCImplementation(
712                                              const ObjCImplementationDecl *D) {
713  ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
714                      /*isRedeclaration=*/true,
715                      /*isImplementation=*/true);
716  return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
717}
718
719bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
720  if (!D->isThisDeclarationADefinition()) {
721    if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->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(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
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(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
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(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
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(), isDef, isContainer);
821  if (isSkipped)
822    DInfo.flags |= CXIdxDeclFlag_Skipped;
823  return handleDecl(D, Loc, getCursor(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(D, Loc, getCursor(D), DInfo, LexicalDC, D->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(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
867bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
868  DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
869                 /*isDefinition=*/true,
870                 /*isContainer=*/true);
871  return handleDecl(D, D->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(D, D->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(D, D->getLocation(), getCursor(D), DInfo);
889}
890
891bool CXIndexDataConsumer::handleConcept(const ConceptDecl *D) {
892  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
893                 /*isDefinition=*/true, /*isContainer=*/false);
894  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
895}
896
897bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
898                                      CXCursor Cursor,
899                                      const NamedDecl *Parent,
900                                      const DeclContext *DC,
901                                      const Expr *E,
902                                      CXIdxEntityRefKind Kind,
903                                      CXSymbolRole Role) {
904  if (!CB.indexEntityReference)
905    return false;
906
907  if (!D || !DC)
908    return false;
909  if (Loc.isInvalid())
910    return false;
911  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
912    return false;
913  if (isNotFromSourceFile(D->getLocation()))
914    return false;
915  if (D->isImplicit() && shouldIgnoreIfImplicit(D))
916    return false;
917
918  if (shouldSuppressRefs()) {
919    if (markEntityOccurrenceInFile(D, Loc))
920      return false; // already occurred.
921  }
922
923  ScratchAlloc SA(*this);
924  EntityInfo RefEntity, ParentEntity;
925  getEntityInfo(D, RefEntity, SA);
926  if (!RefEntity.USR)
927    return false;
928
929  getEntityInfo(Parent, ParentEntity, SA);
930
931  ContainerInfo Container;
932  getContainerInfo(DC, Container);
933
934  CXIdxEntityRefInfo Info = { Kind,
935                              Cursor,
936                              getIndexLoc(Loc),
937                              &RefEntity,
938                              Parent ? &ParentEntity : nullptr,
939                              &Container,
940                              Role };
941  CB.indexEntityReference(ClientData, &Info);
942  return true;
943}
944
945bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const {
946  if (Loc.isInvalid())
947    return true;
948  SourceManager &SM = Ctx->getSourceManager();
949  SourceLocation FileLoc = SM.getFileLoc(Loc);
950  FileID FID = SM.getFileID(FileLoc);
951  return SM.getFileEntryForID(FID) == nullptr;
952}
953
954void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC,
955                                        CXIdxClientContainer container) {
956  if (!DC)
957    return;
958
959  ContainerMapTy::iterator I = ContainerMap.find(DC);
960  if (I == ContainerMap.end()) {
961    if (container)
962      ContainerMap[DC] = container;
963    return;
964  }
965  // Allow changing the container of a previously seen DeclContext so we
966  // can handle invalid user code, like a function re-definition.
967  if (container)
968    I->second = container;
969  else
970    ContainerMap.erase(I);
971}
972
973CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const {
974  if (!D)
975    return nullptr;
976  EntityMapTy::const_iterator I = EntityMap.find(D);
977  if (I == EntityMap.end())
978    return nullptr;
979  return I->second;
980}
981
982void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) {
983  if (!D)
984    return;
985  EntityMap[D] = client;
986}
987
988bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
989                                          const NamedDecl *OrigD) {
990  if (RD->isThisDeclarationADefinition()) {
991    ScratchAlloc SA(*this);
992    CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
993                           /*isDefinition=*/RD->isThisDeclarationADefinition());
994    CXXBasesListInfo BaseList(RD, *this, SA);
995    CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
996    CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
997    CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
998
999    if (shouldSuppressRefs()) {
1000      // Go through bases and mark them as referenced.
1001      for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) {
1002        const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i];
1003        if (baseInfo->base) {
1004          const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl;
1005          SourceLocation
1006            Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data);
1007          markEntityOccurrenceInFile(BaseD, Loc);
1008        }
1009      }
1010    }
1011
1012    return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo);
1013  }
1014
1015  DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
1016                 /*isDefinition=*/RD->isThisDeclarationADefinition(),
1017                 /*isContainer=*/RD->isThisDeclarationADefinition());
1018  return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
1019}
1020
1021bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D,
1022                                                 SourceLocation Loc) {
1023  if (!D || Loc.isInvalid())
1024    return true;
1025
1026  SourceManager &SM = Ctx->getSourceManager();
1027  D = getEntityDecl(D);
1028
1029  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc));
1030  FileID FID = LocInfo.first;
1031  if (FID.isInvalid())
1032    return true;
1033
1034  const FileEntry *FE = SM.getFileEntryForID(FID);
1035  if (!FE)
1036    return true;
1037  RefFileOccurrence RefOccur(FE, D);
1038  std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool>
1039  res = RefFileOccurrences.insert(RefOccur);
1040  return !res.second; // already in map
1041}
1042
1043const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const {
1044  assert(D);
1045  D = cast<NamedDecl>(D->getCanonicalDecl());
1046
1047  if (const ObjCImplementationDecl *
1048               ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
1049    return getEntityDecl(ImplD->getClassInterface());
1050
1051  } else if (const ObjCCategoryImplDecl *
1052               CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) {
1053    return getEntityDecl(CatImplD->getCategoryDecl());
1054  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1055    if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate())
1056      return getEntityDecl(TemplD);
1057  } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
1058    if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate())
1059      return getEntityDecl(TemplD);
1060  }
1061
1062  return D;
1063}
1064
1065const DeclContext *
1066CXIndexDataConsumer::getEntityContainer(const Decl *D) const {
1067  const DeclContext *DC = dyn_cast<DeclContext>(D);
1068  if (DC)
1069    return DC;
1070
1071  if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) {
1072    DC = ClassTempl->getTemplatedDecl();
1073  } else if (const FunctionTemplateDecl *
1074          FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) {
1075    DC = FuncTempl->getTemplatedDecl();
1076  }
1077
1078  return DC;
1079}
1080
1081CXIdxClientContainer
1082CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const {
1083  if (!DC)
1084    return nullptr;
1085
1086  ContainerMapTy::const_iterator I = ContainerMap.find(DC);
1087  if (I == ContainerMap.end())
1088    return nullptr;
1089
1090  return I->second;
1091}
1092
1093CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) {
1094  if (!File)
1095    return nullptr;
1096
1097  FileMapTy::iterator FI = FileMap.find(File);
1098  if (FI != FileMap.end())
1099    return FI->second;
1100
1101  return nullptr;
1102}
1103
1104CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const {
1105  CXIdxLoc idxLoc =  { {nullptr, nullptr}, 0 };
1106  if (Loc.isInvalid())
1107    return idxLoc;
1108
1109  idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this);
1110  idxLoc.int_data = Loc.getRawEncoding();
1111  return idxLoc;
1112}
1113
1114void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
1115                                   CXIdxClientFile *indexFile, CXFile *file,
1116                                   unsigned *line, unsigned *column,
1117                                   unsigned *offset) {
1118  if (Loc.isInvalid())
1119    return;
1120
1121  SourceManager &SM = Ctx->getSourceManager();
1122  Loc = SM.getFileLoc(Loc);
1123
1124  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
1125  FileID FID = LocInfo.first;
1126  unsigned FileOffset = LocInfo.second;
1127
1128  if (FID.isInvalid())
1129    return;
1130
1131  const FileEntry *FE = SM.getFileEntryForID(FID);
1132  if (indexFile)
1133    *indexFile = getIndexFile(FE);
1134  if (file)
1135    *file = const_cast<FileEntry *>(FE);
1136  if (line)
1137    *line = SM.getLineNumber(FID, FileOffset);
1138  if (column)
1139    *column = SM.getColumnNumber(FID, FileOffset);
1140  if (offset)
1141    *offset = FileOffset;
1142}
1143
1144static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L);
1145static CXIdxEntityCXXTemplateKind
1146getEntityKindFromSymbolProperties(SymbolPropertySet K);
1147static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
1148
1149void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
1150                                    EntityInfo &EntityInfo,
1151                                    ScratchAlloc &SA) {
1152  if (!D)
1153    return;
1154
1155  D = getEntityDecl(D);
1156  EntityInfo.cursor = getCursor(D);
1157  EntityInfo.Dcl = D;
1158  EntityInfo.IndexCtx = this;
1159
1160  SymbolInfo SymInfo = getSymbolInfo(D);
1161  EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind, SymInfo.Lang);
1162  EntityInfo.templateKind = getEntityKindFromSymbolProperties(SymInfo.Properties);
1163  EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang);
1164
1165  if (D->hasAttrs()) {
1166    EntityInfo.AttrList = AttrListInfo::create(D, *this);
1167    EntityInfo.attributes = EntityInfo.AttrList->getAttrs();
1168    EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
1169  }
1170
1171  if (EntityInfo.kind == CXIdxEntity_Unexposed)
1172    return;
1173
1174  if (IdentifierInfo *II = D->getIdentifier()) {
1175    EntityInfo.name = SA.toCStr(II->getName());
1176
1177  } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) {
1178    EntityInfo.name = nullptr; // anonymous tag/field/namespace.
1179
1180  } else {
1181    SmallString<256> StrBuf;
1182    {
1183      llvm::raw_svector_ostream OS(StrBuf);
1184      D->printName(OS);
1185    }
1186    EntityInfo.name = SA.copyCStr(StrBuf.str());
1187  }
1188
1189  {
1190    SmallString<512> StrBuf;
1191    bool Ignore = getDeclCursorUSR(D, StrBuf);
1192    if (Ignore) {
1193      EntityInfo.USR = nullptr;
1194    } else {
1195      EntityInfo.USR = SA.copyCStr(StrBuf.str());
1196    }
1197  }
1198}
1199
1200void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC,
1201                                       ContainerInfo &ContInfo) {
1202  ContInfo.cursor = getCursor(cast<Decl>(DC));
1203  ContInfo.DC = DC;
1204  ContInfo.IndexCtx = this;
1205}
1206
1207CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
1208  if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
1209    return MakeCursorTypeRef(TD, Loc, CXTU);
1210  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
1211    return MakeCursorObjCClassRef(ID, Loc, CXTU);
1212  if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
1213    return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
1214  if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
1215    return MakeCursorTemplateRef(Template, Loc, CXTU);
1216  if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
1217    return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1218  if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
1219    return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1220  if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
1221    return MakeCursorMemberRef(Field, Loc, CXTU);
1222  if (const VarDecl *Var = dyn_cast<VarDecl>(D))
1223    return MakeCursorVariableRef(Var, Loc, CXTU);
1224
1225  return clang_getNullCursor();
1226}
1227
1228bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) {
1229  if (isa<ObjCInterfaceDecl>(D))
1230    return false;
1231  if (isa<ObjCCategoryDecl>(D))
1232    return false;
1233  if (isa<ObjCIvarDecl>(D))
1234    return false;
1235  if (isa<ObjCMethodDecl>(D))
1236    return false;
1237  if (isa<ImportDecl>(D))
1238    return false;
1239  return true;
1240}
1241
1242bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) {
1243  if (const ClassTemplateSpecializationDecl *
1244        SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1245    return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
1246  }
1247  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1248    return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
1249  }
1250  return false;
1251}
1252
1253static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage Lang) {
1254  switch (K) {
1255  case SymbolKind::Unknown:
1256  case SymbolKind::Module:
1257  case SymbolKind::Macro:
1258  case SymbolKind::ClassProperty:
1259  case SymbolKind::Using:
1260  case SymbolKind::TemplateTypeParm:
1261  case SymbolKind::TemplateTemplateParm:
1262  case SymbolKind::NonTypeTemplateParm:
1263    return CXIdxEntity_Unexposed;
1264
1265  case SymbolKind::Enum: return CXIdxEntity_Enum;
1266  case SymbolKind::Struct: return CXIdxEntity_Struct;
1267  case SymbolKind::Union: return CXIdxEntity_Union;
1268  case SymbolKind::TypeAlias:
1269    if (Lang == SymbolLanguage::CXX)
1270      return CXIdxEntity_CXXTypeAlias;
1271    return CXIdxEntity_Typedef;
1272  case SymbolKind::Function: return CXIdxEntity_Function;
1273  case SymbolKind::Variable: return CXIdxEntity_Variable;
1274  case SymbolKind::Field:
1275    if (Lang == SymbolLanguage::ObjC)
1276      return CXIdxEntity_ObjCIvar;
1277    return CXIdxEntity_Field;
1278  case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant;
1279  case SymbolKind::Class:
1280    if (Lang == SymbolLanguage::ObjC)
1281      return CXIdxEntity_ObjCClass;
1282    return CXIdxEntity_CXXClass;
1283  case SymbolKind::Protocol:
1284    if (Lang == SymbolLanguage::ObjC)
1285      return CXIdxEntity_ObjCProtocol;
1286    return CXIdxEntity_CXXInterface;
1287  case SymbolKind::Extension: return CXIdxEntity_ObjCCategory;
1288  case SymbolKind::InstanceMethod:
1289    if (Lang == SymbolLanguage::ObjC)
1290      return CXIdxEntity_ObjCInstanceMethod;
1291    return CXIdxEntity_CXXInstanceMethod;
1292  case SymbolKind::ClassMethod: return CXIdxEntity_ObjCClassMethod;
1293  case SymbolKind::StaticMethod: return CXIdxEntity_CXXStaticMethod;
1294  case SymbolKind::InstanceProperty: return CXIdxEntity_ObjCProperty;
1295  case SymbolKind::StaticProperty: return CXIdxEntity_CXXStaticVariable;
1296  case SymbolKind::Namespace: return CXIdxEntity_CXXNamespace;
1297  case SymbolKind::NamespaceAlias: return CXIdxEntity_CXXNamespaceAlias;
1298  case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor;
1299  case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor;
1300  case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction;
1301  case SymbolKind::Parameter: return CXIdxEntity_Variable;
1302  case SymbolKind::Concept:
1303    return CXIdxEntity_CXXConcept;
1304  }
1305  llvm_unreachable("invalid symbol kind");
1306}
1307
1308static CXIdxEntityCXXTemplateKind
1309getEntityKindFromSymbolProperties(SymbolPropertySet K) {
1310  if (K & (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization)
1311    return CXIdxEntity_TemplatePartialSpecialization;
1312  if (K & (SymbolPropertySet)SymbolProperty::TemplateSpecialization)
1313    return CXIdxEntity_TemplateSpecialization;
1314  if (K & (SymbolPropertySet)SymbolProperty::Generic)
1315    return CXIdxEntity_Template;
1316  return CXIdxEntity_NonTemplate;
1317}
1318
1319static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
1320  switch (L) {
1321  case SymbolLanguage::C: return CXIdxEntityLang_C;
1322  case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
1323  case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
1324  case SymbolLanguage::Swift: return CXIdxEntityLang_Swift;
1325  }
1326  llvm_unreachable("invalid symbol language");
1327}
1328