From: Argyrios Kyrtzidis Date: Wed, 29 Jul 2009 23:40:14 +0000 (+0000) Subject: -Introduce the idx::Analyzer class used for getting indexing information, like finding X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7f4656eb6b60a7f3596fb26b9d5aed3731b3109e;p=clang -Introduce the idx::Analyzer class used for getting indexing information, like finding references of a declaration across translation units. -Modify the index-test tool to use it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77536 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Index/Analyzer.h b/include/clang/Index/Analyzer.h new file mode 100644 index 0000000000..90118b5173 --- /dev/null +++ b/include/clang/Index/Analyzer.h @@ -0,0 +1,51 @@ +//===--- Analyzer.h - Analysis for indexing information ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Analyzer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_ANALYZER_H +#define LLVM_CLANG_INDEX_ANALYZER_H + +namespace clang { + class Decl; + +namespace idx { + class Program; + class IndexProvider; + class TULocationHandler; + +/// \brief Provides indexing information, like finding all references of an +/// Entity across translation units. +class Analyzer { + Program &Prog; + IndexProvider &Idxer; + + Analyzer(const Analyzer&); // do not implement + Analyzer &operator=(const Analyzer &); // do not implement + +public: + explicit Analyzer(Program &prog, IndexProvider &idxer) + : Prog(prog), Idxer(idxer) { } + + /// \brief Find all TULocations for declarations of the given Decl and pass + /// them to Handler. + void FindDeclarations(Decl *D, TULocationHandler &Handler); + + /// \brief Find all TULocations for references of the given Decl and pass + /// them to Handler. + void FindReferences(Decl *D, TULocationHandler &Handler); +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/lib/Index/Analyzer.cpp b/lib/Index/Analyzer.cpp new file mode 100644 index 0000000000..bd1d62c668 --- /dev/null +++ b/lib/Index/Analyzer.cpp @@ -0,0 +1,104 @@ +//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Analyzer interface. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/Analyzer.h" +#include "clang/Index/Entity.h" +#include "clang/Index/TranslationUnit.h" +#include "clang/Index/Handlers.h" +#include "clang/Index/ASTLocation.h" +#include "clang/Index/DeclReferenceMap.h" +#include "clang/Index/IndexProvider.h" +#include "clang/AST/Decl.h" +#include "llvm/Support/Compiler.h" +using namespace clang; +using namespace idx; + +namespace { + +//===----------------------------------------------------------------------===// +// DeclEntityAnalyzer Implementation +//===----------------------------------------------------------------------===// + +class VISIBILITY_HIDDEN DeclEntityAnalyzer : public TranslationUnitHandler { + Entity Ent; + TULocationHandler &TULocHandler; + +public: + DeclEntityAnalyzer(Entity ent, TULocationHandler &handler) + : Ent(ent), TULocHandler(handler) { } + + virtual void Handle(TranslationUnit *TU) { + assert(TU && "Passed null translation unit"); + + Decl *D = Ent.getDecl(TU->getASTContext()); + assert(D && "Couldn't resolve Entity"); + + for (Decl::redecl_iterator I = D->redecls_begin(), + E = D->redecls_end(); I != E; ++I) + TULocHandler.Handle(TULocation(TU, ASTLocation(*I))); + } +}; + +//===----------------------------------------------------------------------===// +// RefEntityAnalyzer Implementation +//===----------------------------------------------------------------------===// + +class VISIBILITY_HIDDEN RefEntityAnalyzer : public TranslationUnitHandler { + Entity Ent; + TULocationHandler &TULocHandler; + +public: + RefEntityAnalyzer(Entity ent, TULocationHandler &handler) + : Ent(ent), TULocHandler(handler) { } + + virtual void Handle(TranslationUnit *TU) { + assert(TU && "Passed null translation unit"); + + Decl *D = Ent.getDecl(TU->getASTContext()); + assert(D && "Couldn't resolve Entity"); + NamedDecl *ND = dyn_cast(D); + if (!ND) + return; + + DeclReferenceMap &RefMap = TU->getDeclReferenceMap(); + for (DeclReferenceMap::astlocation_iterator + I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I) + TULocHandler.Handle(TULocation(TU, ASTLocation(*I))); + } +}; + +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Analyzer Implementation +//===----------------------------------------------------------------------===// + +void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) { + assert(D && "Passed null declaration"); + Entity Ent = Entity::get(D, Prog); + if (Ent.isInvalid()) + return; + + DeclEntityAnalyzer DEA(Ent, Handler); + Idxer.GetTranslationUnitsFor(Ent, DEA); +} + +void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) { + assert(D && "Passed null declaration"); + Entity Ent = Entity::get(D, Prog); + if (Ent.isInvalid()) + return; + + RefEntityAnalyzer REA(Ent, Handler); + Idxer.GetTranslationUnitsFor(Ent, REA); +} diff --git a/tools/index-test/index-test.cpp b/tools/index-test/index-test.cpp index 5fc6269f7a..a0d60f7b49 100644 --- a/tools/index-test/index-test.cpp +++ b/tools/index-test/index-test.cpp @@ -39,6 +39,7 @@ #include "clang/Index/ASTLocation.h" #include "clang/Index/DeclReferenceMap.h" #include "clang/Index/Handlers.h" +#include "clang/Index/Analyzer.h" #include "clang/Index/Utils.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CommandLineSourceLoc.h" @@ -100,73 +101,57 @@ DisableFree("disable-free", static bool HadErrors = false; -static void ProcessDecl(Decl *D) { - assert(D); +static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) { + assert(ASTLoc.isValid()); + + Decl *D = ASTLoc.getReferencedDecl(); + if (D == 0) { + llvm::errs() << "Error: Couldn't get referenced Decl for the ASTLocation\n"; + HadErrors = true; + return; + } + llvm::raw_ostream &OS = llvm::outs(); - + typedef Storing ResultsTy; + ResultsTy Results; + + Analyzer Analyz(Idxer.getProgram(), Idxer); + switch (ProgAction) { default: assert(0); case PrintRefs: { - NamedDecl *ND = dyn_cast(D); - if (!ND) - return; - - DeclReferenceMap RefMap(ND->getASTContext()); - for (DeclReferenceMap::astlocation_iterator - I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I) + Analyz.FindReferences(D, Results); + for (ResultsTy::iterator + I = Results.begin(), E = Results.end(); I != E; ++I) I->print(OS); break; } - - case PrintDefs: { - const Decl *DefD = 0; - if (FunctionDecl *FD = dyn_cast(D)) { - const FunctionDecl *DFD = 0; - FD->getBody(DFD); - DefD = DFD; - } else if (VarDecl *VD = dyn_cast(D)) { - const VarDecl *DVD = 0; - VD->getDefinition(DVD); - DefD = DVD; - } - if (DefD) - ASTLocation(DefD).print(OS); - break; - } - - case PrintDecls : - for (Decl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); I != E; ++I) - ASTLocation(*I).print(OS); + case PrintDecls: { + Analyz.FindDeclarations(D, Results); + for (ResultsTy::iterator + I = Results.begin(), E = Results.end(); I != E; ++I) + I->print(OS); break; - } -} -static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) { - assert(ASTLoc.isValid()); + case PrintDefs:{ + Analyz.FindDeclarations(D, Results); + for (ResultsTy::iterator + I = Results.begin(), E = Results.end(); I != E; ++I) { + const Decl *D = I->getDecl(); + bool isDef = false; + if (const FunctionDecl *FD = dyn_cast(D)) + isDef = FD->isThisDeclarationADefinition(); + else if (const VarDecl *VD = dyn_cast(D)) + isDef = VD->getInit() != 0; - Decl *D = ASTLoc.getReferencedDecl(); - if (D == 0) { - llvm::errs() << "Error: Couldn't get referenced Decl for the ASTLocation\n"; - HadErrors = true; - return; + if (isDef) + I->print(OS); + } + break; } - Entity Ent = Entity::get(D, Idxer.getProgram()); - if (Ent.isInvalid() || Ent.isInternalToTU()) - return ProcessDecl(D); - - Storing TURes; - Idxer.GetTranslationUnitsFor(Ent, TURes); - - // Find the "same" Decl in other translation units and print information. - for (Storing::iterator - I = TURes.begin(), E = TURes.end(); I != E; ++I) { - Decl *OtherD = Ent.getDecl((*I)->getASTContext()); - assert(OtherD && "Couldn't resolve Entity"); - ProcessDecl(OtherD); } }