diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2009-07-21 00:07:06 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2009-07-21 00:07:06 +0000 |
commit | f7cf15ca3c9bee7c0348f549e7a8f0af32b5fa54 (patch) | |
tree | 05e1fd135984a32777ddfbd291bfdc913046d50a /lib/Index/Entity.cpp | |
parent | 07ef804f918d8aade8739a02e78c6209fd3062a9 (diff) |
Change the semantics for Entity.
Entity can now refer to declarations that are not visible outside the translation unit.
It is a wrapper of a pointer union, it's either a Decl* for declarations that don't
"cross" translation units, or an EntityImpl* which is associated with the specific "visible" Decl.
Included is a test case for handling fields across translation units.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76515 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Index/Entity.cpp')
-rw-r--r-- | lib/Index/Entity.cpp | 124 |
1 files changed, 77 insertions, 47 deletions
diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp index 7a6c05c416..feed3e4c80 100644 --- a/lib/Index/Entity.cpp +++ b/lib/Index/Entity.cpp @@ -12,9 +12,9 @@ // //===----------------------------------------------------------------------===// -#include "clang/Index/Entity.h" -#include "clang/Index/Program.h" +#include "EntityImpl.h" #include "ProgramImpl.h" +#include "clang/Index/Program.h" #include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclVisitor.h" @@ -33,99 +33,123 @@ namespace clang { namespace idx { /// \brief Gets the Entity associated with a Decl. -class EntityGetter : public DeclVisitor<EntityGetter, Entity *> { +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 VisitNamedDecl(NamedDecl *D); + Entity VisitVarDecl(VarDecl *D); + Entity VisitFunctionDecl(FunctionDecl *D); }; } } -Entity *EntityGetter::get(Entity *Parent, DeclarationName Name) { +Entity EntityGetter::VisitNamedDecl(NamedDecl *D) { + Entity Parent; + if (!D->getDeclContext()->isTranslationUnit()) { + Parent = Visit(cast<Decl>(D->getDeclContext())); + // FIXME: Anonymous structs ? + if (Parent.isInvalid()) + return Entity(); + } + if (Parent.isValid() && Parent.isInternalToTU()) + return Entity(D); + // FIXME: Only works for DeclarationNames that are identifiers. + DeclarationName Name = D->getDeclName(); + if (!Name.isIdentifier()) - return 0; + return Entity(); IdentifierInfo *II = Name.getAsIdentifierInfo(); if (!II) - return 0; + return Entity(); - ProgramImpl::IdEntryTy *Id = + EntityImpl::IdEntryTy *Id = &Prog.getIdents().GetOrCreateValue(II->getName(), II->getName() + II->getLength()); - + unsigned IdNS = D->getIdentifierNamespace(); + llvm::FoldingSetNodeID ID; - Entity::Profile(ID, Parent, Id); - + EntityImpl::Profile(ID, Parent, Id, IdNS); + 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; -} + if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos)) + return Entity(Ent); -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()); + void *Buf = Prog.Allocate(sizeof(EntityImpl)); + EntityImpl *New = new (Buf) EntityImpl(Parent, Id, IdNS); + Entities.InsertNode(New, InsertPos); + + return Entity(New); } -Entity *EntityGetter::VisitVarDecl(VarDecl *D) { +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 Entity(D); return VisitNamedDecl(D); } -Entity *EntityGetter::VisitFunctionDecl(FunctionDecl *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 Entity(D); return VisitNamedDecl(D); } //===----------------------------------------------------------------------===// -// Entity Implementation +// EntityImpl Implementation //===----------------------------------------------------------------------===// -/// \brief Find the Decl that can be referred to by this entity. -Decl *Entity::getDecl(ASTContext &AST) { +Decl *EntityImpl::getDecl(ASTContext &AST) { DeclContext *DC = - Parent == 0 ? AST.getTranslationUnitDecl() - : cast<DeclContext>(Parent->getDecl(AST)); + Parent.isInvalid() ? 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()); + IdentifierInfo &II = AST.Idents.get(Id->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)) + if ((*I)->getIdentifierNamespace() == IdNS) 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 EntityImpl::get(Decl *D, ProgramImpl &Prog) { + assert(D && "Passed null Decl"); + return EntityGetter(Prog).Visit(D); +} + +//===----------------------------------------------------------------------===// +// Entity Implementation +//===----------------------------------------------------------------------===// + +/// \brief Find the Decl that can be referred to by this entity. +Decl *Entity::getDecl(ASTContext &AST) { + if (isInvalid()) + return 0; + + if (Decl *D = Val.dyn_cast<Decl *>()) + // Check that the passed AST is actually the one that this Decl belongs to. + return (&D->getASTContext() == &AST) ? D : 0; + + return Val.get<EntityImpl *>()->getDecl(AST); +} + std::string Entity::getPrintableName(ASTContext &Ctx) { if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl(Ctx))) { return ND->getNameAsString(); @@ -135,8 +159,14 @@ std::string Entity::getPrintableName(ASTContext &Ctx) { /// \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); +Entity Entity::get(Decl *D, Program &Prog) { + if (D == 0) + return Entity(); + ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl); + return EntityImpl::get(D, ProgImpl); +} + +unsigned +llvm::DenseMapInfo<Entity>::getHashValue(Entity E) { + return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr()); } |