forked from OSchip/llvm-project
Introduce the 'Index' library.
Its purpose is to provide the basic infrastructure for cross-translation-unit analysis like indexing, refactoring, etc. Currently it is very "primitive" and with no type-names support. It can provide functionality like "show me all references of this function from these translation units". llvm-svn: 74802
This commit is contained in:
parent
e568a9792f
commit
fe37cc831b
|
@ -0,0 +1,70 @@
|
|||
//===--- Entity.h - Cross-translation-unit "token" for decls ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Entity is a ASTContext-independent way to refer to declarations that are
|
||||
// visible across translation units.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_ENTITY_H
|
||||
#define LLVM_CLANG_INDEX_ENTITY_H
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
|
||||
namespace idx {
|
||||
class Program;
|
||||
|
||||
/// \brief A ASTContext-independent way to refer to declarations that are
|
||||
/// visible across translation units.
|
||||
///
|
||||
/// Entity is basically the link for declarations that are semantically the same
|
||||
/// in multiple ASTContexts. A client will convert a Decl into an Entity and
|
||||
/// later use that Entity to find the "same" Decl into another ASTContext.
|
||||
///
|
||||
/// An Entity may only refer to declarations that can be visible by multiple
|
||||
/// translation units, e.g. a static function cannot have an Entity associated
|
||||
/// with it.
|
||||
///
|
||||
/// Entities are uniqued so pointer equality can be used (note that the same
|
||||
/// Program object should be used when getting Entities).
|
||||
///
|
||||
class Entity : public llvm::FoldingSetNode {
|
||||
public:
|
||||
/// \brief Find the Decl that can be referred to by this entity.
|
||||
Decl *getDecl(ASTContext &AST);
|
||||
|
||||
/// \brief Get an Entity associated with the given Decl.
|
||||
/// \returns Null if an Entity cannot refer to this Decl.
|
||||
static Entity *get(Decl *D, Program &Prog);
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
Profile(ID, Parent, Id);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, Entity *Parent, void *Id) {
|
||||
ID.AddPointer(Parent);
|
||||
ID.AddPointer(Id);
|
||||
}
|
||||
|
||||
private:
|
||||
Entity *Parent;
|
||||
void *Id;
|
||||
|
||||
Entity(Entity *parent, void *id) : Parent(parent), Id(id) { }
|
||||
friend class EntityGetter;
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
//===--- EntityHandler.h - Interface for receiving entities -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Abstract interface for receiving Entities.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_ENTITYHANDLER_H
|
||||
#define LLVM_CLANG_INDEX_ENTITYHANDLER_H
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class Entity;
|
||||
|
||||
/// \brief Abstract interface for receiving Entities.
|
||||
class EntityHandler {
|
||||
public:
|
||||
virtual ~EntityHandler();
|
||||
virtual void HandleEntity(Entity *Ent) { }
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
//===--- IndexProvider.h - Map of entities to translation units -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSaE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Maps Entities to TranslationUnits
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_INDEXPROVIDER_H
|
||||
#define LLVM_CLANG_INDEX_INDEXPROVIDER_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include <map>
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class Program;
|
||||
class Entity;
|
||||
class TranslationUnit;
|
||||
|
||||
/// \brief Maps Entities to TranslationUnits.
|
||||
class IndexProvider {
|
||||
typedef llvm::SmallPtrSet<TranslationUnit *, 4> TUSetTy;
|
||||
typedef std::map<Entity *, TUSetTy> MapTy;
|
||||
class Indexer;
|
||||
|
||||
public:
|
||||
explicit IndexProvider(Program &prog) : Prog(prog) { }
|
||||
|
||||
Program &getProgram() const { return Prog; }
|
||||
|
||||
/// \brief Find all Entities and map them to the given translation unit.
|
||||
void IndexAST(TranslationUnit *TU);
|
||||
|
||||
typedef TUSetTy::iterator translation_unit_iterator;
|
||||
|
||||
translation_unit_iterator translation_units_begin(Entity *Ent) const;
|
||||
translation_unit_iterator translation_units_end(Entity *Ent) const;
|
||||
bool translation_units_empty(Entity *Ent) const;
|
||||
|
||||
private:
|
||||
Program &Prog;
|
||||
mutable MapTy Map;
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
//===--- Program.h - Entity originator and misc -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Storage for Entities and utility functions
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_PROGRAM_H
|
||||
#define LLVM_CLANG_INDEX_PROGRAM_H
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
|
||||
namespace idx {
|
||||
class EntityHandler;
|
||||
|
||||
/// \brief Repository for Entities.
|
||||
class Program {
|
||||
void *Impl;
|
||||
|
||||
Program(const Program&); // do not implement
|
||||
Program &operator=(const Program &); // do not implement
|
||||
friend class Entity;
|
||||
|
||||
public:
|
||||
Program();
|
||||
~Program();
|
||||
|
||||
/// \brief Traverses the AST and passes all the entities to the Handler.
|
||||
void FindEntities(ASTContext &Ctx, EntityHandler *Handler);
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
//===--- TranslationUnit.h - Interface for a translation unit ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSaE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Abstract interface for a translation unit
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
|
||||
#define LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
|
||||
namespace idx {
|
||||
|
||||
/// \brief Abstract interface for a translation unit.
|
||||
class TranslationUnit {
|
||||
public:
|
||||
virtual ~TranslationUnit();
|
||||
virtual ASTContext &getASTContext() = 0;
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -9,3 +9,4 @@ add_subdirectory(Analysis)
|
|||
add_subdirectory(Rewrite)
|
||||
add_subdirectory(Driver)
|
||||
add_subdirectory(Frontend)
|
||||
add_subdirectory(Index)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
add_clang_library(clangIndex
|
||||
Entity.cpp
|
||||
IndexProvider.cpp
|
||||
Program.cpp
|
||||
)
|
|
@ -0,0 +1,132 @@
|
|||
//===--- Entity.h - Cross-translation-unit "token" for decls ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Entity is a ASTContext-independent way to refer to declarations that are
|
||||
// visible across translation units.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "clang/Index/Program.h"
|
||||
#include "ProgramImpl.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
// FIXME: Entity is really really basic currently, mostly written to work
|
||||
// on variables and functions. Should support types and other decls eventually..
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// EntityGetter
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace clang {
|
||||
namespace idx {
|
||||
|
||||
/// \brief Gets the Entity associated with a Decl.
|
||||
class EntityGetter : public DeclVisitor<EntityGetter, Entity *> {
|
||||
ProgramImpl &Prog;
|
||||
|
||||
public:
|
||||
EntityGetter(ProgramImpl &prog) : Prog(prog) { }
|
||||
|
||||
Entity *get(Entity *Parent, DeclarationName Name);
|
||||
|
||||
Entity *VisitNamedDecl(NamedDecl *D);
|
||||
Entity *VisitVarDecl(VarDecl *D);
|
||||
Entity *VisitFunctionDecl(FunctionDecl *D);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Entity *EntityGetter::get(Entity *Parent, DeclarationName Name) {
|
||||
// FIXME: Only works for DeclarationNames that are identifiers.
|
||||
|
||||
if (!Name.isIdentifier())
|
||||
return 0;
|
||||
|
||||
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
||||
ProgramImpl::IdEntryTy *Id =
|
||||
&Prog.getIdents().GetOrCreateValue(II->getName(),
|
||||
II->getName() + II->getLength());
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
Entity::Profile(ID, Parent, Id);
|
||||
|
||||
ProgramImpl::EntitySetTy &Entities = Prog.getEntities();
|
||||
void *InsertPos = 0;
|
||||
if (Entity *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return Ent;
|
||||
|
||||
void *Buf = Prog.Allocate(sizeof(Entity));
|
||||
Entity *New = new (Buf) Entity(Parent, Id);
|
||||
Entities.InsertNode(New, InsertPos);
|
||||
return New;
|
||||
}
|
||||
|
||||
Entity *EntityGetter::VisitNamedDecl(NamedDecl *D) {
|
||||
// FIXME: Function declarations that are inside functions ?
|
||||
if (!D->getDeclContext()->isFileContext())
|
||||
return 0;
|
||||
|
||||
Entity *Parent = Visit(cast<Decl>(D->getDeclContext()));
|
||||
return get(Parent, D->getDeclName());
|
||||
}
|
||||
|
||||
Entity *EntityGetter::VisitVarDecl(VarDecl *D) {
|
||||
// If it's static it cannot be referred to by another translation unit.
|
||||
if (D->getStorageClass() == VarDecl::Static)
|
||||
return 0;
|
||||
|
||||
return VisitNamedDecl(D);
|
||||
}
|
||||
|
||||
Entity *EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
// If it's static it cannot be refered to by another translation unit.
|
||||
if (D->getStorageClass() == FunctionDecl::Static)
|
||||
return 0;
|
||||
|
||||
return VisitNamedDecl(D);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Entity Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Find the Decl that can be referred to by this entity.
|
||||
Decl *Entity::getDecl(ASTContext &AST) {
|
||||
DeclContext *DC =
|
||||
Parent == 0 ? AST.getTranslationUnitDecl()
|
||||
: cast<DeclContext>(Parent->getDecl(AST));
|
||||
if (!DC)
|
||||
return 0; // Couldn't get the parent context.
|
||||
|
||||
ProgramImpl::IdEntryTy *Entry = static_cast<ProgramImpl::IdEntryTy *>(Id);
|
||||
IdentifierInfo &II = AST.Idents.get(Entry->getKeyData());
|
||||
|
||||
DeclContext::lookup_result Res = DC->lookup(DeclarationName(&II));
|
||||
for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
|
||||
if (!isa<TagDecl>(*I))
|
||||
return *I;
|
||||
}
|
||||
|
||||
return 0; // Failed to find a decl using this Entity.
|
||||
}
|
||||
|
||||
/// \brief Get an Entity associated with the given Decl.
|
||||
/// \returns Null if an Entity cannot refer to this Decl.
|
||||
Entity *Entity::get(Decl *D, Program &Prog) {
|
||||
assert(D && "Passed null Decl");
|
||||
ProgramImpl &Impl = *static_cast<ProgramImpl*>(Prog.Impl);
|
||||
return EntityGetter(Impl).Visit(D);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
//===--- IndexProvider.h - Map of entities to translation units -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSaE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Maps Entities to TranslationUnits
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/IndexProvider.h"
|
||||
#include "clang/Index/Program.h"
|
||||
#include "clang/Index/EntityHandler.h"
|
||||
#include "clang/Index/TranslationUnit.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
class IndexProvider::Indexer : public EntityHandler {
|
||||
TranslationUnit *TU;
|
||||
MapTy ⤅
|
||||
|
||||
public:
|
||||
Indexer(TranslationUnit *tu, MapTy &map) : TU(tu), Map(map) { }
|
||||
|
||||
virtual void HandleEntity(Entity *Ent) {
|
||||
MapTy::iterator I = Map.find(Ent);
|
||||
if (I != Map.end()) {
|
||||
I->second.insert(TU);
|
||||
return;
|
||||
}
|
||||
|
||||
Map[Ent].insert(TU);
|
||||
}
|
||||
};
|
||||
|
||||
void IndexProvider::IndexAST(TranslationUnit *TU) {
|
||||
Indexer Idx(TU, Map);
|
||||
Prog.FindEntities(TU->getASTContext(), &Idx);
|
||||
}
|
||||
|
||||
IndexProvider::translation_unit_iterator
|
||||
IndexProvider::translation_units_begin(Entity *Ent) const {
|
||||
MapTy::iterator I = Map.find(Ent);
|
||||
if (I == Map.end())
|
||||
return translation_unit_iterator(0);
|
||||
|
||||
return I->second.begin();
|
||||
}
|
||||
|
||||
IndexProvider::translation_unit_iterator
|
||||
IndexProvider::translation_units_end(Entity *Ent) const {
|
||||
MapTy::iterator I = Map.find(Ent);
|
||||
if (I == Map.end())
|
||||
return translation_unit_iterator(0);
|
||||
|
||||
return I->second.end();
|
||||
}
|
||||
|
||||
bool IndexProvider::translation_units_empty(Entity *Ent) const {
|
||||
MapTy::iterator I = Map.find(Ent);
|
||||
if (I == Map.end())
|
||||
return true;
|
||||
|
||||
return I->second.begin() == I->second.end();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
##===- clang/lib/Index/Makefile ----------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This implements the Indexer library for the C-Language front-end.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL = ../../../..
|
||||
include $(LEVEL)/Makefile.config
|
||||
|
||||
LIBRARYNAME := clangIndex
|
||||
BUILD_ARCHIVE = 1
|
||||
CXXFLAGS = -fno-rtti
|
||||
|
||||
ifeq ($(ARCH),PowerPC)
|
||||
CXXFLAGS += -maltivec
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
//===--- Program.h - Entity originator and misc -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Storage for Entities and utility functions
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/Program.h"
|
||||
#include "ProgramImpl.h"
|
||||
#include "clang/Index/EntityHandler.h"
|
||||
#include "clang/Index/TranslationUnit.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
// Out-of-line to give the virtual tables a home.
|
||||
EntityHandler::~EntityHandler() { }
|
||||
TranslationUnit::~TranslationUnit() { }
|
||||
|
||||
Program::Program() : Impl(new ProgramImpl()) { }
|
||||
|
||||
Program::~Program() {
|
||||
delete static_cast<ProgramImpl *>(Impl);
|
||||
}
|
||||
|
||||
static void FindEntitiesInDC(DeclContext *DC, Program &Prog, EntityHandler *Handler) {
|
||||
for (DeclContext::decl_iterator
|
||||
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
|
||||
Entity *Ent = Entity::get(*I, Prog);
|
||||
if (Ent)
|
||||
Handler->HandleEntity(Ent);
|
||||
if (DeclContext *SubDC = dyn_cast<DeclContext>(*I))
|
||||
FindEntitiesInDC(SubDC, Prog, Handler);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Traverses the AST and passes all the entities to the Handler.
|
||||
void Program::FindEntities(ASTContext &Ctx, EntityHandler *Handler) {
|
||||
FindEntitiesInDC(Ctx.getTranslationUnitDecl(), *this, Handler);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
//===--- ProgramImpl.h - Internal Program implementation---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Internal implementation for the Program class
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_PROGRAMIMPL_H
|
||||
#define LLVM_CLANG_INDEX_PROGRAMIMPL_H
|
||||
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class EntityListener;
|
||||
|
||||
class ProgramImpl {
|
||||
public:
|
||||
typedef llvm::FoldingSet<Entity> EntitySetTy;
|
||||
typedef llvm::StringMapEntry<char> IdEntryTy;
|
||||
|
||||
private:
|
||||
llvm::FoldingSet<Entity> Entities;
|
||||
llvm::StringSet<> Idents;
|
||||
llvm::BumpPtrAllocator BumpAlloc;
|
||||
|
||||
ProgramImpl(const ProgramImpl&); // do not implement
|
||||
ProgramImpl &operator=(const ProgramImpl &); // do not implement
|
||||
|
||||
public:
|
||||
ProgramImpl() { }
|
||||
|
||||
llvm::FoldingSet<Entity> &getEntities() { return Entities; }
|
||||
llvm::StringSet<> &getIdents() { return Idents; }
|
||||
|
||||
void *Allocate(unsigned Size, unsigned Align = 8) {
|
||||
return BumpAlloc.Allocate(Size, Align);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -9,7 +9,7 @@
|
|||
LEVEL = ../../..
|
||||
|
||||
PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis Rewrite \
|
||||
Frontend Driver
|
||||
Frontend Index Driver
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
|
|
Loading…
Reference in New Issue