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 "EntityImpl.h"
16 #include "ProgramImpl.h"
17 #include "clang/Index/Program.h"
18 #include "clang/Index/GlobalSelector.h"
19 #include "clang/AST/Decl.h"
20 #include "clang/AST/ASTContext.h"
21 #include "clang/AST/DeclVisitor.h"
22 using namespace clang
;
25 // FIXME: Entity is really really basic currently, mostly written to work
26 // on variables and functions. Should support types and other decls eventually..
29 //===----------------------------------------------------------------------===//
31 //===----------------------------------------------------------------------===//
36 /// \brief Gets the Entity associated with a Decl.
37 class EntityGetter
: public DeclVisitor
<EntityGetter
, Entity
> {
39 ProgramImpl
&ProgImpl
;
42 EntityGetter(Program
&prog
, ProgramImpl
&progImpl
)
43 : Prog(prog
), ProgImpl(progImpl
) { }
46 Entity
getEntity(Entity Parent
, DeclarationName Name
,
47 unsigned IdNS
, bool isObjCInstanceMethod
);
49 // Get an Entity associated with the name in the global namespace.
50 Entity
getGlobalEntity(llvm::StringRef Name
);
52 Entity
VisitNamedDecl(NamedDecl
*D
);
53 Entity
VisitVarDecl(VarDecl
*D
);
54 Entity
VisitFieldDecl(FieldDecl
*D
);
55 Entity
VisitFunctionDecl(FunctionDecl
*D
);
56 Entity
VisitTypeDecl(TypeDecl
*D
);
62 Entity
EntityGetter::getEntity(Entity Parent
, DeclarationName Name
,
63 unsigned IdNS
, bool isObjCInstanceMethod
) {
64 llvm::FoldingSetNodeID ID
;
65 EntityImpl::Profile(ID
, Parent
, Name
, IdNS
, isObjCInstanceMethod
);
67 ProgramImpl::EntitySetTy
&Entities
= ProgImpl
.getEntities();
69 if (EntityImpl
*Ent
= Entities
.FindNodeOrInsertPos(ID
, InsertPos
))
72 void *Buf
= ProgImpl
.Allocate(sizeof(EntityImpl
));
74 new (Buf
) EntityImpl(Parent
, Name
, IdNS
, isObjCInstanceMethod
);
75 Entities
.InsertNode(New
, InsertPos
);
80 Entity
EntityGetter::getGlobalEntity(llvm::StringRef Name
) {
81 IdentifierInfo
*II
= &ProgImpl
.getIdents().get(Name
);
82 DeclarationName
GlobName(II
);
83 unsigned IdNS
= Decl::IDNS_Ordinary
;
84 return getEntity(Entity(), GlobName
, IdNS
, false);
87 Entity
EntityGetter::VisitNamedDecl(NamedDecl
*D
) {
89 if (!D
->getDeclContext()->isTranslationUnit()) {
90 Parent
= Visit(cast
<Decl
>(D
->getDeclContext()));
91 // FIXME: Anonymous structs ?
92 if (Parent
.isInvalid())
95 if (Parent
.isValid() && Parent
.isInternalToTU())
98 // FIXME: Only works for DeclarationNames that are identifiers and selectors.
99 // Treats other DeclarationNames as internal Decls for now..
101 DeclarationName LocalName
= D
->getDeclName();
105 DeclarationName GlobName
;
107 if (IdentifierInfo
*II
= LocalName
.getAsIdentifierInfo()) {
108 IdentifierInfo
*GlobII
= &ProgImpl
.getIdents().get(II
->getName());
109 GlobName
= DeclarationName(GlobII
);
111 Selector LocalSel
= LocalName
.getObjCSelector();
113 // Treats other DeclarationNames as internal Decls for now..
114 if (LocalSel
.isNull())
118 (uintptr_t)GlobalSelector::get(LocalSel
, Prog
).getAsOpaquePtr();
119 GlobName
= DeclarationName(GlobSel
);
124 unsigned IdNS
= D
->getIdentifierNamespace();
126 ObjCMethodDecl
*MD
= dyn_cast
<ObjCMethodDecl
>(D
);
127 bool isObjCInstanceMethod
= MD
&& MD
->isInstanceMethod();
128 return getEntity(Parent
, GlobName
, IdNS
, isObjCInstanceMethod
);
131 Entity
EntityGetter::VisitVarDecl(VarDecl
*D
) {
132 // Local variables have no linkage, make invalid Entities.
133 if (D
->hasLocalStorage())
136 // If it's static it cannot be referred to by another translation unit.
137 if (D
->getStorageClass() == SC_Static
)
140 return VisitNamedDecl(D
);
143 Entity
EntityGetter::VisitFunctionDecl(FunctionDecl
*D
) {
144 // If it's static it cannot be refered to by another translation unit.
145 if (D
->getStorageClass() == SC_Static
)
148 return VisitNamedDecl(D
);
151 Entity
EntityGetter::VisitFieldDecl(FieldDecl
*D
) {
152 // Make FieldDecl an invalid Entity since it has no linkage.
156 Entity
EntityGetter::VisitTypeDecl(TypeDecl
*D
) {
157 // Although in C++ class name has external linkage, usually the definition of
158 // the class is available in the same translation unit when it's needed. So we
159 // make all of them invalid Entity.
163 //===----------------------------------------------------------------------===//
164 // EntityImpl Implementation
165 //===----------------------------------------------------------------------===//
167 Decl
*EntityImpl::getDecl(ASTContext
&AST
) {
169 Parent
.isInvalid() ? AST
.getTranslationUnitDecl()
170 : cast
<DeclContext
>(Parent
.getDecl(AST
));
172 return 0; // Couldn't get the parent context.
174 DeclarationName LocalName
;
176 if (IdentifierInfo
*GlobII
= Name
.getAsIdentifierInfo()) {
177 IdentifierInfo
&II
= AST
.Idents
.get(GlobII
->getName());
178 LocalName
= DeclarationName(&II
);
180 Selector GlobSel
= Name
.getObjCSelector();
181 assert(!GlobSel
.isNull() && "A not handled yet declaration name");
182 GlobalSelector GSel
=
183 GlobalSelector::getFromOpaquePtr(GlobSel
.getAsOpaquePtr());
184 LocalName
= GSel
.getSelector(AST
);
189 DeclContext::lookup_result Res
= DC
->lookup(LocalName
);
190 for (DeclContext::lookup_iterator I
= Res
.first
, E
= Res
.second
; I
!=E
; ++I
) {
192 if (D
->getIdentifierNamespace() == IdNS
) {
193 if (ObjCMethodDecl
*MD
= dyn_cast
<ObjCMethodDecl
>(D
)) {
194 if (MD
->isInstanceMethod() == IsObjCInstanceMethod
)
201 return 0; // Failed to find a decl using this Entity.
204 /// \brief Get an Entity associated with the given Decl.
205 /// \returns Null if an Entity cannot refer to this Decl.
206 Entity
EntityImpl::get(Decl
*D
, Program
&Prog
, ProgramImpl
&ProgImpl
) {
207 assert(D
&& "Passed null Decl");
208 return EntityGetter(Prog
, ProgImpl
).Visit(D
);
211 /// \brief Get an Entity associated with a global name.
212 Entity
EntityImpl::get(llvm::StringRef Name
, Program
&Prog
,
213 ProgramImpl
&ProgImpl
) {
214 return EntityGetter(Prog
, ProgImpl
).getGlobalEntity(Name
);
217 std::string
EntityImpl::getPrintableName() {
218 return Name
.getAsString();
221 //===----------------------------------------------------------------------===//
222 // Entity Implementation
223 //===----------------------------------------------------------------------===//
225 Entity::Entity(Decl
*D
) : Val(D
->getCanonicalDecl()) { }
227 /// \brief Find the Decl that can be referred to by this entity.
228 Decl
*Entity::getDecl(ASTContext
&AST
) const {
232 if (Decl
*D
= Val
.dyn_cast
<Decl
*>())
233 // Check that the passed AST is actually the one that this Decl belongs to.
234 return (&D
->getASTContext() == &AST
) ? D
: 0;
236 return Val
.get
<EntityImpl
*>()->getDecl(AST
);
239 std::string
Entity::getPrintableName() const {
241 return "<< Invalid >>";
243 if (Decl
*D
= Val
.dyn_cast
<Decl
*>()) {
244 if (NamedDecl
*ND
= dyn_cast
<NamedDecl
>(D
))
245 return ND
->getNameAsString();
247 return std::string();
250 return Val
.get
<EntityImpl
*>()->getPrintableName();
253 /// \brief Get an Entity associated with the given Decl.
254 /// \returns Null if an Entity cannot refer to this Decl.
255 Entity
Entity::get(Decl
*D
, Program
&Prog
) {
258 ProgramImpl
&ProgImpl
= *static_cast<ProgramImpl
*>(Prog
.Impl
);
259 return EntityImpl::get(D
, Prog
, ProgImpl
);
262 Entity
Entity::get(llvm::StringRef Name
, Program
&Prog
) {
263 ProgramImpl
&ProgImpl
= *static_cast<ProgramImpl
*>(Prog
.Impl
);
264 return EntityImpl::get(Name
, Prog
, ProgImpl
);
268 llvm::DenseMapInfo
<Entity
>::getHashValue(Entity E
) {
269 return DenseMapInfo
<void*>::getHashValue(E
.getAsOpaquePtr());