diff options
| author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 | 
|---|---|---|
| committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 | 
| commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
| tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/tools/libclang/IndexingContext.cpp | |
| parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) | |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/tools/libclang/IndexingContext.cpp')
| -rw-r--r-- | clang/tools/libclang/IndexingContext.cpp | 1080 | 
1 files changed, 1080 insertions, 0 deletions
diff --git a/clang/tools/libclang/IndexingContext.cpp b/clang/tools/libclang/IndexingContext.cpp new file mode 100644 index 0000000..ace5c75 --- /dev/null +++ b/clang/tools/libclang/IndexingContext.cpp @@ -0,0 +1,1080 @@ +//===- CIndexHigh.cpp - Higher level API functions ------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "IndexingContext.h" +#include "CXTranslationUnit.h" +#include "CIndexDiagnostic.h" + +#include "clang/Frontend/ASTUnit.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" + +using namespace clang; +using namespace cxindex; +using namespace cxcursor; + +IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo( +                                    const ObjCProtocolList &ProtList, +                                    IndexingContext &IdxCtx, +                                    ScratchAlloc &SA) { +  ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); +  for (ObjCInterfaceDecl::protocol_iterator +         I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { +    SourceLocation Loc = *LI; +    ObjCProtocolDecl *PD = *I; +    ProtEntities.push_back(EntityInfo()); +    IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA); +    CXIdxObjCProtocolRefInfo ProtInfo = { 0, +                                MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU), +                                IdxCtx.getIndexLoc(Loc) }; +    ProtInfos.push_back(ProtInfo); + +    if (IdxCtx.shouldSuppressRefs()) +      IdxCtx.markEntityOccurrenceInFile(PD, Loc); +  } + +  for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i) +    ProtInfos[i].protocol = &ProtEntities[i]; + +  for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i) +    Prots.push_back(&ProtInfos[i]); +} + + +IBOutletCollectionInfo::IBOutletCollectionInfo( +                                          const IBOutletCollectionInfo &other) +  : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) { + +  IBCollInfo.attrInfo = this; +  IBCollInfo.classCursor = other.IBCollInfo.classCursor; +  IBCollInfo.classLoc = other.IBCollInfo.classLoc; +  if (other.IBCollInfo.objcClass) { +    ClassInfo = other.ClassInfo; +    IBCollInfo.objcClass = &ClassInfo; +  } else +    IBCollInfo.objcClass = 0; +} + +AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx) +  : SA(IdxCtx), ref_cnt(0) { + +  if (!D->hasAttrs()) +    return; + +  for (AttrVec::const_iterator AttrI = D->attr_begin(), AttrE = D->attr_end(); +         AttrI != AttrE; ++AttrI) { +    const Attr *A = *AttrI; +    CXCursor C = MakeCXCursor(A, const_cast<Decl *>(D), IdxCtx.CXTU); +    CXIdxLoc Loc =  IdxCtx.getIndexLoc(A->getLocation()); +    switch (C.kind) { +    default: +      Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A)); +      break; +    case CXCursor_IBActionAttr: +      Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A)); +      break; +    case CXCursor_IBOutletAttr: +      Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A)); +      break; +    case CXCursor_IBOutletCollectionAttr: +      IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A)); +      break; +    } +  } + +  for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) { +    IBOutletCollectionInfo &IBInfo = IBCollAttrs[i]; +    CXAttrs.push_back(&IBInfo); + +    const IBOutletCollectionAttr * +      IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A); +    IBInfo.IBCollInfo.attrInfo = &IBInfo; +    IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(IBAttr->getInterfaceLoc()); +    IBInfo.IBCollInfo.objcClass = 0; +    IBInfo.IBCollInfo.classCursor = clang_getNullCursor(); +    QualType Ty = IBAttr->getInterface(); +    if (const ObjCInterfaceType *InterTy = Ty->getAs<ObjCInterfaceType>()) { +      if (const ObjCInterfaceDecl *InterD = InterTy->getInterface()) { +        IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA); +        IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo; +        IBInfo.IBCollInfo.classCursor = MakeCursorObjCClassRef(InterD, +                                        IBAttr->getInterfaceLoc(), IdxCtx.CXTU); +      } +    } +  } + +  for (unsigned i = 0, e = Attrs.size(); i != e; ++i) +    CXAttrs.push_back(&Attrs[i]); +} + +IntrusiveRefCntPtr<AttrListInfo> +AttrListInfo::create(const Decl *D, IndexingContext &IdxCtx) { +  ScratchAlloc SA(IdxCtx); +  AttrListInfo *attrs = SA.allocate<AttrListInfo>(); +  return new (attrs) AttrListInfo(D, IdxCtx); +} + +IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, +                                   IndexingContext &IdxCtx, +                                   ScratchAlloc &SA) { +  for (CXXRecordDecl::base_class_const_iterator +         I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { +    const CXXBaseSpecifier &Base = *I; +    BaseEntities.push_back(EntityInfo()); +    const NamedDecl *BaseD = 0; +    QualType T = Base.getType(); +    SourceLocation Loc = getBaseLoc(Base); + +    if (const TypedefType *TDT = T->getAs<TypedefType>()) { +      BaseD = TDT->getDecl(); +    } else if (const TemplateSpecializationType * +          TST = T->getAs<TemplateSpecializationType>()) { +      BaseD = TST->getTemplateName().getAsTemplateDecl(); +    } else if (const RecordType *RT = T->getAs<RecordType>()) { +      BaseD = RT->getDecl(); +    } + +    if (BaseD) +      IdxCtx.getEntityInfo(BaseD, BaseEntities.back(), SA); +    CXIdxBaseClassInfo BaseInfo = { 0, +                         MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU), +                         IdxCtx.getIndexLoc(Loc) }; +    BaseInfos.push_back(BaseInfo); +  } + +  for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) { +    if (BaseEntities[i].name && BaseEntities[i].USR) +      BaseInfos[i].base = &BaseEntities[i]; +  } + +  for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) +    CXBases.push_back(&BaseInfos[i]); +} + +SourceLocation IndexingContext::CXXBasesListInfo::getBaseLoc( +                                           const CXXBaseSpecifier &Base) const { +  SourceLocation Loc = Base.getSourceRange().getBegin(); +  TypeLoc TL; +  if (Base.getTypeSourceInfo()) +    TL = Base.getTypeSourceInfo()->getTypeLoc(); +  if (TL.isNull()) +    return Loc; + +  if (const QualifiedTypeLoc *QL = dyn_cast<QualifiedTypeLoc>(&TL)) +    TL = QL->getUnqualifiedLoc(); + +  if (const ElaboratedTypeLoc *EL = dyn_cast<ElaboratedTypeLoc>(&TL)) +    return EL->getNamedTypeLoc().getBeginLoc(); +  if (const DependentNameTypeLoc *DL = dyn_cast<DependentNameTypeLoc>(&TL)) +    return DL->getNameLoc(); +  if (const DependentTemplateSpecializationTypeLoc * +        DTL = dyn_cast<DependentTemplateSpecializationTypeLoc>(&TL)) +    return DTL->getTemplateNameLoc(); + +  return Loc; +} + +const char *ScratchAlloc::toCStr(StringRef Str) { +  if (Str.empty()) +    return ""; +  if (Str.data()[Str.size()] == '\0') +    return Str.data(); +  return copyCStr(Str); +} + +const char *ScratchAlloc::copyCStr(StringRef Str) { +  char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1); +  std::uninitialized_copy(Str.begin(), Str.end(), buf); +  buf[Str.size()] = '\0'; +  return buf; +} + +void IndexingContext::setASTContext(ASTContext &ctx) { +  Ctx = &ctx; +  static_cast<ASTUnit*>(CXTU->TUData)->setASTContext(&ctx); +} + +void IndexingContext::setPreprocessor(Preprocessor &PP) { +  static_cast<ASTUnit*>(CXTU->TUData)->setPreprocessor(&PP); +} + +bool IndexingContext::shouldAbort() { +  if (!CB.abortQuery) +    return false; +  return CB.abortQuery(ClientData, 0); +} + +void IndexingContext::enteredMainFile(const FileEntry *File) { +  if (File && CB.enteredMainFile) { +    CXIdxClientFile idxFile = CB.enteredMainFile(ClientData, (CXFile)File, 0); +    FileMap[File] = idxFile; +  } +} + +void IndexingContext::ppIncludedFile(SourceLocation hashLoc, +                                     StringRef filename, +                                     const FileEntry *File, +                                     bool isImport, bool isAngled) { +  if (!CB.ppIncludedFile) +    return; + +  ScratchAlloc SA(*this); +  CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc), +                                 SA.toCStr(filename), +                                 (CXFile)File, +                                 isImport, isAngled }; +  CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info); +  FileMap[File] = idxFile; +} + +void IndexingContext::startedTranslationUnit() { +  CXIdxClientContainer idxCont = 0; +  if (CB.startedTranslationUnit) +    idxCont = CB.startedTranslationUnit(ClientData, 0); +  addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont); +} + +void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) { +  if (!CB.diagnostic) +    return; + +  CB.diagnostic(ClientData, CXDiagSet, 0); +} + +bool IndexingContext::handleDecl(const NamedDecl *D, +                                 SourceLocation Loc, CXCursor Cursor, +                                 DeclInfo &DInfo, +                                 const DeclContext *LexicalDC) { +  if (!CB.indexDeclaration || !D) +    return false; +  if (D->isImplicit() && shouldIgnoreIfImplicit(D)) +    return false; + +  ScratchAlloc SA(*this); +  getEntityInfo(D, DInfo.EntInfo, SA); +  if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR) +      || Loc.isInvalid()) +    return false; + +  if (!LexicalDC) +    LexicalDC = D->getLexicalDeclContext(); + +  if (shouldSuppressRefs()) +    markEntityOccurrenceInFile(D, Loc); +   +  DInfo.entityInfo = &DInfo.EntInfo; +  DInfo.cursor = Cursor; +  DInfo.loc = getIndexLoc(Loc); +  DInfo.isImplicit = D->isImplicit(); + +  DInfo.attributes = DInfo.EntInfo.attributes; +  DInfo.numAttributes = DInfo.EntInfo.numAttributes; + +  getContainerInfo(D->getDeclContext(), DInfo.SemanticContainer); +  DInfo.semanticContainer = &DInfo.SemanticContainer; + +  if (LexicalDC == D->getDeclContext()) { +    DInfo.lexicalContainer = &DInfo.SemanticContainer; +  } else if (isTemplateImplicitInstantiation(D)) { +    // Implicit instantiations have the lexical context of where they were +    // instantiated first. We choose instead the semantic context because: +    // 1) at the time that we see the instantiation we have not seen the +    //   function where it occurred yet. +    // 2) the lexical context of the first instantiation is not useful +    //   information anyway. +    DInfo.lexicalContainer = &DInfo.SemanticContainer; +  } else { +    getContainerInfo(LexicalDC, DInfo.LexicalContainer); +    DInfo.lexicalContainer = &DInfo.LexicalContainer; +  } + +  if (DInfo.isContainer) { +    getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer); +    DInfo.declAsContainer = &DInfo.DeclAsContainer; +  } + +  CB.indexDeclaration(ClientData, &DInfo); +  return true; +} + +bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D, +                                          SourceLocation Loc, CXCursor Cursor, +                                          ObjCContainerDeclInfo &ContDInfo) { +  ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo; +  return handleDecl(D, Loc, Cursor, ContDInfo); +} + +bool IndexingContext::handleFunction(const FunctionDecl *D) { +  DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), +                 D->isThisDeclarationADefinition()); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleVar(const VarDecl *D) { +  DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), +                 /*isContainer=*/false); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleField(const FieldDecl *D) { +  DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, +                 /*isContainer=*/false); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) { +  DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, +                 /*isContainer=*/false); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleTagDecl(const TagDecl *D) { +  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D)) +    return handleCXXRecordDecl(CXXRD, D); + +  DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), +                 D->isThisDeclarationADefinition()); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleTypedefName(const TypedefNameDecl *D) { +  DeclInfo DInfo(!D->isFirstDeclaration(), /*isDefinition=*/true, +                 /*isContainer=*/false); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { +  // For @class forward declarations, suppress them the same way as references. +  if (!D->isThisDeclarationADefinition()) { +    if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) +      return false; // already occurred. + +    // FIXME: This seems like the wrong definition for redeclaration. +    bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl(); +    ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration, +                                    /*isImplementation=*/false); +    return handleObjCContainer(D, D->getLocation(), +                               MakeCursorObjCClassRef(D, D->getLocation(), +                                                      CXTU),  +                               ContDInfo); +  } + +  ScratchAlloc SA(*this); + +  CXIdxBaseClassInfo BaseClass; +  EntityInfo BaseEntity; +  BaseClass.cursor = clang_getNullCursor(); +  if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) { +    getEntityInfo(SuperD, BaseEntity, SA); +    SourceLocation SuperLoc = D->getSuperClassLoc(); +    BaseClass.base = &BaseEntity; +    BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU); +    BaseClass.loc = getIndexLoc(SuperLoc); + +    if (shouldSuppressRefs()) +      markEntityOccurrenceInFile(SuperD, SuperLoc); +  } +   +  ObjCProtocolList EmptyProtoList; +  ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition()  +                                  ? D->getReferencedProtocols() +                                  : EmptyProtoList,  +                                *this, SA); +   +  ObjCInterfaceDeclInfo InterInfo(D); +  InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo(); +  InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo; +  InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass : 0; +  InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo; + +  return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo); +} + +bool IndexingContext::handleObjCImplementation( +                                              const ObjCImplementationDecl *D) { +  ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false, +                      /*isRedeclaration=*/true, +                      /*isImplementation=*/true); +  return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo); +} + +bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { +  if (!D->isThisDeclarationADefinition()) { +    if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) +      return false; // already occurred. +     +    // FIXME: This seems like the wrong definition for redeclaration. +    bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl(); +    ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, +                                    isRedeclaration, +                                    /*isImplementation=*/false); +    return handleObjCContainer(D, D->getLocation(),  +                               MakeCursorObjCProtocolRef(D, D->getLocation(), +                                                         CXTU), +                               ContDInfo);     +  } +   +  ScratchAlloc SA(*this); +  ObjCProtocolList EmptyProtoList; +  ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition() +                                      ? D->getReferencedProtocols() +                                      : EmptyProtoList, +                                    *this, SA); +   +  ObjCProtocolDeclInfo ProtInfo(D); +  ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo(); + +  return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo); +} + +bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { +  ScratchAlloc SA(*this); + +  ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); +  EntityInfo ClassEntity; +  const ObjCInterfaceDecl *IFaceD = D->getClassInterface(); +  SourceLocation ClassLoc = D->getLocation(); +  SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc +                                                     : D->getCategoryNameLoc(); +  getEntityInfo(IFaceD, ClassEntity, SA); + +  if (shouldSuppressRefs()) +    markEntityOccurrenceInFile(IFaceD, ClassLoc); + +  ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA); +   +  CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; +  if (IFaceD) { +    CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; +    CatDInfo.ObjCCatDeclInfo.classCursor = +        MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); +  } else { +    CatDInfo.ObjCCatDeclInfo.objcClass = 0; +    CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); +  } +  CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); +  CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo(); +  CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo; + +  return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); +} + +bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { +  ScratchAlloc SA(*this); + +  const ObjCCategoryDecl *CatD = D->getCategoryDecl(); +  ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true); +  EntityInfo ClassEntity; +  const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface(); +  SourceLocation ClassLoc = D->getLocation(); +  SourceLocation CategoryLoc = D->getCategoryNameLoc(); +  getEntityInfo(IFaceD, ClassEntity, SA); + +  if (shouldSuppressRefs()) +    markEntityOccurrenceInFile(IFaceD, ClassLoc); + +  CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; +  if (IFaceD) { +    CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; +    CatDInfo.ObjCCatDeclInfo.classCursor = +        MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); +  } else { +    CatDInfo.ObjCCatDeclInfo.objcClass = 0; +    CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); +  } +  CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); +  CatDInfo.ObjCCatDeclInfo.protocols = 0; + +  return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); +} + +bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) { +  DeclInfo DInfo(!D->isCanonicalDecl(), D->isThisDeclarationADefinition(), +                 D->isThisDeclarationADefinition()); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleSynthesizedObjCProperty( +                                                const ObjCPropertyImplDecl *D) { +  ObjCPropertyDecl *PD = D->getPropertyDecl(); +  return handleReference(PD, D->getLocation(), getCursor(D), 0, D->getDeclContext()); +} + +bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, +                                                  SourceLocation Loc, +                                                 const DeclContext *LexicalDC) { +  DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true, +                 /*isContainer=*/false); +  return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC); +} + +bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) { +  ScratchAlloc SA(*this); + +  ObjCPropertyDeclInfo DInfo; +  EntityInfo GetterEntity; +  EntityInfo SetterEntity; + +  DInfo.ObjCPropDeclInfo.declInfo = &DInfo; + +  if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) { +    getEntityInfo(Getter, GetterEntity, SA); +    DInfo.ObjCPropDeclInfo.getter = &GetterEntity; +  } else { +    DInfo.ObjCPropDeclInfo.getter = 0; +  } +  if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) { +    getEntityInfo(Setter, SetterEntity, SA); +    DInfo.ObjCPropDeclInfo.setter = &SetterEntity; +  } else { +    DInfo.ObjCPropDeclInfo.setter = 0; +  } + +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleNamespace(const NamespaceDecl *D) { +  DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(), +                 /*isDefinition=*/true, +                 /*isContainer=*/true); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleClassTemplate(const ClassTemplateDecl *D) { +  return handleCXXRecordDecl(D->getTemplatedDecl(), D); +} + +bool IndexingContext::handleFunctionTemplate(const FunctionTemplateDecl *D) { +  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), +                 /*isDefinition=*/D->isThisDeclarationADefinition(), +                 /*isContainer=*/D->isThisDeclarationADefinition()); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) { +  DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), +                 /*isDefinition=*/true, /*isContainer=*/false); +  return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, +                                      const NamedDecl *Parent, +                                      const DeclContext *DC, +                                      const Expr *E, +                                      CXIdxEntityRefKind Kind) { +  if (!D) +    return false; + +  CXCursor Cursor = E ? MakeCXCursor(const_cast<Expr*>(E), +                                     const_cast<Decl*>(cast<Decl>(DC)), CXTU) +                      : getRefCursor(D, Loc); +  return handleReference(D, Loc, Cursor, Parent, DC, E, Kind); +} + +bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, +                                      CXCursor Cursor, +                                      const NamedDecl *Parent, +                                      const DeclContext *DC, +                                      const Expr *E, +                                      CXIdxEntityRefKind Kind) { +  if (!CB.indexEntityReference) +    return false; + +  if (!D) +    return false; +  if (Loc.isInvalid()) +    return false; +  if (!shouldIndexFunctionLocalSymbols() && D->getParentFunctionOrMethod()) +    return false; +  if (isNotFromSourceFile(D->getLocation())) +    return false; +  if (D->isImplicit() && shouldIgnoreIfImplicit(D)) +    return false; + +  if (shouldSuppressRefs()) { +    if (markEntityOccurrenceInFile(D, Loc)) +      return false; // already occurred. +  } + +  ScratchAlloc SA(*this); +  EntityInfo RefEntity, ParentEntity; +  getEntityInfo(D, RefEntity, SA); +  if (!RefEntity.USR) +    return false; + +  getEntityInfo(Parent, ParentEntity, SA); + +  ContainerInfo Container; +  getContainerInfo(DC, Container); + +  CXIdxEntityRefInfo Info = { Kind, +                              Cursor, +                              getIndexLoc(Loc), +                              &RefEntity, +                              Parent ? &ParentEntity : 0, +                              &Container }; +  CB.indexEntityReference(ClientData, &Info); +  return true; +} + +bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const { +  if (Loc.isInvalid()) +    return true; +  SourceManager &SM = Ctx->getSourceManager(); +  SourceLocation FileLoc = SM.getFileLoc(Loc); +  FileID FID = SM.getFileID(FileLoc); +  return SM.getFileEntryForID(FID) == 0; +} + +void IndexingContext::addContainerInMap(const DeclContext *DC, +                                        CXIdxClientContainer container) { +  if (!DC) +    return; + +  ContainerMapTy::iterator I = ContainerMap.find(DC); +  if (I == ContainerMap.end()) { +    if (container) +      ContainerMap[DC] = container; +    return; +  } +  // Allow changing the container of a previously seen DeclContext so we +  // can handle invalid user code, like a function re-definition. +  if (container) +    I->second = container; +  else +    ContainerMap.erase(I); +} + +CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const { +  if (!D) +    return 0; +  EntityMapTy::const_iterator I = EntityMap.find(D); +  if (I == EntityMap.end()) +    return 0; +  return I->second; +} + +void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) { +  if (!D) +    return; +  EntityMap[D] = client; +} + +bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD, +                                          const NamedDecl *OrigD) { +  if (RD->isThisDeclarationADefinition()) { +    ScratchAlloc SA(*this); +    CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), +                           /*isDefinition=*/RD->isThisDeclarationADefinition()); +    CXXBasesListInfo BaseList(RD, *this, SA); +    CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo; +    CXXDInfo.CXXClassInfo.bases = BaseList.getBases(); +    CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases(); + +    if (shouldSuppressRefs()) { +      // Go through bases and mark them as referenced. +      for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) { +        const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i]; +        if (baseInfo->base) { +          const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl; +          SourceLocation +            Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data); +          markEntityOccurrenceInFile(BaseD, Loc); +        } +      } +    } + +    return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo); +  } + +  DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), +                 /*isDefinition=*/RD->isThisDeclarationADefinition(), +                 /*isContainer=*/RD->isThisDeclarationADefinition()); +  return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo); +} + +bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D, +                                                 SourceLocation Loc) { +  if (!D || Loc.isInvalid()) +    return true; + +  SourceManager &SM = Ctx->getSourceManager(); +  D = getEntityDecl(D); +   +  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc)); +  FileID FID = LocInfo.first; +  if (FID.isInvalid()) +    return true; +   +  const FileEntry *FE = SM.getFileEntryForID(FID); +  if (!FE) +    return true; +  RefFileOccurence RefOccur(FE, D); +  std::pair<llvm::DenseSet<RefFileOccurence>::iterator, bool> +  res = RefFileOccurences.insert(RefOccur); +  if (!res.second) +    return true; // already in map. + +  return false; +} + +const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const { +  assert(D); +  D = cast<NamedDecl>(D->getCanonicalDecl()); + +  if (const ObjCImplementationDecl * +               ImplD = dyn_cast<ObjCImplementationDecl>(D)) { +    return getEntityDecl(ImplD->getClassInterface()); + +  } else if (const ObjCCategoryImplDecl * +               CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) { +    return getEntityDecl(CatImplD->getCategoryDecl()); +  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +    if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate()) +      return getEntityDecl(TemplD); +  } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { +    if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate()) +      return getEntityDecl(TemplD); +  } + +  return D; +} + +const DeclContext * +IndexingContext::getEntityContainer(const Decl *D) const { +  const DeclContext *DC = dyn_cast<DeclContext>(D); +  if (DC) +    return DC; + +  if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) { +    DC = ClassTempl->getTemplatedDecl(); +  } if (const FunctionTemplateDecl * +          FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) { +    DC = FuncTempl->getTemplatedDecl(); +  } + +  return DC; +} + +CXIdxClientContainer +IndexingContext::getClientContainerForDC(const DeclContext *DC) const { +  if (!DC) +    return 0; + +  ContainerMapTy::const_iterator I = ContainerMap.find(DC); +  if (I == ContainerMap.end()) +    return 0; + +  return I->second; +} + +CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) { +  if (!File) +    return 0; + +  FileMapTy::iterator FI = FileMap.find(File); +  if (FI != FileMap.end()) +    return FI->second; + +  return 0; +} + +CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const { +  CXIdxLoc idxLoc =  { {0, 0}, 0 }; +  if (Loc.isInvalid()) +    return idxLoc; + +  idxLoc.ptr_data[0] = (void*)this; +  idxLoc.int_data = Loc.getRawEncoding(); +  return idxLoc; +} + +void IndexingContext::translateLoc(SourceLocation Loc, +                                   CXIdxClientFile *indexFile, CXFile *file, +                                   unsigned *line, unsigned *column, +                                   unsigned *offset) { +  if (Loc.isInvalid()) +    return; + +  SourceManager &SM = Ctx->getSourceManager(); +  Loc = SM.getFileLoc(Loc); + +  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); +  FileID FID = LocInfo.first; +  unsigned FileOffset = LocInfo.second; + +  if (FID.isInvalid()) +    return; +   +  const FileEntry *FE = SM.getFileEntryForID(FID); +  if (indexFile) +    *indexFile = getIndexFile(FE); +  if (file) +    *file = (void *)FE; +  if (line) +    *line = SM.getLineNumber(FID, FileOffset); +  if (column) +    *column = SM.getColumnNumber(FID, FileOffset); +  if (offset) +    *offset = FileOffset; +} + +void IndexingContext::getEntityInfo(const NamedDecl *D, +                                    EntityInfo &EntityInfo, +                                    ScratchAlloc &SA) { +  if (!D) +    return; + +  D = getEntityDecl(D); +  EntityInfo.cursor = getCursor(D); +  EntityInfo.Dcl = D; +  EntityInfo.IndexCtx = this; +  EntityInfo.kind = CXIdxEntity_Unexposed; +  EntityInfo.templateKind = CXIdxEntity_NonTemplate; +  EntityInfo.lang = CXIdxEntityLang_C; + +  if (D->hasAttrs()) { +    EntityInfo.AttrList = AttrListInfo::create(D, *this); +    EntityInfo.attributes = EntityInfo.AttrList->getAttrs(); +    EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs(); +  } + +  if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { +    switch (TD->getTagKind()) { +    case TTK_Struct: +      EntityInfo.kind = CXIdxEntity_Struct; break; +    case TTK_Union: +      EntityInfo.kind = CXIdxEntity_Union; break; +    case TTK_Class: +      EntityInfo.kind = CXIdxEntity_CXXClass; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    case TTK_Enum: +      EntityInfo.kind = CXIdxEntity_Enum; break; +    } + +    if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) +      if (!CXXRec->isCLike()) +        EntityInfo.lang = CXIdxEntityLang_CXX; + +    if (isa<ClassTemplatePartialSpecializationDecl>(D)) { +      EntityInfo.templateKind = CXIdxEntity_TemplatePartialSpecialization; +    } else if (isa<ClassTemplateSpecializationDecl>(D)) { +      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization; +    } + +  } else { +    switch (D->getKind()) { +    case Decl::Typedef: +      EntityInfo.kind = CXIdxEntity_Typedef; break; +    case Decl::Function: +      EntityInfo.kind = CXIdxEntity_Function; +      break; +    case Decl::ParmVar: +      EntityInfo.kind = CXIdxEntity_Variable; +      break; +    case Decl::Var: +      EntityInfo.kind = CXIdxEntity_Variable; +      if (isa<CXXRecordDecl>(D->getDeclContext())) { +        EntityInfo.kind = CXIdxEntity_CXXStaticVariable; +        EntityInfo.lang = CXIdxEntityLang_CXX; +      } +      break; +    case Decl::Field: +      EntityInfo.kind = CXIdxEntity_Field; +      if (const CXXRecordDecl * +            CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) { +        // FIXME: isPOD check is not sufficient, a POD can contain methods, +        // we want a isCStructLike check. +        if (!CXXRec->isPOD()) +          EntityInfo.lang = CXIdxEntityLang_CXX; +      } +      break; +    case Decl::EnumConstant: +      EntityInfo.kind = CXIdxEntity_EnumConstant; break; +    case Decl::ObjCInterface: +      EntityInfo.kind = CXIdxEntity_ObjCClass; +      EntityInfo.lang = CXIdxEntityLang_ObjC; +      break; +    case Decl::ObjCProtocol: +      EntityInfo.kind = CXIdxEntity_ObjCProtocol; +      EntityInfo.lang = CXIdxEntityLang_ObjC; +      break; +    case Decl::ObjCCategory: +      EntityInfo.kind = CXIdxEntity_ObjCCategory; +      EntityInfo.lang = CXIdxEntityLang_ObjC; +      break; +    case Decl::ObjCMethod: +      if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) +        EntityInfo.kind = CXIdxEntity_ObjCInstanceMethod; +      else +        EntityInfo.kind = CXIdxEntity_ObjCClassMethod; +      EntityInfo.lang = CXIdxEntityLang_ObjC; +      break; +    case Decl::ObjCProperty: +      EntityInfo.kind = CXIdxEntity_ObjCProperty; +      EntityInfo.lang = CXIdxEntityLang_ObjC; +      break; +    case Decl::ObjCIvar: +      EntityInfo.kind = CXIdxEntity_ObjCIvar; +      EntityInfo.lang = CXIdxEntityLang_ObjC; +      break; +    case Decl::Namespace: +      EntityInfo.kind = CXIdxEntity_CXXNamespace; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    case Decl::NamespaceAlias: +      EntityInfo.kind = CXIdxEntity_CXXNamespaceAlias; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    case Decl::CXXConstructor: +      EntityInfo.kind = CXIdxEntity_CXXConstructor; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    case Decl::CXXDestructor: +      EntityInfo.kind = CXIdxEntity_CXXDestructor; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    case Decl::CXXConversion: +      EntityInfo.kind = CXIdxEntity_CXXConversionFunction; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    case Decl::CXXMethod: { +      const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); +      if (MD->isStatic()) +        EntityInfo.kind = CXIdxEntity_CXXStaticMethod; +      else +        EntityInfo.kind = CXIdxEntity_CXXInstanceMethod; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    } +    case Decl::ClassTemplate: +      EntityInfo.kind = CXIdxEntity_CXXClass; +      EntityInfo.templateKind = CXIdxEntity_Template; +      break; +    case Decl::FunctionTemplate: +      EntityInfo.kind = CXIdxEntity_Function; +      EntityInfo.templateKind = CXIdxEntity_Template; +      if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>( +                           cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) { +        if (isa<CXXConstructorDecl>(MD)) +          EntityInfo.kind = CXIdxEntity_CXXConstructor; +        else if (isa<CXXDestructorDecl>(MD)) +          EntityInfo.kind = CXIdxEntity_CXXDestructor; +        else if (isa<CXXConversionDecl>(MD)) +          EntityInfo.kind = CXIdxEntity_CXXConversionFunction; +        else { +          if (MD->isStatic()) +            EntityInfo.kind = CXIdxEntity_CXXStaticMethod; +          else +            EntityInfo.kind = CXIdxEntity_CXXInstanceMethod; +        } +      } +      break; +    case Decl::TypeAliasTemplate: +      EntityInfo.kind = CXIdxEntity_CXXTypeAlias; +      EntityInfo.templateKind = CXIdxEntity_Template; +      break; +    case Decl::TypeAlias: +      EntityInfo.kind = CXIdxEntity_CXXTypeAlias; +      EntityInfo.lang = CXIdxEntityLang_CXX; +      break; +    default: +      break; +    } +  } + +  if (EntityInfo.kind == CXIdxEntity_Unexposed) +    return; + +  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +    if (FD->getTemplatedKind() == +          FunctionDecl::TK_FunctionTemplateSpecialization) +      EntityInfo.templateKind = CXIdxEntity_TemplateSpecialization; +  } + +  if (EntityInfo.templateKind != CXIdxEntity_NonTemplate) +    EntityInfo.lang = CXIdxEntityLang_CXX; + +  if (IdentifierInfo *II = D->getIdentifier()) { +    EntityInfo.name = SA.toCStr(II->getName()); + +  } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) { +    EntityInfo.name = 0; // anonymous tag/field/namespace. + +  } else { +    SmallString<256> StrBuf; +    { +      llvm::raw_svector_ostream OS(StrBuf); +      D->printName(OS); +    } +    EntityInfo.name = SA.copyCStr(StrBuf.str()); +  } + +  { +    SmallString<512> StrBuf; +    bool Ignore = getDeclCursorUSR(D, StrBuf); +    if (Ignore) { +      EntityInfo.USR = 0; +    } else { +      EntityInfo.USR = SA.copyCStr(StrBuf.str()); +    } +  } +} + +void IndexingContext::getContainerInfo(const DeclContext *DC, +                                       ContainerInfo &ContInfo) { +  ContInfo.cursor = getCursor(cast<Decl>(DC)); +  ContInfo.DC = DC; +  ContInfo.IndexCtx = this; +} + +CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) { +  if (const TypeDecl *TD = dyn_cast<TypeDecl>(D)) +    return MakeCursorTypeRef(TD, Loc, CXTU); +  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) +    return MakeCursorObjCClassRef(ID, Loc, CXTU); +  if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) +    return MakeCursorObjCProtocolRef(PD, Loc, CXTU); +  if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) +    return MakeCursorTemplateRef(Template, Loc, CXTU); +  if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D)) +    return MakeCursorNamespaceRef(Namespace, Loc, CXTU); +  if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D)) +    return MakeCursorNamespaceRef(Namespace, Loc, CXTU); +  if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) +    return MakeCursorMemberRef(Field, Loc, CXTU); +  if (const VarDecl *Var = dyn_cast<VarDecl>(D)) +    return MakeCursorVariableRef(Var, Loc, CXTU); +   +  return clang_getNullCursor(); +} + +bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { +  if (isa<ObjCInterfaceDecl>(D)) +    return false; +  if (isa<ObjCCategoryDecl>(D)) +    return false; +  if (isa<ObjCIvarDecl>(D)) +    return false; +  if (isa<ObjCMethodDecl>(D)) +    return false; +  return true; +} + +bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { +  if (const ClassTemplateSpecializationDecl * +        SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { +    return SD->getSpecializationKind() == TSK_ImplicitInstantiation; +  } +  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +    return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation; +  } +  return false; +}  | 
