blob: fb3c7ae4c0a99bb748a8d9dac86aa325dce450af [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
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000045 Entity VisitNamedDecl(NamedDecl *D);
46 Entity VisitVarDecl(VarDecl *D);
Zhongxing Xu139d0b32010-07-05 01:44:14 +000047 Entity VisitFieldDecl(FieldDecl *D);
Mike Stump1eb44332009-09-09 15:08:12 +000048 Entity VisitFunctionDecl(FunctionDecl *D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000049};
50
51}
52}
53
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000054Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
55 Entity Parent;
56 if (!D->getDeclContext()->isTranslationUnit()) {
57 Parent = Visit(cast<Decl>(D->getDeclContext()));
58 // FIXME: Anonymous structs ?
59 if (Parent.isInvalid())
60 return Entity();
61 }
62 if (Parent.isValid() && Parent.isInternalToTU())
63 return Entity(D);
64
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000065 // FIXME: Only works for DeclarationNames that are identifiers and selectors.
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +000066 // Treats other DeclarationNames as internal Decls for now..
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000067
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000068 DeclarationName LocalName = D->getDeclName();
69 if (!LocalName)
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +000070 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000071
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000072 DeclarationName GlobName;
Argyrios Kyrtzidisdc0b11e2009-07-17 01:19:03 +000073
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000074 if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
Kovarththanan Rajaratnam2781deb2010-03-12 09:33:31 +000075 IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000076 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);
Mike Stump1eb44332009-09-09 15:08:12 +000083
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000084 Selector GlobSel =
85 (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
86 GlobName = DeclarationName(GlobSel);
87 }
Mike Stump1eb44332009-09-09 15:08:12 +000088
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +000089 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);
Mike Stump1eb44332009-09-09 15:08:12 +0000108
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000109 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);
Mike Stump1eb44332009-09-09 15:08:12 +0000116
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000117 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);
Mike Stump1eb44332009-09-09 15:08:12 +0000124
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000125 return VisitNamedDecl(D);
126}
127
Zhongxing Xu139d0b32010-07-05 01:44:14 +0000128Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
129 // Make FieldDecl an internal Entity.
130 return Entity(D);
131}
132
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000133//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000134// EntityImpl Implementation
135//===----------------------------------------------------------------------===//
136
137Decl *EntityImpl::getDecl(ASTContext &AST) {
138 DeclContext *DC =
139 Parent.isInvalid() ? AST.getTranslationUnitDecl()
140 : cast<DeclContext>(Parent.getDecl(AST));
141 if (!DC)
142 return 0; // Couldn't get the parent context.
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000143
144 DeclarationName LocalName;
145
146 if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
Kovarththanan Rajaratnam2781deb2010-03-12 09:33:31 +0000147 IdentifierInfo &II = AST.Idents.get(GlobII->getName());
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000148 LocalName = DeclarationName(&II);
149 } else {
150 Selector GlobSel = Name.getObjCSelector();
151 assert(!GlobSel.isNull() && "A not handled yet declaration name");
152 GlobalSelector GSel =
153 GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr());
154 LocalName = GSel.getSelector(AST);
155 }
156
157 assert(LocalName);
158
159 DeclContext::lookup_result Res = DC->lookup(LocalName);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000160 for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000161 Decl *D = *I;
162 if (D->getIdentifierNamespace() == IdNS) {
163 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
164 if (MD->isInstanceMethod() == IsObjCInstanceMethod)
165 return MD;
166 } else
167 return D;
168 }
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000169 }
170
171 return 0; // Failed to find a decl using this Entity.
172}
173
174/// \brief Get an Entity associated with the given Decl.
175/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000176Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000177 assert(D && "Passed null Decl");
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000178 return EntityGetter(Prog, ProgImpl).Visit(D);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000179}
180
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000181std::string EntityImpl::getPrintableName() {
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000182 return Name.getAsString();
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000183}
184
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000185//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000186// Entity Implementation
187//===----------------------------------------------------------------------===//
188
Argyrios Kyrtzidis1f717272009-07-21 02:10:32 +0000189Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
190
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000191/// \brief Find the Decl that can be referred to by this entity.
Zhongxing Xu6d8f56f2009-07-24 03:38:27 +0000192Decl *Entity::getDecl(ASTContext &AST) const {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000193 if (isInvalid())
194 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000195
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000196 if (Decl *D = Val.dyn_cast<Decl *>())
197 // Check that the passed AST is actually the one that this Decl belongs to.
198 return (&D->getASTContext() == &AST) ? D : 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000199
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000200 return Val.get<EntityImpl *>()->getDecl(AST);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000201}
202
Zhongxing Xuf7856432009-07-23 08:32:25 +0000203std::string Entity::getPrintableName() const {
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000204 if (isInvalid())
205 return "<< Invalid >>";
Mike Stump1eb44332009-09-09 15:08:12 +0000206
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000207 if (Decl *D = Val.dyn_cast<Decl *>()) {
208 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
209 return ND->getNameAsString();
210 else
211 return std::string();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000212 }
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000213
214 return Val.get<EntityImpl *>()->getPrintableName();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000215}
216
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000217/// \brief Get an Entity associated with the given Decl.
218/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000219Entity Entity::get(Decl *D, Program &Prog) {
220 if (D == 0)
221 return Entity();
222 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
Argyrios Kyrtzidis87bcb502009-07-29 23:41:46 +0000223 return EntityImpl::get(D, Prog, ProgImpl);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000224}
225
Mike Stump1eb44332009-09-09 15:08:12 +0000226unsigned
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000227llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
228 return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000229}