IndexingContext.cpp revision 58d2dbea680a75de266c5eff77cc15c323cfd48a
1//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "IndexingContext.h"
11#include "CXTranslationUnit.h"
12#include "CIndexDiagnostic.h"
13
14#include "clang/Frontend/ASTUnit.h"
15#include "clang/AST/DeclCXX.h"
16#include "clang/AST/DeclTemplate.h"
17
18using namespace clang;
19using namespace cxindex;
20using namespace cxcursor;
21
22IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo(
23                                    const ObjCProtocolList &ProtList,
24                                    IndexingContext &IdxCtx,
25                                    ScratchAlloc &SA) {
26  ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
27  for (ObjCInterfaceDecl::protocol_iterator
28         I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
29    SourceLocation Loc = *LI;
30    ObjCProtocolDecl *PD = *I;
31    ProtEntities.push_back(EntityInfo());
32    IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA);
33    CXIdxObjCProtocolRefInfo ProtInfo = { 0,
34                                MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU),
35                                IdxCtx.getIndexLoc(Loc) };
36    ProtInfos.push_back(ProtInfo);
37
38    if (IdxCtx.shouldSuppressRefs())
39      IdxCtx.markEntityOccurrenceInFile(PD, Loc);
40  }
41
42  for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
43    ProtInfos[i].protocol = &ProtEntities[i];
44
45  for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
46    Prots.push_back(&ProtInfos[i]);
47}
48
49
50IBOutletCollectionInfo::IBOutletCollectionInfo(
51                                          const IBOutletCollectionInfo &other)
52  : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) {
53
54  IBCollInfo.attrInfo = this;
55  IBCollInfo.classCursor = other.IBCollInfo.classCursor;
56  IBCollInfo.classLoc = other.IBCollInfo.classLoc;
57  if (other.IBCollInfo.objcClass) {
58    ClassInfo = other.ClassInfo;
59    IBCollInfo.objcClass = &ClassInfo;
60  } else
61    IBCollInfo.objcClass = 0;
62}
63
64AttrListInfo::AttrListInfo(const Decl *D,
65                           IndexingContext &IdxCtx,
66                           ScratchAlloc &SA) : ref_cnt(0) {
67  if (!D->hasAttrs())
68    return;
69
70  for (AttrVec::const_iterator AttrI = D->attr_begin(), AttrE = D->attr_end();
71         AttrI != AttrE; ++AttrI) {
72    const Attr *A = *AttrI;
73    CXCursor C = MakeCXCursor(A, const_cast<Decl *>(D), IdxCtx.CXTU);
74    CXIdxLoc Loc =  IdxCtx.getIndexLoc(A->getLocation());
75    switch (C.kind) {
76    default:
77      Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A));
78      break;
79    case CXCursor_IBActionAttr:
80      Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A));
81      break;
82    case CXCursor_IBOutletAttr:
83      Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A));
84      break;
85    case CXCursor_IBOutletCollectionAttr:
86      IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A));
87      break;
88    }
89  }
90
91  for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) {
92    IBOutletCollectionInfo &IBInfo = IBCollAttrs[i];
93    CXAttrs.push_back(&IBInfo);
94
95    const IBOutletCollectionAttr *
96      IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
97    IBInfo.IBCollInfo.attrInfo = &IBInfo;
98    IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(IBAttr->getInterfaceLoc());
99    IBInfo.IBCollInfo.objcClass = 0;
100    IBInfo.IBCollInfo.classCursor = clang_getNullCursor();
101    QualType Ty = IBAttr->getInterface();
102    if (const ObjCInterfaceType *InterTy = Ty->getAs<ObjCInterfaceType>()) {
103      if (const ObjCInterfaceDecl *InterD = InterTy->getInterface()) {
104        IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA);
105        IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo;
106        IBInfo.IBCollInfo.classCursor = MakeCursorObjCClassRef(InterD,
107                                        IBAttr->getInterfaceLoc(), IdxCtx.CXTU);
108      }
109    }
110  }
111
112  for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
113    CXAttrs.push_back(&Attrs[i]);
114}
115
116AttrListInfo::AttrListInfo(const AttrListInfo &other) {
117  assert(other.ref_cnt == 0 &&
118         "Should not copy an AttrListInfo that is ref-counted");
119  ref_cnt = 0;
120
121  Attrs = other.Attrs;
122  IBCollAttrs = other.IBCollAttrs;
123
124  for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i)
125    CXAttrs.push_back(&IBCollAttrs[i]);
126
127  for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
128    CXAttrs.push_back(&Attrs[i]);
129}
130
131IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
132                                   IndexingContext &IdxCtx,
133                                   ScratchAlloc &SA) {
134  for (CXXRecordDecl::base_class_const_iterator
135         I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
136    const CXXBaseSpecifier &Base = *I;
137    BaseEntities.push_back(EntityInfo());
138    const NamedDecl *BaseD = 0;
139    QualType T = Base.getType();
140    SourceLocation Loc = getBaseLoc(Base);
141
142    if (const TypedefType *TDT = T->getAs<TypedefType>()) {
143      BaseD = TDT->getDecl();
144    } else if (const TemplateSpecializationType *
145          TST = T->getAs<TemplateSpecializationType>()) {
146      BaseD = TST->getTemplateName().getAsTemplateDecl();
147    } else if (const RecordType *RT = T->getAs<RecordType>()) {
148      BaseD = RT->getDecl();
149    }
150
151    if (BaseD)
152      IdxCtx.getEntityInfo(BaseD, BaseEntities.back(), SA);
153    CXIdxBaseClassInfo BaseInfo = { 0,
154                         MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU),
155                         IdxCtx.getIndexLoc(Loc) };
156    BaseInfos.push_back(BaseInfo);
157  }
158
159  for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) {
160    if (BaseEntities[i].name && BaseEntities[i].USR)
161      BaseInfos[i].base = &BaseEntities[i];
162  }
163
164  for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i)
165    CXBases.push_back(&BaseInfos[i]);
166}
167
168SourceLocation IndexingContext::CXXBasesListInfo::getBaseLoc(
169                                           const CXXBaseSpecifier &Base) const {
170  SourceLocation Loc = Base.getSourceRange().getBegin();
171  TypeLoc TL;
172  if (Base.getTypeSourceInfo())
173    TL = Base.getTypeSourceInfo()->getTypeLoc();
174  if (TL.isNull())
175    return Loc;
176
177  if (const QualifiedTypeLoc *QL = dyn_cast<QualifiedTypeLoc>(&TL))
178    TL = QL->getUnqualifiedLoc();
179
180  if (const ElaboratedTypeLoc *EL = dyn_cast<ElaboratedTypeLoc>(&TL))
181    return EL->getNamedTypeLoc().getBeginLoc();
182  if (const DependentNameTypeLoc *DL = dyn_cast<DependentNameTypeLoc>(&TL))
183    return DL->getNameLoc();
184  if (const DependentTemplateSpecializationTypeLoc *
185        DTL = dyn_cast<DependentTemplateSpecializationTypeLoc>(&TL))
186    return DTL->getTemplateNameLoc();
187
188  return Loc;
189}
190
191const char *ScratchAlloc::toCStr(StringRef Str) {
192  if (Str.empty())
193    return "";
194  if (Str.data()[Str.size()] == '\0')
195    return Str.data();
196  return copyCStr(Str);
197}
198
199const char *ScratchAlloc::copyCStr(StringRef Str) {
200  char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1);
201  std::uninitialized_copy(Str.begin(), Str.end(), buf);
202  buf[Str.size()] = '\0';
203  return buf;
204}
205
206void IndexingContext::setASTContext(ASTContext &ctx) {
207  Ctx = &ctx;
208  static_cast<ASTUnit*>(CXTU->TUData)->setASTContext(&ctx);
209}
210
211void IndexingContext::setPreprocessor(Preprocessor &PP) {
212  static_cast<ASTUnit*>(CXTU->TUData)->setPreprocessor(&PP);
213}
214
215bool IndexingContext::shouldAbort() {
216  if (!CB.abortQuery)
217    return false;
218  return CB.abortQuery(ClientData, 0);
219}
220
221void IndexingContext::enteredMainFile(const FileEntry *File) {
222  if (File && CB.enteredMainFile) {
223    CXIdxClientFile idxFile = CB.enteredMainFile(ClientData, (CXFile)File, 0);
224    FileMap[File] = idxFile;
225  }
226}
227
228void IndexingContext::ppIncludedFile(SourceLocation hashLoc,
229                                     StringRef filename,
230                                     const FileEntry *File,
231                                     bool isImport, bool isAngled) {
232  if (!CB.ppIncludedFile)
233    return;
234
235  ScratchAlloc SA(*this);
236  CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
237                                 SA.toCStr(filename),
238                                 (CXFile)File,
239                                 isImport, isAngled };
240  CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
241  FileMap[File] = idxFile;
242}
243
244void IndexingContext::startedTranslationUnit() {
245  CXIdxClientContainer idxCont = 0;
246  if (CB.startedTranslationUnit)
247    idxCont = CB.startedTranslationUnit(ClientData, 0);
248  addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
249}
250
251void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
252  if (!CB.diagnostic)
253    return;
254
255  CB.diagnostic(ClientData, CXDiagSet, 0);
256}
257
258bool IndexingContext::handleDecl(const NamedDecl *D,
259                                 SourceLocation Loc, CXCursor Cursor,
260                                 DeclInfo &DInfo) {
261  if (!CB.indexDeclaration || !D)
262    return false;
263  if (D->isImplicit() && shouldIgnoreIfImplicit(D))
264    return false;
265
266  ScratchAlloc SA(*this);
267  getEntityInfo(D, DInfo.EntInfo, SA);
268  if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR)
269      || Loc.isInvalid())
270    return false;
271
272  if (shouldSuppressRefs())
273    markEntityOccurrenceInFile(D, Loc);
274
275  DInfo.entityInfo = &DInfo.EntInfo;
276  DInfo.cursor = Cursor;
277  DInfo.loc = getIndexLoc(Loc);
278  DInfo.isImplicit = D->isImplicit();
279
280  AttrListInfo AttrList(D, *this, SA);
281  DInfo.attributes = AttrList.getAttrs();
282  DInfo.numAttributes = AttrList.getNumAttrs();
283
284  getContainerInfo(D->getDeclContext(), DInfo.SemanticContainer);
285  DInfo.semanticContainer = &DInfo.SemanticContainer;
286
287  if (D->getLexicalDeclContext() == D->getDeclContext()) {
288    DInfo.lexicalContainer = &DInfo.SemanticContainer;
289  } else if (isTemplateImplicitInstantiation(D)) {
290    // Implicit instantiations have the lexical context of where they were
291    // instantiated first. We choose instead the semantic context because:
292    // 1) at the time that we see the instantiation we have not seen the
293    //   function where it occurred yet.
294    // 2) the lexical context of the first instantiation is not useful
295    //   information anyway.
296    DInfo.lexicalContainer = &DInfo.SemanticContainer;
297  } else {
298    getContainerInfo(D->getLexicalDeclContext(), DInfo.LexicalContainer);
299    DInfo.lexicalContainer = &DInfo.LexicalContainer;
300  }
301
302  if (DInfo.isContainer) {
303    getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer);
304    DInfo.declAsContainer = &DInfo.DeclAsContainer;
305  }
306
307  CB.indexDeclaration(ClientData, &DInfo);
308  return true;
309}
310
311bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D,
312                                          SourceLocation Loc, CXCursor Cursor,
313                                          ObjCContainerDeclInfo &ContDInfo) {
314  ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
315  return handleDecl(D, Loc, Cursor, ContDInfo);
316}
317
318bool IndexingContext::handleFunction(const FunctionDecl *D) {
319  DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
320                 D->isThisDeclarationADefinition());
321  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
322}
323
324bool IndexingContext::handleVar(const VarDecl *D) {
325  DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
326                 /*isContainer=*/false);
327  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
328}
329
330bool IndexingContext::handleField(const FieldDecl *D) {
331  DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
332                 /*isContainer=*/false);
333  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
334}
335
336bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) {
337  DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
338                 /*isContainer=*/false);
339  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
340}
341
342bool IndexingContext::handleTagDecl(const TagDecl *D) {
343  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D))
344    return handleCXXRecordDecl(CXXRD, D);
345
346  DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(),
347                 D->isThisDeclarationADefinition());
348  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
349}
350
351bool IndexingContext::handleTypedefName(const TypedefNameDecl *D) {
352  DeclInfo DInfo(!D->isFirstDeclaration(), /*isDefinition=*/true,
353                 /*isContainer=*/false);
354  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
355}
356
357bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) {
358  // For @class forward declarations, suppress them the same way as references.
359  if (!D->isThisDeclarationADefinition()) {
360    if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
361      return false; // already occurred.
362
363    // FIXME: This seems like the wrong definition for redeclaration.
364    bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
365    ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration,
366                                    /*isImplementation=*/false);
367    return handleObjCContainer(D, D->getLocation(),
368                               MakeCursorObjCClassRef(D, D->getLocation(),
369                                                      CXTU),
370                               ContDInfo);
371  }
372
373  ScratchAlloc SA(*this);
374
375  CXIdxBaseClassInfo BaseClass;
376  EntityInfo BaseEntity;
377  BaseClass.cursor = clang_getNullCursor();
378  if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) {
379    getEntityInfo(SuperD, BaseEntity, SA);
380    SourceLocation SuperLoc = D->getSuperClassLoc();
381    BaseClass.base = &BaseEntity;
382    BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU);
383    BaseClass.loc = getIndexLoc(SuperLoc);
384
385    if (shouldSuppressRefs())
386      markEntityOccurrenceInFile(SuperD, SuperLoc);
387  }
388
389  ObjCProtocolList EmptyProtoList;
390  ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition()
391                                  ? D->getReferencedProtocols()
392                                  : EmptyProtoList,
393                                *this, SA);
394
395  ObjCInterfaceDeclInfo InterInfo(D);
396  InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
397  InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo;
398  InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass : 0;
399  InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo;
400
401  return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
402}
403
404bool IndexingContext::handleObjCImplementation(
405                                              const ObjCImplementationDecl *D) {
406  ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
407                      /*isRedeclaration=*/true,
408                      /*isImplementation=*/true);
409  return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
410}
411
412bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
413  if (!D->isThisDeclarationADefinition()) {
414    if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
415      return false; // already occurred.
416
417    // FIXME: This seems like the wrong definition for redeclaration.
418    bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
419    ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true,
420                                    isRedeclaration,
421                                    /*isImplementation=*/false);
422    return handleObjCContainer(D, D->getLocation(),
423                               MakeCursorObjCProtocolRef(D, D->getLocation(),
424                                                         CXTU),
425                               ContDInfo);
426  }
427
428  ScratchAlloc SA(*this);
429  ObjCProtocolList EmptyProtoList;
430  ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition()
431                                      ? D->getReferencedProtocols()
432                                      : EmptyProtoList,
433                                    *this, SA);
434
435  ObjCProtocolDeclInfo ProtInfo(D);
436  ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo();
437
438  return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
439}
440
441bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
442  ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
443  EntityInfo ClassEntity;
444  ScratchAlloc SA(*this);
445  const ObjCInterfaceDecl *IFaceD = D->getClassInterface();
446  SourceLocation ClassLoc = D->getLocation();
447  SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc
448                                                     : D->getCategoryNameLoc();
449  getEntityInfo(IFaceD, ClassEntity, SA);
450
451  if (shouldSuppressRefs())
452    markEntityOccurrenceInFile(IFaceD, ClassLoc);
453
454  ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA);
455
456  CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
457  if (IFaceD) {
458    CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
459    CatDInfo.ObjCCatDeclInfo.classCursor =
460        MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
461  } else {
462    CatDInfo.ObjCCatDeclInfo.objcClass = 0;
463    CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
464  }
465  CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
466  CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
467  CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo;
468
469  return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
470}
471
472bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
473  const ObjCCategoryDecl *CatD = D->getCategoryDecl();
474  ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
475  EntityInfo ClassEntity;
476  ScratchAlloc SA(*this);
477  const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface();
478  SourceLocation ClassLoc = D->getLocation();
479  SourceLocation CategoryLoc = D->getCategoryNameLoc();
480  getEntityInfo(IFaceD, ClassEntity, SA);
481
482  if (shouldSuppressRefs())
483    markEntityOccurrenceInFile(IFaceD, ClassLoc);
484
485  CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
486  if (IFaceD) {
487    CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
488    CatDInfo.ObjCCatDeclInfo.classCursor =
489        MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
490  } else {
491    CatDInfo.ObjCCatDeclInfo.objcClass = 0;
492    CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
493  }
494  CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
495  CatDInfo.ObjCCatDeclInfo.protocols = 0;
496
497  return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
498}
499
500bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) {
501  DeclInfo DInfo(!D->isCanonicalDecl(), D->isThisDeclarationADefinition(),
502                 D->isThisDeclarationADefinition());
503  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
504}
505
506bool IndexingContext::handleSynthesizedObjCProperty(
507                                                const ObjCPropertyImplDecl *D) {
508  ObjCPropertyDecl *PD = D->getPropertyDecl();
509  return handleReference(PD, D->getLocation(), getCursor(D), 0, D->getDeclContext());
510}
511
512bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
513                                                  SourceLocation Loc) {
514  DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
515                 /*isContainer=*/false);
516  return handleDecl(D, Loc, getCursor(D), DInfo);
517}
518
519bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
520  DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/false,
521                 /*isContainer=*/false);
522  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
523}
524
525bool IndexingContext::handleNamespace(const NamespaceDecl *D) {
526  DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
527                 /*isDefinition=*/true,
528                 /*isContainer=*/true);
529  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
530}
531
532bool IndexingContext::handleClassTemplate(const ClassTemplateDecl *D) {
533  return handleCXXRecordDecl(D->getTemplatedDecl(), D);
534}
535
536bool IndexingContext::handleFunctionTemplate(const FunctionTemplateDecl *D) {
537  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
538                 /*isDefinition=*/D->isThisDeclarationADefinition(),
539                 /*isContainer=*/D->isThisDeclarationADefinition());
540  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
541}
542
543bool IndexingContext::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
544  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
545                 /*isDefinition=*/true, /*isContainer=*/false);
546  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
547}
548
549bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
550                                      const NamedDecl *Parent,
551                                      const DeclContext *DC,
552                                      const Expr *E,
553                                      CXIdxEntityRefKind Kind) {
554  if (!D)
555    return false;
556
557  CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E),
558                                     const_cast<Decl*>(cast<Decl>(DC)), CXTU)
559                      : getRefCursor(D, Loc);
560  return handleReference(D, Loc, Cursor, Parent, DC, E, Kind);
561}
562
563bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
564                                      CXCursor Cursor,
565                                      const NamedDecl *Parent,
566                                      const DeclContext *DC,
567                                      const Expr *E,
568                                      CXIdxEntityRefKind Kind) {
569  if (!CB.indexEntityReference)
570    return false;
571
572  if (!D)
573    return false;
574  if (Loc.isInvalid())
575    return false;
576  if (!shouldIndexFunctionLocalSymbols() && D->getParentFunctionOrMethod())
577    return false;
578  if (isNotFromSourceFile(D->getLocation()))
579    return false;
580  if (D->isImplicit() && shouldIgnoreIfImplicit(D))
581    return false;
582
583  if (shouldSuppressRefs()) {
584    if (markEntityOccurrenceInFile(D, Loc))
585      return false; // already occurred.
586  }
587
588  ScratchAlloc SA(*this);
589  EntityInfo RefEntity, ParentEntity;
590  getEntityInfo(D, RefEntity, SA);
591  if (!RefEntity.USR)
592    return false;
593
594  getEntityInfo(Parent, ParentEntity, SA);
595
596  ContainerInfo Container;
597  getContainerInfo(DC, Container);
598
599  CXIdxEntityRefInfo Info = { Kind,
600                              Cursor,
601                              getIndexLoc(Loc),
602                              &RefEntity,
603                              Parent ? &ParentEntity : 0,
604                              &Container };
605  CB.indexEntityReference(ClientData, &Info);
606  return true;
607}
608
609bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
610  if (Loc.isInvalid())
611    return true;
612  SourceManager &SM = Ctx->getSourceManager();
613  SourceLocation FileLoc = SM.getFileLoc(Loc);
614  FileID FID = SM.getFileID(FileLoc);
615  return SM.getFileEntryForID(FID) == 0;
616}
617
618void IndexingContext::addContainerInMap(const DeclContext *DC,
619                                        CXIdxClientContainer container) {
620  if (!DC)
621    return;
622
623  ContainerMapTy::iterator I = ContainerMap.find(DC);
624  if (I == ContainerMap.end()) {
625    if (container)
626      ContainerMap[DC] = container;
627    return;
628  }
629  // Allow changing the container of a previously seen DeclContext so we
630  // can handle invalid user code, like a function re-definition.
631  if (container)
632    I->second = container;
633  else
634    ContainerMap.erase(I);
635}
636
637CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const {
638  if (!D)
639    return 0;
640  EntityMapTy::const_iterator I = EntityMap.find(D);
641  if (I == EntityMap.end())
642    return 0;
643  return I->second;
644}
645
646void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) {
647  if (!D)
648    return;
649  EntityMap[D] = client;
650}
651
652bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD,
653                                          const NamedDecl *OrigD) {
654  if (RD->isThisDeclarationADefinition()) {
655    ScratchAlloc SA(*this);
656    CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
657                           /*isDefinition=*/RD->isThisDeclarationADefinition());
658    CXXBasesListInfo BaseList(RD, *this, SA);
659    CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
660    CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
661    CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
662
663    if (shouldSuppressRefs()) {
664      // Go through bases and mark them as referenced.
665      for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) {
666        const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i];
667        if (baseInfo->base) {
668          const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl;
669          SourceLocation
670            Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data);
671          markEntityOccurrenceInFile(BaseD, Loc);
672        }
673      }
674    }
675
676    return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo);
677  }
678
679  DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
680                 /*isDefinition=*/RD->isThisDeclarationADefinition(),
681                 /*isContainer=*/RD->isThisDeclarationADefinition());
682  return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
683}
684
685bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
686                                                 SourceLocation Loc) {
687  if (!D || Loc.isInvalid())
688    return true;
689
690  SourceManager &SM = Ctx->getSourceManager();
691  D = getEntityDecl(D);
692
693  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc));
694  FileID FID = LocInfo.first;
695  if (FID.isInvalid())
696    return true;
697
698  const FileEntry *FE = SM.getFileEntryForID(FID);
699  if (!FE)
700    return true;
701  RefFileOccurence RefOccur(FE, D);
702  std::pair<llvm::DenseSet<RefFileOccurence>::iterator, bool>
703  res = RefFileOccurences.insert(RefOccur);
704  if (!res.second)
705    return true; // already in map.
706
707  return false;
708}
709
710const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
711  assert(D);
712  D = cast<NamedDecl>(D->getCanonicalDecl());
713
714  if (const ObjCImplementationDecl *
715               ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
716    return getEntityDecl(ImplD->getClassInterface());
717
718  } else if (const ObjCCategoryImplDecl *
719               CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) {
720    return getEntityDecl(CatImplD->getCategoryDecl());
721  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
722    if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate())
723      return getEntityDecl(TemplD);
724  } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
725    if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate())
726      return getEntityDecl(TemplD);
727  }
728
729  return D;
730}
731
732const DeclContext *
733IndexingContext::getEntityContainer(const Decl *D) const {
734  const DeclContext *DC = dyn_cast<DeclContext>(D);
735  if (DC)
736    return DC;
737
738  if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) {
739    DC = ClassTempl->getTemplatedDecl();
740  } if (const FunctionTemplateDecl *
741          FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) {
742    DC = FuncTempl->getTemplatedDecl();
743  }
744
745  return DC;
746}
747
748CXIdxClientContainer
749IndexingContext::getClientContainerForDC(const DeclContext *DC) const {
750  if (!DC)
751    return 0;
752
753  ContainerMapTy::const_iterator I = ContainerMap.find(DC);
754  if (I == ContainerMap.end())
755    return 0;
756
757  return I->second;
758}
759
760CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
761  if (!File)
762    return 0;
763
764  FileMapTy::iterator FI = FileMap.find(File);
765  if (FI != FileMap.end())
766    return FI->second;
767
768  return 0;
769}
770
771CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const {
772  CXIdxLoc idxLoc =  { {0, 0}, 0 };
773  if (Loc.isInvalid())
774    return idxLoc;
775
776  idxLoc.ptr_data[0] = (void*)this;
777  idxLoc.int_data = Loc.getRawEncoding();
778  return idxLoc;
779}
780
781void IndexingContext::translateLoc(SourceLocation Loc,
782                                   CXIdxClientFile *indexFile, CXFile *file,
783                                   unsigned *line, unsigned *column,
784                                   unsigned *offset) {
785  if (Loc.isInvalid())
786    return;
787
788  SourceManager &SM = Ctx->getSourceManager();
789  Loc = SM.getFileLoc(Loc);
790
791  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
792  FileID FID = LocInfo.first;
793  unsigned FileOffset = LocInfo.second;
794
795  if (FID.isInvalid())
796    return;
797
798  const FileEntry *FE = SM.getFileEntryForID(FID);
799  if (indexFile)
800    *indexFile = getIndexFile(FE);
801  if (file)
802    *file = (void *)FE;
803  if (line)
804    *line = SM.getLineNumber(FID, FileOffset);
805  if (column)
806    *column = SM.getColumnNumber(FID, FileOffset);
807  if (offset)
808    *offset = FileOffset;
809}
810
811void IndexingContext::getEntityInfo(const NamedDecl *D,
812                                    EntityInfo &EntityInfo,
813                                    ScratchAlloc &SA) {
814  if (!D)
815    return;
816
817  D = getEntityDecl(D);
818  EntityInfo.cursor = getCursor(D);
819  EntityInfo.Dcl = D;
820  EntityInfo.IndexCtx = this;
821  EntityInfo.kind = CXIdxEntity_Unexposed;
822  EntityInfo.templateKind = CXIdxEntity_NonTemplate;
823  EntityInfo.lang = CXIdxEntityLang_C;
824
825  if (D->hasAttrs()) {
826    AttrListInfo *attrs = SA.allocate<AttrListInfo>();
827    new (attrs) AttrListInfo(D, *this, SA);
828    EntityInfo.AttrList = attrs;
829    EntityInfo.attributes = attrs->getAttrs();
830    EntityInfo.numAttributes = attrs->getNumAttrs();
831  }
832
833  if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
834    switch (TD->getTagKind()) {
835    case TTK_Struct:
836      EntityInfo.kind = CXIdxEntity_Struct; break;
837    case TTK_Union:
838      EntityInfo.kind = CXIdxEntity_Union; break;
839    case TTK_Class:
840      EntityInfo.kind = CXIdxEntity_CXXClass;
841      EntityInfo.lang = CXIdxEntityLang_CXX;
842      break;
843    case TTK_Enum:
844      EntityInfo.kind = CXIdxEntity_Enum; break;
845    }
846
847    if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
848      if (!CXXRec->isCLike())
849        EntityInfo.lang = CXIdxEntityLang_CXX;
850
851    if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
852      EntityInfo.templateKind = CXIdxEntity_TemplatePartialSpecialization;
853    } else if (isa<ClassTemplateSpecializationDecl>(D)) {
854      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
855    }
856
857  } else {
858    switch (D->getKind()) {
859    case Decl::Typedef:
860      EntityInfo.kind = CXIdxEntity_Typedef; break;
861    case Decl::Function:
862      EntityInfo.kind = CXIdxEntity_Function;
863      break;
864    case Decl::ParmVar:
865      EntityInfo.kind = CXIdxEntity_Variable;
866      break;
867    case Decl::Var:
868      EntityInfo.kind = CXIdxEntity_Variable;
869      if (isa<CXXRecordDecl>(D->getDeclContext())) {
870        EntityInfo.kind = CXIdxEntity_CXXStaticVariable;
871        EntityInfo.lang = CXIdxEntityLang_CXX;
872      }
873      break;
874    case Decl::Field:
875      EntityInfo.kind = CXIdxEntity_Field;
876      if (const CXXRecordDecl *
877            CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
878        // FIXME: isPOD check is not sufficient, a POD can contain methods,
879        // we want a isCStructLike check.
880        if (!CXXRec->isPOD())
881          EntityInfo.lang = CXIdxEntityLang_CXX;
882      }
883      break;
884    case Decl::EnumConstant:
885      EntityInfo.kind = CXIdxEntity_EnumConstant; break;
886    case Decl::ObjCInterface:
887      EntityInfo.kind = CXIdxEntity_ObjCClass;
888      EntityInfo.lang = CXIdxEntityLang_ObjC;
889      break;
890    case Decl::ObjCProtocol:
891      EntityInfo.kind = CXIdxEntity_ObjCProtocol;
892      EntityInfo.lang = CXIdxEntityLang_ObjC;
893      break;
894    case Decl::ObjCCategory:
895      EntityInfo.kind = CXIdxEntity_ObjCCategory;
896      EntityInfo.lang = CXIdxEntityLang_ObjC;
897      break;
898    case Decl::ObjCMethod:
899      if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
900        EntityInfo.kind = CXIdxEntity_ObjCInstanceMethod;
901      else
902        EntityInfo.kind = CXIdxEntity_ObjCClassMethod;
903      EntityInfo.lang = CXIdxEntityLang_ObjC;
904      break;
905    case Decl::ObjCProperty:
906      EntityInfo.kind = CXIdxEntity_ObjCProperty;
907      EntityInfo.lang = CXIdxEntityLang_ObjC;
908      break;
909    case Decl::ObjCIvar:
910      EntityInfo.kind = CXIdxEntity_ObjCIvar;
911      EntityInfo.lang = CXIdxEntityLang_ObjC;
912      break;
913    case Decl::Namespace:
914      EntityInfo.kind = CXIdxEntity_CXXNamespace;
915      EntityInfo.lang = CXIdxEntityLang_CXX;
916      break;
917    case Decl::NamespaceAlias:
918      EntityInfo.kind = CXIdxEntity_CXXNamespaceAlias;
919      EntityInfo.lang = CXIdxEntityLang_CXX;
920      break;
921    case Decl::CXXConstructor:
922      EntityInfo.kind = CXIdxEntity_CXXConstructor;
923      EntityInfo.lang = CXIdxEntityLang_CXX;
924      break;
925    case Decl::CXXDestructor:
926      EntityInfo.kind = CXIdxEntity_CXXDestructor;
927      EntityInfo.lang = CXIdxEntityLang_CXX;
928      break;
929    case Decl::CXXConversion:
930      EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
931      EntityInfo.lang = CXIdxEntityLang_CXX;
932      break;
933    case Decl::CXXMethod: {
934      const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
935      if (MD->isStatic())
936        EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
937      else
938        EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
939      EntityInfo.lang = CXIdxEntityLang_CXX;
940      break;
941    }
942    case Decl::ClassTemplate:
943      EntityInfo.kind = CXIdxEntity_CXXClass;
944      EntityInfo.templateKind = CXIdxEntity_Template;
945      break;
946    case Decl::FunctionTemplate:
947      EntityInfo.kind = CXIdxEntity_Function;
948      EntityInfo.templateKind = CXIdxEntity_Template;
949      if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
950                           cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
951        if (isa<CXXConstructorDecl>(MD))
952          EntityInfo.kind = CXIdxEntity_CXXConstructor;
953        else if (isa<CXXDestructorDecl>(MD))
954          EntityInfo.kind = CXIdxEntity_CXXDestructor;
955        else if (isa<CXXConversionDecl>(MD))
956          EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
957        else {
958          if (MD->isStatic())
959            EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
960          else
961            EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
962        }
963      }
964      break;
965    case Decl::TypeAliasTemplate:
966      EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
967      EntityInfo.templateKind = CXIdxEntity_Template;
968      break;
969    case Decl::TypeAlias:
970      EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
971      EntityInfo.lang = CXIdxEntityLang_CXX;
972      break;
973    default:
974      break;
975    }
976  }
977
978  if (EntityInfo.kind == CXIdxEntity_Unexposed)
979    return;
980
981  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
982    if (FD->getTemplatedKind() ==
983          FunctionDecl::TK_FunctionTemplateSpecialization)
984      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
985  }
986
987  if (EntityInfo.templateKind != CXIdxEntity_NonTemplate)
988    EntityInfo.lang = CXIdxEntityLang_CXX;
989
990  if (IdentifierInfo *II = D->getIdentifier()) {
991    EntityInfo.name = SA.toCStr(II->getName());
992
993  } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) {
994    EntityInfo.name = 0; // anonymous tag/field/namespace.
995
996  } else {
997    SmallString<256> StrBuf;
998    {
999      llvm::raw_svector_ostream OS(StrBuf);
1000      D->printName(OS);
1001    }
1002    EntityInfo.name = SA.copyCStr(StrBuf.str());
1003  }
1004
1005  {
1006    SmallString<512> StrBuf;
1007    bool Ignore = getDeclCursorUSR(D, StrBuf);
1008    if (Ignore) {
1009      EntityInfo.USR = 0;
1010    } else {
1011      EntityInfo.USR = SA.copyCStr(StrBuf.str());
1012    }
1013  }
1014}
1015
1016void IndexingContext::getContainerInfo(const DeclContext *DC,
1017                                       ContainerInfo &ContInfo) {
1018  ContInfo.cursor = getCursor(cast<Decl>(DC));
1019  ContInfo.DC = DC;
1020  ContInfo.IndexCtx = this;
1021}
1022
1023CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
1024  if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
1025    return MakeCursorTypeRef(TD, Loc, CXTU);
1026  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
1027    return MakeCursorObjCClassRef(ID, Loc, CXTU);
1028  if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
1029    return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
1030  if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
1031    return MakeCursorTemplateRef(Template, Loc, CXTU);
1032  if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
1033    return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1034  if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
1035    return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1036  if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
1037    return MakeCursorMemberRef(Field, Loc, CXTU);
1038
1039  return clang_getNullCursor();
1040}
1041
1042bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
1043  if (isa<ObjCInterfaceDecl>(D))
1044    return false;
1045  if (isa<ObjCCategoryDecl>(D))
1046    return false;
1047  if (isa<ObjCIvarDecl>(D))
1048    return false;
1049  if (isa<ObjCMethodDecl>(D))
1050    return false;
1051  return true;
1052}
1053
1054bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
1055  if (const ClassTemplateSpecializationDecl *
1056        SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1057    return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
1058  }
1059  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1060    return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
1061  }
1062  return false;
1063}
1064