blob: 245fc9a5551a9cf2691b85be700f59ade5c3d933 [file] [log] [blame]
Chris Lattnerc3a65402009-07-12 22:33:12 +00001//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Entity is a ASTContext-independent way to refer to declarations that are
11// visible across translation units.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000015#include "EntityImpl.h"
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000016#include "ProgramImpl.h"
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000017#include "clang/Index/Program.h"
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000018#include "clang/Index/GlobalSelector.h"
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000019#include "clang/AST/Decl.h"
20#include "clang/AST/ASTContext.h"
21#include "clang/AST/DeclVisitor.h"
22using namespace clang;
23using namespace idx;
24
25// FIXME: Entity is really really basic currently, mostly written to work
26// on variables and functions. Should support types and other decls eventually..
27
28
29//===----------------------------------------------------------------------===//
30// EntityGetter
31//===----------------------------------------------------------------------===//
32
33namespace clang {
34namespace idx {
35
36/// \brief Gets the Entity associated with a Decl.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000037class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000038 Program &Prog;
39 ProgramImpl &ProgImpl;
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000040
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000041public:
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000042 EntityGetter(Program &prog, ProgramImpl &progImpl)
43 : Prog(prog), ProgImpl(progImpl) { }
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000044
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000045 Entity VisitNamedDecl(NamedDecl *D);
46 Entity VisitVarDecl(VarDecl *D);
47 Entity VisitFunctionDecl(FunctionDecl *D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000048};
49
50}
51}
52
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000053Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
54 Entity Parent;
55 if (!D->getDeclContext()->isTranslationUnit()) {
56 Parent = Visit(cast<Decl>(D->getDeclContext()));
57 // FIXME: Anonymous structs ?
58 if (Parent.isInvalid())
59 return Entity();
60 }
61 if (Parent.isValid() && Parent.isInternalToTU())
62 return Entity(D);
63
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000064 // FIXME: Only works for DeclarationNames that are identifiers and selectors.
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +000065 // Treats other DeclarationNames as internal Decls for now..
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000066
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000067 DeclarationName LocalName = D->getDeclName();
68 if (!LocalName)
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +000069 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000070
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000071 DeclarationName GlobName;
Argyrios Kyrtzidisdc0b11e2009-07-17 01:19:03 +000072
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000073 if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
74 IdentifierInfo *GlobII =
75 &ProgImpl.getIdents().get(II->getName(), II->getName() + II->getLength());
76 GlobName = DeclarationName(GlobII);
77 } else {
78 Selector LocalSel = LocalName.getObjCSelector();
79
80 // Treats other DeclarationNames as internal Decls for now..
81 if (LocalSel.isNull())
82 return Entity(D);
83
84 Selector GlobSel =
85 (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
86 GlobName = DeclarationName(GlobSel);
87 }
88
89 assert(GlobName);
90
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000091 unsigned IdNS = D->getIdentifierNamespace();
92
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000093 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
94 bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000095
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000096 llvm::FoldingSetNodeID ID;
97 EntityImpl::Profile(ID, Parent, GlobName, IdNS, isObjCInstanceMethod);
98
99 ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000100 void *InsertPos = 0;
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000101 if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
102 return Entity(Ent);
103
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000104 void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
105 EntityImpl *New =
106 new (Buf) EntityImpl(Parent, GlobName, IdNS, isObjCInstanceMethod);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000107 Entities.InsertNode(New, InsertPos);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000108
109 return Entity(New);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000110}
111
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000112Entity EntityGetter::VisitVarDecl(VarDecl *D) {
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000113 // If it's static it cannot be referred to by another translation unit.
114 if (D->getStorageClass() == VarDecl::Static)
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000115 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000116
117 return VisitNamedDecl(D);
118}
119
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000120Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000121 // If it's static it cannot be refered to by another translation unit.
122 if (D->getStorageClass() == FunctionDecl::Static)
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000123 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000124
125 return VisitNamedDecl(D);
126}
127
128//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000129// EntityImpl Implementation
130//===----------------------------------------------------------------------===//
131
132Decl *EntityImpl::getDecl(ASTContext &AST) {
133 DeclContext *DC =
134 Parent.isInvalid() ? AST.getTranslationUnitDecl()
135 : cast<DeclContext>(Parent.getDecl(AST));
136 if (!DC)
137 return 0; // Couldn't get the parent context.
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000138
139 DeclarationName LocalName;
140
141 if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
142 IdentifierInfo &II = AST.Idents.get(GlobII->getName(),
143 GlobII->getName() + GlobII->getLength());
144 LocalName = DeclarationName(&II);
145 } else {
146 Selector GlobSel = Name.getObjCSelector();
147 assert(!GlobSel.isNull() && "A not handled yet declaration name");
148 GlobalSelector GSel =
149 GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr());
150 LocalName = GSel.getSelector(AST);
151 }
152
153 assert(LocalName);
154
155 DeclContext::lookup_result Res = DC->lookup(LocalName);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000156 for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000157 Decl *D = *I;
158 if (D->getIdentifierNamespace() == IdNS) {
159 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
160 if (MD->isInstanceMethod() == IsObjCInstanceMethod)
161 return MD;
162 } else
163 return D;
164 }
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000165 }
166
167 return 0; // Failed to find a decl using this Entity.
168}
169
170/// \brief Get an Entity associated with the given Decl.
171/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000172Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000173 assert(D && "Passed null Decl");
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000174 return EntityGetter(Prog, ProgImpl).Visit(D);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000175}
176
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000177std::string EntityImpl::getPrintableName() {
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000178 return Name.getAsString();
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000179}
180
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000181//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000182// Entity Implementation
183//===----------------------------------------------------------------------===//
184
Argyrios Kyrtzidis1f717272009-07-21 02:10:32 +0000185Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
186
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000187/// \brief Find the Decl that can be referred to by this entity.
Zhongxing Xu6d8f56f2009-07-24 03:38:27 +0000188Decl *Entity::getDecl(ASTContext &AST) const {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000189 if (isInvalid())
190 return 0;
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000191
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000192 if (Decl *D = Val.dyn_cast<Decl *>())
193 // Check that the passed AST is actually the one that this Decl belongs to.
194 return (&D->getASTContext() == &AST) ? D : 0;
195
196 return Val.get<EntityImpl *>()->getDecl(AST);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000197}
198
Zhongxing Xuf7856432009-07-23 08:32:25 +0000199std::string Entity::getPrintableName() const {
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000200 if (isInvalid())
201 return "<< Invalid >>";
202
203 if (Decl *D = Val.dyn_cast<Decl *>()) {
204 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
205 return ND->getNameAsString();
206 else
207 return std::string();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000208 }
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000209
210 return Val.get<EntityImpl *>()->getPrintableName();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000211}
212
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000213/// \brief Get an Entity associated with the given Decl.
214/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000215Entity Entity::get(Decl *D, Program &Prog) {
216 if (D == 0)
217 return Entity();
218 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000219 return EntityImpl::get(D, Prog, ProgImpl);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000220}
221
222unsigned
223llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
224 return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000225}