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:
Argyrios Kyrtzidis 2009-07-05 22:22:19 +00:00
parent e568a9792f
commit fe37cc831b
13 changed files with 573 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -9,3 +9,4 @@ add_subdirectory(Analysis)
add_subdirectory(Rewrite)
add_subdirectory(Driver)
add_subdirectory(Frontend)
add_subdirectory(Index)

View File

@ -0,0 +1,7 @@
set(LLVM_NO_RTTI 1)
add_clang_library(clangIndex
Entity.cpp
IndexProvider.cpp
Program.cpp
)

132
clang/lib/Index/Entity.cpp Normal file
View File

@ -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);
}

View File

@ -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 &Map;
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();
}

28
clang/lib/Index/Makefile Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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