Home | History | Annotate | Download | only in Index
      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