From 87bcb504f6ea453c50e47beb850258ebe57e9248 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 29 Jul 2009 23:41:46 +0000 Subject: [PATCH] Support ObjC methods as Entities. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77547 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Index/GlobalSelector.h | 4 ++ lib/Index/Entity.cpp | 91 ++++++++++++++++++++-------- lib/Index/EntityImpl.h | 24 +++++--- tools/index-test/index-test.cpp | 2 + 4 files changed, 87 insertions(+), 34 deletions(-) diff --git a/include/clang/Index/GlobalSelector.h b/include/clang/Index/GlobalSelector.h index 7bbd303262..e24c419d1e 100644 --- a/include/clang/Index/GlobalSelector.h +++ b/include/clang/Index/GlobalSelector.h @@ -46,6 +46,10 @@ public: static GlobalSelector get(Selector Sel, Program &Prog); void *getAsOpaquePtr() const { return Val; } + + static GlobalSelector getFromOpaquePtr(void *Ptr) { + return GlobalSelector(Ptr); + } friend bool operator==(const GlobalSelector &LHS, const GlobalSelector &RHS) { return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr(); diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp index 8c7c8d0ef5..245fc9a555 100644 --- a/lib/Index/Entity.cpp +++ b/lib/Index/Entity.cpp @@ -15,6 +15,7 @@ #include "EntityImpl.h" #include "ProgramImpl.h" #include "clang/Index/Program.h" +#include "clang/Index/GlobalSelector.h" #include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclVisitor.h" @@ -34,10 +35,12 @@ namespace idx { /// \brief Gets the Entity associated with a Decl. class EntityGetter : public DeclVisitor { - ProgramImpl &Prog; + Program &Prog; + ProgramImpl &ProgImpl; public: - EntityGetter(ProgramImpl &prog) : Prog(prog) { } + EntityGetter(Program &prog, ProgramImpl &progImpl) + : Prog(prog), ProgImpl(progImpl) { } Entity VisitNamedDecl(NamedDecl *D); Entity VisitVarDecl(VarDecl *D); @@ -58,32 +61,49 @@ Entity EntityGetter::VisitNamedDecl(NamedDecl *D) { if (Parent.isValid() && Parent.isInternalToTU()) return Entity(D); - // FIXME: Only works for DeclarationNames that are identifiers. + // FIXME: Only works for DeclarationNames that are identifiers and selectors. // Treats other DeclarationNames as internal Decls for now.. - DeclarationName Name = D->getDeclName(); - - if (!Name.isIdentifier()) + DeclarationName LocalName = D->getDeclName(); + if (!LocalName) return Entity(D); - IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (!II) - return Entity(); + DeclarationName GlobName; + + if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) { + IdentifierInfo *GlobII = + &ProgImpl.getIdents().get(II->getName(), II->getName() + II->getLength()); + GlobName = DeclarationName(GlobII); + } else { + Selector LocalSel = LocalName.getObjCSelector(); + + // Treats other DeclarationNames as internal Decls for now.. + if (LocalSel.isNull()) + return Entity(D); + + Selector GlobSel = + (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr(); + GlobName = DeclarationName(GlobSel); + } + + assert(GlobName); - IdentifierInfo *Id = &Prog.getIdents().get(II->getName(), - II->getName() + II->getLength()); unsigned IdNS = D->getIdentifierNamespace(); + ObjCMethodDecl *MD = dyn_cast(D); + bool isObjCInstanceMethod = MD && MD->isInstanceMethod(); + llvm::FoldingSetNodeID ID; - EntityImpl::Profile(ID, Parent, Id, IdNS); + EntityImpl::Profile(ID, Parent, GlobName, IdNS, isObjCInstanceMethod); - ProgramImpl::EntitySetTy &Entities = Prog.getEntities(); + ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities(); void *InsertPos = 0; if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos)) return Entity(Ent); - void *Buf = Prog.Allocate(sizeof(EntityImpl)); - EntityImpl *New = new (Buf) EntityImpl(Parent, Id, IdNS); + void *Buf = ProgImpl.Allocate(sizeof(EntityImpl)); + EntityImpl *New = + new (Buf) EntityImpl(Parent, GlobName, IdNS, isObjCInstanceMethod); Entities.InsertNode(New, InsertPos); return Entity(New); @@ -115,14 +135,33 @@ Decl *EntityImpl::getDecl(ASTContext &AST) { : cast(Parent.getDecl(AST)); if (!DC) return 0; // Couldn't get the parent context. - - IdentifierInfo &II = AST.Idents.get(Id->getName(), - Id->getName() + Id->getLength()); - - DeclContext::lookup_result Res = DC->lookup(DeclarationName(&II)); + + DeclarationName LocalName; + + if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) { + IdentifierInfo &II = AST.Idents.get(GlobII->getName(), + GlobII->getName() + GlobII->getLength()); + LocalName = DeclarationName(&II); + } else { + Selector GlobSel = Name.getObjCSelector(); + assert(!GlobSel.isNull() && "A not handled yet declaration name"); + GlobalSelector GSel = + GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr()); + LocalName = GSel.getSelector(AST); + } + + assert(LocalName); + + DeclContext::lookup_result Res = DC->lookup(LocalName); for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) { - if ((*I)->getIdentifierNamespace() == IdNS) - return *I; + Decl *D = *I; + if (D->getIdentifierNamespace() == IdNS) { + if (ObjCMethodDecl *MD = dyn_cast(D)) { + if (MD->isInstanceMethod() == IsObjCInstanceMethod) + return MD; + } else + return D; + } } return 0; // Failed to find a decl using this Entity. @@ -130,13 +169,13 @@ Decl *EntityImpl::getDecl(ASTContext &AST) { /// \brief Get an Entity associated with the given Decl. /// \returns Null if an Entity cannot refer to this Decl. -Entity EntityImpl::get(Decl *D, ProgramImpl &Prog) { +Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) { assert(D && "Passed null Decl"); - return EntityGetter(Prog).Visit(D); + return EntityGetter(Prog, ProgImpl).Visit(D); } std::string EntityImpl::getPrintableName() { - return Id->getName(); + return Name.getAsString(); } //===----------------------------------------------------------------------===// @@ -177,7 +216,7 @@ Entity Entity::get(Decl *D, Program &Prog) { if (D == 0) return Entity(); ProgramImpl &ProgImpl = *static_cast(Prog.Impl); - return EntityImpl::get(D, ProgImpl); + return EntityImpl::get(D, Prog, ProgImpl); } unsigned diff --git a/lib/Index/EntityImpl.h b/lib/Index/EntityImpl.h index d28936ee2c..b4a883a3bf 100644 --- a/lib/Index/EntityImpl.h +++ b/lib/Index/EntityImpl.h @@ -15,43 +15,51 @@ #define LLVM_CLANG_INDEX_ENTITYIMPL_H #include "clang/Index/Entity.h" +#include "clang/AST/DeclarationName.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/StringSet.h" namespace clang { - class IdentifierInfo; namespace idx { class ProgramImpl; class EntityImpl : public llvm::FoldingSetNode { Entity Parent; - IdentifierInfo *Id; + DeclarationName Name; /// \brief Identifier namespace. unsigned IdNS; + + /// \brief If Name is a selector, this keeps track whether it's for an + /// instance method. + bool IsObjCInstanceMethod; public: - EntityImpl(Entity parent, IdentifierInfo *id, unsigned idNS) - : Parent(parent), Id(id), IdNS(idNS) { } + EntityImpl(Entity parent, DeclarationName name, unsigned idNS, + bool isObjCInstanceMethod) + : Parent(parent), Name(name), IdNS(idNS), + IsObjCInstanceMethod(isObjCInstanceMethod) { } /// \brief Find the Decl that can be referred to by this entity. Decl *getDecl(ASTContext &AST); /// \brief Get an Entity associated with the given Decl. /// \returns Null if an Entity cannot refer to this Decl. - static Entity get(Decl *D, ProgramImpl &Prog); + static Entity get(Decl *D, Program &Prog, ProgramImpl &ProgImpl); std::string getPrintableName(); void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, Parent, Id, IdNS); + Profile(ID, Parent, Name, IdNS, IsObjCInstanceMethod); } static void Profile(llvm::FoldingSetNodeID &ID, Entity Parent, - IdentifierInfo *Id, unsigned IdNS) { + DeclarationName Name, unsigned IdNS, + bool isObjCInstanceMethod) { ID.AddPointer(Parent.getAsOpaquePtr()); - ID.AddPointer(Id); + ID.AddPointer(Name.getAsOpaquePtr()); ID.AddInteger(IdNS); + ID.AddBoolean(isObjCInstanceMethod); } }; diff --git a/tools/index-test/index-test.cpp b/tools/index-test/index-test.cpp index 037221fcef..fd522d54d0 100644 --- a/tools/index-test/index-test.cpp +++ b/tools/index-test/index-test.cpp @@ -150,6 +150,8 @@ static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) { isDef = FD->isThisDeclarationADefinition(); else if (const VarDecl *VD = dyn_cast(D)) isDef = VD->getInit() != 0; + else if (const ObjCMethodDecl *MD = dyn_cast(D)) + isDef = MD->isThisDeclarationADefinition(); if (isDef) I->print(OS); -- 2.40.0