Chris Lattner | c3a6540 | 2009-07-12 22:33:12 +0000 | [diff] [blame] | 1 | //===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===// |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 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 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 15 | #include "EntityImpl.h" |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 16 | #include "ProgramImpl.h" |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 17 | #include "clang/Index/Program.h" |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 18 | #include "clang/Index/GlobalSelector.h" |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 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. |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 37 | class EntityGetter : public DeclVisitor<EntityGetter, Entity> { |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 38 | Program &Prog; |
| 39 | ProgramImpl &ProgImpl; |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 40 | |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 41 | public: |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 42 | EntityGetter(Program &prog, ProgramImpl &progImpl) |
| 43 | : Prog(prog), ProgImpl(progImpl) { } |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 44 | |
Zhongxing Xu | dc01a15 | 2010-07-06 05:55:13 +0000 | [diff] [blame] | 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(llvm::StringRef Name); |
| 51 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 52 | Entity VisitNamedDecl(NamedDecl *D); |
| 53 | Entity VisitVarDecl(VarDecl *D); |
Zhongxing Xu | 139d0b3 | 2010-07-05 01:44:14 +0000 | [diff] [blame] | 54 | Entity VisitFieldDecl(FieldDecl *D); |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 55 | Entity VisitFunctionDecl(FunctionDecl *D); |
Zhongxing Xu | c8822e0 | 2010-07-05 02:35:40 +0000 | [diff] [blame] | 56 | Entity VisitTypeDecl(TypeDecl *D); |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 57 | }; |
| 58 | |
| 59 | } |
| 60 | } |
| 61 | |
Zhongxing Xu | dc01a15 | 2010-07-06 05:55:13 +0000 | [diff] [blame] | 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(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 Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 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 | |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 98 | // FIXME: Only works for DeclarationNames that are identifiers and selectors. |
Argyrios Kyrtzidis | 52f1d47 | 2009-07-29 23:39:52 +0000 | [diff] [blame] | 99 | // Treats other DeclarationNames as internal Decls for now.. |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 100 | |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 101 | DeclarationName LocalName = D->getDeclName(); |
| 102 | if (!LocalName) |
Argyrios Kyrtzidis | 52f1d47 | 2009-07-29 23:39:52 +0000 | [diff] [blame] | 103 | return Entity(D); |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 104 | |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 105 | DeclarationName GlobName; |
Argyrios Kyrtzidis | dc0b11e | 2009-07-17 01:19:03 +0000 | [diff] [blame] | 106 | |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 107 | if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) { |
Kovarththanan Rajaratnam | 2781deb | 2010-03-12 09:33:31 +0000 | [diff] [blame] | 108 | IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName()); |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 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); |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 116 | |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 117 | Selector GlobSel = |
| 118 | (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr(); |
| 119 | GlobName = DeclarationName(GlobSel); |
| 120 | } |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 121 | |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 122 | assert(GlobName); |
| 123 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 124 | unsigned IdNS = D->getIdentifierNamespace(); |
| 125 | |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 126 | ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D); |
| 127 | bool isObjCInstanceMethod = MD && MD->isInstanceMethod(); |
Zhongxing Xu | dc01a15 | 2010-07-06 05:55:13 +0000 | [diff] [blame] | 128 | return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod); |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 129 | } |
| 130 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 131 | Entity EntityGetter::VisitVarDecl(VarDecl *D) { |
Zhongxing Xu | 6c47a9b | 2010-07-06 01:20:49 +0000 | [diff] [blame] | 132 | // Local variables have no linkage, make invalid Entities. |
| 133 | if (D->hasLocalStorage()) |
| 134 | return Entity(); |
| 135 | |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 136 | // If it's static it cannot be referred to by another translation unit. |
John McCall | d931b08 | 2010-08-26 03:08:43 +0000 | [diff] [blame] | 137 | if (D->getStorageClass() == SC_Static) |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 138 | return Entity(D); |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 139 | |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 140 | return VisitNamedDecl(D); |
| 141 | } |
| 142 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 143 | Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) { |
Chris Lattner | fc8f0e1 | 2011-04-15 05:22:18 +0000 | [diff] [blame] | 144 | // If it's static it cannot be referred to by another translation unit. |
John McCall | d931b08 | 2010-08-26 03:08:43 +0000 | [diff] [blame] | 145 | if (D->getStorageClass() == SC_Static) |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 146 | return Entity(D); |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 147 | |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 148 | return VisitNamedDecl(D); |
| 149 | } |
| 150 | |
Zhongxing Xu | 139d0b3 | 2010-07-05 01:44:14 +0000 | [diff] [blame] | 151 | Entity EntityGetter::VisitFieldDecl(FieldDecl *D) { |
Zhongxing Xu | 423030c | 2010-07-05 02:31:16 +0000 | [diff] [blame] | 152 | // Make FieldDecl an invalid Entity since it has no linkage. |
| 153 | return Entity(); |
Zhongxing Xu | 139d0b3 | 2010-07-05 01:44:14 +0000 | [diff] [blame] | 154 | } |
| 155 | |
Zhongxing Xu | c8822e0 | 2010-07-05 02:35:40 +0000 | [diff] [blame] | 156 | Entity EntityGetter::VisitTypeDecl(TypeDecl *D) { |
Zhongxing Xu | 8d26bb7 | 2010-07-05 02:36:16 +0000 | [diff] [blame] | 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. |
Zhongxing Xu | c8822e0 | 2010-07-05 02:35:40 +0000 | [diff] [blame] | 160 | return Entity(); |
| 161 | } |
| 162 | |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 163 | //===----------------------------------------------------------------------===// |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 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. |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 173 | |
| 174 | DeclarationName LocalName; |
| 175 | |
| 176 | if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) { |
Kovarththanan Rajaratnam | 2781deb | 2010-03-12 09:33:31 +0000 | [diff] [blame] | 177 | IdentifierInfo &II = AST.Idents.get(GlobII->getName()); |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 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); |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 190 | for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) { |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 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 | } |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 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. |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 206 | Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) { |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 207 | assert(D && "Passed null Decl"); |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 208 | return EntityGetter(Prog, ProgImpl).Visit(D); |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 209 | } |
| 210 | |
Zhongxing Xu | dc01a15 | 2010-07-06 05:55:13 +0000 | [diff] [blame] | 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); |
| 215 | } |
| 216 | |
Argyrios Kyrtzidis | 4c7c5a1 | 2009-07-21 07:52:21 +0000 | [diff] [blame] | 217 | std::string EntityImpl::getPrintableName() { |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 218 | return Name.getAsString(); |
Argyrios Kyrtzidis | 4c7c5a1 | 2009-07-21 07:52:21 +0000 | [diff] [blame] | 219 | } |
| 220 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 221 | //===----------------------------------------------------------------------===// |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 222 | // Entity Implementation |
| 223 | //===----------------------------------------------------------------------===// |
| 224 | |
Argyrios Kyrtzidis | 1f71727 | 2009-07-21 02:10:32 +0000 | [diff] [blame] | 225 | Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { } |
| 226 | |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 227 | /// \brief Find the Decl that can be referred to by this entity. |
Zhongxing Xu | 6d8f56f | 2009-07-24 03:38:27 +0000 | [diff] [blame] | 228 | Decl *Entity::getDecl(ASTContext &AST) const { |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 229 | if (isInvalid()) |
| 230 | return 0; |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 231 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 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; |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 235 | |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 236 | return Val.get<EntityImpl *>()->getDecl(AST); |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 237 | } |
| 238 | |
Zhongxing Xu | f785643 | 2009-07-23 08:32:25 +0000 | [diff] [blame] | 239 | std::string Entity::getPrintableName() const { |
Argyrios Kyrtzidis | 4c7c5a1 | 2009-07-21 07:52:21 +0000 | [diff] [blame] | 240 | if (isInvalid()) |
| 241 | return "<< Invalid >>"; |
Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 242 | |
Argyrios Kyrtzidis | 4c7c5a1 | 2009-07-21 07:52:21 +0000 | [diff] [blame] | 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(); |
Zhongxing Xu | 53363b2 | 2009-07-15 04:39:21 +0000 | [diff] [blame] | 248 | } |
Argyrios Kyrtzidis | 4c7c5a1 | 2009-07-21 07:52:21 +0000 | [diff] [blame] | 249 | |
| 250 | return Val.get<EntityImpl *>()->getPrintableName(); |
Zhongxing Xu | 53363b2 | 2009-07-15 04:39:21 +0000 | [diff] [blame] | 251 | } |
| 252 | |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 253 | /// \brief Get an Entity associated with the given Decl. |
| 254 | /// \returns Null if an Entity cannot refer to this Decl. |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 255 | Entity Entity::get(Decl *D, Program &Prog) { |
| 256 | if (D == 0) |
| 257 | return Entity(); |
| 258 | ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl); |
Argyrios Kyrtzidis | 87bcb50 | 2009-07-29 23:41:46 +0000 | [diff] [blame] | 259 | return EntityImpl::get(D, Prog, ProgImpl); |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 260 | } |
| 261 | |
Zhongxing Xu | dc01a15 | 2010-07-06 05:55:13 +0000 | [diff] [blame] | 262 | Entity 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 Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 267 | unsigned |
Argyrios Kyrtzidis | f7cf15c | 2009-07-21 00:07:06 +0000 | [diff] [blame] | 268 | llvm::DenseMapInfo<Entity>::getHashValue(Entity E) { |
| 269 | return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr()); |
Argyrios Kyrtzidis | 9eec4ed | 2009-07-05 22:22:19 +0000 | [diff] [blame] | 270 | } |