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 } 271