]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/Index/Entity.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / lib / Index / Entity.cpp
1 //===--- 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"
22 using namespace clang;
23 using 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
33 namespace clang {
34 namespace idx {
35
36 /// \brief Gets the Entity associated with a Decl.
37 class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
38   Program &Prog;
39   ProgramImpl &ProgImpl;
40
41 public:
42   EntityGetter(Program &prog, ProgramImpl &progImpl)
43     : Prog(prog), ProgImpl(progImpl) { }
44
45   // 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(StringRef Name);
51
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);
57 };
58
59 }
60 }
61
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);
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
80 Entity EntityGetter::getGlobalEntity(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
87 Entity 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
98   // FIXME: Only works for DeclarationNames that are identifiers and selectors.
99   // Treats other DeclarationNames as internal Decls for now..
100
101   DeclarationName LocalName = D->getDeclName();
102   if (!LocalName)
103     return Entity(D);
104
105   DeclarationName GlobName;
106
107   if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
108     IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
109     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);
116
117     Selector GlobSel =
118         (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
119     GlobName = DeclarationName(GlobSel);
120   }
121
122   assert(GlobName);
123
124   unsigned IdNS = D->getIdentifierNamespace();
125
126   ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
127   bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
128   return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod);
129 }
130
131 Entity EntityGetter::VisitVarDecl(VarDecl *D) {
132   // Local variables have no linkage, make invalid Entities.
133   if (D->hasLocalStorage())
134     return Entity();
135
136   // If it's static it cannot be referred to by another translation unit.
137   if (D->getStorageClass() == SC_Static)
138     return Entity(D);
139
140   return VisitNamedDecl(D);
141 }
142
143 Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
144   // If it's static it cannot be referred to by another translation unit.
145   if (D->getStorageClass() == SC_Static)
146     return Entity(D);
147
148   return VisitNamedDecl(D);
149 }
150
151 Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
152   // Make FieldDecl an invalid Entity since it has no linkage.
153   return Entity();
154 }
155
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.
160   return Entity();
161 }
162
163 //===----------------------------------------------------------------------===//
164 // EntityImpl Implementation
165 //===----------------------------------------------------------------------===//
166
167 Decl *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.
173
174   DeclarationName LocalName;
175
176   if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
177     IdentifierInfo &II = AST.Idents.get(GlobII->getName());
178     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);
190   for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
191     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     }
199   }
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.
206 Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
207   assert(D && "Passed null Decl");
208   return EntityGetter(Prog, ProgImpl).Visit(D);
209 }
210
211 /// \brief Get an Entity associated with a global name.
212 Entity EntityImpl::get(StringRef Name, Program &Prog, 
213                        ProgramImpl &ProgImpl) {
214   return EntityGetter(Prog, ProgImpl).getGlobalEntity(Name);
215 }
216
217 std::string EntityImpl::getPrintableName() {
218   return Name.getAsString();
219 }
220
221 //===----------------------------------------------------------------------===//
222 // Entity Implementation
223 //===----------------------------------------------------------------------===//
224
225 Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
226
227 /// \brief Find the Decl that can be referred to by this entity.
228 Decl *Entity::getDecl(ASTContext &AST) const {
229   if (isInvalid())
230     return 0;
231
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;
235
236   return Val.get<EntityImpl *>()->getDecl(AST);
237 }
238
239 std::string Entity::getPrintableName() const {
240   if (isInvalid())
241     return "<< Invalid >>";
242
243   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();
248   }
249
250   return Val.get<EntityImpl *>()->getPrintableName();
251 }
252
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) {
256   if (D == 0)
257     return Entity();
258   ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
259   return EntityImpl::get(D, Prog, ProgImpl);
260 }
261
262 Entity Entity::get(StringRef Name, Program &Prog) {
263   ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
264   return EntityImpl::get(Name, Prog, ProgImpl);
265 }
266
267 unsigned
268 llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
269   return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
270 }