forked from OSchip/llvm-project
133 lines
4.1 KiB
C++
133 lines
4.1 KiB
C++
//===--- 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);
|
|
}
|