From: Argyrios Kyrtzidis Date: Fri, 12 Feb 2016 23:10:59 +0000 (+0000) Subject: [libclang] Separate the underlying indexing functionality of libclang and introduce... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=754b721c2005bfe3c417e3b6bb06b77e840db131;p=clang [libclang] Separate the underlying indexing functionality of libclang and introduce it into the clangIndex library. It is a general goodness for libclang itself to mostly be a wrapper of functionality provided by the libraries. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@260760 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h new file mode 100644 index 0000000000..cb00345f56 --- /dev/null +++ b/include/clang/Index/IndexDataConsumer.h @@ -0,0 +1,61 @@ +//===--- IndexDataConsumer.h - Abstract index data consumer ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_INDEXDATACONSUMER_H +#define LLVM_CLANG_INDEX_INDEXDATACONSUMER_H + +#include "clang/Index/IndexSymbol.h" + +namespace clang { + class DeclContext; + class Expr; + class FileID; + class IdentifierInfo; + class ImportDecl; + class MacroInfo; + +namespace index { + +class IndexDataConsumer { +public: + struct ASTNodeInfo { + const Expr *OrigE; + const Decl *OrigD; + const Decl *Parent; + const DeclContext *ContainerDC; + }; + + virtual ~IndexDataConsumer() {} + + /// \returns true to continue indexing, or false to abort. + virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, + ArrayRef Relations, + FileID FID, unsigned Offset, + ASTNodeInfo ASTNode); + + /// \returns true to continue indexing, or false to abort. + virtual bool handleMacroOccurence(const IdentifierInfo *Name, + const MacroInfo *MI, SymbolRoleSet Roles, + FileID FID, unsigned Offset); + + /// \returns true to continue indexing, or false to abort. + virtual bool handleModuleOccurence(const ImportDecl *ImportD, + SymbolRoleSet Roles, + FileID FID, unsigned Offset); + + virtual void finish() {} + +private: + virtual void _anchor(); +}; + +} // namespace index +} // namespace clang + +#endif diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h new file mode 100644 index 0000000000..0849241b60 --- /dev/null +++ b/include/clang/Index/IndexSymbol.h @@ -0,0 +1,112 @@ +//===--- IndexSymbol.h - Types and functions for indexing symbols ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_INDEXSYMBOL_H +#define LLVM_CLANG_INDEX_INDEXSYMBOL_H + +#include "clang/Basic/LLVM.h" + +namespace clang { + class Decl; + +namespace index { + +enum class SymbolKind : uint8_t { + Unknown, + + Module, + Macro, + + Enum, + Struct, + Union, + Typedef, + + Function, + Variable, + Field, + EnumConstant, + + ObjCClass, + ObjCProtocol, + ObjCCategory, + + ObjCInstanceMethod, + ObjCClassMethod, + ObjCProperty, + ObjCIvar, + + CXXClass, + CXXNamespace, + CXXNamespaceAlias, + CXXStaticVariable, + CXXStaticMethod, + CXXInstanceMethod, + CXXConstructor, + CXXDestructor, + CXXConversionFunction, + CXXTypeAlias, + CXXInterface, +}; + +enum class SymbolLanguage { + C, + ObjC, + CXX, +}; + +enum class SymbolCXXTemplateKind { + NonTemplate, + Template, + TemplatePartialSpecialization, + TemplateSpecialization, +}; + +/// Set of roles that are attributed to symbol occurrences. +enum class SymbolRole : uint16_t { + Declaration = 1 << 0, + Definition = 1 << 1, + Reference = 1 << 2, + Read = 1 << 3, + Write = 1 << 4, + Call = 1 << 5, + Dynamic = 1 << 6, + AddressOf = 1 << 7, + Implicit = 1 << 8, + + // Relation roles. + RelationChildOf = 1 << 9, + RelationBaseOf = 1 << 10, + RelationOverrideOf = 1 << 11, + RelationReceivedBy = 1 << 12, +}; +static const unsigned SymbolRoleBitNum = 13; +typedef unsigned SymbolRoleSet; + +/// Represents a relation to another symbol for a symbol occurrence. +struct SymbolRelation { + SymbolRoleSet Roles; + const Decl *RelatedSymbol; + + SymbolRelation(SymbolRoleSet Roles, const Decl *Sym) + : Roles(Roles), RelatedSymbol(Sym) {} +}; + +struct SymbolInfo { + SymbolKind Kind; + SymbolCXXTemplateKind TemplateKind; + SymbolLanguage Lang; +}; + +SymbolInfo getSymbolInfo(const Decl *D); + +} // namespace index +} // namespace clang + +#endif diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h new file mode 100644 index 0000000000..dfc363a049 --- /dev/null +++ b/include/clang/Index/IndexingAction.h @@ -0,0 +1,47 @@ +//===--- IndexingAction.h - Frontend index action -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_INDEXINGACTION_H +#define LLVM_CLANG_INDEX_INDEXINGACTION_H + +#include "clang/Basic/LLVM.h" +#include + +namespace clang { + class ASTUnit; + class FrontendAction; + +namespace index { + class IndexDataConsumer; + +struct IndexingOptions { + enum class SystemSymbolFilterKind { + None, + DeclarationsOnly, + All, + }; + + SystemSymbolFilterKind SystemSymbolFilter + = SystemSymbolFilterKind::DeclarationsOnly; + bool IndexFunctionLocals = false; +}; + +std::unique_ptr +createIndexingAction(std::unique_ptr WrappedAction, + std::shared_ptr DataConsumer, + IndexingOptions Opts); + +void indexASTUnit(ASTUnit &Unit, + std::shared_ptr DataConsumer, + IndexingOptions Opts); + +} // namespace index +} // namespace clang + +#endif diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt index 3869c32c87..cb2b931235 100644 --- a/lib/Index/CMakeLists.txt +++ b/lib/Index/CMakeLists.txt @@ -5,14 +5,22 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangIndex CommentToXML.cpp USRGeneration.cpp + IndexBody.cpp + IndexDecl.cpp + IndexingAction.cpp + IndexingContext.cpp + IndexSymbol.cpp + IndexTypeSourceInfo.cpp ADDITIONAL_HEADERS + IndexingContext.h SimpleFormatContext.h LINK_LIBS clangAST clangBasic clangFormat + clangFrontend clangRewrite clangToolingCore ) diff --git a/lib/Index/IndexBody.cpp b/lib/Index/IndexBody.cpp new file mode 100644 index 0000000000..56fba28387 --- /dev/null +++ b/lib/Index/IndexBody.cpp @@ -0,0 +1,347 @@ +//===- IndexBody.cpp - Indexing statements --------------------------------===// +// +// 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 "clang/AST/RecursiveASTVisitor.h" + +using namespace clang; +using namespace clang::index; + +namespace { + +class BodyIndexer : public RecursiveASTVisitor { + IndexingContext &IndexCtx; + const NamedDecl *Parent; + const DeclContext *ParentDC; + SmallVector StmtStack; + + typedef RecursiveASTVisitor base; +public: + BodyIndexer(IndexingContext &indexCtx, + const NamedDecl *Parent, const DeclContext *DC) + : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } + + bool shouldWalkTypesOfTypeLocs() const { return false; } + + bool TraverseStmt(Stmt *S) { + StmtStack.push_back(S); + bool ret = base::TraverseStmt(S); + StmtStack.pop_back(); + return ret; + } + + bool TraverseTypeLoc(TypeLoc TL) { + IndexCtx.indexTypeLoc(TL, Parent, ParentDC); + return true; + } + + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); + return true; + } + + SymbolRoleSet getRolesForRef(const Expr *E, + SmallVectorImpl &Relations) { + SymbolRoleSet Roles{}; + assert(!StmtStack.empty() && E == StmtStack.back()); + if (StmtStack.size() == 1) + return Roles; + auto It = StmtStack.end()-2; + while (isa(*It) || isa(*It)) { + if (auto ICE = dyn_cast(*It)) { + if (ICE->getCastKind() == CK_LValueToRValue) + Roles |= (unsigned)(unsigned)SymbolRole::Read; + } + if (It == StmtStack.begin()) + break; + --It; + } + const Stmt *Parent = *It; + + if (auto BO = dyn_cast(Parent)) { + if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E) + Roles |= (unsigned)SymbolRole::Write; + + } else if (auto UO = dyn_cast(Parent)) { + if (UO->isIncrementDecrementOp()) { + Roles |= (unsigned)SymbolRole::Read; + Roles |= (unsigned)SymbolRole::Write; + } else if (UO->getOpcode() == UO_AddrOf) { + Roles |= (unsigned)SymbolRole::AddressOf; + } + + } else if (auto CA = dyn_cast(Parent)) { + if (CA->getLHS()->IgnoreParenCasts() == E) { + Roles |= (unsigned)SymbolRole::Read; + Roles |= (unsigned)SymbolRole::Write; + } + + } else if (auto CE = dyn_cast(Parent)) { + if (CE->getCallee()->IgnoreParenCasts() == E) { + Roles |= (unsigned)SymbolRole::Call; + if (auto *ME = dyn_cast(E)) { + if (auto *CXXMD = dyn_cast_or_null(ME->getMemberDecl())) + if (CXXMD->isVirtual() && !ME->hasQualifier()) { + Roles |= (unsigned)SymbolRole::Dynamic; + auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType(); + if (!BaseTy.isNull()) + if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl()) + Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, + CXXRD); + } + } + } else if (auto CXXOp = dyn_cast(CE)) { + if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) { + OverloadedOperatorKind Op = CXXOp->getOperator(); + if (Op == OO_Equal) { + Roles |= (unsigned)SymbolRole::Write; + } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) || + Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual || + Op == OO_PlusPlus || Op == OO_MinusMinus) { + Roles |= (unsigned)SymbolRole::Read; + Roles |= (unsigned)SymbolRole::Write; + } else if (Op == OO_Amp) { + Roles |= (unsigned)SymbolRole::AddressOf; + } + } + } + } + + return Roles; + } + + bool VisitDeclRefExpr(DeclRefExpr *E) { + SmallVector Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); + return IndexCtx.handleReference(E->getDecl(), E->getLocation(), + Parent, ParentDC, Roles, Relations, E); + } + + bool VisitMemberExpr(MemberExpr *E) { + SourceLocation Loc = E->getMemberLoc(); + if (Loc.isInvalid()) + Loc = E->getLocStart(); + SmallVector Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); + return IndexCtx.handleReference(E->getMemberDecl(), Loc, + Parent, ParentDC, Roles, Relations, E); + } + + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { + for (DesignatedInitExpr::reverse_designators_iterator + D = E->designators_rbegin(), DEnd = E->designators_rend(); + D != DEnd; ++D) { + if (D->isFieldDesignator()) + return IndexCtx.handleReference(D->getField(), D->getFieldLoc(), + Parent, ParentDC, SymbolRoleSet(), + {}, E); + } + return true; + } + + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + SmallVector Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); + return IndexCtx.handleReference(E->getDecl(), E->getLocation(), + Parent, ParentDC, Roles, Relations, E); + } + + bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { + if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) + return false; + if (auto *RecE = dyn_cast( + MsgE->getInstanceReceiver()->IgnoreParenCasts())) { + if (RecE->getMethodFamily() == OMF_alloc) + return false; + } + return true; + }; + + if (ObjCMethodDecl *MD = E->getMethodDecl()) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Call; + if (E->isImplicit()) + Roles |= (unsigned)SymbolRole::Implicit; + + SmallVector Relations; + if (isDynamic(E)) { + Roles |= (unsigned)SymbolRole::Dynamic; + if (auto *RecD = E->getReceiverInterface()) + Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD); + } + + return IndexCtx.handleReference(MD, E->getSelectorStartLoc(), + Parent, ParentDC, Roles, Relations, E); + } + return true; + } + + bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { + if (E->isExplicitProperty()) + return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), + Parent, ParentDC, SymbolRoleSet(), {}, E); + + // No need to do a handleReference for the objc method, because there will + // be a message expr as part of PseudoObjectExpr. + return true; + } + + bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { + return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), + Parent, ParentDC, SymbolRoleSet(), {}, E); + } + + bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { + return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), + Parent, ParentDC, SymbolRoleSet(), {}, E); + } + + bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { + if (ObjCMethodDecl *MD = E->getBoxingMethod()) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Call; + Roles |= (unsigned)SymbolRole::Implicit; + return IndexCtx.handleReference(MD, E->getLocStart(), + Parent, ParentDC, Roles, {}, E); + } + return true; + } + + bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Call; + Roles |= (unsigned)SymbolRole::Implicit; + return IndexCtx.handleReference(MD, E->getLocStart(), + Parent, ParentDC, Roles, {}, E); + } + return true; + } + + bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { + if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Call; + Roles |= (unsigned)SymbolRole::Implicit; + return IndexCtx.handleReference(MD, E->getLocStart(), + Parent, ParentDC, Roles, {}, E); + } + return true; + } + + bool VisitCXXConstructExpr(CXXConstructExpr *E) { + return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), + Parent, ParentDC, (unsigned)SymbolRole::Call, {}, E); + } + + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, + DataRecursionQueue *Q = nullptr) { + if (E->getOperatorLoc().isInvalid()) + return true; // implicit. + return base::TraverseCXXOperatorCallExpr(E); + } + + bool VisitDeclStmt(DeclStmt *S) { + if (IndexCtx.shouldIndexFunctionLocalSymbols()) { + IndexCtx.indexDeclGroupRef(S->getDeclGroup()); + return true; + } + + DeclGroupRef DG = S->getDeclGroup(); + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { + const Decl *D = *I; + if (!D) + continue; + if (!IndexCtx.isFunctionLocalDecl(D)) + IndexCtx.indexTopLevelDecl(D); + } + + return true; + } + + bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) { + if (C->capturesThis() || C->capturesVLAType()) + return true; + + if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) + return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), + Parent, ParentDC, SymbolRoleSet()); + + // FIXME: Lambda init-captures. + return true; + } + + // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating + // the things that we visit. Make sure to only visit the semantic form. + // Also visit things that are in the syntactic form but not the semantic one, + // for example the indices in DesignatedInitExprs. + bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { + + class SyntacticFormIndexer : + public RecursiveASTVisitor { + IndexingContext &IndexCtx; + const NamedDecl *Parent; + const DeclContext *ParentDC; + + public: + SyntacticFormIndexer(IndexingContext &indexCtx, + const NamedDecl *Parent, const DeclContext *DC) + : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } + + bool shouldWalkTypesOfTypeLocs() const { return false; } + + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { + for (DesignatedInitExpr::reverse_designators_iterator + D = E->designators_rbegin(), DEnd = E->designators_rend(); + D != DEnd; ++D) { + if (D->isFieldDesignator()) + return IndexCtx.handleReference(D->getField(), D->getFieldLoc(), + Parent, ParentDC, SymbolRoleSet(), + {}, E); + } + return true; + } + }; + + auto visitForm = [&](InitListExpr *Form) { + for (Stmt *SubStmt : Form->children()) { + if (!TraverseStmt(SubStmt)) + return false; + } + return true; + }; + + InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); + InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; + + if (SemaForm) { + // Visit things present in syntactic form but not the semantic form. + if (SyntaxForm) { + SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm); + } + return visitForm(SemaForm); + } + + // No semantic, try the syntactic. + if (SyntaxForm) { + return visitForm(SyntaxForm); + } + + return true; + } +}; + +} // anonymous namespace + +void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, + const DeclContext *DC) { + if (!S) + return; + + if (!DC) + DC = Parent->getLexicalDeclContext(); + BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast(S)); +} diff --git a/tools/libclang/IndexDecl.cpp b/lib/Index/IndexDecl.cpp similarity index 50% rename from tools/libclang/IndexDecl.cpp rename to lib/Index/IndexDecl.cpp index aa97129c23..76f68e564c 100644 --- a/tools/libclang/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -1,4 +1,4 @@ -//===- CIndexHigh.cpp - Higher level API functions ------------------------===// +//===- IndexDecl.cpp - Indexing declarations ------------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,10 +8,11 @@ //===----------------------------------------------------------------------===// #include "IndexingContext.h" +#include "clang/Index/IndexDataConsumer.h" #include "clang/AST/DeclVisitor.h" using namespace clang; -using namespace cxindex; +using namespace index; namespace { @@ -22,6 +23,13 @@ public: explicit IndexingDeclVisitor(IndexingContext &indexCtx) : IndexCtx(indexCtx) { } + bool Handled = true; + + bool VisitDecl(const Decl *D) { + Handled = false; + return true; + } + /// \brief Returns true if the given method has been defined explicitly by the /// user. static bool hasUserDefined(const ObjCMethodDecl *D, @@ -35,25 +43,35 @@ public: const NamedDecl *Parent = nullptr) { if (!Parent) Parent = D; - if (!IndexCtx.shouldIndexFunctionLocalSymbols()) { - IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent); - IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); - } else { + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent); + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); + if (IndexCtx.shouldIndexFunctionLocalSymbols()) { + // Only index parameters in definitions, parameters in declarations are + // not useful. if (const ParmVarDecl *Parm = dyn_cast(D)) { - IndexCtx.handleVar(Parm); + auto *DC = Parm->getDeclContext(); + if (auto *FD = dyn_cast(DC)) { + if (FD->isThisDeclarationADefinition()) + IndexCtx.handleDecl(Parm); + } else if (auto *MD = dyn_cast(DC)) { + if (MD->isThisDeclarationADefinition()) + IndexCtx.handleDecl(Parm); + } else { + IndexCtx.handleDecl(Parm); + } } else if (const FunctionDecl *FD = dyn_cast(D)) { - for (auto PI : FD->params()) { - IndexCtx.handleVar(PI); + if (FD->isThisDeclarationADefinition()) { + for (auto PI : FD->params()) { + IndexCtx.handleDecl(PI); + } } } } } - void handleObjCMethod(const ObjCMethodDecl *D) { - IndexCtx.handleObjCMethod(D); - if (D->isImplicit()) - return; - + bool handleObjCMethod(const ObjCMethodDecl *D) { + if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic)) + return false; IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); for (const auto *I : D->params()) handleDeclarator(I, D); @@ -64,10 +82,26 @@ public: IndexCtx.indexBody(Body, D, D); } } + return true; } bool VisitFunctionDecl(const FunctionDecl *D) { - IndexCtx.handleFunction(D); + if (D->isDeleted()) + return true; + + SymbolRoleSet Roles{}; + SmallVector Relations; + if (auto *CXXMD = dyn_cast(D)) { + if (CXXMD->isVirtual()) + Roles |= (unsigned)SymbolRole::Dynamic; + for (auto I = CXXMD->begin_overridden_methods(), + E = CXXMD->end_overridden_methods(); I != E; ++I) { + Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I); + } + } + + if (!IndexCtx.handleDecl(D, Roles, Relations)) + return false; handleDeclarator(D); if (const CXXConstructorDecl *Ctor = dyn_cast(D)) { @@ -76,7 +110,8 @@ public: if (Init->isWritten()) { IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); if (const FieldDecl *Member = Init->getAnyMember()) - IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D); + IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, + (unsigned)SymbolRole::Write); IndexCtx.indexBody(Init->getInit(), D, D); } } @@ -92,14 +127,16 @@ public: } bool VisitVarDecl(const VarDecl *D) { - IndexCtx.handleVar(D); + if (!IndexCtx.handleDecl(D)) + return false; handleDeclarator(D); IndexCtx.indexBody(D->getInit(), D); return true; } bool VisitFieldDecl(const FieldDecl *D) { - IndexCtx.handleField(D); + if (!IndexCtx.handleDecl(D)) + return false; handleDeclarator(D); if (D->isBitField()) IndexCtx.indexBody(D->getBitWidth(), D); @@ -108,44 +145,77 @@ public: return true; } + bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { + if (D->getSynthesize()) { + // For synthesized ivars, use the location of the ObjC implementation, + // not the location of the property. + // Otherwise the header file containing the @interface will have different + // indexing contents based on whether the @implementation was present or + // not in the translation unit. + return IndexCtx.handleDecl(D, + cast(D->getDeclContext())->getLocation(), + (unsigned)SymbolRole::Implicit); + } + if (!IndexCtx.handleDecl(D)) + return false; + handleDeclarator(D); + return true; + } + bool VisitMSPropertyDecl(const MSPropertyDecl *D) { handleDeclarator(D); return true; } bool VisitEnumConstantDecl(const EnumConstantDecl *D) { - IndexCtx.handleEnumerator(D); + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexBody(D->getInitExpr(), D); return true; } bool VisitTypedefNameDecl(const TypedefNameDecl *D) { - IndexCtx.handleTypedefName(D); + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); return true; } bool VisitTagDecl(const TagDecl *D) { // Non-free standing tags are handled in indexTypeSourceInfo. - if (D->isFreeStanding()) - IndexCtx.indexTagDecl(D); + if (D->isFreeStanding()) { + if (D->isThisDeclarationADefinition()) { + IndexCtx.indexTagDecl(D); + } else { + auto *Parent = dyn_cast(D->getDeclContext()); + return IndexCtx.handleReference(D, D->getLocation(), Parent, + D->getLexicalDeclContext(), + SymbolRoleSet()); + } + } return true; } bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { - IndexCtx.handleObjCInterface(D); - if (D->isThisDeclarationADefinition()) { + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexDeclContext(D); + } else { + return IndexCtx.handleReference(D, D->getLocation(), nullptr, nullptr, + SymbolRoleSet()); } return true; } bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { - IndexCtx.handleObjCProtocol(D); - if (D->isThisDeclarationADefinition()) { + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexDeclContext(D); + } else { + return IndexCtx.handleReference(D, D->getLocation(), nullptr, nullptr, + SymbolRoleSet()); } return true; } @@ -156,9 +226,10 @@ public: return true; if (Class->isImplicitInterfaceDecl()) - IndexCtx.handleObjCInterface(Class); + IndexCtx.handleDecl(Class); - IndexCtx.handleObjCImplementation(D); + if (!IndexCtx.handleDecl(D)) + return false; // Index the ivars first to make sure the synthesized ivars are indexed // before indexing the methods that can reference them. @@ -173,7 +244,8 @@ public: } bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { - IndexCtx.handleObjCCategory(D); + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexDeclContext(D); return true; } @@ -183,7 +255,8 @@ public: if (!Cat) return true; - IndexCtx.handleObjCCategoryImpl(D); + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexDeclContext(D); return true; } @@ -205,14 +278,19 @@ public: if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) handleObjCMethod(MD); - IndexCtx.handleObjCProperty(D); + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); return true; } bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { ObjCPropertyDecl *PD = D->getPropertyDecl(); - IndexCtx.handleSynthesizedObjCProperty(D); + if (!IndexCtx.handleReference(PD, D->getLocation(), + /*Parent=*/cast(D->getDeclContext()), + D->getDeclContext(), SymbolRoleSet(), {}, + /*RefE=*/nullptr, D)) + return false; if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) return true; @@ -221,121 +299,131 @@ public: if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { if (!IvarD->getSynthesize()) IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, - D->getDeclContext()); + D->getDeclContext(), SymbolRoleSet()); } + auto *ImplD = cast(D->getDeclContext()); if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { if (MD->isPropertyAccessor() && - !hasUserDefined(MD, cast(D->getDeclContext()))) - IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), - D->getLexicalDeclContext()); + !hasUserDefined(MD, ImplD)) + IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); } if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { if (MD->isPropertyAccessor() && - !hasUserDefined(MD, cast(D->getDeclContext()))) - IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), - D->getLexicalDeclContext()); + !hasUserDefined(MD, ImplD)) + IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); } return true; } bool VisitNamespaceDecl(const NamespaceDecl *D) { - IndexCtx.handleNamespace(D); + if (!IndexCtx.handleDecl(D)) + return false; IndexCtx.indexDeclContext(D); return true; } bool VisitUsingDecl(const UsingDecl *D) { - // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, - // we should do better. + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + const NamedDecl *Parent = dyn_cast(DC); - IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, + D->getLexicalDeclContext()); for (const auto *I : D->shadows()) - IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), D, - D->getLexicalDeclContext()); + IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, + D->getLexicalDeclContext(), SymbolRoleSet()); return true; } bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { - // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, - // we should do better. - - IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); - IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), - D->getLocation(), D, D->getLexicalDeclContext()); - return true; - } - - bool VisitClassTemplateDecl(const ClassTemplateDecl *D) { - IndexCtx.handleClassTemplate(D); - if (D->isThisDeclarationADefinition()) - IndexCtx.indexDeclContext(D->getTemplatedDecl()); - return true; + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + const NamedDecl *Parent = dyn_cast(DC); + + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, + D->getLexicalDeclContext()); + return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), + D->getLocation(), Parent, + D->getLexicalDeclContext(), + SymbolRoleSet()); } bool VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl *D) { // FIXME: Notify subsequent callbacks if info comes from implicit // instantiation. - if (D->isThisDeclarationADefinition() && - (IndexCtx.shouldIndexImplicitTemplateInsts() || - !IndexCtx.isTemplateImplicitInstantiation(D))) + if (D->isThisDeclarationADefinition()) IndexCtx.indexTagDecl(D); return true; } - bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { - IndexCtx.handleFunctionTemplate(D); - FunctionDecl *FD = D->getTemplatedDecl(); - handleDeclarator(FD, D); - if (FD->isThisDeclarationADefinition()) { - const Stmt *Body = FD->getBody(); - if (Body) { - IndexCtx.indexBody(Body, D, FD); - } - } - return true; + bool VisitTemplateDecl(const TemplateDecl *D) { + // FIXME: Template parameters. + return Visit(D->getTemplatedDecl()); } - bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { - IndexCtx.handleTypeAliasTemplate(D); - IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); + bool VisitFriendDecl(const FriendDecl *D) { + if (auto ND = D->getFriendDecl()) { + // FIXME: Ignore a class template in a dependent context, these are not + // linked properly with their redeclarations, ending up with duplicate + // USRs. + // See comment "Friend templates are visible in fairly strange ways." in + // SemaTemplate.cpp which precedes code that prevents the friend template + // from becoming visible from the enclosing context. + if (isa(ND) && D->getDeclContext()->isDependentContext()) + return true; + return Visit(ND); + } + if (auto Ty = D->getFriendType()) { + IndexCtx.indexTypeSourceInfo(Ty, cast(D->getDeclContext())); + } return true; } bool VisitImportDecl(const ImportDecl *D) { - IndexCtx.importedModule(D); - return true; + return IndexCtx.importedModule(D); } }; } // anonymous namespace -void IndexingContext::indexDecl(const Decl *D) { +bool IndexingContext::indexDecl(const Decl *D) { if (D->isImplicit() && shouldIgnoreIfImplicit(D)) - return; + return true; - bool Handled = IndexingDeclVisitor(*this).Visit(D); - if (!Handled && isa(D)) - indexDeclContext(cast(D)); + if (isTemplateImplicitInstantiation(D)) + return true; + + IndexingDeclVisitor Visitor(*this); + bool ShouldContinue = Visitor.Visit(D); + if (!ShouldContinue) + return false; + + if (!Visitor.Handled && isa(D)) + return indexDeclContext(cast(D)); + + return true; } -void IndexingContext::indexDeclContext(const DeclContext *DC) { +bool IndexingContext::indexDeclContext(const DeclContext *DC) { for (const auto *I : DC->decls()) - indexDecl(I); + if (!indexDecl(I)) + return false; + return true; } -void IndexingContext::indexTopLevelDecl(const Decl *D) { - if (isNotFromSourceFile(D->getLocation())) - return; +bool IndexingContext::indexTopLevelDecl(const Decl *D) { + if (D->getLocation().isInvalid()) + return true; if (isa(D)) - return; // Wait for the objc container. + return true; // Wait for the objc container. - indexDecl(D); + return indexDecl(D); } -void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { +bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) - indexTopLevelDecl(*I); + if (!indexTopLevelDecl(*I)) + return false; + return true; } diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp new file mode 100644 index 0000000000..c7c3c8c4d6 --- /dev/null +++ b/lib/Index/IndexSymbol.cpp @@ -0,0 +1,187 @@ +//===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/IndexSymbol.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" + +using namespace clang; +using namespace clang::index; + +SymbolInfo index::getSymbolInfo(const Decl *D) { + assert(D); + SymbolInfo Info; + Info.Kind = SymbolKind::Unknown; + Info.TemplateKind = SymbolCXXTemplateKind::NonTemplate; + Info.Lang = SymbolLanguage::C; + + if (const TagDecl *TD = dyn_cast(D)) { + switch (TD->getTagKind()) { + case TTK_Struct: + Info.Kind = SymbolKind::Struct; break; + case TTK_Union: + Info.Kind = SymbolKind::Union; break; + case TTK_Class: + Info.Kind = SymbolKind::CXXClass; + Info.Lang = SymbolLanguage::CXX; + break; + case TTK_Interface: + Info.Kind = SymbolKind::CXXInterface; + Info.Lang = SymbolLanguage::CXX; + break; + case TTK_Enum: + Info.Kind = SymbolKind::Enum; break; + } + + if (const CXXRecordDecl *CXXRec = dyn_cast(D)) + if (!CXXRec->isCLike()) + Info.Lang = SymbolLanguage::CXX; + + if (isa(D)) { + Info.TemplateKind = SymbolCXXTemplateKind::TemplatePartialSpecialization; + } else if (isa(D)) { + Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization; + } + + } else { + switch (D->getKind()) { + case Decl::Typedef: + Info.Kind = SymbolKind::Typedef; break; + case Decl::Function: + Info.Kind = SymbolKind::Function; + break; + case Decl::ParmVar: + Info.Kind = SymbolKind::Variable; + break; + case Decl::Var: + Info.Kind = SymbolKind::Variable; + if (isa(D->getDeclContext())) { + Info.Kind = SymbolKind::CXXStaticVariable; + Info.Lang = SymbolLanguage::CXX; + } + break; + case Decl::Field: + Info.Kind = SymbolKind::Field; + if (const CXXRecordDecl * + CXXRec = dyn_cast(D->getDeclContext())) { + if (!CXXRec->isCLike()) + Info.Lang = SymbolLanguage::CXX; + } + break; + case Decl::EnumConstant: + Info.Kind = SymbolKind::EnumConstant; break; + case Decl::ObjCInterface: + case Decl::ObjCImplementation: + Info.Kind = SymbolKind::ObjCClass; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::ObjCProtocol: + Info.Kind = SymbolKind::ObjCProtocol; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::ObjCCategory: + case Decl::ObjCCategoryImpl: + Info.Kind = SymbolKind::ObjCCategory; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::ObjCMethod: + if (cast(D)->isInstanceMethod()) + Info.Kind = SymbolKind::ObjCInstanceMethod; + else + Info.Kind = SymbolKind::ObjCClassMethod; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::ObjCProperty: + Info.Kind = SymbolKind::ObjCProperty; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::ObjCIvar: + Info.Kind = SymbolKind::ObjCIvar; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::Namespace: + Info.Kind = SymbolKind::CXXNamespace; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::NamespaceAlias: + Info.Kind = SymbolKind::CXXNamespaceAlias; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXConstructor: + Info.Kind = SymbolKind::CXXConstructor; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXDestructor: + Info.Kind = SymbolKind::CXXDestructor; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXConversion: + Info.Kind = SymbolKind::CXXConversionFunction; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXMethod: { + const CXXMethodDecl *MD = cast(D); + if (MD->isStatic()) + Info.Kind = SymbolKind::CXXStaticMethod; + else + Info.Kind = SymbolKind::CXXInstanceMethod; + Info.Lang = SymbolLanguage::CXX; + break; + } + case Decl::ClassTemplate: + Info.Kind = SymbolKind::CXXClass; + Info.TemplateKind = SymbolCXXTemplateKind::Template; + break; + case Decl::FunctionTemplate: + Info.Kind = SymbolKind::Function; + Info.TemplateKind = SymbolCXXTemplateKind::Template; + if (const CXXMethodDecl *MD = dyn_cast_or_null( + cast(D)->getTemplatedDecl())) { + if (isa(MD)) + Info.Kind = SymbolKind::CXXConstructor; + else if (isa(MD)) + Info.Kind = SymbolKind::CXXDestructor; + else if (isa(MD)) + Info.Kind = SymbolKind::CXXConversionFunction; + else { + if (MD->isStatic()) + Info.Kind = SymbolKind::CXXStaticMethod; + else + Info.Kind = SymbolKind::CXXInstanceMethod; + } + } + break; + case Decl::TypeAliasTemplate: + Info.Kind = SymbolKind::CXXTypeAlias; + Info.TemplateKind = SymbolCXXTemplateKind::Template; + break; + case Decl::TypeAlias: + Info.Kind = SymbolKind::CXXTypeAlias; + Info.Lang = SymbolLanguage::CXX; + break; + default: + break; + } + } + + if (Info.Kind == SymbolKind::Unknown) + return Info; + + if (const FunctionDecl *FD = dyn_cast(D)) { + if (FD->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization) + Info.TemplateKind = SymbolCXXTemplateKind::TemplateSpecialization; + } + + if (Info.TemplateKind != SymbolCXXTemplateKind::NonTemplate) + Info.Lang = SymbolLanguage::CXX; + + return Info; +} diff --git a/tools/libclang/IndexTypeSourceInfo.cpp b/lib/Index/IndexTypeSourceInfo.cpp similarity index 52% rename from tools/libclang/IndexTypeSourceInfo.cpp rename to lib/Index/IndexTypeSourceInfo.cpp index 9666052ed1..619a9a48be 100644 --- a/tools/libclang/IndexTypeSourceInfo.cpp +++ b/lib/Index/IndexTypeSourceInfo.cpp @@ -1,4 +1,4 @@ -//===- CIndexHigh.cpp - Higher level API functions ------------------------===// +//===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,7 +11,7 @@ #include "clang/AST/RecursiveASTVisitor.h" using namespace clang; -using namespace cxindex; +using namespace index; namespace { @@ -19,20 +19,58 @@ class TypeIndexer : public RecursiveASTVisitor { IndexingContext &IndexCtx; const NamedDecl *Parent; const DeclContext *ParentDC; + bool IsBase; + SmallVector Relations; + + typedef RecursiveASTVisitor base; public: TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent, - const DeclContext *DC) - : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { } + const DeclContext *DC, bool isBase) + : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) { + if (IsBase) { + assert(Parent); + Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent); + } + } bool shouldWalkTypesOfTypeLocs() const { return false; } bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { - IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(), - Parent, ParentDC); + return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(), + Parent, ParentDC, SymbolRoleSet(), + Relations); + } + +#define TRY_TO(CALL_EXPR) \ + do { \ + if (!CALL_EXPR) \ + return false; \ + } while (0) + + bool traverseParamVarHelper(ParmVarDecl *D) { + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + if (D->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); return true; } + bool TraverseParmVarDecl(ParmVarDecl *D) { + // Avoid visiting default arguments from the definition that were already + // visited in the declaration. + // FIXME: A free function definition can have default arguments. + // Avoiding double visitaiton of default arguments should be handled by the + // visitor probably with a bit in the AST to indicate if the attached + // default argument was 'inherited' or written in source. + if (auto FD = dyn_cast(D->getDeclContext())) { + if (FD->isThisDeclarationADefinition()) { + return traverseParamVarHelper(D); + } + } + + return base::TraverseParmVarDecl(D); + } + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); return true; @@ -48,24 +86,20 @@ public: return true; } - if (D->getLocation() == TL.getNameLoc()) - IndexCtx.handleTagDecl(D); - else - IndexCtx.handleReference(D, TL.getNameLoc(), - Parent, ParentDC); - return true; + return IndexCtx.handleReference(D, TL.getNameLoc(), + Parent, ParentDC, SymbolRoleSet(), + Relations); } bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { - IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(), - Parent, ParentDC); - return true; + return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(), + Parent, ParentDC, SymbolRoleSet()); } bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) { IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i), - Parent, ParentDC); + Parent, ParentDC, SymbolRoleSet()); } return true; } @@ -75,11 +109,11 @@ public: if (IndexCtx.shouldIndexImplicitTemplateInsts()) { if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), - Parent, ParentDC); + Parent, ParentDC, SymbolRoleSet(), Relations); } else { if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl()) IndexCtx.handleReference(D, TL.getTemplateNameLoc(), - Parent, ParentDC); + Parent, ParentDC, SymbolRoleSet(), Relations); } } return true; @@ -95,22 +129,24 @@ public: void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, - const DeclContext *DC) { + const DeclContext *DC, + bool isBase) { if (!TInfo || TInfo->getTypeLoc().isNull()) return; - indexTypeLoc(TInfo->getTypeLoc(), Parent, DC); + indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase); } void IndexingContext::indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, - const DeclContext *DC) { + const DeclContext *DC, + bool isBase) { if (TL.isNull()) return; if (!DC) DC = Parent->getLexicalDeclContext(); - TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL); + TypeIndexer(*this, Parent, DC, isBase).TraverseTypeLoc(TL); } void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, @@ -134,11 +170,11 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, case NestedNameSpecifier::Namespace: handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(), - Loc, Parent, DC); + Loc, Parent, DC, SymbolRoleSet()); break; case NestedNameSpecifier::NamespaceAlias: handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), - Loc, Parent, DC); + Loc, Parent, DC, SymbolRoleSet()); break; case NestedNameSpecifier::TypeSpec: @@ -149,8 +185,18 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, } void IndexingContext::indexTagDecl(const TagDecl *D) { - if (handleTagDecl(D)) { - if (D->isThisDeclarationADefinition()) + if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) + return; + + if (handleDecl(D)) { + if (D->isThisDeclarationADefinition()) { + indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + if (auto CXXRD = dyn_cast(D)) { + for (const auto &I : CXXRD->bases()) { + indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true); + } + } indexDeclContext(D); + } } } diff --git a/lib/Index/IndexingAction.cpp b/lib/Index/IndexingAction.cpp new file mode 100644 index 0000000000..3f7ef43e7d --- /dev/null +++ b/lib/Index/IndexingAction.cpp @@ -0,0 +1,140 @@ +//===- IndexingAction.cpp - Frontend index action -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/IndexingAction.h" +#include "clang/Index/IndexDataConsumer.h" +#include "IndexingContext.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace clang::index; + +void IndexDataConsumer::_anchor() {} + +bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, + ArrayRef Relations, + FileID FID, unsigned Offset, + ASTNodeInfo ASTNode) { + return true; +} + +bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name, + const MacroInfo *MI, SymbolRoleSet Roles, + FileID FID, unsigned Offset) { + return true; +} + +bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD, + SymbolRoleSet Roles, + FileID FID, unsigned Offset) { + return true; +} + +namespace { + +class IndexASTConsumer : public ASTConsumer { + IndexingContext &IndexCtx; + +public: + IndexASTConsumer(IndexingContext &IndexCtx) + : IndexCtx(IndexCtx) {} + +protected: + void Initialize(ASTContext &Context) override { + IndexCtx.setASTContext(Context); + } + + bool HandleTopLevelDecl(DeclGroupRef DG) override { + return IndexCtx.indexDeclGroupRef(DG); + } + + void HandleInterestingDecl(DeclGroupRef DG) override { + // Ignore deserialized decls. + } + + void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override { + IndexCtx.indexDeclGroupRef(DG); + } + + void HandleTranslationUnit(ASTContext &Ctx) override { + } +}; + +class IndexAction : public WrapperFrontendAction { + IndexingOptions IndexOpts; + std::shared_ptr DataConsumer; + std::unique_ptr IndexCtx; + +public: + IndexAction(std::unique_ptr WrappedAction, + std::shared_ptr DataConsumer, + IndexingOptions Opts) + : WrapperFrontendAction(std::move(WrappedAction)), + IndexOpts(Opts), + DataConsumer(std::move(DataConsumer)) {} + +protected: + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + void EndSourceFileAction() override; +}; + +} // anonymous namespace + +void IndexAction::EndSourceFileAction() { + // Invoke wrapped action's method. + WrapperFrontendAction::EndSourceFileAction(); + + bool IndexActionFailed = !IndexCtx; + if (!IndexActionFailed) + DataConsumer->finish(); +} + +std::unique_ptr +IndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); + if (!OtherConsumer) + return nullptr; + + IndexCtx.reset(new IndexingContext(IndexOpts, *DataConsumer)); + + std::vector> Consumers; + Consumers.push_back(std::move(OtherConsumer)); + Consumers.push_back(llvm::make_unique(*IndexCtx)); + return llvm::make_unique(std::move(Consumers)); +} + +std::unique_ptr +index::createIndexingAction(std::unique_ptr WrappedAction, + std::shared_ptr DataConsumer, + IndexingOptions Opts) { + return llvm::make_unique(std::move(WrappedAction), + std::move(DataConsumer), + Opts); +} + + +static bool topLevelDeclVisitor(void *context, const Decl *D) { + IndexingContext &IndexCtx = *static_cast(context); + return IndexCtx.indexTopLevelDecl(D); +} + +static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) { + Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor); +} + +void index::indexASTUnit(ASTUnit &Unit, + std::shared_ptr DataConsumer, + IndexingOptions Opts) { + IndexingContext IndexCtx(Opts, *DataConsumer); + IndexCtx.setASTContext(Unit.getASTContext()); + indexTranslationUnit(Unit, IndexCtx); +} diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp new file mode 100644 index 0000000000..91fbbfb268 --- /dev/null +++ b/lib/Index/IndexingContext.cpp @@ -0,0 +1,325 @@ +//===- IndexingContext.cpp - Indexing context data ------------------------===// +// +// 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 "clang/Index/IndexDataConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/SourceManager.h" + +using namespace clang; +using namespace index; + +bool IndexingContext::shouldIndexFunctionLocalSymbols() const { + return IndexOpts.IndexFunctionLocals; +} + +bool IndexingContext::handleDecl(const Decl *D, + SymbolRoleSet Roles, + ArrayRef Relations) { + return handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false, + cast(D->getDeclContext()), Roles, Relations, + nullptr, nullptr, D->getDeclContext()); +} + +bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, + SymbolRoleSet Roles, + ArrayRef Relations, + const DeclContext *DC) { + if (!DC) + DC = D->getDeclContext(); + return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast(DC), + Roles, Relations, + nullptr, nullptr, DC); +} + +bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, + const NamedDecl *Parent, + const DeclContext *DC, + SymbolRoleSet Roles, + ArrayRef Relations, + const Expr *RefE, + const Decl *RefD) { + if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) + return true; + + if (isa(D) || isa(D)) + return true; + + return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations, + RefE, RefD, DC); +} + +bool IndexingContext::importedModule(const ImportDecl *ImportD) { + SourceLocation Loc = ImportD->getLocation(); + SourceManager &SM = Ctx->getSourceManager(); + Loc = SM.getFileLoc(Loc); + if (Loc.isInvalid()) + return true; + + FileID FID; + unsigned Offset; + std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); + if (FID.isInvalid()) + return true; + + bool Invalid = false; + const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); + if (Invalid || !SEntry.isFile()) + return true; + + if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { + switch (IndexOpts.SystemSymbolFilter) { + case IndexingOptions::SystemSymbolFilterKind::None: + case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: + return true; + case IndexingOptions::SystemSymbolFilterKind::All: + break; + } + } + + SymbolRoleSet Roles{}; + if (ImportD->isImplicit()) + Roles |= (unsigned)SymbolRole::Implicit; + + return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset); +} + +bool IndexingContext::isFunctionLocalDecl(const Decl *D) { + assert(D); + + if (isa(D)) + return true; + + if (!D->getParentFunctionOrMethod()) + return false; + + if (const NamedDecl *ND = dyn_cast(D)) { + switch (ND->getFormalLinkage()) { + case NoLinkage: + case VisibleNoLinkage: + case InternalLinkage: + return true; + case UniqueExternalLinkage: + llvm_unreachable("Not a sema linkage"); + case ExternalLinkage: + return false; + } + } + + return true; +} + +bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { + TemplateSpecializationKind TKind = TSK_Undeclared; + if (const ClassTemplateSpecializationDecl * + SD = dyn_cast(D)) { + TKind = SD->getSpecializationKind(); + } + if (const FunctionDecl *FD = dyn_cast(D)) { + TKind = FD->getTemplateSpecializationKind(); + } + switch (TKind) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + return false; + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + return true; + } +} + +bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { + if (isa(D)) + return false; + if (isa(D)) + return false; + if (isa(D)) + return false; + if (isa(D)) + return false; + if (isa(D)) + return false; + return true; +} + +static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { + if (const ClassTemplateSpecializationDecl * + SD = dyn_cast(D)) { + return SD->getTemplateInstantiationPattern(); + } + if (const FunctionDecl *FD = dyn_cast(D)) { + return FD->getTemplateInstantiationPattern(); + } + return nullptr; +} + +static bool isDeclADefinition(const Decl *D, ASTContext &Ctx) { + if (auto VD = dyn_cast(D)) + return VD->isThisDeclarationADefinition(Ctx); + + if (auto FD = dyn_cast(D)) + return FD->isThisDeclarationADefinition(); + + if (auto TD = dyn_cast(D)) + return TD->isThisDeclarationADefinition(); + + if (auto MD = dyn_cast(D)) + return MD->isThisDeclarationADefinition(); + + if (isa(D) || + isa(D) || + isa(D) || + isa(D) || + isa(D) || + isa(D)) + return true; + + return false; +} + +static const Decl *adjustParent(const Decl *Parent) { + if (!Parent) + return nullptr; + for (;; Parent = cast(Parent->getDeclContext())) { + if (isa(Parent)) + return nullptr; + if (isa(Parent) || isa(Parent)) + continue; + if (auto NS = dyn_cast(Parent)) { + if (NS->isAnonymousNamespace()) + continue; + } else if (auto EnumD = dyn_cast(Parent)) { + // Move enumerators under anonymous enum to the enclosing parent. + if (EnumD->getDeclName().isEmpty()) + continue; + } else if (auto RD = dyn_cast(Parent)) { + if (RD->isAnonymousStructOrUnion()) + continue; + } else if (auto FD = dyn_cast(Parent)) { + if (FD->getDeclName().isEmpty()) + continue; + } + return Parent; + } +} + +static const Decl *getCanonicalDecl(const Decl *D) { + D = D->getCanonicalDecl(); + if (auto TD = dyn_cast(D)) { + D = TD->getTemplatedDecl(); + assert(D->isCanonicalDecl()); + } + + return D; +} + +bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, + bool IsRef, const Decl *Parent, + SymbolRoleSet Roles, + ArrayRef Relations, + const Expr *OrigE, + const Decl *OrigD, + const DeclContext *ContainerDC) { + if (D->isImplicit() && !isa(D)) + return true; + if (!isa(D) || + (cast(D)->getDeclName().isEmpty() && + !isa(D) && !isa(D))) + return true; + + SourceManager &SM = Ctx->getSourceManager(); + Loc = SM.getFileLoc(Loc); + if (Loc.isInvalid()) + return true; + + FileID FID; + unsigned Offset; + std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); + if (FID.isInvalid()) + return true; + + bool Invalid = false; + const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); + if (Invalid || !SEntry.isFile()) + return true; + + if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { + switch (IndexOpts.SystemSymbolFilter) { + case IndexingOptions::SystemSymbolFilterKind::None: + return true; + case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: + if (IsRef) + return true; + break; + case IndexingOptions::SystemSymbolFilterKind::All: + break; + } + } + + if (isTemplateImplicitInstantiation(D)) { + if (!IsRef) + return true; + D = adjustTemplateImplicitInstantiation(D); + if (!D) + return true; + assert(!isTemplateImplicitInstantiation(D)); + } + + if (!OrigD) + OrigD = D; + + if (IsRef) + Roles |= (unsigned)SymbolRole::Reference; + else if (isDeclADefinition(D, *Ctx)) + Roles |= (unsigned)SymbolRole::Definition; + else + Roles |= (unsigned)SymbolRole::Declaration; + + D = getCanonicalDecl(D); + if (D->isImplicit() && !isa(D)) { + // operator new declarations will link to the implicit one as canonical. + return true; + } + Parent = adjustParent(Parent); + if (Parent) + Parent = getCanonicalDecl(Parent); + assert(!Parent || !Parent->isImplicit() || + isa(Parent) || isa(Parent)); + + SmallVector FinalRelations; + FinalRelations.reserve(Relations.size()+1); + + auto addRelation = [&](SymbolRelation Rel) { + auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(), + [&](SymbolRelation Elem)->bool { + return Elem.RelatedSymbol == Rel.RelatedSymbol; + }); + if (It != FinalRelations.end()) { + It->Roles |= Rel.Roles; + } else { + FinalRelations.push_back(Rel); + } + Roles |= Rel.Roles; + }; + + if (!IsRef && Parent && !cast(Parent)->isFunctionOrMethod()) { + addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent}); + } + for (auto &Rel : Relations) { + addRelation(SymbolRelation(Rel.Roles, + Rel.RelatedSymbol->getCanonicalDecl())); + } + + IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC }; + return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset, + Node); +} diff --git a/lib/Index/IndexingContext.h b/lib/Index/IndexingContext.h new file mode 100644 index 0000000000..774650547f --- /dev/null +++ b/lib/Index/IndexingContext.h @@ -0,0 +1,121 @@ +//===- IndexingContext.h - Indexing context data ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H +#define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H + +#include "clang/Basic/LLVM.h" +#include "clang/Index/IndexSymbol.h" +#include "clang/Index/IndexingAction.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { + class ASTContext; + class Decl; + class DeclGroupRef; + class ImportDecl; + class TagDecl; + class TypeSourceInfo; + class NamedDecl; + class ObjCMethodDecl; + class DeclContext; + class NestedNameSpecifierLoc; + class Stmt; + class Expr; + class TypeLoc; + class SourceLocation; + +namespace index { + class IndexDataConsumer; + +class IndexingContext { + IndexingOptions IndexOpts; + IndexDataConsumer &DataConsumer; + ASTContext *Ctx = nullptr; + +public: + IndexingContext(IndexingOptions IndexOpts, IndexDataConsumer &DataConsumer) + : IndexOpts(IndexOpts), DataConsumer(DataConsumer) {} + + const IndexingOptions &getIndexOpts() const { return IndexOpts; } + IndexDataConsumer &getDataConsumer() { return DataConsumer; } + + void setASTContext(ASTContext &ctx) { Ctx = &ctx; } + + bool shouldSuppressRefs() const { + return false; + } + + bool shouldIndexFunctionLocalSymbols() const; + + bool shouldIndexImplicitTemplateInsts() const { + return false; + } + + static bool isFunctionLocalDecl(const Decl *D); + static bool isTemplateImplicitInstantiation(const Decl *D); + + bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(), + ArrayRef Relations = {}); + + bool handleDecl(const Decl *D, SourceLocation Loc, + SymbolRoleSet Roles = SymbolRoleSet(), + ArrayRef Relations = {}, + const DeclContext *DC = nullptr); + + bool handleReference(const NamedDecl *D, SourceLocation Loc, + const NamedDecl *Parent, + const DeclContext *DC, + SymbolRoleSet Roles, + ArrayRef Relations = {}, + const Expr *RefE = nullptr, + const Decl *RefD = nullptr); + + bool importedModule(const ImportDecl *ImportD); + + bool indexDecl(const Decl *D); + + void indexTagDecl(const TagDecl *D); + + void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, + const DeclContext *DC = nullptr, + bool isBase = false); + + void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent, + const DeclContext *DC = nullptr, + bool isBase = false); + + void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const NamedDecl *Parent, + const DeclContext *DC = nullptr); + + bool indexDeclContext(const DeclContext *DC); + + void indexBody(const Stmt *S, const NamedDecl *Parent, + const DeclContext *DC = nullptr); + + bool indexTopLevelDecl(const Decl *D); + bool indexDeclGroupRef(DeclGroupRef DG); + +private: + bool shouldIgnoreIfImplicit(const Decl *D); + + bool handleDeclOccurrence(const Decl *D, SourceLocation Loc, + bool IsRef, const Decl *Parent, + SymbolRoleSet Roles, + ArrayRef Relations, + const Expr *RefE, + const Decl *RefD, + const DeclContext *ContainerDC); +}; + +} // end namespace index +} // end namespace clang + +#endif diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt index d7eaca1094..d893b5e5c1 100644 --- a/tools/libclang/CMakeLists.txt +++ b/tools/libclang/CMakeLists.txt @@ -11,17 +11,14 @@ set(SOURCES CIndexer.cpp CXComment.cpp CXCursor.cpp + CXIndexDataConsumer.cpp CXCompilationDatabase.cpp CXLoadedDiagnostic.cpp CXSourceLocation.cpp CXStoredDiagnostic.cpp CXString.cpp CXType.cpp - IndexBody.cpp - IndexDecl.cpp - IndexTypeSourceInfo.cpp Indexing.cpp - IndexingContext.cpp ADDITIONAL_HEADERS CIndexDiagnostic.h diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/CXIndexDataConsumer.cpp similarity index 70% rename from tools/libclang/IndexingContext.cpp rename to tools/libclang/CXIndexDataConsumer.cpp index 7f65412f98..f6f8e30679 100644 --- a/tools/libclang/IndexingContext.cpp +++ b/tools/libclang/CXIndexDataConsumer.cpp @@ -1,4 +1,4 @@ -//===- IndexingContext.cpp - Higher level API functions -------------------===// +//===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===// // // The LLVM Compiler Infrastructure // @@ -7,21 +7,219 @@ // //===----------------------------------------------------------------------===// -#include "IndexingContext.h" +#include "CXIndexDataConsumer.h" #include "CIndexDiagnostic.h" #include "CXTranslationUnit.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclVisitor.h" #include "clang/Frontend/ASTUnit.h" using namespace clang; +using namespace clang::index; using namespace cxindex; using namespace cxcursor; -IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo( +namespace { +class IndexingDeclVisitor : public ConstDeclVisitor { + CXIndexDataConsumer &DataConsumer; + SourceLocation DeclLoc; + const DeclContext *LexicalDC; + +public: + IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc, + const DeclContext *lexicalDC) + : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { } + + bool VisitFunctionDecl(const FunctionDecl *D) { + DataConsumer.handleFunction(D); + return true; + } + + bool VisitVarDecl(const VarDecl *D) { + DataConsumer.handleVar(D); + return true; + } + + bool VisitFieldDecl(const FieldDecl *D) { + DataConsumer.handleField(D); + return true; + } + + bool VisitMSPropertyDecl(const MSPropertyDecl *D) { + return true; + } + + bool VisitEnumConstantDecl(const EnumConstantDecl *D) { + DataConsumer.handleEnumerator(D); + return true; + } + + bool VisitTypedefNameDecl(const TypedefNameDecl *D) { + DataConsumer.handleTypedefName(D); + return true; + } + + bool VisitTagDecl(const TagDecl *D) { + DataConsumer.handleTagDecl(D); + return true; + } + + bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { + DataConsumer.handleObjCInterface(D); + return true; + } + + bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { + DataConsumer.handleObjCProtocol(D); + return true; + } + + bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { + DataConsumer.handleObjCImplementation(D); + return true; + } + + bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + DataConsumer.handleObjCCategory(D); + return true; + } + + bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { + DataConsumer.handleObjCCategoryImpl(D); + return true; + } + + bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { + if (D->getDeclContext() != LexicalDC) + DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC); + else + DataConsumer.handleObjCMethod(D); + return true; + } + + bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { + DataConsumer.handleObjCProperty(D); + return true; + } + + bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { + DataConsumer.handleSynthesizedObjCProperty(D); + return true; + } + + bool VisitNamespaceDecl(const NamespaceDecl *D) { + DataConsumer.handleNamespace(D); + return true; + } + + bool VisitUsingDecl(const UsingDecl *D) { + return true; + } + + bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { + return true; + } + + bool VisitClassTemplateDecl(const ClassTemplateDecl *D) { + DataConsumer.handleClassTemplate(D); + return true; + } + + bool VisitClassTemplateSpecializationDecl(const + ClassTemplateSpecializationDecl *D) { + DataConsumer.handleTagDecl(D); + return true; + } + + bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + DataConsumer.handleFunctionTemplate(D); + return true; + } + + bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { + DataConsumer.handleTypeAliasTemplate(D); + return true; + } + + bool VisitImportDecl(const ImportDecl *D) { + DataConsumer.importedModule(D); + return true; + } +}; +} + +bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D, + SymbolRoleSet Roles, + ArrayRef Relations, + FileID FID, unsigned Offset, + ASTNodeInfo ASTNode) { + SourceLocation Loc = getASTContext().getSourceManager() + .getLocForStartOfFile(FID).getLocWithOffset(Offset); + + if (Roles & (unsigned)SymbolRole::Reference) { + const NamedDecl *ND = dyn_cast(D); + if (!ND) + return true; + + if (auto *ObjCID = dyn_cast_or_null(ASTNode.OrigD)) { + if (!ObjCID->isThisDeclarationADefinition() && + ObjCID->getLocation() == Loc) { + // The libclang API treats this as ObjCClassRef declaration. + IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID); + return true; + } + } + + CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct; + if (Roles & (unsigned)SymbolRole::Implicit) { + Kind = CXIdxEntityRef_Implicit; + } + + CXCursor Cursor; + if (ASTNode.OrigE) { + Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE, + cast(ASTNode.ContainerDC), + getCXTU()); + } else { + const NamedDecl *CursorD = dyn_cast_or_null(ASTNode.OrigD); + if (!CursorD) + CursorD = ND; + Cursor = getRefCursor(CursorD, Loc); + } + handleReference(ND, Loc, Cursor, + dyn_cast_or_null(ASTNode.Parent), + ASTNode.ContainerDC, ASTNode.OrigE, Kind); + + } else { + const DeclContext *DC = nullptr; + for (const auto &SymRel : Relations) { + if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf) + DC = dyn_cast(SymRel.RelatedSymbol); + } + IndexingDeclVisitor(*this, Loc, DC).Visit(ASTNode.OrigD); + } + + return !shouldAbort(); +} + +bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD, + SymbolRoleSet Roles, + FileID FID, + unsigned Offset) { + IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD); + return !shouldAbort(); +} + +void CXIndexDataConsumer::finish() { + indexDiagnostics(); +} + + +CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo( const ObjCProtocolList &ProtList, - IndexingContext &IdxCtx, + CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA) { ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); for (ObjCInterfaceDecl::protocol_iterator @@ -61,7 +259,7 @@ IBOutletCollectionInfo::IBOutletCollectionInfo( IBCollInfo.objcClass = nullptr; } -AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx) +AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx) : SA(IdxCtx), ref_cnt(0) { if (!D->hasAttrs()) @@ -114,14 +312,14 @@ AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx) } IntrusiveRefCntPtr -AttrListInfo::create(const Decl *D, IndexingContext &IdxCtx) { +AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) { ScratchAlloc SA(IdxCtx); AttrListInfo *attrs = SA.allocate(); return new (attrs) AttrListInfo(D, IdxCtx); } -IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, - IndexingContext &IdxCtx, +CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, + CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA) { for (const auto &Base : D->bases()) { BaseEntities.push_back(EntityInfo()); @@ -155,7 +353,7 @@ IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, CXBases.push_back(&BaseInfos[i]); } -SourceLocation IndexingContext::CXXBasesListInfo::getBaseLoc( +SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc( const CXXBaseSpecifier &Base) const { SourceLocation Loc = Base.getSourceRange().getBegin(); TypeLoc TL; @@ -193,16 +391,16 @@ const char *ScratchAlloc::copyCStr(StringRef Str) { return buf; } -void IndexingContext::setASTContext(ASTContext &ctx) { +void CXIndexDataConsumer::setASTContext(ASTContext &ctx) { Ctx = &ctx; cxtu::getASTUnit(CXTU)->setASTContext(&ctx); } -void IndexingContext::setPreprocessor(Preprocessor &PP) { +void CXIndexDataConsumer::setPreprocessor(Preprocessor &PP) { cxtu::getASTUnit(CXTU)->setPreprocessor(&PP); } -bool IndexingContext::isFunctionLocalDecl(const Decl *D) { +bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) { assert(D); if (!D->getParentFunctionOrMethod()) @@ -224,13 +422,13 @@ bool IndexingContext::isFunctionLocalDecl(const Decl *D) { return true; } -bool IndexingContext::shouldAbort() { +bool CXIndexDataConsumer::shouldAbort() { if (!CB.abortQuery) return false; return CB.abortQuery(ClientData, nullptr); } -void IndexingContext::enteredMainFile(const FileEntry *File) { +void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) { if (File && CB.enteredMainFile) { CXIdxClientFile idxFile = CB.enteredMainFile(ClientData, @@ -240,7 +438,7 @@ void IndexingContext::enteredMainFile(const FileEntry *File) { } } -void IndexingContext::ppIncludedFile(SourceLocation hashLoc, +void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc, StringRef filename, const FileEntry *File, bool isImport, bool isAngled, @@ -258,7 +456,7 @@ void IndexingContext::ppIncludedFile(SourceLocation hashLoc, FileMap[File] = idxFile; } -void IndexingContext::importedModule(const ImportDecl *ImportD) { +void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) { if (!CB.importedASTFile) return; @@ -277,7 +475,7 @@ void IndexingContext::importedModule(const ImportDecl *ImportD) { (void)astFile; } -void IndexingContext::importedPCH(const FileEntry *File) { +void CXIndexDataConsumer::importedPCH(const FileEntry *File) { if (!CB.importedASTFile) return; @@ -292,21 +490,29 @@ void IndexingContext::importedPCH(const FileEntry *File) { (void)astFile; } -void IndexingContext::startedTranslationUnit() { +void CXIndexDataConsumer::startedTranslationUnit() { CXIdxClientContainer idxCont = nullptr; if (CB.startedTranslationUnit) idxCont = CB.startedTranslationUnit(ClientData, nullptr); addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont); } -void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) { +void CXIndexDataConsumer::indexDiagnostics() { + if (!hasDiagnosticCallback()) + return; + + CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU()); + handleDiagnosticSet(DiagSet); +} + +void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) { if (!CB.diagnostic) return; CB.diagnostic(ClientData, CXDiagSet, nullptr); } -bool IndexingContext::handleDecl(const NamedDecl *D, +bool CXIndexDataConsumer::handleDecl(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, DeclInfo &DInfo, const DeclContext *LexicalDC, @@ -365,14 +571,14 @@ bool IndexingContext::handleDecl(const NamedDecl *D, return true; } -bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D, +bool CXIndexDataConsumer::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) { +bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) { bool isDef = D->isThisDeclarationADefinition(); bool isContainer = isDef; bool isSkipped = false; @@ -388,31 +594,31 @@ bool IndexingContext::handleFunction(const FunctionDecl *D) { return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleVar(const VarDecl *D) { +bool CXIndexDataConsumer::handleVar(const VarDecl *D) { DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(), /*isContainer=*/false); return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleField(const FieldDecl *D) { +bool CXIndexDataConsumer::handleField(const FieldDecl *D) { DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, /*isContainer=*/false); return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleMSProperty(const MSPropertyDecl *D) { +bool CXIndexDataConsumer::handleMSProperty(const MSPropertyDecl *D) { DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, /*isContainer=*/false); return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) { +bool CXIndexDataConsumer::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) { +bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) { if (const CXXRecordDecl *CXXRD = dyn_cast(D)) return handleCXXRecordDecl(CXXRD, D); @@ -421,13 +627,13 @@ bool IndexingContext::handleTagDecl(const TagDecl *D) { return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleTypedefName(const TypedefNameDecl *D) { +bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) { DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true, /*isContainer=*/false); return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { +bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) { // For @class forward declarations, suppress them the same way as references. if (!D->isThisDeclarationADefinition()) { if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) @@ -475,7 +681,7 @@ bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo); } -bool IndexingContext::handleObjCImplementation( +bool CXIndexDataConsumer::handleObjCImplementation( const ObjCImplementationDecl *D) { ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false, /*isRedeclaration=*/true, @@ -483,7 +689,7 @@ bool IndexingContext::handleObjCImplementation( return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo); } -bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { +bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) { if (!D->isThisDeclarationADefinition()) { if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) return false; // already occurred. @@ -512,7 +718,7 @@ bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo); } -bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { +bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) { ScratchAlloc SA(*this); ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); @@ -544,7 +750,7 @@ bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); } -bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { +bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { ScratchAlloc SA(*this); const ObjCCategoryDecl *CatD = D->getCategoryDecl(); @@ -573,7 +779,7 @@ bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); } -bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) { +bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D) { bool isDef = D->isThisDeclarationADefinition(); bool isContainer = isDef; bool isSkipped = false; @@ -589,7 +795,7 @@ bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) { return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleSynthesizedObjCProperty( +bool CXIndexDataConsumer::handleSynthesizedObjCProperty( const ObjCPropertyImplDecl *D) { ObjCPropertyDecl *PD = D->getPropertyDecl(); auto *DC = D->getDeclContext(); @@ -597,7 +803,7 @@ bool IndexingContext::handleSynthesizedObjCProperty( dyn_cast(DC), DC); } -bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, +bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc, const DeclContext *LexicalDC) { DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true, @@ -605,7 +811,7 @@ bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, LexicalDC); } -bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) { +bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) { ScratchAlloc SA(*this); ObjCPropertyDeclInfo DInfo; @@ -630,31 +836,31 @@ bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) { return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -bool IndexingContext::handleNamespace(const NamespaceDecl *D) { +bool CXIndexDataConsumer::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) { +bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) { return handleCXXRecordDecl(D->getTemplatedDecl(), D); } -bool IndexingContext::handleFunctionTemplate(const FunctionTemplateDecl *D) { +bool CXIndexDataConsumer::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) { +bool CXIndexDataConsumer::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, +bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, const Expr *E, @@ -667,7 +873,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, return handleReference(D, Loc, Cursor, Parent, DC, E, Kind); } -bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, +bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, const NamedDecl *Parent, const DeclContext *DC, @@ -713,7 +919,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, return true; } -bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const { +bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const { if (Loc.isInvalid()) return true; SourceManager &SM = Ctx->getSourceManager(); @@ -722,7 +928,7 @@ bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const { return SM.getFileEntryForID(FID) == nullptr; } -void IndexingContext::addContainerInMap(const DeclContext *DC, +void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC, CXIdxClientContainer container) { if (!DC) return; @@ -741,7 +947,7 @@ void IndexingContext::addContainerInMap(const DeclContext *DC, ContainerMap.erase(I); } -CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const { +CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const { if (!D) return nullptr; EntityMapTy::const_iterator I = EntityMap.find(D); @@ -750,13 +956,13 @@ CXIdxClientEntity IndexingContext::getClientEntity(const Decl *D) const { return I->second; } -void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) { +void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) { if (!D) return; EntityMap[D] = client; } -bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD, +bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD) { if (RD->isThisDeclarationADefinition()) { ScratchAlloc SA(*this); @@ -789,7 +995,7 @@ bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD, return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo); } -bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D, +bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc) { if (!D || Loc.isInvalid()) return true; @@ -811,7 +1017,7 @@ bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D, return !res.second; // already in map } -const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const { +const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const { assert(D); D = cast(D->getCanonicalDecl()); @@ -834,7 +1040,7 @@ const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const { } const DeclContext * -IndexingContext::getEntityContainer(const Decl *D) const { +CXIndexDataConsumer::getEntityContainer(const Decl *D) const { const DeclContext *DC = dyn_cast(D); if (DC) return DC; @@ -850,7 +1056,7 @@ IndexingContext::getEntityContainer(const Decl *D) const { } CXIdxClientContainer -IndexingContext::getClientContainerForDC(const DeclContext *DC) const { +CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const { if (!DC) return nullptr; @@ -861,7 +1067,7 @@ IndexingContext::getClientContainerForDC(const DeclContext *DC) const { return I->second; } -CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) { +CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) { if (!File) return nullptr; @@ -872,17 +1078,17 @@ CXIdxClientFile IndexingContext::getIndexFile(const FileEntry *File) { return nullptr; } -CXIdxLoc IndexingContext::getIndexLoc(SourceLocation Loc) const { +CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const { CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 }; if (Loc.isInvalid()) return idxLoc; - idxLoc.ptr_data[0] = const_cast(this); + idxLoc.ptr_data[0] = const_cast(this); idxLoc.int_data = Loc.getRawEncoding(); return idxLoc; } -void IndexingContext::translateLoc(SourceLocation Loc, +void CXIndexDataConsumer::translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file, unsigned *line, unsigned *column, unsigned *offset) { @@ -912,7 +1118,12 @@ void IndexingContext::translateLoc(SourceLocation Loc, *offset = FileOffset; } -void IndexingContext::getEntityInfo(const NamedDecl *D, +static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K); +static CXIdxEntityCXXTemplateKind +getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K); +static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L); + +void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D, EntityInfo &EntityInfo, ScratchAlloc &SA) { if (!D) @@ -922,9 +1133,12 @@ void IndexingContext::getEntityInfo(const NamedDecl *D, EntityInfo.cursor = getCursor(D); EntityInfo.Dcl = D; EntityInfo.IndexCtx = this; - EntityInfo.kind = CXIdxEntity_Unexposed; - EntityInfo.templateKind = CXIdxEntity_NonTemplate; - EntityInfo.lang = CXIdxEntityLang_C; + + SymbolInfo SymInfo = getSymbolInfo(D); + EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind); + EntityInfo.templateKind = + getEntityKindFromSymbolCXXTemplateKind(SymInfo.TemplateKind); + EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang); if (D->hasAttrs()) { EntityInfo.AttrList = AttrListInfo::create(D, *this); @@ -932,167 +1146,9 @@ void IndexingContext::getEntityInfo(const NamedDecl *D, EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs(); } - if (const TagDecl *TD = dyn_cast(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_Interface: - EntityInfo.kind = CXIdxEntity_CXXInterface; - EntityInfo.lang = CXIdxEntityLang_CXX; - break; - case TTK_Enum: - EntityInfo.kind = CXIdxEntity_Enum; break; - } - - if (const CXXRecordDecl *CXXRec = dyn_cast(D)) - if (!CXXRec->isCLike()) - EntityInfo.lang = CXIdxEntityLang_CXX; - - if (isa(D)) { - EntityInfo.templateKind = CXIdxEntity_TemplatePartialSpecialization; - } else if (isa(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(D->getDeclContext())) { - EntityInfo.kind = CXIdxEntity_CXXStaticVariable; - EntityInfo.lang = CXIdxEntityLang_CXX; - } - break; - case Decl::Field: - EntityInfo.kind = CXIdxEntity_Field; - if (const CXXRecordDecl * - CXXRec = dyn_cast(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(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(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( - cast(D)->getTemplatedDecl())) { - if (isa(MD)) - EntityInfo.kind = CXIdxEntity_CXXConstructor; - else if (isa(MD)) - EntityInfo.kind = CXIdxEntity_CXXDestructor; - else if (isa(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(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()); @@ -1119,14 +1175,14 @@ void IndexingContext::getEntityInfo(const NamedDecl *D, } } -void IndexingContext::getContainerInfo(const DeclContext *DC, +void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo) { ContInfo.cursor = getCursor(cast(DC)); ContInfo.DC = DC; ContInfo.IndexCtx = this; } -CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) { +CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) { if (const TypeDecl *TD = dyn_cast(D)) return MakeCursorTypeRef(TD, Loc, CXTU); if (const ObjCInterfaceDecl *ID = dyn_cast(D)) @@ -1147,7 +1203,7 @@ CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) { return clang_getNullCursor(); } -bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { +bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) { if (isa(D)) return false; if (isa(D)) @@ -1161,7 +1217,7 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { return true; } -bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { +bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) { if (const ClassTemplateSpecializationDecl * SD = dyn_cast(D)) { return SD->getSpecializationKind() == TSK_ImplicitInstantiation; @@ -1171,3 +1227,60 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { } return false; } + +static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K) { + switch (K) { + case SymbolKind::Unknown: + case SymbolKind::Module: + case SymbolKind::Macro: + return CXIdxEntity_Unexposed; + + case SymbolKind::Enum: return CXIdxEntity_Enum; + case SymbolKind::Struct: return CXIdxEntity_Struct; + case SymbolKind::Union: return CXIdxEntity_Union; + case SymbolKind::Typedef: return CXIdxEntity_Typedef; + case SymbolKind::Function: return CXIdxEntity_Function; + case SymbolKind::Variable: return CXIdxEntity_Variable; + case SymbolKind::Field: return CXIdxEntity_Field; + case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant; + case SymbolKind::ObjCClass: return CXIdxEntity_ObjCClass; + case SymbolKind::ObjCProtocol: return CXIdxEntity_ObjCProtocol; + case SymbolKind::ObjCCategory: return CXIdxEntity_ObjCCategory; + case SymbolKind::ObjCInstanceMethod: return CXIdxEntity_ObjCInstanceMethod; + case SymbolKind::ObjCClassMethod: return CXIdxEntity_ObjCClassMethod; + case SymbolKind::ObjCProperty: return CXIdxEntity_ObjCProperty; + case SymbolKind::ObjCIvar: return CXIdxEntity_ObjCIvar; + case SymbolKind::CXXClass: return CXIdxEntity_CXXClass; + case SymbolKind::CXXNamespace: return CXIdxEntity_CXXNamespace; + case SymbolKind::CXXNamespaceAlias: return CXIdxEntity_CXXNamespaceAlias; + case SymbolKind::CXXStaticVariable: return CXIdxEntity_CXXStaticVariable; + case SymbolKind::CXXStaticMethod: return CXIdxEntity_CXXStaticMethod; + case SymbolKind::CXXInstanceMethod: return CXIdxEntity_CXXInstanceMethod; + case SymbolKind::CXXConstructor: return CXIdxEntity_CXXConstructor; + case SymbolKind::CXXDestructor: return CXIdxEntity_CXXDestructor; + case SymbolKind::CXXConversionFunction: + return CXIdxEntity_CXXConversionFunction; + case SymbolKind::CXXTypeAlias: return CXIdxEntity_CXXTypeAlias; + case SymbolKind::CXXInterface: return CXIdxEntity_CXXInterface; + } +} + +static CXIdxEntityCXXTemplateKind +getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K) { + switch (K) { + case SymbolCXXTemplateKind::NonTemplate: return CXIdxEntity_NonTemplate; + case SymbolCXXTemplateKind::Template: return CXIdxEntity_Template; + case SymbolCXXTemplateKind::TemplatePartialSpecialization: + return CXIdxEntity_TemplatePartialSpecialization; + case SymbolCXXTemplateKind::TemplateSpecialization: + return CXIdxEntity_TemplateSpecialization; + } +} + +static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) { + switch (L) { + case SymbolLanguage::C: return CXIdxEntityLang_C; + case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC; + case SymbolLanguage::CXX: return CXIdxEntityLang_CXX; + } +} diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/CXIndexDataConsumer.h similarity index 91% rename from tools/libclang/IndexingContext.h rename to tools/libclang/CXIndexDataConsumer.h index d1d62c90d4..308fa79488 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/CXIndexDataConsumer.h @@ -1,4 +1,4 @@ -//===- IndexingContext.h - Higher level API functions -----------*- C++ -*-===// +//===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H -#define LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H +#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H +#define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H #include "CXCursor.h" #include "Index_Internal.h" +#include "clang/Index/IndexDataConsumer.h" #include "clang/AST/DeclGroup.h" #include "clang/AST/DeclObjC.h" #include "llvm/ADT/DenseSet.h" @@ -27,14 +28,14 @@ namespace clang { class ClassTemplateSpecializationDecl; namespace cxindex { - class IndexingContext; + class CXIndexDataConsumer; class AttrListInfo; class ScratchAlloc { - IndexingContext &IdxCtx; + CXIndexDataConsumer &IdxCtx; public: - explicit ScratchAlloc(IndexingContext &indexCtx); + explicit ScratchAlloc(CXIndexDataConsumer &indexCtx); ScratchAlloc(const ScratchAlloc &SA); ~ScratchAlloc(); @@ -48,7 +49,7 @@ public: struct EntityInfo : public CXIdxEntityInfo { const NamedDecl *Dcl; - IndexingContext *IndexCtx; + CXIndexDataConsumer *IndexCtx; IntrusiveRefCntPtr AttrList; EntityInfo() { @@ -60,7 +61,7 @@ struct EntityInfo : public CXIdxEntityInfo { struct ContainerInfo : public CXIdxContainerInfo { const DeclContext *DC; - IndexingContext *IndexCtx; + CXIndexDataConsumer *IndexCtx; }; struct DeclInfo : public CXIdxDeclInfo { @@ -248,10 +249,10 @@ class AttrListInfo { AttrListInfo(const AttrListInfo &) = delete; void operator=(const AttrListInfo &) = delete; public: - AttrListInfo(const Decl *D, IndexingContext &IdxCtx); + AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx); static IntrusiveRefCntPtr create(const Decl *D, - IndexingContext &IdxCtx); + CXIndexDataConsumer &IdxCtx); const CXIdxAttrInfo *const *getAttrs() const { if (CXAttrs.empty()) @@ -273,7 +274,7 @@ public: } }; -class IndexingContext { +class CXIndexDataConsumer : public index::IndexDataConsumer { ASTContext *Ctx; CXClientData ClientData; IndexerCallbacks &CB; @@ -308,7 +309,7 @@ class IndexingContext { } ObjCProtocolListInfo(const ObjCProtocolList &ProtList, - IndexingContext &IdxCtx, + CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA); }; @@ -323,7 +324,7 @@ class IndexingContext { unsigned getNumBases() const { return (unsigned)CXBases.size(); } CXXBasesListInfo(const CXXRecordDecl *D, - IndexingContext &IdxCtx, ScratchAlloc &SA); + CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA); private: SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const; @@ -332,13 +333,14 @@ class IndexingContext { friend class AttrListInfo; public: - IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks, + CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks, unsigned indexOptions, CXTranslationUnit cxTU) : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks), IndexOptions(indexOptions), CXTU(cxTU), StrScratch(), StrAdapterCount(0) { } ASTContext &getASTContext() const { return *Ctx; } + CXTranslationUnit getCXTU() const { return CXTU; } void setASTContext(ASTContext &ctx); void setPreprocessor(Preprocessor &PP); @@ -391,6 +393,8 @@ public: void indexBody(const Stmt *S, const NamedDecl *Parent, const DeclContext *DC = nullptr); + void indexDiagnostics(); + void handleDiagnosticSet(CXDiagnosticSet CXDiagSet); bool handleFunction(const FunctionDecl *FD); @@ -458,6 +462,17 @@ public: static bool isTemplateImplicitInstantiation(const Decl *D); private: + bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles, + ArrayRef Relations, + FileID FID, unsigned Offset, + ASTNodeInfo ASTNode) override; + + bool handleModuleOccurence(const ImportDecl *ImportD, + index::SymbolRoleSet Roles, + FileID FID, unsigned Offset) override; + + void finish() override; + bool handleDecl(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, DeclInfo &DInfo, @@ -495,7 +510,7 @@ private: static bool shouldIgnoreIfImplicit(const Decl *D); }; -inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) { +inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) { ++IdxCtx.StrAdapterCount; } inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) { diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp deleted file mode 100644 index 58dc11722b..0000000000 --- a/tools/libclang/IndexBody.cpp +++ /dev/null @@ -1,224 +0,0 @@ -//===- 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 "clang/AST/RecursiveASTVisitor.h" - -using namespace clang; -using namespace cxindex; - -namespace { - -class BodyIndexer : public RecursiveASTVisitor { - IndexingContext &IndexCtx; - const NamedDecl *Parent; - const DeclContext *ParentDC; - - typedef RecursiveASTVisitor base; -public: - BodyIndexer(IndexingContext &indexCtx, - const NamedDecl *Parent, const DeclContext *DC) - : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } - - bool shouldWalkTypesOfTypeLocs() const { return false; } - - bool TraverseTypeLoc(TypeLoc TL) { - IndexCtx.indexTypeLoc(TL, Parent, ParentDC); - return true; - } - - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { - IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); - return true; - } - - bool VisitDeclRefExpr(DeclRefExpr *E) { - IndexCtx.handleReference(E->getDecl(), E->getLocation(), - Parent, ParentDC, E); - return true; - } - - bool VisitMemberExpr(MemberExpr *E) { - IndexCtx.handleReference(E->getMemberDecl(), E->getMemberLoc(), - Parent, ParentDC, E); - return true; - } - - bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - IndexCtx.handleReference(E->getDecl(), E->getLocation(), - Parent, ParentDC, E); - return true; - } - - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { - if (ObjCMethodDecl *MD = E->getMethodDecl()) - IndexCtx.handleReference(MD, E->getSelectorStartLoc(), - Parent, ParentDC, E, - E->isImplicit() ? CXIdxEntityRef_Implicit - : CXIdxEntityRef_Direct); - return true; - } - - bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - if (E->isExplicitProperty()) - IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), - Parent, ParentDC, E); - - // No need to do a handleReference for the objc method, because there will - // be a message expr as part of PseudoObjectExpr. - return true; - } - - bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { - IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), Parent, - ParentDC, E, CXIdxEntityRef_Direct); - return true; - } - - bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), - Parent, ParentDC, E, CXIdxEntityRef_Direct); - return true; - } - - bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { - if (ObjCMethodDecl *MD = E->getBoxingMethod()) - IndexCtx.handleReference(MD, E->getLocStart(), - Parent, ParentDC, E, CXIdxEntityRef_Implicit); - return true; - } - - bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { - if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) - IndexCtx.handleReference(MD, E->getLocStart(), - Parent, ParentDC, E, CXIdxEntityRef_Implicit); - return true; - } - - bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { - if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) - IndexCtx.handleReference(MD, E->getLocStart(), - Parent, ParentDC, E, CXIdxEntityRef_Implicit); - return true; - } - - bool VisitCXXConstructExpr(CXXConstructExpr *E) { - IndexCtx.handleReference(E->getConstructor(), E->getLocation(), - Parent, ParentDC, E); - return true; - } - - bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, - DataRecursionQueue *Q = nullptr) { - if (E->getOperatorLoc().isInvalid()) - return true; // implicit. - return base::TraverseCXXOperatorCallExpr(E, Q); - } - - bool VisitDeclStmt(DeclStmt *S) { - if (IndexCtx.shouldIndexFunctionLocalSymbols()) { - IndexCtx.indexDeclGroupRef(S->getDeclGroup()); - return true; - } - - DeclGroupRef DG = S->getDeclGroup(); - for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { - const Decl *D = *I; - if (!D) - continue; - if (!IndexCtx.isFunctionLocalDecl(D)) - IndexCtx.indexTopLevelDecl(D); - } - - return true; - } - - bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) { - if (C->capturesThis() || C->capturesVLAType()) - return true; - - if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) - IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), Parent, - ParentDC); - - // FIXME: Lambda init-captures. - return true; - } - - // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating - // the things that we visit. Make sure to only visit the semantic form. - // Also visit things that are in the syntactic form but not the semantic one, - // for example the indices in DesignatedInitExprs. - bool TraverseInitListExpr(InitListExpr *S) { - - class SyntacticFormIndexer : - public RecursiveASTVisitor { - IndexingContext &IndexCtx; - const NamedDecl *Parent; - const DeclContext *ParentDC; - - public: - SyntacticFormIndexer(IndexingContext &indexCtx, - const NamedDecl *Parent, const DeclContext *DC) - : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } - - bool shouldWalkTypesOfTypeLocs() const { return false; } - - bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { - for (DesignatedInitExpr::reverse_designators_iterator - D = E->designators_rbegin(), DEnd = E->designators_rend(); - D != DEnd; ++D) { - if (D->isFieldDesignator()) - IndexCtx.handleReference(D->getField(), D->getFieldLoc(), - Parent, ParentDC, E); - } - return true; - } - }; - - auto visitForm = [&](InitListExpr *Form) { - for (Stmt *SubStmt : Form->children()) { - if (!TraverseStmt(SubStmt)) - return false; - } - return true; - }; - - InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); - InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; - - if (SemaForm) { - // Visit things present in syntactic form but not the semantic form. - if (SyntaxForm) { - SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm); - } - return visitForm(SemaForm); - } - - // No semantic, try the syntactic. - if (SyntaxForm) { - return visitForm(SyntaxForm); - } - - return true; - } - -}; - -} // anonymous namespace - -void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, - const DeclContext *DC) { - if (!S) - return; - - if (!DC) - DC = Parent->getLexicalDeclContext(); - BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast(S)); -} diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index 01f1b956b2..d901b5315d 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "IndexingContext.h" +#include "CXIndexDataConsumer.h" #include "CIndexDiagnostic.h" #include "CIndexer.h" #include "CLog.h" @@ -16,12 +16,12 @@ #include "CXString.h" #include "CXTranslationUnit.h" #include "clang/AST/ASTConsumer.h" -#include "clang/AST/DeclVisitor.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/Utils.h" +#include "clang/Index/IndexingAction.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/PPConditionalDirectiveRecord.h" @@ -34,11 +34,10 @@ #include using namespace clang; +using namespace clang::index; using namespace cxtu; using namespace cxindex; -static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx); - namespace { //===----------------------------------------------------------------------===// @@ -224,12 +223,12 @@ private: class IndexPPCallbacks : public PPCallbacks { Preprocessor &PP; - IndexingContext &IndexCtx; + CXIndexDataConsumer &DataConsumer; bool IsMainFileEntered; public: - IndexPPCallbacks(Preprocessor &PP, IndexingContext &indexCtx) - : PP(PP), IndexCtx(indexCtx), IsMainFileEntered(false) { } + IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer) + : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { } void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID) override { @@ -241,7 +240,7 @@ public: if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) { IsMainFileEntered = true; - IndexCtx.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID())); + DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID())); } } @@ -252,7 +251,7 @@ public: const Module *Imported) override { bool isImport = (IncludeTok.is(tok::identifier) && IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import); - IndexCtx.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled, + DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled, Imported); } @@ -279,18 +278,18 @@ public: //===----------------------------------------------------------------------===// class IndexingConsumer : public ASTConsumer { - IndexingContext &IndexCtx; + CXIndexDataConsumer &DataConsumer; TUSkipBodyControl *SKCtrl; public: - IndexingConsumer(IndexingContext &indexCtx, TUSkipBodyControl *skCtrl) - : IndexCtx(indexCtx), SKCtrl(skCtrl) { } + IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl) + : DataConsumer(dataConsumer), SKCtrl(skCtrl) { } // ASTConsumer Implementation void Initialize(ASTContext &Context) override { - IndexCtx.setASTContext(Context); - IndexCtx.startedTranslationUnit(); + DataConsumer.setASTContext(Context); + DataConsumer.startedTranslationUnit(); } void HandleTranslationUnit(ASTContext &Ctx) override { @@ -299,34 +298,7 @@ public: } bool HandleTopLevelDecl(DeclGroupRef DG) override { - IndexCtx.indexDeclGroupRef(DG); - return !IndexCtx.shouldAbort(); - } - - /// \brief Handle the specified top-level declaration that occurred inside - /// and ObjC container. - void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override { - IndexCtx.indexDeclGroupRef(DG); - } - - /// \brief This is called by the AST reader when deserializing things. - /// The default implementation forwards to HandleTopLevelDecl but we don't - /// care about them when indexing, so have an empty definition. - void HandleInterestingDecl(DeclGroupRef D) override {} - - void HandleTagDeclDefinition(TagDecl *D) override { - if (!IndexCtx.shouldIndexImplicitTemplateInsts()) - return; - - if (IndexCtx.isTemplateImplicitInstantiation(D)) - IndexCtx.indexDecl(D); - } - - void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override { - if (!IndexCtx.shouldIndexImplicitTemplateInsts()) - return; - - IndexCtx.indexDecl(D); + return !DataConsumer.shouldAbort(); } bool shouldSkipFunctionBody(Decl *D) override { @@ -335,7 +307,7 @@ public: return true; } - const SourceManager &SM = IndexCtx.getASTContext().getSourceManager(); + const SourceManager &SM = DataConsumer.getASTContext().getSourceManager(); SourceLocation Loc = D->getLocation(); if (Loc.isMacroID()) return false; @@ -376,34 +348,29 @@ public: //===----------------------------------------------------------------------===// class IndexingFrontendAction : public ASTFrontendAction { - IndexingContext IndexCtx; - CXTranslationUnit CXTU; + std::shared_ptr DataConsumer; SessionSkipBodyData *SKData; std::unique_ptr SKCtrl; public: - IndexingFrontendAction(CXClientData clientData, - IndexerCallbacks &indexCallbacks, - unsigned indexOptions, - CXTranslationUnit cxTU, + IndexingFrontendAction(std::shared_ptr dataConsumer, SessionSkipBodyData *skData) - : IndexCtx(clientData, indexCallbacks, indexOptions, cxTU), - CXTU(cxTU), SKData(skData) { } + : DataConsumer(dataConsumer), SKData(skData) { } std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); if (!PPOpts.ImplicitPCHInclude.empty()) { - IndexCtx.importedPCH( + DataConsumer->importedPCH( CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude)); } - IndexCtx.setASTContext(CI.getASTContext()); + DataConsumer->setASTContext(CI.getASTContext()); Preprocessor &PP = CI.getPreprocessor(); - PP.addPPCallbacks(llvm::make_unique(PP, IndexCtx)); - IndexCtx.setPreprocessor(PP); + PP.addPPCallbacks(llvm::make_unique(PP, *DataConsumer)); + DataConsumer->setPreprocessor(PP); if (SKData) { auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager()); @@ -411,15 +378,11 @@ public: SKCtrl = llvm::make_unique(*SKData, *PPRec, PP); } - return llvm::make_unique(IndexCtx, SKCtrl.get()); - } - - void EndSourceFileAction() override { - indexDiagnostics(CXTU, IndexCtx); + return llvm::make_unique(*DataConsumer, SKCtrl.get()); } TranslationUnitKind getTranslationUnitKind() override { - if (IndexCtx.shouldIndexImplicitTemplateInsts()) + if (DataConsumer->shouldIndexImplicitTemplateInsts()) return TU_Complete; else return TU_Prefix; @@ -431,6 +394,13 @@ public: // clang_indexSourceFileUnit Implementation //===----------------------------------------------------------------------===// +static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) { + IndexingOptions IdxOpts; + if (index_options & CXIndexOpt_IndexFunctionLocalSymbols) + IdxOpts.IndexFunctionLocals = true; + return IdxOpts; +} + struct IndexSessionData { CXIndex CIdx; std::unique_ptr SkipBodyData; @@ -566,13 +536,17 @@ static CXErrorCode clang_indexSourceFile_Impl( if (SkipBodies) CInvok->getFrontendOpts().SkipFunctionBodies = true; - std::unique_ptr IndexAction; - IndexAction.reset(new IndexingFrontendAction(client_data, CB, - index_options, CXTU->getTU(), - SkipBodies ? IdxSession->SkipBodyData.get() : nullptr)); + auto DataConsumer = + std::make_shared(client_data, CB, index_options, + CXTU->getTU()); + auto InterAction = llvm::make_unique(DataConsumer, + SkipBodies ? IdxSession->SkipBodyData.get() : nullptr); + std::unique_ptr IndexAction; + IndexAction = createIndexingAction(std::move(InterAction), DataConsumer, + getIndexingOptionsFromCXOptions(index_options)); // Recover resources if we crash before exiting this method. - llvm::CrashRecoveryContextCleanupRegistrar + llvm::CrashRecoveryContextCleanupRegistrar IndexActionCleanup(IndexAction.get()); bool Persistent = requestedToGetTU; @@ -632,7 +606,7 @@ static CXErrorCode clang_indexSourceFile_Impl( // clang_indexTranslationUnit Implementation //===----------------------------------------------------------------------===// -static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { +static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) { Preprocessor &PP = Unit.getPreprocessor(); if (!PP.getPreprocessingRecord()) return; @@ -655,24 +629,6 @@ static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { } } -static bool topLevelDeclVisitor(void *context, const Decl *D) { - IndexingContext &IdxCtx = *static_cast(context); - IdxCtx.indexTopLevelDecl(D); - return !IdxCtx.shouldAbort(); -} - -static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) { - Unit.visitLocalTopLevelDecls(&IdxCtx, topLevelDeclVisitor); -} - -static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) { - if (!IdxCtx.hasDiagnosticCallback()) - return; - - CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(TU); - IdxCtx.handleDiagnosticSet(DiagSet); -} - static CXErrorCode clang_indexTranslationUnit_Impl( CXIndexAction idxAction, CXClientData client_data, IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, @@ -696,19 +652,8 @@ static CXErrorCode clang_indexTranslationUnit_Impl( ? index_callbacks_size : sizeof(CB); memcpy(&CB, client_index_callbacks, ClientCBSize); - std::unique_ptr IndexCtx; - IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU)); - - // Recover resources if we crash before exiting this method. - llvm::CrashRecoveryContextCleanupRegistrar - IndexCtxCleanup(IndexCtx.get()); - - std::unique_ptr IndexConsumer; - IndexConsumer.reset(new IndexingConsumer(*IndexCtx, nullptr)); - - // Recover resources if we crash before exiting this method. - llvm::CrashRecoveryContextCleanupRegistrar - IndexConsumerCleanup(IndexConsumer.get()); + auto DataConsumer = std::make_shared(client_data, CB, + index_options, TU); ASTUnit *Unit = cxtu::getASTUnit(TU); if (!Unit) @@ -717,20 +662,21 @@ static CXErrorCode clang_indexTranslationUnit_Impl( ASTUnit::ConcurrencyCheck Check(*Unit); if (const FileEntry *PCHFile = Unit->getPCHFile()) - IndexCtx->importedPCH(PCHFile); + DataConsumer->importedPCH(PCHFile); FileManager &FileMgr = Unit->getFileManager(); if (Unit->getOriginalSourceFileName().empty()) - IndexCtx->enteredMainFile(nullptr); + DataConsumer->enteredMainFile(nullptr); else - IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); + DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); - IndexConsumer->Initialize(Unit->getASTContext()); + DataConsumer->setASTContext(Unit->getASTContext()); + DataConsumer->startedTranslationUnit(); - indexPreprocessingRecord(*Unit, *IndexCtx); - indexTranslationUnit(*Unit, *IndexCtx); - indexDiagnostics(TU, *IndexCtx); + indexPreprocessingRecord(*Unit, *DataConsumer); + indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options)); + DataConsumer->indexDiagnostics(); return CXError_Success; } @@ -1015,9 +961,9 @@ void clang_indexLoc_getFileLocation(CXIdxLoc location, if (!location.ptr_data[0] || Loc.isInvalid()) return; - IndexingContext &IndexCtx = - *static_cast(location.ptr_data[0]); - IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset); + CXIndexDataConsumer &DataConsumer = + *static_cast(location.ptr_data[0]); + DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset); } CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { @@ -1025,9 +971,9 @@ CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { if (!location.ptr_data[0] || Loc.isInvalid()) return clang_getNullLocation(); - IndexingContext &IndexCtx = - *static_cast(location.ptr_data[0]); - return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc); + CXIndexDataConsumer &DataConsumer = + *static_cast(location.ptr_data[0]); + return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc); } } // end: extern "C"