blob: 7a247191bee6914b45be33084b7454129d18d350 [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) { }
Mike Stump1eb44332009-09-09 15:08:12 +000044
Zhongxing Xudc01a152010-07-06 05:55:13 +000045 // Get an Entity.
46 Entity getEntity(Entity Parent, DeclarationName Name,
47 unsigned IdNS, bool isObjCInstanceMethod);
48
49 // Get an Entity associated with the name in the global namespace.
50 Entity getGlobalEntity(llvm::StringRef Name);
51
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000052 Entity VisitNamedDecl(NamedDecl *D);
53 Entity VisitVarDecl(VarDecl *D);
Zhongxing Xu139d0b32010-07-05 01:44:14 +000054 Entity VisitFieldDecl(FieldDecl *D);
Mike Stump1eb44332009-09-09 15:08:12 +000055 Entity VisitFunctionDecl(FunctionDecl *D);
Zhongxing Xuc8822e02010-07-05 02:35:40 +000056 Entity VisitTypeDecl(TypeDecl *D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000057};
58
59}
60}
61
Zhongxing Xudc01a152010-07-06 05:55:13 +000062Entity EntityGetter::getEntity(Entity Parent, DeclarationName Name,
63 unsigned IdNS, bool isObjCInstanceMethod) {
64 llvm::FoldingSetNodeID ID;
65 EntityImpl::Profile(ID, Parent, Name, IdNS, isObjCInstanceMethod);
66
67 ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
68 void *InsertPos = 0;
69 if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
70 return Entity(Ent);
71
72 void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
73 EntityImpl *New =
74 new (Buf) EntityImpl(Parent, Name, IdNS, isObjCInstanceMethod);
75 Entities.InsertNode(New, InsertPos);
76
77 return Entity(New);
78}
79
80Entity 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);
85}
86
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000087Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
88 Entity Parent;
89 if (!D->getDeclContext()->isTranslationUnit()) {
90 Parent = Visit(cast<Decl>(D->getDeclContext()));
91 // FIXME: Anonymous structs ?
92 if (Parent.isInvalid())
93 return Entity();
94 }
95 if (Parent.isValid() && Parent.isInternalToTU())
96 return Entity(D);
97
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000098 // FIXME: Only works for DeclarationNames that are identifiers and selectors.
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +000099 // Treats other DeclarationNames as internal Decls for now..
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000100
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000101 DeclarationName LocalName = D->getDeclName();
102 if (!LocalName)
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +0000103 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000104
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000105 DeclarationName GlobName;
Argyrios Kyrtzidisdc0b11e2009-07-17 01:19:03 +0000106
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000107 if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
Kovarththanan Rajaratnam2781deb2010-03-12 09:33:31 +0000108 IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000109 GlobName = DeclarationName(GlobII);
110 } else {
111 Selector LocalSel = LocalName.getObjCSelector();
112
113 // Treats other DeclarationNames as internal Decls for now..
114 if (LocalSel.isNull())
115 return Entity(D);
Mike Stump1eb44332009-09-09 15:08:12 +0000116
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000117 Selector GlobSel =
118 (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
119 GlobName = DeclarationName(GlobSel);
120 }
Mike Stump1eb44332009-09-09 15:08:12 +0000121
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000122 assert(GlobName);
123
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000124 unsigned IdNS = D->getIdentifierNamespace();
125
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000126 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
127 bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
Zhongxing Xudc01a152010-07-06 05:55:13 +0000128 return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000129}
130
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000131Entity EntityGetter::VisitVarDecl(VarDecl *D) {
Zhongxing Xu6c47a9b2010-07-06 01:20:49 +0000132 // Local variables have no linkage, make invalid Entities.
133 if (D->hasLocalStorage())
134 return Entity();
135
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000136 // If it's static it cannot be referred to by another translation unit.
137 if (D->getStorageClass() == VarDecl::Static)
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000138 return Entity(D);
Mike Stump1eb44332009-09-09 15:08:12 +0000139
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000140 return VisitNamedDecl(D);
141}
142
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000143Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000144 // If it's static it cannot be refered to by another translation unit.
145 if (D->getStorageClass() == FunctionDecl::Static)
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000146 return Entity(D);
Mike Stump1eb44332009-09-09 15:08:12 +0000147
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000148 return VisitNamedDecl(D);
149}
150
Zhongxing Xu139d0b32010-07-05 01:44:14 +0000151Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
Zhongxing Xu423030c2010-07-05 02:31:16 +0000152 // Make FieldDecl an invalid Entity since it has no linkage.
153 return Entity();
Zhongxing Xu139d0b32010-07-05 01:44:14 +0000154}
155
Zhongxing Xuc8822e02010-07-05 02:35:40 +0000156Entity EntityGetter::VisitTypeDecl(TypeDecl *D) {
Zhongxing Xu8d26bb72010-07-05 02:36:16 +0000157 // 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.
Zhongxing Xuc8822e02010-07-05 02:35:40 +0000160 return Entity();
161}
162
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000163//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000164// EntityImpl Implementation
165//===----------------------------------------------------------------------===//
166
167Decl *EntityImpl::getDecl(ASTContext &AST) {
168 DeclContext *DC =
169 Parent.isInvalid() ? AST.getTranslationUnitDecl()
170 : cast<DeclContext>(Parent.getDecl(AST));
171 if (!DC)
172 return 0; // Couldn't get the parent context.
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000173
174 DeclarationName LocalName;
175
176 if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
Kovarththanan Rajaratnam2781deb2010-03-12 09:33:31 +0000177 IdentifierInfo &II = AST.Idents.get(GlobII->getName());
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000178 LocalName = DeclarationName(&II);
179 } else {
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);
185 }
186
187 assert(LocalName);
188
189 DeclContext::lookup_result Res = DC->lookup(LocalName);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000190 for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000191 Decl *D = *I;
192 if (D->getIdentifierNamespace() == IdNS) {
193 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
194 if (MD->isInstanceMethod() == IsObjCInstanceMethod)
195 return MD;
196 } else
197 return D;
198 }
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000199 }
200
201 return 0; // Failed to find a decl using this Entity.
202}
203
204/// \brief Get an Entity associated with the given Decl.
205/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000206Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000207 assert(D && "Passed null Decl");
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000208 return EntityGetter(Prog, ProgImpl).Visit(D);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000209}
210
Zhongxing Xudc01a152010-07-06 05:55:13 +0000211/// \brief Get an Entity associated with a global name.
212Entity EntityImpl::get(llvm::StringRef Name, Program &Prog,
213 ProgramImpl &ProgImpl) {
214 return EntityGetter(Prog, ProgImpl).getGlobalEntity(Name);
215}
216
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000217std::string EntityImpl::getPrintableName() {
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000218 return Name.getAsString();
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000219}
220
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000221//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000222// Entity Implementation
223//===----------------------------------------------------------------------===//
224
Argyrios Kyrtzidis1f717272009-07-21 02:10:32 +0000225Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
226
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000227/// \brief Find the Decl that can be referred to by this entity.
Zhongxing Xu6d8f56f2009-07-24 03:38:27 +0000228Decl *Entity::getDecl(ASTContext &AST) const {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000229 if (isInvalid())
230 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000231
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000232 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;
Mike Stump1eb44332009-09-09 15:08:12 +0000235
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000236 return Val.get<EntityImpl *>()->getDecl(AST);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000237}
238
Zhongxing Xuf7856432009-07-23 08:32:25 +0000239std::string Entity::getPrintableName() const {
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000240 if (isInvalid())
241 return "<< Invalid >>";
Mike Stump1eb44332009-09-09 15:08:12 +0000242
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000243 if (Decl *D = Val.dyn_cast<Decl *>()) {
244 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
245 return ND->getNameAsString();
246 else
247 return std::string();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000248 }
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000249
250 return Val.get<EntityImpl *>()->getPrintableName();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000251}
252
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000253/// \brief Get an Entity associated with the given Decl.
254/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000255Entity Entity::get(Decl *D, Program &Prog) {
256 if (D == 0)
257 return Entity();
258 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000259 return EntityImpl::get(D, Prog, ProgImpl);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000260}
261
Zhongxing Xudc01a152010-07-06 05:55:13 +0000262Entity Entity::get(llvm::StringRef Name, Program &Prog) {
263 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
264 return EntityImpl::get(Name, Prog, ProgImpl);
265}
266
Mike Stump1eb44332009-09-09 15:08:12 +0000267unsigned
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000268llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
269 return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000270}