1 //===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Entity is a ASTContext-independent way to refer to declarations that are
11 // visible across translation units.
13 //===----------------------------------------------------------------------===//
15 #include "clang/Index/Entity.h"
16 #include "clang/Index/Program.h"
17 #include "ProgramImpl.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/ASTContext.h"
20 #include "clang/AST/DeclVisitor.h"
21 using namespace clang
;
24 // FIXME: Entity is really really basic currently, mostly written to work
25 // on variables and functions. Should support types and other decls eventually..
28 //===----------------------------------------------------------------------===//
30 //===----------------------------------------------------------------------===//
35 /// \brief Gets the Entity associated with a Decl.
36 class EntityGetter
: public DeclVisitor
<EntityGetter
, Entity
*> {
40 EntityGetter(ProgramImpl
&prog
) : Prog(prog
) { }
42 Entity
*get(Entity
*Parent
, DeclarationName Name
);
44 Entity
*VisitNamedDecl(NamedDecl
*D
);
45 Entity
*VisitVarDecl(VarDecl
*D
);
46 Entity
*VisitFunctionDecl(FunctionDecl
*D
);
52 Entity
*EntityGetter::get(Entity
*Parent
, DeclarationName Name
) {
53 // FIXME: Only works for DeclarationNames that are identifiers.
55 if (!Name
.isIdentifier())
58 IdentifierInfo
*II
= Name
.getAsIdentifierInfo();
62 ProgramImpl::IdEntryTy
*Id
=
63 &Prog
.getIdents().GetOrCreateValue(II
->getName(),
64 II
->getName() + II
->getLength());
66 llvm::FoldingSetNodeID ID
;
67 Entity::Profile(ID
, Parent
, Id
);
69 ProgramImpl::EntitySetTy
&Entities
= Prog
.getEntities();
71 if (Entity
*Ent
= Entities
.FindNodeOrInsertPos(ID
, InsertPos
))
74 void *Buf
= Prog
.Allocate(sizeof(Entity
));
75 Entity
*New
= new (Buf
) Entity(Parent
, Id
);
76 Entities
.InsertNode(New
, InsertPos
);
80 Entity
*EntityGetter::VisitNamedDecl(NamedDecl
*D
) {
81 // FIXME: Function declarations that are inside functions ?
82 if (!D
->getDeclContext()->isFileContext())
85 Entity
*Parent
= Visit(cast
<Decl
>(D
->getDeclContext()));
86 return get(Parent
, D
->getDeclName());
89 Entity
*EntityGetter::VisitVarDecl(VarDecl
*D
) {
90 // If it's static it cannot be referred to by another translation unit.
91 if (D
->getStorageClass() == VarDecl::Static
)
94 return VisitNamedDecl(D
);
97 Entity
*EntityGetter::VisitFunctionDecl(FunctionDecl
*D
) {
98 // If it's static it cannot be refered to by another translation unit.
99 if (D
->getStorageClass() == FunctionDecl::Static
)
102 return VisitNamedDecl(D
);
105 //===----------------------------------------------------------------------===//
106 // Entity Implementation
107 //===----------------------------------------------------------------------===//
109 /// \brief Find the Decl that can be referred to by this entity.
110 Decl
*Entity::getDecl(ASTContext
&AST
) {
112 Parent
== 0 ? AST
.getTranslationUnitDecl()
113 : cast
<DeclContext
>(Parent
->getDecl(AST
));
115 return 0; // Couldn't get the parent context.
117 ProgramImpl::IdEntryTy
*Entry
= static_cast<ProgramImpl::IdEntryTy
*>(Id
);
118 IdentifierInfo
&II
= AST
.Idents
.get(Entry
->getKeyData());
120 DeclContext::lookup_result Res
= DC
->lookup(DeclarationName(&II
));
121 for (DeclContext::lookup_iterator I
= Res
.first
, E
= Res
.second
; I
!=E
; ++I
) {
122 if (!isa
<TagDecl
>(*I
))
126 return 0; // Failed to find a decl using this Entity.
129 std::string
Entity::getPrintableName(ASTContext
&Ctx
) {
130 if (const NamedDecl
*ND
= dyn_cast_or_null
<NamedDecl
>(getDecl(Ctx
))) {
131 return ND
->getNameAsString();
133 return std::string();
136 /// \brief Get an Entity associated with the given Decl.
137 /// \returns Null if an Entity cannot refer to this Decl.
138 Entity
*Entity::get(Decl
*D
, Program
&Prog
) {
139 assert(D
&& "Passed null Decl");
140 ProgramImpl
&Impl
= *static_cast<ProgramImpl
*>(Prog
.Impl
);
141 return EntityGetter(Impl
).Visit(D
);