blob: 03fe9f73af402369941e2e1c6e7a7c1b1080ab37 [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
2//
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
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"
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.
37class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
38 Program &Prog;
39 ProgramImpl &ProgImpl;
40
41public:
42 EntityGetter(Program &prog, ProgramImpl &progImpl)
43 : Prog(prog), ProgImpl(progImpl) { }
44
45 Entity VisitNamedDecl(NamedDecl *D);
46 Entity VisitVarDecl(VarDecl *D);
47 Entity VisitFunctionDecl(FunctionDecl *D);
48};
49
50}
51}
52
53Entity 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
64 // FIXME: Only works for DeclarationNames that are identifiers and selectors.
65 // Treats other DeclarationNames as internal Decls for now..
66
67 DeclarationName LocalName = D->getDeclName();
68 if (!LocalName)
69 return Entity(D);
70
71 DeclarationName GlobName;
72
73 if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
74 IdentifierInfo *GlobII =
75 &ProgImpl.getIdents().get(II->getNameStart(),
76 II->getNameStart() + II->getLength());
77 GlobName = DeclarationName(GlobII);
78 } else {
79 Selector LocalSel = LocalName.getObjCSelector();
80
81 // Treats other DeclarationNames as internal Decls for now..
82 if (LocalSel.isNull())
83 return Entity(D);
84
85 Selector GlobSel =
86 (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
87 GlobName = DeclarationName(GlobSel);
88 }
89
90 assert(GlobName);
91
92 unsigned IdNS = D->getIdentifierNamespace();
93
94 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
95 bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
96
97 llvm::FoldingSetNodeID ID;
98 EntityImpl::Profile(ID, Parent, GlobName, IdNS, isObjCInstanceMethod);
99
100 ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
101 void *InsertPos = 0;
102 if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
103 return Entity(Ent);
104
105 void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
106 EntityImpl *New =
107 new (Buf) EntityImpl(Parent, GlobName, IdNS, isObjCInstanceMethod);
108 Entities.InsertNode(New, InsertPos);
109
110 return Entity(New);
111}
112
113Entity EntityGetter::VisitVarDecl(VarDecl *D) {
114 // If it's static it cannot be referred to by another translation unit.
115 if (D->getStorageClass() == VarDecl::Static)
116 return Entity(D);
117
118 return VisitNamedDecl(D);
119}
120
121Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
122 // If it's static it cannot be refered to by another translation unit.
123 if (D->getStorageClass() == FunctionDecl::Static)
124 return Entity(D);
125
126 return VisitNamedDecl(D);
127}
128
129//===----------------------------------------------------------------------===//
130// EntityImpl Implementation
131//===----------------------------------------------------------------------===//
132
133Decl *EntityImpl::getDecl(ASTContext &AST) {
134 DeclContext *DC =
135 Parent.isInvalid() ? AST.getTranslationUnitDecl()
136 : cast<DeclContext>(Parent.getDecl(AST));
137 if (!DC)
138 return 0; // Couldn't get the parent context.
139
140 DeclarationName LocalName;
141
142 if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
143 IdentifierInfo &II =
144 AST.Idents.get(GlobII->getNameStart(),
145 GlobII->getNameStart() + GlobII->getLength());
146 LocalName = DeclarationName(&II);
147 } else {
148 Selector GlobSel = Name.getObjCSelector();
149 assert(!GlobSel.isNull() && "A not handled yet declaration name");
150 GlobalSelector GSel =
151 GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr());
152 LocalName = GSel.getSelector(AST);
153 }
154
155 assert(LocalName);
156
157 DeclContext::lookup_result Res = DC->lookup(LocalName);
158 for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
159 Decl *D = *I;
160 if (D->getIdentifierNamespace() == IdNS) {
161 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
162 if (MD->isInstanceMethod() == IsObjCInstanceMethod)
163 return MD;
164 } else
165 return D;
166 }
167 }
168
169 return 0; // Failed to find a decl using this Entity.
170}
171
172/// \brief Get an Entity associated with the given Decl.
173/// \returns Null if an Entity cannot refer to this Decl.
174Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
175 assert(D && "Passed null Decl");
176 return EntityGetter(Prog, ProgImpl).Visit(D);
177}
178
179std::string EntityImpl::getPrintableName() {
180 return Name.getAsString();
181}
182
183//===----------------------------------------------------------------------===//
184// Entity Implementation
185//===----------------------------------------------------------------------===//
186
187Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
188
189/// \brief Find the Decl that can be referred to by this entity.
190Decl *Entity::getDecl(ASTContext &AST) const {
191 if (isInvalid())
192 return 0;
193
194 if (Decl *D = Val.dyn_cast<Decl *>())
195 // Check that the passed AST is actually the one that this Decl belongs to.
196 return (&D->getASTContext() == &AST) ? D : 0;
197
198 return Val.get<EntityImpl *>()->getDecl(AST);
199}
200
201std::string Entity::getPrintableName() const {
202 if (isInvalid())
203 return "<< Invalid >>";
204
205 if (Decl *D = Val.dyn_cast<Decl *>()) {
206 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
207 return ND->getNameAsString();
208 else
209 return std::string();
210 }
211
212 return Val.get<EntityImpl *>()->getPrintableName();
213}
214
215/// \brief Get an Entity associated with the given Decl.
216/// \returns Null if an Entity cannot refer to this Decl.
217Entity Entity::get(Decl *D, Program &Prog) {
218 if (D == 0)
219 return Entity();
220 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
221 return EntityImpl::get(D, Prog, ProgImpl);
222}
223
224unsigned
225llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
226 return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
227}