diff options
Diffstat (limited to 'clang/tools/libclang/IndexingContext.h')
-rw-r--r-- | clang/tools/libclang/IndexingContext.h | 556 |
1 files changed, 556 insertions, 0 deletions
diff --git a/clang/tools/libclang/IndexingContext.h b/clang/tools/libclang/IndexingContext.h new file mode 100644 index 0000000..6271660 --- /dev/null +++ b/clang/tools/libclang/IndexingContext.h @@ -0,0 +1,556 @@ +//===- IndexingContext.h - 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 "Index_Internal.h" +#include "CXCursor.h" + +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclGroup.h" +#include "llvm/ADT/DenseSet.h" +#include <deque> + +namespace clang { + class FileEntry; + class ObjCPropertyDecl; + class ClassTemplateDecl; + class FunctionTemplateDecl; + class TypeAliasTemplateDecl; + class ClassTemplateSpecializationDecl; + +namespace cxindex { + class IndexingContext; + class AttrListInfo; + +class ScratchAlloc { + IndexingContext &IdxCtx; + +public: + explicit ScratchAlloc(IndexingContext &indexCtx); + ScratchAlloc(const ScratchAlloc &SA); + + ~ScratchAlloc(); + + const char *toCStr(StringRef Str); + const char *copyCStr(StringRef Str); + + template <typename T> + T *allocate(); +}; + +struct EntityInfo : public CXIdxEntityInfo { + const NamedDecl *Dcl; + IndexingContext *IndexCtx; + IntrusiveRefCntPtr<AttrListInfo> AttrList; + + EntityInfo() { + name = USR = 0; + attributes = 0; + numAttributes = 0; + } +}; + +struct ContainerInfo : public CXIdxContainerInfo { + const DeclContext *DC; + IndexingContext *IndexCtx; +}; + +struct DeclInfo : public CXIdxDeclInfo { + enum DInfoKind { + Info_Decl, + + Info_ObjCContainer, + Info_ObjCInterface, + Info_ObjCProtocol, + Info_ObjCCategory, + + Info_ObjCProperty, + + Info_CXXClass + }; + + DInfoKind Kind; + + EntityInfo EntInfo; + ContainerInfo SemanticContainer; + ContainerInfo LexicalContainer; + ContainerInfo DeclAsContainer; + + DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer) + : Kind(Info_Decl) { + this->isRedeclaration = isRedeclaration; + this->isDefinition = isDefinition; + this->isContainer = isContainer; + attributes = 0; + numAttributes = 0; + declAsContainer = semanticContainer = lexicalContainer = 0; + } + DeclInfo(DInfoKind K, + bool isRedeclaration, bool isDefinition, bool isContainer) + : Kind(K) { + this->isRedeclaration = isRedeclaration; + this->isDefinition = isDefinition; + this->isContainer = isContainer; + attributes = 0; + numAttributes = 0; + declAsContainer = semanticContainer = lexicalContainer = 0; + } + + static bool classof(const DeclInfo *) { return true; } +}; + +struct ObjCContainerDeclInfo : public DeclInfo { + CXIdxObjCContainerDeclInfo ObjCContDeclInfo; + + ObjCContainerDeclInfo(bool isForwardRef, + bool isRedeclaration, + bool isImplementation) + : DeclInfo(Info_ObjCContainer, isRedeclaration, + /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) { + init(isForwardRef, isImplementation); + } + ObjCContainerDeclInfo(DInfoKind K, + bool isForwardRef, + bool isRedeclaration, + bool isImplementation) + : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef, + /*isContainer=*/!isForwardRef) { + init(isForwardRef, isImplementation); + } + + static bool classof(const DeclInfo *D) { + return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory; + } + static bool classof(const ObjCContainerDeclInfo *D) { return true; } + +private: + void init(bool isForwardRef, bool isImplementation) { + if (isForwardRef) + ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef; + else if (isImplementation) + ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation; + else + ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface; + } +}; + +struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo { + CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo; + CXIdxObjCProtocolRefListInfo ObjCProtoListInfo; + + ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D) + : ObjCContainerDeclInfo(Info_ObjCInterface, + /*isForwardRef=*/false, + /*isRedeclaration=*/D->getPreviousDecl() != 0, + /*isImplementation=*/false) { } + + static bool classof(const DeclInfo *D) { + return D->Kind == Info_ObjCInterface; + } + static bool classof(const ObjCInterfaceDeclInfo *D) { return true; } +}; + +struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo { + CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo; + + ObjCProtocolDeclInfo(const ObjCProtocolDecl *D) + : ObjCContainerDeclInfo(Info_ObjCProtocol, + /*isForwardRef=*/false, + /*isRedeclaration=*/D->getPreviousDecl(), + /*isImplementation=*/false) { } + + static bool classof(const DeclInfo *D) { + return D->Kind == Info_ObjCProtocol; + } + static bool classof(const ObjCProtocolDeclInfo *D) { return true; } +}; + +struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo { + CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo; + CXIdxObjCProtocolRefListInfo ObjCProtoListInfo; + + explicit ObjCCategoryDeclInfo(bool isImplementation) + : ObjCContainerDeclInfo(Info_ObjCCategory, + /*isForwardRef=*/false, + /*isRedeclaration=*/isImplementation, + /*isImplementation=*/isImplementation) { } + + static bool classof(const DeclInfo *D) { + return D->Kind == Info_ObjCCategory; + } + static bool classof(const ObjCCategoryDeclInfo *D) { return true; } +}; + +struct ObjCPropertyDeclInfo : public DeclInfo { + CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo; + + ObjCPropertyDeclInfo() + : DeclInfo(Info_ObjCProperty, + /*isRedeclaration=*/false, /*isDefinition=*/false, + /*isContainer=*/false) { } + + static bool classof(const DeclInfo *D) { + return D->Kind == Info_ObjCProperty; + } + static bool classof(const ObjCPropertyDeclInfo *D) { return true; } +}; + +struct CXXClassDeclInfo : public DeclInfo { + CXIdxCXXClassDeclInfo CXXClassInfo; + + CXXClassDeclInfo(bool isRedeclaration, bool isDefinition) + : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { } + + static bool classof(const DeclInfo *D) { + return D->Kind == Info_CXXClass; + } + static bool classof(const CXXClassDeclInfo *D) { return true; } +}; + +struct AttrInfo : public CXIdxAttrInfo { + const Attr *A; + + AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) { + kind = Kind; + cursor = C; + loc = Loc; + this->A = A; + } + + static bool classof(const AttrInfo *) { return true; } +}; + +struct IBOutletCollectionInfo : public AttrInfo { + EntityInfo ClassInfo; + CXIdxIBOutletCollectionAttrInfo IBCollInfo; + + IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) : + AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) { + assert(C.kind == CXCursor_IBOutletCollectionAttr); + IBCollInfo.objcClass = 0; + } + + IBOutletCollectionInfo(const IBOutletCollectionInfo &other); + + static bool classof(const AttrInfo *A) { + return A->kind == CXIdxAttr_IBOutletCollection; + } + static bool classof(const IBOutletCollectionInfo *D) { return true; } +}; + +class AttrListInfo { + ScratchAlloc SA; + + SmallVector<AttrInfo, 2> Attrs; + SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs; + SmallVector<CXIdxAttrInfo *, 2> CXAttrs; + unsigned ref_cnt; + + AttrListInfo(const AttrListInfo&); // DO NOT IMPLEMENT + void operator=(const AttrListInfo&); // DO NOT IMPLEMENT +public: + AttrListInfo(const Decl *D, IndexingContext &IdxCtx); + + static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D, + IndexingContext &IdxCtx); + + const CXIdxAttrInfo *const *getAttrs() const { + if (CXAttrs.empty()) + return 0; + return CXAttrs.data(); + } + unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); } + + /// \brief Retain/Release only useful when we allocate a AttrListInfo from the + /// BumpPtrAllocator, and not from the stack; so that we keep a pointer + // in the EntityInfo + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) { + // Memory is allocated from a BumpPtrAllocator, no need to delete it. + this->~AttrListInfo(); + } + } +}; + +struct RefFileOccurence { + const FileEntry *File; + const Decl *Dcl; + + RefFileOccurence(const FileEntry *File, const Decl *Dcl) + : File(File), Dcl(Dcl) { } +}; + +class IndexingContext { + ASTContext *Ctx; + CXClientData ClientData; + IndexerCallbacks &CB; + unsigned IndexOptions; + CXTranslationUnit CXTU; + + typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy; + typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer> + ContainerMapTy; + typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy; + + FileMapTy FileMap; + ContainerMapTy ContainerMap; + EntityMapTy EntityMap; + + llvm::DenseSet<RefFileOccurence> RefFileOccurences; + + std::deque<DeclGroupRef> TUDeclsInObjCContainer; + + llvm::BumpPtrAllocator StrScratch; + unsigned StrAdapterCount; + friend class ScratchAlloc; + + struct ObjCProtocolListInfo { + SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos; + SmallVector<EntityInfo, 4> ProtEntities; + SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots; + + CXIdxObjCProtocolRefListInfo getListInfo() const { + CXIdxObjCProtocolRefListInfo Info = { Prots.data(), + (unsigned)Prots.size() }; + return Info; + } + + ObjCProtocolListInfo(const ObjCProtocolList &ProtList, + IndexingContext &IdxCtx, + ScratchAlloc &SA); + }; + + struct CXXBasesListInfo { + SmallVector<CXIdxBaseClassInfo, 4> BaseInfos; + SmallVector<EntityInfo, 4> BaseEntities; + SmallVector<CXIdxBaseClassInfo *, 4> CXBases; + + const CXIdxBaseClassInfo *const *getBases() const { + return CXBases.data(); + } + unsigned getNumBases() const { return (unsigned)CXBases.size(); } + + CXXBasesListInfo(const CXXRecordDecl *D, + IndexingContext &IdxCtx, ScratchAlloc &SA); + + private: + SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const; + }; + + friend class AttrListInfo; + +public: + IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks, + unsigned indexOptions, CXTranslationUnit cxTU) + : Ctx(0), ClientData(clientData), CB(indexCallbacks), + IndexOptions(indexOptions), CXTU(cxTU), + StrScratch(/*size=*/1024), StrAdapterCount(0) { } + + ASTContext &getASTContext() const { return *Ctx; } + + void setASTContext(ASTContext &ctx); + void setPreprocessor(Preprocessor &PP); + + bool shouldSuppressRefs() const { + return IndexOptions & CXIndexOpt_SuppressRedundantRefs; + } + + bool shouldIndexFunctionLocalSymbols() const { + return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols; + } + + bool shouldIndexImplicitTemplateInsts() const { + return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations; + } + + bool shouldAbort(); + + bool hasDiagnosticCallback() const { return CB.diagnostic; } + + void enteredMainFile(const FileEntry *File); + + void ppIncludedFile(SourceLocation hashLoc, + StringRef filename, const FileEntry *File, + bool isImport, bool isAngled); + + void startedTranslationUnit(); + + void indexDecl(const Decl *D); + + void indexTagDecl(const TagDecl *D); + + void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, + const DeclContext *DC = 0); + + void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, + const DeclContext *DC = 0); + + void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const NamedDecl *Parent, + const DeclContext *DC = 0); + + void indexDeclContext(const DeclContext *DC); + + void indexBody(const Stmt *S, const NamedDecl *Parent, + const DeclContext *DC = 0); + + void handleDiagnosticSet(CXDiagnosticSet CXDiagSet); + + bool handleFunction(const FunctionDecl *FD); + + bool handleVar(const VarDecl *D); + + bool handleField(const FieldDecl *D); + + bool handleEnumerator(const EnumConstantDecl *D); + + bool handleTagDecl(const TagDecl *D); + + bool handleTypedefName(const TypedefNameDecl *D); + + bool handleObjCInterface(const ObjCInterfaceDecl *D); + bool handleObjCImplementation(const ObjCImplementationDecl *D); + + bool handleObjCProtocol(const ObjCProtocolDecl *D); + + bool handleObjCCategory(const ObjCCategoryDecl *D); + bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); + + bool handleObjCMethod(const ObjCMethodDecl *D); + + bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D); + bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc, + const DeclContext *LexicalDC); + + bool handleObjCProperty(const ObjCPropertyDecl *D); + + bool handleNamespace(const NamespaceDecl *D); + + bool handleClassTemplate(const ClassTemplateDecl *D); + bool handleFunctionTemplate(const FunctionTemplateDecl *D); + bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D); + + bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, + const NamedDecl *Parent, + const DeclContext *DC, + const Expr *E = 0, + CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); + + bool handleReference(const NamedDecl *D, SourceLocation Loc, + const NamedDecl *Parent, + const DeclContext *DC, + const Expr *E = 0, + CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); + + bool isNotFromSourceFile(SourceLocation Loc) const; + + void indexTopLevelDecl(Decl *D); + void indexTUDeclsInObjCContainer(); + void indexDeclGroupRef(DeclGroupRef DG); + + void addTUDeclInObjCContainer(DeclGroupRef DG) { + TUDeclsInObjCContainer.push_back(DG); + } + + void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file, + unsigned *line, unsigned *column, unsigned *offset); + + CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const; + void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container); + + CXIdxClientEntity getClientEntity(const Decl *D) const; + void setClientEntity(const Decl *D, CXIdxClientEntity client); + + static bool isTemplateImplicitInstantiation(const Decl *D); + +private: + bool handleDecl(const NamedDecl *D, + SourceLocation Loc, CXCursor Cursor, + DeclInfo &DInfo, + const DeclContext *LexicalDC = 0); + + bool handleObjCContainer(const ObjCContainerDecl *D, + SourceLocation Loc, CXCursor Cursor, + ObjCContainerDeclInfo &ContDInfo); + + bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD); + + bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc); + + const NamedDecl *getEntityDecl(const NamedDecl *D) const; + + const DeclContext *getEntityContainer(const Decl *D) const; + + CXIdxClientFile getIndexFile(const FileEntry *File); + + CXIdxLoc getIndexLoc(SourceLocation Loc) const; + + void getEntityInfo(const NamedDecl *D, + EntityInfo &EntityInfo, + ScratchAlloc &SA); + + void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo); + + CXCursor getCursor(const Decl *D) { + return cxcursor::MakeCXCursor(const_cast<Decl*>(D), CXTU); + } + + CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc); + + static bool shouldIgnoreIfImplicit(const Decl *D); +}; + +inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) { + ++IdxCtx.StrAdapterCount; +} +inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) { + ++IdxCtx.StrAdapterCount; +} + +inline ScratchAlloc::~ScratchAlloc() { + --IdxCtx.StrAdapterCount; + if (IdxCtx.StrAdapterCount == 0) + IdxCtx.StrScratch.Reset(); +} + +template <typename T> +inline T *ScratchAlloc::allocate() { + return IdxCtx.StrScratch.Allocate<T>(); +} + +}} // end clang::cxindex + +namespace llvm { + /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and + /// DenseSets. + template <> + struct DenseMapInfo<clang::cxindex::RefFileOccurence> { + static inline clang::cxindex::RefFileOccurence getEmptyKey() { + return clang::cxindex::RefFileOccurence(0, 0); + } + + static inline clang::cxindex::RefFileOccurence getTombstoneKey() { + return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0, + (const clang::Decl *)~0); + } + + static unsigned getHashValue(clang::cxindex::RefFileOccurence S) { + llvm::FoldingSetNodeID ID; + ID.AddPointer(S.File); + ID.AddPointer(S.Dcl); + return ID.ComputeHash(); + } + + static bool isEqual(clang::cxindex::RefFileOccurence LHS, + clang::cxindex::RefFileOccurence RHS) { + return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl; + } + }; +} |