diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Index')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp | 195 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp | 5 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexBody.cpp | 359 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp | 454 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp | 385 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp | 202 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp | 176 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp | 334 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexingContext.h | 121 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp | 83 |
10 files changed, 2284 insertions, 30 deletions
diff --git a/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp b/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp new file mode 100644 index 0000000..92740b0 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp @@ -0,0 +1,195 @@ +//===- CodegenNameGenerator.cpp - Codegen name generation -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Determines the name that the symbol will get for code generation. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/CodegenNameGenerator.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Mangle.h" +#include "clang/AST/VTableBuilder.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; +using namespace clang::index; + +struct CodegenNameGenerator::Implementation { + std::unique_ptr<MangleContext> MC; + llvm::DataLayout DL; + + Implementation(ASTContext &Ctx) + : MC(Ctx.createMangleContext()), + DL(Ctx.getTargetInfo().getDataLayout()) {} + + bool writeName(const Decl *D, raw_ostream &OS) { + // First apply frontend mangling. + SmallString<128> FrontendBuf; + llvm::raw_svector_ostream FrontendBufOS(FrontendBuf); + if (auto *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->isDependentContext()) + return true; + if (writeFuncOrVarName(FD, FrontendBufOS)) + return true; + } else if (auto *VD = dyn_cast<VarDecl>(D)) { + if (writeFuncOrVarName(VD, FrontendBufOS)) + return true; + } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) { + MC->mangleObjCMethodNameWithoutSize(MD, OS); + return false; + } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + writeObjCClassName(ID, FrontendBufOS); + } else { + return true; + } + + // Now apply backend mangling. + llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL); + return false; + } + + std::string getName(const Decl *D) { + std::string Name; + { + llvm::raw_string_ostream OS(Name); + writeName(D, OS); + } + return Name; + } + + std::vector<std::string> getAllManglings(const Decl *D) { + if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D))) + return {}; + + const NamedDecl *ND = cast<NamedDecl>(D); + + ASTContext &Ctx = ND->getASTContext(); + std::unique_ptr<MangleContext> M(Ctx.createMangleContext()); + + std::vector<std::string> Manglings; + + auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { + auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, + /*IsCSSMethod=*/true); + auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv(); + return CC == DefaultCC; + }; + + if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) { + Manglings.emplace_back(getMangledStructor(CD, Ctor_Base)); + + if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) + if (!CD->getParent()->isAbstract()) + Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete)); + + if (Ctx.getTargetInfo().getCXXABI().isMicrosoft()) + if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor()) + if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0)) + Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure)); + } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) { + Manglings.emplace_back(getMangledStructor(DD, Dtor_Base)); + if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) { + Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete)); + if (DD->isVirtual()) + Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting)); + } + } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) { + Manglings.emplace_back(getName(ND)); + if (MD->isVirtual()) + if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) + for (const auto &T : *TIV) + Manglings.emplace_back(getMangledThunk(MD, T)); + } + + return Manglings; + } + +private: + bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) { + if (MC->shouldMangleDeclName(D)) { + if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D)) + MC->mangleCXXCtor(CtorD, Ctor_Complete, OS); + else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D)) + MC->mangleCXXDtor(DtorD, Dtor_Complete, OS); + else + MC->mangleName(D, OS); + return false; + } else { + IdentifierInfo *II = D->getIdentifier(); + if (!II) + return true; + OS << II->getName(); + return false; + } + } + + void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) { + OS << getClassSymbolPrefix(); + OS << D->getObjCRuntimeNameAsString(); + } + + static StringRef getClassSymbolPrefix() { + return "OBJC_CLASS_$_"; + } + + std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) { + std::string FrontendBuf; + llvm::raw_string_ostream FOS(FrontendBuf); + + if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) + MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS); + else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) + MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS); + + std::string BackendBuf; + llvm::raw_string_ostream BOS(BackendBuf); + + llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); + + return BOS.str(); + } + + std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) { + std::string FrontendBuf; + llvm::raw_string_ostream FOS(FrontendBuf); + + MC->mangleThunk(MD, T, FOS); + + std::string BackendBuf; + llvm::raw_string_ostream BOS(BackendBuf); + + llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); + + return BOS.str(); + } +}; + +CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx) + : Impl(new Implementation(Ctx)) { +} + +CodegenNameGenerator::~CodegenNameGenerator() { +} + +bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) { + return Impl->writeName(D, OS); +} + +std::string CodegenNameGenerator::getName(const Decl *D) { + return Impl->getName(D); +} + +std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) { + return Impl->getAllManglings(D); +} diff --git a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp index 15f1696..c4beef2 100644 --- a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp +++ b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp @@ -592,9 +592,8 @@ void getSourceTextOfDeclaration(const DeclInfo *ThisDecl, void CommentASTToXMLConverter::formatTextOfDeclaration( const DeclInfo *DI, SmallString<128> &Declaration) { - // FIXME. formatting API expects null terminated input string. - // There might be more efficient way of doing this. - std::string StringDecl = Declaration.str(); + // Formatting API expects null terminated input string. + StringRef StringDecl(Declaration.c_str(), Declaration.size()); // Formatter specific code. // Form a unique in memory buffer name. diff --git a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp new file mode 100644 index 0000000..4908d85 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp @@ -0,0 +1,359 @@ +//===- 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<BodyIndexer> { + IndexingContext &IndexCtx; + const NamedDecl *Parent; + const DeclContext *ParentDC; + SmallVector<Stmt*, 16> StmtStack; + + typedef RecursiveASTVisitor<BodyIndexer> base; +public: + BodyIndexer(IndexingContext &indexCtx, + const NamedDecl *Parent, const DeclContext *DC) + : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } + + bool shouldWalkTypesOfTypeLocs() const { return false; } + + bool dataTraverseStmtPre(Stmt *S) { + StmtStack.push_back(S); + return true; + } + + bool dataTraverseStmtPost(Stmt *S) { + assert(StmtStack.back() == S); + StmtStack.pop_back(); + return true; + } + + 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<SymbolRelation> &Relations) { + SymbolRoleSet Roles{}; + assert(!StmtStack.empty() && E == StmtStack.back()); + if (StmtStack.size() == 1) + return Roles; + auto It = StmtStack.end()-2; + while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) { + if (auto ICE = dyn_cast<ImplicitCastExpr>(*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<BinaryOperator>(Parent)) { + if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E) + Roles |= (unsigned)SymbolRole::Write; + + } else if (auto UO = dyn_cast<UnaryOperator>(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<CompoundAssignOperator>(Parent)) { + if (CA->getLHS()->IgnoreParenCasts() == E) { + Roles |= (unsigned)SymbolRole::Read; + Roles |= (unsigned)SymbolRole::Write; + } + + } else if (auto CE = dyn_cast<CallExpr>(Parent)) { + if (CE->getCallee()->IgnoreParenCasts() == E) { + addCallRole(Roles, Relations); + if (auto *ME = dyn_cast<MemberExpr>(E)) { + if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(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<CXXOperatorCallExpr>(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; + } + + void addCallRole(SymbolRoleSet &Roles, + SmallVectorImpl<SymbolRelation> &Relations) { + Roles |= (unsigned)SymbolRole::Call; + if (auto *FD = dyn_cast<FunctionDecl>(ParentDC)) + Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD); + else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC)) + Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD); + } + + bool VisitDeclRefExpr(DeclRefExpr *E) { + SmallVector<SymbolRelation, 4> 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<SymbolRelation, 4> Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); + return IndexCtx.handleReference(E->getMemberDecl(), Loc, + Parent, ParentDC, Roles, Relations, E); + } + + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { + for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { + if (D.isFieldDesignator()) + return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent, + ParentDC, SymbolRoleSet(), {}, E); + } + return true; + } + + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + SmallVector<SymbolRelation, 4> 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<ObjCMessageExpr>( + MsgE->getInstanceReceiver()->IgnoreParenCasts())) { + if (RecE->getMethodFamily() == OMF_alloc) + return false; + } + return true; + }; + + if (ObjCMethodDecl *MD = E->getMethodDecl()) { + SymbolRoleSet Roles{}; + SmallVector<SymbolRelation, 2> Relations; + addCallRole(Roles, Relations); + if (E->isImplicit()) + Roles |= (unsigned)SymbolRole::Implicit; + + 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 passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) { + SymbolRoleSet Roles{}; + SmallVector<SymbolRelation, 2> Relations; + addCallRole(Roles, Relations); + Roles |= (unsigned)SymbolRole::Implicit; + return IndexCtx.handleReference(MD, E->getLocStart(), + Parent, ParentDC, Roles, Relations, E); + } + + bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { + if (ObjCMethodDecl *MD = E->getBoxingMethod()) { + return passObjCLiteralMethodCall(MD, E); + } + return true; + } + + bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { + return passObjCLiteralMethodCall(MD, E); + } + return true; + } + + bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { + if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { + return passObjCLiteralMethodCall(MD, E); + } + return true; + } + + bool VisitCXXConstructExpr(CXXConstructExpr *E) { + SymbolRoleSet Roles{}; + SmallVector<SymbolRelation, 2> Relations; + addCallRole(Roles, Relations); + return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), + Parent, ParentDC, Roles, Relations, E); + } + + 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()) + 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<SyntacticFormIndexer> { + 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::Designator &D : llvm::reverse(E->designators())) { + 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, Q)) + 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<Stmt*>(S)); +} diff --git a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp new file mode 100644 index 0000000..eb3e151 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp @@ -0,0 +1,454 @@ +//===- IndexDecl.cpp - Indexing declarations ------------------------------===// +// +// 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/DeclVisitor.h" + +using namespace clang; +using namespace index; + +#define TRY_TO(CALL_EXPR) \ + do { \ + if (!CALL_EXPR) \ + return false; \ + } while (0) + +namespace { + +class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { + IndexingContext &IndexCtx; + +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, + const ObjCImplDecl *Container) { + const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), + D->isInstanceMethod()); + return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); + } + + void handleDeclarator(const DeclaratorDecl *D, + const NamedDecl *Parent = nullptr) { + if (!Parent) Parent = D; + + 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<ParmVarDecl>(D)) { + auto *DC = Parm->getDeclContext(); + if (auto *FD = dyn_cast<FunctionDecl>(DC)) { + if (FD->isThisDeclarationADefinition()) + IndexCtx.handleDecl(Parm); + } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { + if (MD->isThisDeclarationADefinition()) + IndexCtx.handleDecl(Parm); + } else { + IndexCtx.handleDecl(Parm); + } + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->isThisDeclarationADefinition()) { + for (auto PI : FD->parameters()) { + IndexCtx.handleDecl(PI); + } + } + } + } + } + + bool handleObjCMethod(const ObjCMethodDecl *D) { + if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic)) + return false; + IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); + for (const auto *I : D->parameters()) + handleDeclarator(I, D); + + if (D->isThisDeclarationADefinition()) { + const Stmt *Body = D->getBody(); + if (Body) { + IndexCtx.indexBody(Body, D, D); + } + } + return true; + } + + bool VisitFunctionDecl(const FunctionDecl *D) { + if (D->isDeleted()) + return true; + + SymbolRoleSet Roles{}; + SmallVector<SymbolRelation, 4> Relations; + if (auto *CXXMD = dyn_cast<CXXMethodDecl>(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<CXXConstructorDecl>(D)) { + // Constructor initializers. + for (const auto *Init : Ctor->inits()) { + if (Init->isWritten()) { + IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); + if (const FieldDecl *Member = Init->getAnyMember()) + IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, + (unsigned)SymbolRole::Write); + IndexCtx.indexBody(Init->getInit(), D, D); + } + } + } + + if (D->isThisDeclarationADefinition()) { + const Stmt *Body = D->getBody(); + if (Body) { + IndexCtx.indexBody(Body, D, D); + } + } + return true; + } + + bool VisitVarDecl(const VarDecl *D) { + if (!IndexCtx.handleDecl(D)) + return false; + handleDeclarator(D); + IndexCtx.indexBody(D->getInit(), D); + return true; + } + + bool VisitFieldDecl(const FieldDecl *D) { + if (!IndexCtx.handleDecl(D)) + return false; + handleDeclarator(D); + if (D->isBitField()) + IndexCtx.indexBody(D->getBitWidth(), D); + else if (D->hasInClassInitializer()) + IndexCtx.indexBody(D->getInClassInitializer(), D); + 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<Decl>(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) { + if (!IndexCtx.handleDecl(D)) + return false; + IndexCtx.indexBody(D->getInitExpr(), D); + return true; + } + + bool VisitTypedefNameDecl(const TypedefNameDecl *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()) { + if (D->isThisDeclarationADefinition()) { + IndexCtx.indexTagDecl(D); + } else { + auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext()); + return IndexCtx.handleReference(D, D->getLocation(), Parent, + D->getLexicalDeclContext(), + SymbolRoleSet()); + } + } + return true; + } + + bool handleReferencedProtocols(const ObjCProtocolList &ProtList, + const ObjCContainerDecl *ContD) { + ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); + for (ObjCInterfaceDecl::protocol_iterator + I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { + SourceLocation Loc = *LI; + ObjCProtocolDecl *PD = *I; + TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, + SymbolRoleSet(), + SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); + } + return true; + } + + bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { + if (D->isThisDeclarationADefinition()) { + TRY_TO(IndexCtx.handleDecl(D)); + if (auto *SuperD = D->getSuperClass()) { + TRY_TO(IndexCtx.handleReference(SuperD, D->getSuperClassLoc(), D, D, + SymbolRoleSet(), + SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); + } + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_TO(IndexCtx.indexDeclContext(D)); + } else { + return IndexCtx.handleReference(D, D->getLocation(), nullptr, + D->getDeclContext(), SymbolRoleSet()); + } + return true; + } + + bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { + if (D->isThisDeclarationADefinition()) { + TRY_TO(IndexCtx.handleDecl(D)); + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_TO(IndexCtx.indexDeclContext(D)); + } else { + return IndexCtx.handleReference(D, D->getLocation(), nullptr, + D->getDeclContext(), SymbolRoleSet()); + } + return true; + } + + bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { + const ObjCInterfaceDecl *Class = D->getClassInterface(); + if (!Class) + return true; + + if (Class->isImplicitInterfaceDecl()) + IndexCtx.handleDecl(Class); + + 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. + for (const auto *IvarI : D->ivars()) + IndexCtx.indexDecl(IvarI); + for (const auto *I : D->decls()) { + if (!isa<ObjCIvarDecl>(I)) + IndexCtx.indexDecl(I); + } + + return true; + } + + bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + if (!IndexCtx.handleDecl(D)) + return false; + IndexCtx.indexDeclContext(D); + return true; + } + + bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { + const ObjCCategoryDecl *Cat = D->getCategoryDecl(); + if (!Cat) + return true; + + if (!IndexCtx.handleDecl(D)) + return false; + IndexCtx.indexDeclContext(D); + return true; + } + + bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { + // Methods associated with a property, even user-declared ones, are + // handled when we handle the property. + if (D->isPropertyAccessor()) + return true; + + handleObjCMethod(D); + return true; + } + + bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { + if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) + if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) + handleObjCMethod(MD); + if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) + if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) + handleObjCMethod(MD); + if (!IndexCtx.handleDecl(D)) + return false; + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + return true; + } + + bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { + ObjCPropertyDecl *PD = D->getPropertyDecl(); + if (!IndexCtx.handleReference(PD, D->getLocation(), + /*Parent=*/cast<NamedDecl>(D->getDeclContext()), + D->getDeclContext(), SymbolRoleSet(), {}, + /*RefE=*/nullptr, D)) + return false; + + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + return true; + assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); + + if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { + if (!IvarD->getSynthesize()) + IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, + D->getDeclContext(), SymbolRoleSet()); + } + + auto *ImplD = cast<ObjCImplDecl>(D->getDeclContext()); + if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { + if (MD->isPropertyAccessor() && + !hasUserDefined(MD, ImplD)) + IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); + } + if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { + if (MD->isPropertyAccessor() && + !hasUserDefined(MD, ImplD)) + IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); + } + return true; + } + + bool VisitNamespaceDecl(const NamespaceDecl *D) { + if (!IndexCtx.handleDecl(D)) + return false; + IndexCtx.indexDeclContext(D); + return true; + } + + bool VisitUsingDecl(const UsingDecl *D) { + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); + + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, + D->getLexicalDeclContext()); + for (const auto *I : D->shadows()) + IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, + D->getLexicalDeclContext(), SymbolRoleSet()); + return true; + } + + bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + const NamedDecl *Parent = dyn_cast<NamedDecl>(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.indexTagDecl(D); + return true; + } + + bool VisitTemplateDecl(const TemplateDecl *D) { + // FIXME: Template parameters. + return Visit(D->getTemplatedDecl()); + } + + 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<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) + return true; + return Visit(ND); + } + if (auto Ty = D->getFriendType()) { + IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); + } + return true; + } + + bool VisitImportDecl(const ImportDecl *D) { + return IndexCtx.importedModule(D); + } +}; + +} // anonymous namespace + +bool IndexingContext::indexDecl(const Decl *D) { + if (D->isImplicit() && shouldIgnoreIfImplicit(D)) + return true; + + if (isTemplateImplicitInstantiation(D)) + return true; + + IndexingDeclVisitor Visitor(*this); + bool ShouldContinue = Visitor.Visit(D); + if (!ShouldContinue) + return false; + + if (!Visitor.Handled && isa<DeclContext>(D)) + return indexDeclContext(cast<DeclContext>(D)); + + return true; +} + +bool IndexingContext::indexDeclContext(const DeclContext *DC) { + for (const auto *I : DC->decls()) + if (!indexDecl(I)) + return false; + return true; +} + +bool IndexingContext::indexTopLevelDecl(const Decl *D) { + if (D->getLocation().isInvalid()) + return true; + + if (isa<ObjCMethodDecl>(D)) + return true; // Wait for the objc container. + + return indexDecl(D); +} + +bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + if (!indexTopLevelDecl(*I)) + return false; + return true; +} diff --git a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp new file mode 100644 index 0000000..13a8452 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp @@ -0,0 +1,385 @@ +//===--- 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" +#include "clang/AST/PrettyPrinter.h" + +using namespace clang; +using namespace clang::index; + +/// \returns true if \c D is a subclass of 'XCTestCase'. +static bool isUnitTestCase(const ObjCInterfaceDecl *D) { + if (!D) + return false; + while (const ObjCInterfaceDecl *SuperD = D->getSuperClass()) { + if (SuperD->getName() == "XCTestCase") + return true; + D = SuperD; + } + return false; +} + +/// \returns true if \c D is in a subclass of 'XCTestCase', returns void, has +/// no parameters, and its name starts with 'test'. +static bool isUnitTest(const ObjCMethodDecl *D) { + if (!D->parameters().empty()) + return false; + if (!D->getReturnType()->isVoidType()) + return false; + if (!D->getSelector().getNameForSlot(0).startswith("test")) + return false; + return isUnitTestCase(D->getClassInterface()); +} + +static void checkForIBOutlets(const Decl *D, SymbolSubKindSet &SubKindSet) { + if (D->hasAttr<IBOutletAttr>()) { + SubKindSet |= (unsigned)SymbolSubKind::IBAnnotated; + } else if (D->hasAttr<IBOutletCollectionAttr>()) { + SubKindSet |= (unsigned)SymbolSubKind::IBAnnotated; + SubKindSet |= (unsigned)SymbolSubKind::IBOutletCollection; + } +} + +SymbolInfo index::getSymbolInfo(const Decl *D) { + assert(D); + SymbolInfo Info; + Info.Kind = SymbolKind::Unknown; + Info.SubKinds = SymbolSubKindSet(); + Info.Lang = SymbolLanguage::C; + + if (const TagDecl *TD = dyn_cast<TagDecl>(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::Class; + Info.Lang = SymbolLanguage::CXX; + break; + case TTK_Interface: + Info.Kind = SymbolKind::Protocol; + Info.Lang = SymbolLanguage::CXX; + break; + case TTK_Enum: + Info.Kind = SymbolKind::Enum; break; + } + + if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) + if (!CXXRec->isCLike()) + Info.Lang = SymbolLanguage::CXX; + + if (isa<ClassTemplatePartialSpecializationDecl>(D)) { + Info.SubKinds |= (unsigned)SymbolSubKind::Generic; + Info.SubKinds |= (unsigned)SymbolSubKind::TemplatePartialSpecialization; + } else if (isa<ClassTemplateSpecializationDecl>(D)) { + Info.SubKinds |= (unsigned)SymbolSubKind::Generic; + Info.SubKinds |= (unsigned)SymbolSubKind::TemplateSpecialization; + } + + } else { + switch (D->getKind()) { + case Decl::Import: + Info.Kind = SymbolKind::Module; + break; + case Decl::Typedef: + Info.Kind = SymbolKind::TypeAlias; break; // Lang = C + 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<CXXRecordDecl>(D->getDeclContext())) { + Info.Kind = SymbolKind::StaticProperty; + Info.Lang = SymbolLanguage::CXX; + } + break; + case Decl::Field: + Info.Kind = SymbolKind::Field; + if (const CXXRecordDecl * + CXXRec = dyn_cast<CXXRecordDecl>(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::Class; + Info.Lang = SymbolLanguage::ObjC; + const ObjCInterfaceDecl *ClsD = dyn_cast<ObjCInterfaceDecl>(D); + if (!ClsD) + ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface(); + if (isUnitTestCase(ClsD)) + Info.SubKinds |= (unsigned)SymbolSubKind::UnitTest; + break; + } + case Decl::ObjCProtocol: + Info.Kind = SymbolKind::Protocol; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::ObjCCategory: + case Decl::ObjCCategoryImpl: + Info.Kind = SymbolKind::Extension; + Info.Lang = SymbolLanguage::ObjC; + break; + case Decl::ObjCMethod: + if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) + Info.Kind = SymbolKind::InstanceMethod; + else + Info.Kind = SymbolKind::ClassMethod; + Info.Lang = SymbolLanguage::ObjC; + if (isUnitTest(cast<ObjCMethodDecl>(D))) + Info.SubKinds |= (unsigned)SymbolSubKind::UnitTest; + if (D->hasAttr<IBActionAttr>()) + Info.SubKinds |= (unsigned)SymbolSubKind::IBAnnotated; + break; + case Decl::ObjCProperty: + Info.Kind = SymbolKind::InstanceProperty; + Info.Lang = SymbolLanguage::ObjC; + checkForIBOutlets(D, Info.SubKinds); + break; + case Decl::ObjCIvar: + Info.Kind = SymbolKind::Field; + Info.Lang = SymbolLanguage::ObjC; + checkForIBOutlets(D, Info.SubKinds); + break; + case Decl::Namespace: + Info.Kind = SymbolKind::Namespace; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::NamespaceAlias: + Info.Kind = SymbolKind::NamespaceAlias; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXConstructor: + Info.Kind = SymbolKind::Constructor; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXDestructor: + Info.Kind = SymbolKind::Destructor; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXConversion: + Info.Kind = SymbolKind::ConversionFunction; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::CXXMethod: { + const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); + if (MD->isStatic()) + Info.Kind = SymbolKind::StaticMethod; + else + Info.Kind = SymbolKind::InstanceMethod; + Info.Lang = SymbolLanguage::CXX; + break; + } + case Decl::ClassTemplate: + Info.Kind = SymbolKind::Class; + Info.SubKinds |= (unsigned)SymbolSubKind::Generic; + Info.Lang = SymbolLanguage::CXX; + break; + case Decl::FunctionTemplate: + Info.Kind = SymbolKind::Function; + Info.SubKinds |= (unsigned)SymbolSubKind::Generic; + Info.Lang = SymbolLanguage::CXX; + if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>( + cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) { + if (isa<CXXConstructorDecl>(MD)) + Info.Kind = SymbolKind::Constructor; + else if (isa<CXXDestructorDecl>(MD)) + Info.Kind = SymbolKind::Destructor; + else if (isa<CXXConversionDecl>(MD)) + Info.Kind = SymbolKind::ConversionFunction; + else { + if (MD->isStatic()) + Info.Kind = SymbolKind::StaticMethod; + else + Info.Kind = SymbolKind::InstanceMethod; + } + } + break; + case Decl::TypeAliasTemplate: + Info.Kind = SymbolKind::TypeAlias; + Info.Lang = SymbolLanguage::CXX; + Info.SubKinds |= (unsigned)SymbolSubKind::Generic; + break; + case Decl::TypeAlias: + Info.Kind = SymbolKind::TypeAlias; + Info.Lang = SymbolLanguage::CXX; + break; + default: + break; + } + } + + if (Info.Kind == SymbolKind::Unknown) + return Info; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization) { + Info.SubKinds |= (unsigned)SymbolSubKind::Generic; + Info.SubKinds |= (unsigned)SymbolSubKind::TemplateSpecialization; + } + } + + if (Info.SubKinds & (unsigned)SymbolSubKind::Generic) + Info.Lang = SymbolLanguage::CXX; + + return Info; +} + +void index::applyForEachSymbolRole(SymbolRoleSet Roles, + llvm::function_ref<void(SymbolRole)> Fn) { +#define APPLY_FOR_ROLE(Role) \ + if (Roles & (unsigned)SymbolRole::Role) \ + Fn(SymbolRole::Role) + + APPLY_FOR_ROLE(Declaration); + APPLY_FOR_ROLE(Definition); + APPLY_FOR_ROLE(Reference); + APPLY_FOR_ROLE(Read); + APPLY_FOR_ROLE(Write); + APPLY_FOR_ROLE(Call); + APPLY_FOR_ROLE(Dynamic); + APPLY_FOR_ROLE(AddressOf); + APPLY_FOR_ROLE(Implicit); + APPLY_FOR_ROLE(RelationChildOf); + APPLY_FOR_ROLE(RelationBaseOf); + APPLY_FOR_ROLE(RelationOverrideOf); + APPLY_FOR_ROLE(RelationReceivedBy); + APPLY_FOR_ROLE(RelationCalledBy); + +#undef APPLY_FOR_ROLE +} + +void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { + bool VisitedOnce = false; + applyForEachSymbolRole(Roles, [&](SymbolRole Role) { + if (VisitedOnce) + OS << ','; + else + VisitedOnce = true; + switch (Role) { + case SymbolRole::Declaration: OS << "Decl"; break; + case SymbolRole::Definition: OS << "Def"; break; + case SymbolRole::Reference: OS << "Ref"; break; + case SymbolRole::Read: OS << "Read"; break; + case SymbolRole::Write: OS << "Writ"; break; + case SymbolRole::Call: OS << "Call"; break; + case SymbolRole::Dynamic: OS << "Dyn"; break; + case SymbolRole::AddressOf: OS << "Addr"; break; + case SymbolRole::Implicit: OS << "Impl"; break; + case SymbolRole::RelationChildOf: OS << "RelChild"; break; + case SymbolRole::RelationBaseOf: OS << "RelBase"; break; + case SymbolRole::RelationOverrideOf: OS << "RelOver"; break; + case SymbolRole::RelationReceivedBy: OS << "RelRec"; break; + case SymbolRole::RelationCalledBy: OS << "RelCall"; break; + } + }); +} + +bool index::printSymbolName(const Decl *D, const LangOptions &LO, + raw_ostream &OS) { + if (auto *ND = dyn_cast<NamedDecl>(D)) { + PrintingPolicy Policy(LO); + // Forward references can have different template argument names. Suppress + // the template argument names in constructors to make their name more + // stable. + Policy.SuppressTemplateArgsInCXXConstructors = true; + DeclarationName DeclName = ND->getDeclName(); + if (DeclName.isEmpty()) + return true; + DeclName.print(OS, Policy); + return false; + } else { + return true; + } +} + +StringRef index::getSymbolKindString(SymbolKind K) { + switch (K) { + case SymbolKind::Unknown: return "<unknown>"; + case SymbolKind::Module: return "module"; + case SymbolKind::Namespace: return "namespace"; + case SymbolKind::NamespaceAlias: return "namespace-alias"; + case SymbolKind::Macro: return "macro"; + case SymbolKind::Enum: return "enum"; + case SymbolKind::Struct: return "struct"; + case SymbolKind::Class: return "class"; + case SymbolKind::Protocol: return "protocol"; + case SymbolKind::Extension: return "extension"; + case SymbolKind::Union: return "union"; + case SymbolKind::TypeAlias: return "type-alias"; + case SymbolKind::Function: return "function"; + case SymbolKind::Variable: return "variable"; + case SymbolKind::Field: return "field"; + case SymbolKind::EnumConstant: return "enumerator"; + case SymbolKind::InstanceMethod: return "instance-method"; + case SymbolKind::ClassMethod: return "class-method"; + case SymbolKind::StaticMethod: return "static-method"; + case SymbolKind::InstanceProperty: return "instance-property"; + case SymbolKind::ClassProperty: return "class-property"; + case SymbolKind::StaticProperty: return "static-property"; + case SymbolKind::Constructor: return "constructor"; + case SymbolKind::Destructor: return "destructor"; + case SymbolKind::ConversionFunction: return "coversion-func"; + } + llvm_unreachable("invalid symbol kind"); +} + +StringRef index::getSymbolLanguageString(SymbolLanguage K) { + switch (K) { + case SymbolLanguage::C: return "C"; + case SymbolLanguage::ObjC: return "ObjC"; + case SymbolLanguage::CXX: return "C++"; + } + llvm_unreachable("invalid symbol language kind"); +} + +void index::applyForEachSymbolSubKind(SymbolSubKindSet SubKinds, + llvm::function_ref<void(SymbolSubKind)> Fn) { +#define APPLY_FOR_SUBKIND(K) \ + if (SubKinds & (unsigned)SymbolSubKind::K) \ + Fn(SymbolSubKind::K) + + APPLY_FOR_SUBKIND(Generic); + APPLY_FOR_SUBKIND(TemplatePartialSpecialization); + APPLY_FOR_SUBKIND(TemplateSpecialization); + APPLY_FOR_SUBKIND(UnitTest); + APPLY_FOR_SUBKIND(IBAnnotated); + APPLY_FOR_SUBKIND(IBOutletCollection); + +#undef APPLY_FOR_SUBKIND +} + +void index::printSymbolSubKinds(SymbolSubKindSet SubKinds, raw_ostream &OS) { + bool VisitedOnce = false; + applyForEachSymbolSubKind(SubKinds, [&](SymbolSubKind SubKind) { + if (VisitedOnce) + OS << ','; + else + VisitedOnce = true; + switch (SubKind) { + case SymbolSubKind::Generic: OS << "Gen"; break; + case SymbolSubKind::TemplatePartialSpecialization: OS << "TPS"; break; + case SymbolSubKind::TemplateSpecialization: OS << "TS"; break; + case SymbolSubKind::UnitTest: OS << "test"; break; + case SymbolSubKind::IBAnnotated: OS << "IB"; break; + case SymbolSubKind::IBOutletCollection: OS << "IBColl"; break; + } + }); +} diff --git a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp new file mode 100644 index 0000000..619a9a4 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -0,0 +1,202 @@ +//===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===// +// +// 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 index; + +namespace { + +class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> { + IndexingContext &IndexCtx; + const NamedDecl *Parent; + const DeclContext *ParentDC; + bool IsBase; + SmallVector<SymbolRelation, 3> Relations; + + typedef RecursiveASTVisitor<TypeIndexer> base; + +public: + TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent, + 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) { + 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<FunctionDecl>(D->getDeclContext())) { + if (FD->isThisDeclarationADefinition()) { + return traverseParamVarHelper(D); + } + } + + return base::TraverseParmVarDecl(D); + } + + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); + return true; + } + + bool VisitTagTypeLoc(TagTypeLoc TL) { + TagDecl *D = TL.getDecl(); + if (D->getParentFunctionOrMethod()) + return true; + + if (TL.isDefinition()) { + IndexCtx.indexTagDecl(D); + return true; + } + + return IndexCtx.handleReference(D, TL.getNameLoc(), + Parent, ParentDC, SymbolRoleSet(), + Relations); + } + + bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { + 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, SymbolRoleSet()); + } + return true; + } + + bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { + if (const TemplateSpecializationType *T = TL.getTypePtr()) { + if (IndexCtx.shouldIndexImplicitTemplateInsts()) { + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), + Parent, ParentDC, SymbolRoleSet(), Relations); + } else { + if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl()) + IndexCtx.handleReference(D, TL.getTemplateNameLoc(), + Parent, ParentDC, SymbolRoleSet(), Relations); + } + } + return true; + } + + bool TraverseStmt(Stmt *S) { + IndexCtx.indexBody(S, Parent, ParentDC); + return true; + } +}; + +} // anonymous namespace + +void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo, + const NamedDecl *Parent, + const DeclContext *DC, + bool isBase) { + if (!TInfo || TInfo->getTypeLoc().isNull()) + return; + + indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase); +} + +void IndexingContext::indexTypeLoc(TypeLoc TL, + const NamedDecl *Parent, + const DeclContext *DC, + bool isBase) { + if (TL.isNull()) + return; + + if (!DC) + DC = Parent->getLexicalDeclContext(); + TypeIndexer(*this, Parent, DC, isBase).TraverseTypeLoc(TL); +} + +void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const NamedDecl *Parent, + const DeclContext *DC) { + if (!NNS) + return; + + if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) + indexNestedNameSpecifierLoc(Prefix, Parent, DC); + + if (!DC) + DC = Parent->getLexicalDeclContext(); + SourceLocation Loc = NNS.getSourceRange().getBegin(); + + switch (NNS.getNestedNameSpecifier()->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: + break; + + case NestedNameSpecifier::Namespace: + handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(), + Loc, Parent, DC, SymbolRoleSet()); + break; + case NestedNameSpecifier::NamespaceAlias: + handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), + Loc, Parent, DC, SymbolRoleSet()); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + indexTypeLoc(NNS.getTypeLoc(), Parent, DC); + break; + } +} + +void IndexingContext::indexTagDecl(const TagDecl *D) { + if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) + return; + + if (handleDecl(D)) { + if (D->isThisDeclarationADefinition()) { + indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) { + for (const auto &I : CXXRD->bases()) { + indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true); + } + } + indexDeclContext(D); + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp new file mode 100644 index 0000000..d744293 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp @@ -0,0 +1,176 @@ +//===- 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<SymbolRelation> 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); + IndexCtx.getDataConsumer().initialize(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 IndexActionBase { +protected: + std::shared_ptr<IndexDataConsumer> DataConsumer; + IndexingContext IndexCtx; + + IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer, + IndexingOptions Opts) + : DataConsumer(std::move(dataConsumer)), + IndexCtx(Opts, *DataConsumer) {} + + std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() { + return llvm::make_unique<IndexASTConsumer>(IndexCtx); + } + + void finish() { + DataConsumer->finish(); + } +}; + +class IndexAction : public ASTFrontendAction, IndexActionBase { +public: + IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer, + IndexingOptions Opts) + : IndexActionBase(std::move(DataConsumer), Opts) {} + +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { + return createIndexASTConsumer(); + } + + void EndSourceFileAction() override { + FrontendAction::EndSourceFileAction(); + finish(); + } +}; + +class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase { + bool IndexActionFailed = false; + +public: + WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction, + std::shared_ptr<IndexDataConsumer> DataConsumer, + IndexingOptions Opts) + : WrapperFrontendAction(std::move(WrappedAction)), + IndexActionBase(std::move(DataConsumer), Opts) {} + +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + void EndSourceFileAction() override; +}; + +} // anonymous namespace + +void WrappingIndexAction::EndSourceFileAction() { + // Invoke wrapped action's method. + WrapperFrontendAction::EndSourceFileAction(); + if (!IndexActionFailed) + finish(); +} + +std::unique_ptr<ASTConsumer> +WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); + if (!OtherConsumer) { + IndexActionFailed = true; + return nullptr; + } + + std::vector<std::unique_ptr<ASTConsumer>> Consumers; + Consumers.push_back(std::move(OtherConsumer)); + Consumers.push_back(createIndexASTConsumer()); + return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); +} + +std::unique_ptr<FrontendAction> +index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer, + IndexingOptions Opts, + std::unique_ptr<FrontendAction> WrappedAction) { + if (WrappedAction) + return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction), + std::move(DataConsumer), + Opts); + return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts); +} + + +static bool topLevelDeclVisitor(void *context, const Decl *D) { + IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context); + return IndexCtx.indexTopLevelDecl(D); +} + +static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) { + Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor); +} + +void index::indexASTUnit(ASTUnit &Unit, + std::shared_ptr<IndexDataConsumer> DataConsumer, + IndexingOptions Opts) { + IndexingContext IndexCtx(Opts, *DataConsumer); + IndexCtx.setASTContext(Unit.getASTContext()); + DataConsumer->initialize(Unit.getASTContext()); + indexTranslationUnit(Unit, IndexCtx); +} diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp new file mode 100644 index 0000000..bcc367c --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp @@ -0,0 +1,334 @@ +//===- 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<SymbolRelation> Relations) { + return handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false, + cast<Decl>(D->getDeclContext()), Roles, Relations, + nullptr, nullptr, D->getDeclContext()); +} + +bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, + SymbolRoleSet Roles, + ArrayRef<SymbolRelation> Relations, + const DeclContext *DC) { + if (!DC) + DC = D->getDeclContext(); + return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC), + Roles, Relations, + nullptr, nullptr, DC); +} + +bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, + const NamedDecl *Parent, + const DeclContext *DC, + SymbolRoleSet Roles, + ArrayRef<SymbolRelation> Relations, + const Expr *RefE, + const Decl *RefD) { + if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) + return true; + + if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D)) + return true; + + return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations, + RefE, RefD, DC); +} + +bool IndexingContext::importedModule(const ImportDecl *ImportD) { + SourceLocation Loc; + auto IdLocs = ImportD->getIdentifierLocs(); + if (!IdLocs.empty()) + Loc = IdLocs.front(); + else + 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: + return true; + case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: + case IndexingOptions::SystemSymbolFilterKind::All: + break; + } + } + + SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration; + if (ImportD->isImplicit()) + Roles |= (unsigned)SymbolRole::Implicit; + + return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset); +} + +bool IndexingContext::isFunctionLocalDecl(const Decl *D) { + assert(D); + + if (isa<TemplateTemplateParmDecl>(D)) + return true; + + if (isa<ObjCTypeParamDecl>(D)) + return true; + + if (!D->getParentFunctionOrMethod()) + return false; + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(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<ClassTemplateSpecializationDecl>(D)) { + TKind = SD->getSpecializationKind(); + } + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(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; + } + llvm_unreachable("invalid TemplateSpecializationKind"); +} + +bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { + if (isa<ObjCInterfaceDecl>(D)) + return false; + if (isa<ObjCCategoryDecl>(D)) + return false; + if (isa<ObjCIvarDecl>(D)) + return false; + if (isa<ObjCMethodDecl>(D)) + return false; + if (isa<ImportDecl>(D)) + return false; + return true; +} + +static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { + if (const ClassTemplateSpecializationDecl * + SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + return SD->getTemplateInstantiationPattern(); + } + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + return FD->getTemplateInstantiationPattern(); + } + return nullptr; +} + +static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) { + if (auto VD = dyn_cast<VarDecl>(D)) + return VD->isThisDeclarationADefinition(Ctx); + + if (auto FD = dyn_cast<FunctionDecl>(D)) + return FD->isThisDeclarationADefinition(); + + if (auto TD = dyn_cast<TagDecl>(D)) + return TD->isThisDeclarationADefinition(); + + if (auto MD = dyn_cast<ObjCMethodDecl>(D)) + return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC); + + if (isa<TypedefNameDecl>(D) || + isa<EnumConstantDecl>(D) || + isa<FieldDecl>(D) || + isa<MSPropertyDecl>(D) || + isa<ObjCImplDecl>(D) || + isa<ObjCPropertyImplDecl>(D)) + return true; + + return false; +} + +static const Decl *adjustParent(const Decl *Parent) { + if (!Parent) + return nullptr; + for (;; Parent = cast<Decl>(Parent->getDeclContext())) { + if (isa<TranslationUnitDecl>(Parent)) + return nullptr; + if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent)) + continue; + if (auto NS = dyn_cast<NamespaceDecl>(Parent)) { + if (NS->isAnonymousNamespace()) + continue; + } else if (auto RD = dyn_cast<RecordDecl>(Parent)) { + if (RD->isAnonymousStructOrUnion()) + continue; + } else if (auto FD = dyn_cast<FieldDecl>(Parent)) { + if (FD->getDeclName().isEmpty()) + continue; + } + return Parent; + } +} + +static const Decl *getCanonicalDecl(const Decl *D) { + D = D->getCanonicalDecl(); + if (auto TD = dyn_cast<TemplateDecl>(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<SymbolRelation> Relations, + const Expr *OrigE, + const Decl *OrigD, + const DeclContext *ContainerDC) { + if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) + return true; + if (!isa<NamedDecl>(D) || + (cast<NamedDecl>(D)->getDeclName().isEmpty() && + !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(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, ContainerDC, *Ctx)) + Roles |= (unsigned)SymbolRole::Definition; + else + Roles |= (unsigned)SymbolRole::Declaration; + + D = getCanonicalDecl(D); + if (D->isImplicit() && !isa<ObjCMethodDecl>(D) && + !(isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->getBuiltinID())) { + // 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<FunctionDecl>(Parent) && + cast<FunctionDecl>(Parent)->getBuiltinID()) || + isa<ObjCInterfaceDecl>(Parent) || isa<ObjCMethodDecl>(Parent)) && + "unexpected implicit parent!"); + + SmallVector<SymbolRelation, 6> 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<DeclContext>(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/contrib/llvm/tools/clang/lib/Index/IndexingContext.h b/contrib/llvm/tools/clang/lib/Index/IndexingContext.h new file mode 100644 index 0000000..600fc43 --- /dev/null +++ b/contrib/llvm/tools/clang/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<SymbolRelation> Relations = None); + + bool handleDecl(const Decl *D, SourceLocation Loc, + SymbolRoleSet Roles = SymbolRoleSet(), + ArrayRef<SymbolRelation> Relations = None, + const DeclContext *DC = nullptr); + + bool handleReference(const NamedDecl *D, SourceLocation Loc, + const NamedDecl *Parent, + const DeclContext *DC, + SymbolRoleSet Roles, + ArrayRef<SymbolRelation> Relations = None, + 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<SymbolRelation> Relations, + const Expr *RefE, + const Decl *RefD, + const DeclContext *ContainerDC); +}; + +} // end namespace index +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp index c57694f..30f1add 100644 --- a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp +++ b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp @@ -90,18 +90,23 @@ public: void VisitVarDecl(const VarDecl *D); void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); + void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { IgnoreResults = true; } + void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { IgnoreResults = true; } + void VisitUsingDecl(const UsingDecl *D) { IgnoreResults = true; } + void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { IgnoreResults = true; } + void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { IgnoreResults = true; } @@ -126,14 +131,17 @@ public: void GenObjCClass(StringRef cls) { generateUSRForObjCClass(cls, Out); } + /// Generate a USR for an Objective-C class category. void GenObjCCategory(StringRef cls, StringRef cat) { generateUSRForObjCCategory(cls, cat, Out); } + /// Generate a USR fragment for an Objective-C property. - void GenObjCProperty(StringRef prop) { - generateUSRForObjCProperty(prop, Out); + void GenObjCProperty(StringRef prop, bool isClassProp) { + generateUSRForObjCProperty(prop, isClassProp, Out); } + /// Generate a USR for an Objective-C protocol. void GenObjCProtocol(StringRef prot) { generateUSRForObjCProtocol(prot, Out); @@ -148,7 +156,6 @@ public: /// the decl had no name. bool EmitDeclName(const NamedDecl *D); }; - } // end anonymous namespace //===----------------------------------------------------------------------===// @@ -203,10 +210,16 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { VisitTemplateParameterList(FunTmpl->getTemplateParameters()); } else Out << "@F@"; - D->printName(Out); + + PrintingPolicy Policy(Context->getLangOpts()); + // Forward references can have different template argument names. Suppress the + // template argument names in constructors to make their USR more stable. + Policy.SuppressTemplateArgsInCXXConstructors = true; + D->getDeclName().print(Out, Policy); ASTContext &Ctx = *Context; - if (!Ctx.getLangOpts().CPlusPlus || D->isExternC()) + if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) && + !D->hasAttr<OverloadableAttr>()) return; if (const TemplateArgumentList * @@ -220,7 +233,7 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { } // Mangle in type information for the arguments. - for (auto PD : D->params()) { + for (auto PD : D->parameters()) { Out << '#'; VisitType(PD->getType()); } @@ -287,13 +300,11 @@ void USRGenerator::VisitVarDecl(const VarDecl *D) { void USRGenerator::VisitNonTypeTemplateParmDecl( const NonTypeTemplateParmDecl *D) { GenLoc(D, /*IncludeOffset=*/true); - return; } void USRGenerator::VisitTemplateTemplateParmDecl( const TemplateTemplateParmDecl *D) { GenLoc(D, /*IncludeOffset=*/true); - return; } void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { @@ -400,7 +411,7 @@ void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { Visit(ID); else Visit(cast<Decl>(D->getDeclContext())); - GenObjCProperty(D->getName()); + GenObjCProperty(D->getName(), D->isClassProperty()); } void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { @@ -415,7 +426,8 @@ void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { void USRGenerator::VisitTagDecl(const TagDecl *D) { // Add the location of the tag decl to handle resolution across // translation units. - if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) + if (!isa<EnumDecl>(D) && + ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; D = D->getCanonicalDecl(); @@ -471,8 +483,16 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { else { if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) { printLoc(Out, D->getLocation(), Context->getSourceManager(), true); - } else + } else { Buf[off] = 'a'; + if (auto *ED = dyn_cast<EnumDecl>(D)) { + // Distinguish USRs of anonymous enums by using their first enumerator. + auto enum_range = ED->enumerators(); + if (enum_range.begin() != enum_range.end()) { + Out << '@' << **enum_range.begin(); + } + } + } } } @@ -500,7 +520,6 @@ void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { GenLoc(D, /*IncludeOffset=*/true); - return; } bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { @@ -599,24 +618,17 @@ void USRGenerator::VisitType(QualType T) { c = 'd'; break; case BuiltinType::LongDouble: c = 'D'; break; + case BuiltinType::Float128: + c = 'Q'; break; case BuiltinType::NullPtr: c = 'n'; break; #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: #include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - case BuiltinType::OCLImage1d: - case BuiltinType::OCLImage1dArray: - case BuiltinType::OCLImage1dBuffer: - case BuiltinType::OCLImage2d: - case BuiltinType::OCLImage2dArray: - case BuiltinType::OCLImage2dDepth: - case BuiltinType::OCLImage2dArrayDepth: - case BuiltinType::OCLImage2dMSAA: - case BuiltinType::OCLImage2dArrayMSAA: - case BuiltinType::OCLImage2dMSAADepth: - case BuiltinType::OCLImage2dArrayMSAADepth: - case BuiltinType::OCLImage3d: +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: @@ -654,6 +666,11 @@ void USRGenerator::VisitType(QualType T) { T = PT->getPointeeType(); continue; } + if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) { + Out << '*'; + T = OPT->getPointeeType(); + continue; + } if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) { Out << "&&"; T = RT->getPointeeType(); @@ -688,6 +705,18 @@ void USRGenerator::VisitType(QualType T) { VisitTagDecl(TT->getDecl()); return; } + if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { + Out << '$'; + VisitObjCInterfaceDecl(OIT->getDecl()); + return; + } + if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) { + Out << 'Q'; + VisitType(OIT->getBaseType()); + for (auto *Prot : OIT->getProtocols()) + VisitObjCProtocolDecl(Prot); + return; + } if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); return; @@ -835,8 +864,9 @@ void clang::index::generateUSRForObjCMethod(StringRef Sel, OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel; } -void clang::index::generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS) { - OS << "(py)" << Prop; +void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp, + raw_ostream &OS) { + OS << (isClassProp ? "(cpy)" : "(py)") << Prop; } void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) { @@ -875,4 +905,3 @@ bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD, Out << MD->getName()->getName(); return false; } - |