Initialize the array with the "C++ way".
[clang.git] / lib / Index / Entity.cpp
blob749dcc899322de5d0f869b66c063095cb9f97532
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.
13 //===----------------------------------------------------------------------===//
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;
25 // FIXME: Entity is really really basic currently, mostly written to work
26 // on variables and functions. Should support types and other decls eventually..
29 //===----------------------------------------------------------------------===//
30 // EntityGetter
31 //===----------------------------------------------------------------------===//
33 namespace clang {
34 namespace idx {
36 /// \brief Gets the Entity associated with a Decl.
37 class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
38 Program &Prog;
39 ProgramImpl &ProgImpl;
41 public:
42 EntityGetter(Program &prog, ProgramImpl &progImpl)
43 : Prog(prog), ProgImpl(progImpl) { }
45 // Get an Entity.
46 Entity getEntity(Entity Parent, DeclarationName Name,
47 unsigned IdNS, bool isObjCInstanceMethod);
49 // Get an Entity associated with the name in the global namespace.
50 Entity getGlobalEntity(llvm::StringRef Name);
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);
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);
67 ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
68 void *InsertPos = 0;
69 if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
70 return Entity(Ent);
72 void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
73 EntityImpl *New =
74 new (Buf) EntityImpl(Parent, Name, IdNS, isObjCInstanceMethod);
75 Entities.InsertNode(New, InsertPos);
77 return Entity(New);
80 Entity 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);
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();
95 if (Parent.isValid() && Parent.isInternalToTU())
96 return Entity(D);
98 // FIXME: Only works for DeclarationNames that are identifiers and selectors.
99 // Treats other DeclarationNames as internal Decls for now..
101 DeclarationName LocalName = D->getDeclName();
102 if (!LocalName)
103 return Entity(D);
105 DeclarationName GlobName;
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();
113 // Treats other DeclarationNames as internal Decls for now..
114 if (LocalSel.isNull())
115 return Entity(D);
117 Selector GlobSel =
118 (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
119 GlobName = DeclarationName(GlobSel);
122 assert(GlobName);
124 unsigned IdNS = D->getIdentifierNamespace();
126 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
127 bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
128 return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod);
131 Entity EntityGetter::VisitVarDecl(VarDecl *D) {
132 // Local variables have no linkage, make invalid Entities.
133 if (D->hasLocalStorage())
134 return Entity();
136 // If it's static it cannot be referred to by another translation unit.
137 if (D->getStorageClass() == SC_Static)
138 return Entity(D);
140 return VisitNamedDecl(D);
143 Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
144 // If it's static it cannot be refered to by another translation unit.
145 if (D->getStorageClass() == SC_Static)
146 return Entity(D);
148 return VisitNamedDecl(D);
151 Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
152 // Make FieldDecl an invalid Entity since it has no linkage.
153 return Entity();
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();
163 //===----------------------------------------------------------------------===//
164 // EntityImpl Implementation
165 //===----------------------------------------------------------------------===//
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.
174 DeclarationName LocalName;
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);
187 assert(LocalName);
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;
201 return 0; // Failed to find a decl using this Entity.
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);
211 /// \brief Get an Entity associated with a global name.
212 Entity EntityImpl::get(llvm::StringRef Name, Program &Prog,
213 ProgramImpl &ProgImpl) {
214 return EntityGetter(Prog, ProgImpl).getGlobalEntity(Name);
217 std::string EntityImpl::getPrintableName() {
218 return Name.getAsString();
221 //===----------------------------------------------------------------------===//
222 // Entity Implementation
223 //===----------------------------------------------------------------------===//
225 Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
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;
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;
236 return Val.get<EntityImpl *>()->getDecl(AST);
239 std::string Entity::getPrintableName() const {
240 if (isInvalid())
241 return "<< Invalid >>";
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();
250 return Val.get<EntityImpl *>()->getPrintableName();
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);
262 Entity Entity::get(llvm::StringRef Name, Program &Prog) {
263 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
264 return EntityImpl::get(Name, Prog, ProgImpl);
267 unsigned
268 llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
269 return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());