IndexingContext.cpp revision 792db266f3d2f12a7a16bf37d90074f54bca1e6f
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  ObjCPropertyDeclInfo DInfo;
521  EntityInfo GetterEntity;
522  EntityInfo SetterEntity;
523  ScratchAlloc SA(*this);
524
525  DInfo.ObjCPropDeclInfo.declInfo = &DInfo;
526
527  if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) {
528    getEntityInfo(Getter, GetterEntity, SA);
529    DInfo.ObjCPropDeclInfo.getter = &GetterEntity;
530  } else {
531    DInfo.ObjCPropDeclInfo.getter = 0;
532  }
533  if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) {
534    getEntityInfo(Setter, SetterEntity, SA);
535    DInfo.ObjCPropDeclInfo.setter = &SetterEntity;
536  } else {
537    DInfo.ObjCPropDeclInfo.setter = 0;
538  }
539
540  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
541}
542
543bool IndexingContext::handleNamespace(const NamespaceDecl *D) {
544  DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
545                 /*isDefinition=*/true,
546                 /*isContainer=*/true);
547  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
548}
549
550bool IndexingContext::handleClassTemplate(const ClassTemplateDecl *D) {
551  return handleCXXRecordDecl(D->getTemplatedDecl(), D);
552}
553
554bool IndexingContext::handleFunctionTemplate(const FunctionTemplateDecl *D) {
555  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
556                 /*isDefinition=*/D->isThisDeclarationADefinition(),
557                 /*isContainer=*/D->isThisDeclarationADefinition());
558  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
559}
560
561bool IndexingContext::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
562  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
563                 /*isDefinition=*/true, /*isContainer=*/false);
564  return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
565}
566
567bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
568                                      const NamedDecl *Parent,
569                                      const DeclContext *DC,
570                                      const Expr *E,
571                                      CXIdxEntityRefKind Kind) {
572  if (!D)
573    return false;
574
575  CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E),
576                                     const_cast<Decl*>(cast<Decl>(DC)), CXTU)
577                      : getRefCursor(D, Loc);
578  return handleReference(D, Loc, Cursor, Parent, DC, E, Kind);
579}
580
581bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
582                                      CXCursor Cursor,
583                                      const NamedDecl *Parent,
584                                      const DeclContext *DC,
585                                      const Expr *E,
586                                      CXIdxEntityRefKind Kind) {
587  if (!CB.indexEntityReference)
588    return false;
589
590  if (!D)
591    return false;
592  if (Loc.isInvalid())
593    return false;
594  if (!shouldIndexFunctionLocalSymbols() && D->getParentFunctionOrMethod())
595    return false;
596  if (isNotFromSourceFile(D->getLocation()))
597    return false;
598  if (D->isImplicit() && shouldIgnoreIfImplicit(D))
599    return false;
600
601  if (shouldSuppressRefs()) {
602    if (markEntityOccurrenceInFile(D, Loc))
603      return false; // already occurred.
604  }
605
606  ScratchAlloc SA(*this);
607  EntityInfo RefEntity, ParentEntity;
608  getEntityInfo(D, RefEntity, SA);
609  if (!RefEntity.USR)
610    return false;
611
612  getEntityInfo(Parent, ParentEntity, SA);
613
614  ContainerInfo Container;
615  getContainerInfo(DC, Container);
616
617  CXIdxEntityRefInfo Info = { Kind,
618                              Cursor,
619                              getIndexLoc(Loc),
620                              &RefEntity,
621                              Parent ? &ParentEntity : 0,
622                              &Container };
623  CB.indexEntityReference(ClientData, &Info);
624  return true;
625}
626
627bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const {
628  if (Loc.isInvalid())
629    return true;
630  SourceManager &SM = Ctx->getSourceManager();
631  SourceLocation FileLoc = SM.getFileLoc(Loc);
632  FileID FID = SM.getFileID(FileLoc);
633  return SM.getFileEntryForID(FID) == 0;
634}
635
636void IndexingContext::addContainerInMap(const DeclContext *DC,
637                                        CXIdxClientContainer container) {
638  if (!DC)
639    return;
640
641  ContainerMapTy::iterator I = ContainerMap.find(DC);
642  if (I == ContainerMap.end()) {
643    if (container)
644      ContainerMap[DC] = container;
645    return;
646  }
647  // Allow changing the container of a previously seen DeclContext so we
648  // can handle invalid user code, like a function re-definition.
649  if (container)
650    I->second = container;
651  else
652    ContainerMap.erase(I);
653}
654
655CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const {
656  if (!D)
657    return 0;
658  EntityMapTy::const_iterator I = EntityMap.find(D);
659  if (I == EntityMap.end())
660    return 0;
661  return I->second;
662}
663
664void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) {
665  if (!D)
666    return;
667  EntityMap[D] = client;
668}
669
670bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD,
671                                          const NamedDecl *OrigD) {
672  if (RD->isThisDeclarationADefinition()) {
673    ScratchAlloc SA(*this);
674    CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
675                           /*isDefinition=*/RD->isThisDeclarationADefinition());
676    CXXBasesListInfo BaseList(RD, *this, SA);
677    CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
678    CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
679    CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
680
681    if (shouldSuppressRefs()) {
682      // Go through bases and mark them as referenced.
683      for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) {
684        const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i];
685        if (baseInfo->base) {
686          const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl;
687          SourceLocation
688            Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data);
689          markEntityOccurrenceInFile(BaseD, Loc);
690        }
691      }
692    }
693
694    return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo);
695  }
696
697  DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
698                 /*isDefinition=*/RD->isThisDeclarationADefinition(),
699                 /*isContainer=*/RD->isThisDeclarationADefinition());
700  return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
701}
702
703bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D,
704                                                 SourceLocation Loc) {
705  if (!D || Loc.isInvalid())
706    return true;
707
708  SourceManager &SM = Ctx->getSourceManager();
709  D = getEntityDecl(D);
710
711  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc));
712  FileID FID = LocInfo.first;
713  if (FID.isInvalid())
714    return true;
715
716  const FileEntry *FE = SM.getFileEntryForID(FID);
717  if (!FE)
718    return true;
719  RefFileOccurence RefOccur(FE, D);
720  std::pair<llvm::DenseSet<RefFileOccurence>::iterator, bool>
721  res = RefFileOccurences.insert(RefOccur);
722  if (!res.second)
723    return true; // already in map.
724
725  return false;
726}
727
728const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const {
729  assert(D);
730  D = cast<NamedDecl>(D->getCanonicalDecl());
731
732  if (const ObjCImplementationDecl *
733               ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
734    return getEntityDecl(ImplD->getClassInterface());
735
736  } else if (const ObjCCategoryImplDecl *
737               CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) {
738    return getEntityDecl(CatImplD->getCategoryDecl());
739  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
740    if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate())
741      return getEntityDecl(TemplD);
742  } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
743    if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate())
744      return getEntityDecl(TemplD);
745  }
746
747  return D;
748}
749
750const DeclContext *
751IndexingContext::getEntityContainer(const Decl *D) const {
752  const DeclContext *DC = dyn_cast<DeclContext>(D);
753  if (DC)
754    return DC;
755
756  if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) {
757    DC = ClassTempl->getTemplatedDecl();
758  } if (const FunctionTemplateDecl *
759          FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) {
760    DC = FuncTempl->getTemplatedDecl();
761  }
762
763  return DC;
764}
765
766CXIdxClientContainer
767IndexingContext::getClientContainerForDC(const DeclContext *DC) const {
768  if (!DC)
769    return 0;
770
771  ContainerMapTy::const_iterator I = ContainerMap.find(DC);
772  if (I == ContainerMap.end())
773    return 0;
774
775  return I->second;
776}
777
778CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) {
779  if (!File)
780    return 0;
781
782  FileMapTy::iterator FI = FileMap.find(File);
783  if (FI != FileMap.end())
784    return FI->second;
785
786  return 0;
787}
788
789CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const {
790  CXIdxLoc idxLoc =  { {0, 0}, 0 };
791  if (Loc.isInvalid())
792    return idxLoc;
793
794  idxLoc.ptr_data[0] = (void*)this;
795  idxLoc.int_data = Loc.getRawEncoding();
796  return idxLoc;
797}
798
799void IndexingContext::translateLoc(SourceLocation Loc,
800                                   CXIdxClientFile *indexFile, CXFile *file,
801                                   unsigned *line, unsigned *column,
802                                   unsigned *offset) {
803  if (Loc.isInvalid())
804    return;
805
806  SourceManager &SM = Ctx->getSourceManager();
807  Loc = SM.getFileLoc(Loc);
808
809  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
810  FileID FID = LocInfo.first;
811  unsigned FileOffset = LocInfo.second;
812
813  if (FID.isInvalid())
814    return;
815
816  const FileEntry *FE = SM.getFileEntryForID(FID);
817  if (indexFile)
818    *indexFile = getIndexFile(FE);
819  if (file)
820    *file = (void *)FE;
821  if (line)
822    *line = SM.getLineNumber(FID, FileOffset);
823  if (column)
824    *column = SM.getColumnNumber(FID, FileOffset);
825  if (offset)
826    *offset = FileOffset;
827}
828
829void IndexingContext::getEntityInfo(const NamedDecl *D,
830                                    EntityInfo &EntityInfo,
831                                    ScratchAlloc &SA) {
832  if (!D)
833    return;
834
835  D = getEntityDecl(D);
836  EntityInfo.cursor = getCursor(D);
837  EntityInfo.Dcl = D;
838  EntityInfo.IndexCtx = this;
839  EntityInfo.kind = CXIdxEntity_Unexposed;
840  EntityInfo.templateKind = CXIdxEntity_NonTemplate;
841  EntityInfo.lang = CXIdxEntityLang_C;
842
843  if (D->hasAttrs()) {
844    AttrListInfo *attrs = SA.allocate<AttrListInfo>();
845    new (attrs) AttrListInfo(D, *this, SA);
846    EntityInfo.AttrList = attrs;
847    EntityInfo.attributes = attrs->getAttrs();
848    EntityInfo.numAttributes = attrs->getNumAttrs();
849  }
850
851  if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
852    switch (TD->getTagKind()) {
853    case TTK_Struct:
854      EntityInfo.kind = CXIdxEntity_Struct; break;
855    case TTK_Union:
856      EntityInfo.kind = CXIdxEntity_Union; break;
857    case TTK_Class:
858      EntityInfo.kind = CXIdxEntity_CXXClass;
859      EntityInfo.lang = CXIdxEntityLang_CXX;
860      break;
861    case TTK_Enum:
862      EntityInfo.kind = CXIdxEntity_Enum; break;
863    }
864
865    if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
866      if (!CXXRec->isCLike())
867        EntityInfo.lang = CXIdxEntityLang_CXX;
868
869    if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
870      EntityInfo.templateKind = CXIdxEntity_TemplatePartialSpecialization;
871    } else if (isa<ClassTemplateSpecializationDecl>(D)) {
872      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
873    }
874
875  } else {
876    switch (D->getKind()) {
877    case Decl::Typedef:
878      EntityInfo.kind = CXIdxEntity_Typedef; break;
879    case Decl::Function:
880      EntityInfo.kind = CXIdxEntity_Function;
881      break;
882    case Decl::ParmVar:
883      EntityInfo.kind = CXIdxEntity_Variable;
884      break;
885    case Decl::Var:
886      EntityInfo.kind = CXIdxEntity_Variable;
887      if (isa<CXXRecordDecl>(D->getDeclContext())) {
888        EntityInfo.kind = CXIdxEntity_CXXStaticVariable;
889        EntityInfo.lang = CXIdxEntityLang_CXX;
890      }
891      break;
892    case Decl::Field:
893      EntityInfo.kind = CXIdxEntity_Field;
894      if (const CXXRecordDecl *
895            CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
896        // FIXME: isPOD check is not sufficient, a POD can contain methods,
897        // we want a isCStructLike check.
898        if (!CXXRec->isPOD())
899          EntityInfo.lang = CXIdxEntityLang_CXX;
900      }
901      break;
902    case Decl::EnumConstant:
903      EntityInfo.kind = CXIdxEntity_EnumConstant; break;
904    case Decl::ObjCInterface:
905      EntityInfo.kind = CXIdxEntity_ObjCClass;
906      EntityInfo.lang = CXIdxEntityLang_ObjC;
907      break;
908    case Decl::ObjCProtocol:
909      EntityInfo.kind = CXIdxEntity_ObjCProtocol;
910      EntityInfo.lang = CXIdxEntityLang_ObjC;
911      break;
912    case Decl::ObjCCategory:
913      EntityInfo.kind = CXIdxEntity_ObjCCategory;
914      EntityInfo.lang = CXIdxEntityLang_ObjC;
915      break;
916    case Decl::ObjCMethod:
917      if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
918        EntityInfo.kind = CXIdxEntity_ObjCInstanceMethod;
919      else
920        EntityInfo.kind = CXIdxEntity_ObjCClassMethod;
921      EntityInfo.lang = CXIdxEntityLang_ObjC;
922      break;
923    case Decl::ObjCProperty:
924      EntityInfo.kind = CXIdxEntity_ObjCProperty;
925      EntityInfo.lang = CXIdxEntityLang_ObjC;
926      break;
927    case Decl::ObjCIvar:
928      EntityInfo.kind = CXIdxEntity_ObjCIvar;
929      EntityInfo.lang = CXIdxEntityLang_ObjC;
930      break;
931    case Decl::Namespace:
932      EntityInfo.kind = CXIdxEntity_CXXNamespace;
933      EntityInfo.lang = CXIdxEntityLang_CXX;
934      break;
935    case Decl::NamespaceAlias:
936      EntityInfo.kind = CXIdxEntity_CXXNamespaceAlias;
937      EntityInfo.lang = CXIdxEntityLang_CXX;
938      break;
939    case Decl::CXXConstructor:
940      EntityInfo.kind = CXIdxEntity_CXXConstructor;
941      EntityInfo.lang = CXIdxEntityLang_CXX;
942      break;
943    case Decl::CXXDestructor:
944      EntityInfo.kind = CXIdxEntity_CXXDestructor;
945      EntityInfo.lang = CXIdxEntityLang_CXX;
946      break;
947    case Decl::CXXConversion:
948      EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
949      EntityInfo.lang = CXIdxEntityLang_CXX;
950      break;
951    case Decl::CXXMethod: {
952      const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
953      if (MD->isStatic())
954        EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
955      else
956        EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
957      EntityInfo.lang = CXIdxEntityLang_CXX;
958      break;
959    }
960    case Decl::ClassTemplate:
961      EntityInfo.kind = CXIdxEntity_CXXClass;
962      EntityInfo.templateKind = CXIdxEntity_Template;
963      break;
964    case Decl::FunctionTemplate:
965      EntityInfo.kind = CXIdxEntity_Function;
966      EntityInfo.templateKind = CXIdxEntity_Template;
967      if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
968                           cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
969        if (isa<CXXConstructorDecl>(MD))
970          EntityInfo.kind = CXIdxEntity_CXXConstructor;
971        else if (isa<CXXDestructorDecl>(MD))
972          EntityInfo.kind = CXIdxEntity_CXXDestructor;
973        else if (isa<CXXConversionDecl>(MD))
974          EntityInfo.kind = CXIdxEntity_CXXConversionFunction;
975        else {
976          if (MD->isStatic())
977            EntityInfo.kind = CXIdxEntity_CXXStaticMethod;
978          else
979            EntityInfo.kind = CXIdxEntity_CXXInstanceMethod;
980        }
981      }
982      break;
983    case Decl::TypeAliasTemplate:
984      EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
985      EntityInfo.templateKind = CXIdxEntity_Template;
986      break;
987    case Decl::TypeAlias:
988      EntityInfo.kind = CXIdxEntity_CXXTypeAlias;
989      EntityInfo.lang = CXIdxEntityLang_CXX;
990      break;
991    default:
992      break;
993    }
994  }
995
996  if (EntityInfo.kind == CXIdxEntity_Unexposed)
997    return;
998
999  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1000    if (FD->getTemplatedKind() ==
1001          FunctionDecl::TK_FunctionTemplateSpecialization)
1002      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization;
1003  }
1004
1005  if (EntityInfo.templateKind != CXIdxEntity_NonTemplate)
1006    EntityInfo.lang = CXIdxEntityLang_CXX;
1007
1008  if (IdentifierInfo *II = D->getIdentifier()) {
1009    EntityInfo.name = SA.toCStr(II->getName());
1010
1011  } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) {
1012    EntityInfo.name = 0; // anonymous tag/field/namespace.
1013
1014  } else {
1015    SmallString<256> StrBuf;
1016    {
1017      llvm::raw_svector_ostream OS(StrBuf);
1018      D->printName(OS);
1019    }
1020    EntityInfo.name = SA.copyCStr(StrBuf.str());
1021  }
1022
1023  {
1024    SmallString<512> StrBuf;
1025    bool Ignore = getDeclCursorUSR(D, StrBuf);
1026    if (Ignore) {
1027      EntityInfo.USR = 0;
1028    } else {
1029      EntityInfo.USR = SA.copyCStr(StrBuf.str());
1030    }
1031  }
1032}
1033
1034void IndexingContext::getContainerInfo(const DeclContext *DC,
1035                                       ContainerInfo &ContInfo) {
1036  ContInfo.cursor = getCursor(cast<Decl>(DC));
1037  ContInfo.DC = DC;
1038  ContInfo.IndexCtx = this;
1039}
1040
1041CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
1042  if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
1043    return MakeCursorTypeRef(TD, Loc, CXTU);
1044  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
1045    return MakeCursorObjCClassRef(ID, Loc, CXTU);
1046  if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
1047    return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
1048  if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
1049    return MakeCursorTemplateRef(Template, Loc, CXTU);
1050  if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
1051    return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1052  if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
1053    return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
1054  if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
1055    return MakeCursorMemberRef(Field, Loc, CXTU);
1056  if (const VarDecl *Var = dyn_cast<VarDecl>(D))
1057    return MakeCursorVariableRef(Var, Loc, CXTU);
1058
1059  return clang_getNullCursor();
1060}
1061
1062bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
1063  if (isa<ObjCInterfaceDecl>(D))
1064    return false;
1065  if (isa<ObjCCategoryDecl>(D))
1066    return false;
1067  if (isa<ObjCIvarDecl>(D))
1068    return false;
1069  if (isa<ObjCMethodDecl>(D))
1070    return false;
1071  return true;
1072}
1073
1074bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
1075  if (const ClassTemplateSpecializationDecl *
1076        SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1077    return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
1078  }
1079  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1080    return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
1081  }
1082  return false;
1083}
1084