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".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74802 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
new file mode 100644
index 0000000..90b6001
--- /dev/null
+++ b/lib/Index/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangIndex
+ Entity.cpp
+ IndexProvider.cpp
+ Program.cpp
+ )
diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp
new file mode 100644
index 0000000..c1d8702
--- /dev/null
+++ b/lib/Index/Entity.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);
+}
diff --git a/lib/Index/IndexProvider.cpp b/lib/Index/IndexProvider.cpp
new file mode 100644
index 0000000..45719bb
--- /dev/null
+++ b/lib/Index/IndexProvider.cpp
@@ -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();
+}
diff --git a/lib/Index/Makefile b/lib/Index/Makefile
new file mode 100644
index 0000000..7dee87f
--- /dev/null
+++ b/lib/Index/Makefile
@@ -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
+
diff --git a/lib/Index/Program.cpp b/lib/Index/Program.cpp
new file mode 100644
index 0000000..22fad9f
--- /dev/null
+++ b/lib/Index/Program.cpp
@@ -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);
+}
diff --git a/lib/Index/ProgramImpl.h b/lib/Index/ProgramImpl.h
new file mode 100644
index 0000000..52f153f
--- /dev/null
+++ b/lib/Index/ProgramImpl.h
@@ -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