diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Index')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp | 116 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/ASTVisitor.h | 143 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/Analyzer.cpp | 470 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/CallGraph.cpp | 150 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp | 90 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/Entity.cpp | 270 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/EntityImpl.h | 71 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp | 71 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/Handlers.cpp | 22 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp | 20 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/Indexer.cpp | 121 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/Program.cpp | 50 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/ProgramImpl.h | 56 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp | 84 |
14 files changed, 1734 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp b/contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp new file mode 100644 index 0000000..66b393e --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp @@ -0,0 +1,116 @@ +//===--- ASTLocation.cpp - A <Decl, Stmt> pair ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ASTLocation is Decl or a Stmt and its immediate Decl parent. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/ASTLocation.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +using namespace clang; +using namespace idx; + +static Decl *getDeclFromExpr(Stmt *E) { + if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E)) + return RefExpr->getDecl(); + if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) + return ME->getMemberDecl(); + if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E)) + return RE->getDecl(); + + if (CallExpr *CE = dyn_cast<CallExpr>(E)) + return getDeclFromExpr(CE->getCallee()); + if (CastExpr *CE = dyn_cast<CastExpr>(E)) + return getDeclFromExpr(CE->getSubExpr()); + + return 0; +} + +Decl *ASTLocation::getReferencedDecl() { + if (isInvalid()) + return 0; + + switch (getKind()) { + default: llvm_unreachable("Invalid Kind"); + case N_Type: + return 0; + case N_Decl: + return D; + case N_NamedRef: + return NDRef.ND; + case N_Stmt: + return getDeclFromExpr(Stm); + } + + return 0; +} + +SourceRange ASTLocation::getSourceRange() const { + if (isInvalid()) + return SourceRange(); + + switch (getKind()) { + default: llvm_unreachable("Invalid Kind"); + case N_Decl: + return D->getSourceRange(); + case N_Stmt: + return Stm->getSourceRange(); + case N_NamedRef: + return SourceRange(AsNamedRef().Loc, AsNamedRef().Loc); + case N_Type: + return AsTypeLoc().getLocalSourceRange(); + } + + return SourceRange(); +} + +void ASTLocation::print(raw_ostream &OS) const { + if (isInvalid()) { + OS << "<< Invalid ASTLocation >>\n"; + return; + } + + ASTContext &Ctx = getParentDecl()->getASTContext(); + + switch (getKind()) { + case N_Decl: + OS << "[Decl: " << AsDecl()->getDeclKindName() << " "; + if (const NamedDecl *ND = dyn_cast<NamedDecl>(AsDecl())) + OS << *ND; + break; + + case N_Stmt: + OS << "[Stmt: " << AsStmt()->getStmtClassName() << " "; + AsStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions())); + break; + + case N_NamedRef: + OS << "[NamedRef: " << AsNamedRef().ND->getDeclKindName() << " "; + OS << *AsNamedRef().ND; + break; + + case N_Type: { + QualType T = AsTypeLoc().getType(); + OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString(); + } + } + + OS << "] <"; + + SourceRange Range = getSourceRange(); + SourceManager &SourceMgr = Ctx.getSourceManager(); + Range.getBegin().print(OS, SourceMgr); + OS << ", "; + Range.getEnd().print(OS, SourceMgr); + OS << ">\n"; +} diff --git a/contrib/llvm/tools/clang/lib/Index/ASTVisitor.h b/contrib/llvm/tools/clang/lib/Index/ASTVisitor.h new file mode 100644 index 0000000..0b8425b --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/ASTVisitor.h @@ -0,0 +1,143 @@ +//===--- ASTVisitor.h - Visitor for an ASTContext ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ASTVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_ASTVISITOR_H +#define LLVM_CLANG_INDEX_ASTVISITOR_H + +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeLocVisitor.h" + +namespace clang { + +namespace idx { + +/// \brief Traverses the full AST, both Decls and Stmts. +template<typename ImplClass> +class ASTVisitor : public DeclVisitor<ImplClass>, + public StmtVisitor<ImplClass>, + public TypeLocVisitor<ImplClass> { +public: + ASTVisitor() : CurrentDecl(0) { } + + Decl *CurrentDecl; + + typedef ASTVisitor<ImplClass> Base; + typedef DeclVisitor<ImplClass> BaseDeclVisitor; + typedef StmtVisitor<ImplClass> BaseStmtVisitor; + typedef TypeLocVisitor<ImplClass> BaseTypeLocVisitor; + + using BaseStmtVisitor::Visit; + + //===--------------------------------------------------------------------===// + // DeclVisitor + //===--------------------------------------------------------------------===// + + void Visit(Decl *D) { + Decl *PrevDecl = CurrentDecl; + CurrentDecl = D; + BaseDeclVisitor::Visit(D); + CurrentDecl = PrevDecl; + } + + void VisitDeclaratorDecl(DeclaratorDecl *D) { + BaseDeclVisitor::VisitDeclaratorDecl(D); + if (TypeSourceInfo *TInfo = D->getTypeSourceInfo()) + Visit(TInfo->getTypeLoc()); + } + + void VisitFunctionDecl(FunctionDecl *D) { + BaseDeclVisitor::VisitFunctionDecl(D); + if (D->isThisDeclarationADefinition()) + Visit(D->getBody()); + } + + void VisitObjCMethodDecl(ObjCMethodDecl *D) { + BaseDeclVisitor::VisitObjCMethodDecl(D); + if (D->getBody()) + Visit(D->getBody()); + } + + void VisitBlockDecl(BlockDecl *D) { + BaseDeclVisitor::VisitBlockDecl(D); + Visit(D->getBody()); + } + + void VisitVarDecl(VarDecl *D) { + BaseDeclVisitor::VisitVarDecl(D); + if (Expr *Init = D->getInit()) + Visit(Init); + } + + void VisitDecl(Decl *D) { + if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D)) + return; + + if (DeclContext *DC = dyn_cast<DeclContext>(D)) + static_cast<ImplClass*>(this)->VisitDeclContext(DC); + } + + void VisitDeclContext(DeclContext *DC) { + for (DeclContext::decl_iterator + I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) + Visit(*I); + } + + //===--------------------------------------------------------------------===// + // StmtVisitor + //===--------------------------------------------------------------------===// + + void VisitDeclStmt(DeclStmt *Node) { + for (DeclStmt::decl_iterator + I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) + Visit(*I); + } + + void VisitBlockExpr(BlockExpr *Node) { + // The BlockDecl is also visited by 'VisitDeclContext()'. No need to visit it twice. + } + + void VisitStmt(Stmt *Node) { + for (Stmt::child_range I = Node->children(); I; ++I) + if (*I) + Visit(*I); + } + + //===--------------------------------------------------------------------===// + // TypeLocVisitor + //===--------------------------------------------------------------------===// + + void Visit(TypeLoc TL) { + for (; TL; TL = TL.getNextTypeLoc()) + BaseTypeLocVisitor::Visit(TL); + } + + void VisitArrayLoc(ArrayTypeLoc TL) { + BaseTypeLocVisitor::VisitArrayTypeLoc(TL); + if (TL.getSizeExpr()) + Visit(TL.getSizeExpr()); + } + + void VisitFunctionTypeLoc(FunctionTypeLoc TL) { + BaseTypeLocVisitor::VisitFunctionTypeLoc(TL); + for (unsigned i = 0; i != TL.getNumArgs(); ++i) + Visit(TL.getArg(i)); + } + +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/lib/Index/Analyzer.cpp b/contrib/llvm/tools/clang/lib/Index/Analyzer.cpp new file mode 100644 index 0000000..6be35ab --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/Analyzer.cpp @@ -0,0 +1,470 @@ +//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Analyzer interface. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/Analyzer.h" +#include "clang/Index/Entity.h" +#include "clang/Index/TranslationUnit.h" +#include "clang/Index/Handlers.h" +#include "clang/Index/ASTLocation.h" +#include "clang/Index/GlobalSelector.h" +#include "clang/Index/DeclReferenceMap.h" +#include "clang/Index/SelectorMap.h" +#include "clang/Index/IndexProvider.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprObjC.h" +#include "llvm/ADT/SmallSet.h" +using namespace clang; +using namespace idx; + +namespace { + +//===----------------------------------------------------------------------===// +// DeclEntityAnalyzer Implementation +//===----------------------------------------------------------------------===// + +class DeclEntityAnalyzer : public TranslationUnitHandler { + Entity Ent; + TULocationHandler &TULocHandler; + +public: + DeclEntityAnalyzer(Entity ent, TULocationHandler &handler) + : Ent(ent), TULocHandler(handler) { } + + virtual void Handle(TranslationUnit *TU) { + assert(TU && "Passed null translation unit"); + + Decl *D = Ent.getDecl(TU->getASTContext()); + assert(D && "Couldn't resolve Entity"); + + for (Decl::redecl_iterator I = D->redecls_begin(), + E = D->redecls_end(); I != E; ++I) + TULocHandler.Handle(TULocation(TU, ASTLocation(*I))); + } +}; + +//===----------------------------------------------------------------------===// +// RefEntityAnalyzer Implementation +//===----------------------------------------------------------------------===// + +class RefEntityAnalyzer : public TranslationUnitHandler { + Entity Ent; + TULocationHandler &TULocHandler; + +public: + RefEntityAnalyzer(Entity ent, TULocationHandler &handler) + : Ent(ent), TULocHandler(handler) { } + + virtual void Handle(TranslationUnit *TU) { + assert(TU && "Passed null translation unit"); + + Decl *D = Ent.getDecl(TU->getASTContext()); + assert(D && "Couldn't resolve Entity"); + NamedDecl *ND = dyn_cast<NamedDecl>(D); + if (!ND) + return; + + DeclReferenceMap &RefMap = TU->getDeclReferenceMap(); + for (DeclReferenceMap::astlocation_iterator + I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I) + TULocHandler.Handle(TULocation(TU, *I)); + } +}; + +//===----------------------------------------------------------------------===// +// RefSelectorAnalyzer Implementation +//===----------------------------------------------------------------------===// + +/// \brief Accepts an ObjC method and finds all message expressions that this +/// method may respond to. +class RefSelectorAnalyzer : public TranslationUnitHandler { + Program &Prog; + TULocationHandler &TULocHandler; + + // The original ObjCInterface associated with the method. + Entity IFaceEnt; + GlobalSelector GlobSel; + bool IsInstanceMethod; + + /// \brief Super classes of the ObjCInterface. + typedef llvm::SmallSet<Entity, 16> EntitiesSetTy; + EntitiesSetTy HierarchyEntities; + +public: + RefSelectorAnalyzer(ObjCMethodDecl *MD, + Program &prog, TULocationHandler &handler) + : Prog(prog), TULocHandler(handler) { + assert(MD); + + // FIXME: Protocol methods. + assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) && + "Protocol methods not supported yet"); + + ObjCInterfaceDecl *IFD = MD->getClassInterface(); + assert(IFD); + IFaceEnt = Entity::get(IFD, Prog); + GlobSel = GlobalSelector::get(MD->getSelector(), Prog); + IsInstanceMethod = MD->isInstanceMethod(); + + for (ObjCInterfaceDecl *Cls = IFD->getSuperClass(); + Cls; Cls = Cls->getSuperClass()) + HierarchyEntities.insert(Entity::get(Cls, Prog)); + } + + virtual void Handle(TranslationUnit *TU) { + assert(TU && "Passed null translation unit"); + + ASTContext &Ctx = TU->getASTContext(); + // Null means it doesn't exist in this translation unit. + ObjCInterfaceDecl *IFace = + cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx)); + Selector Sel = GlobSel.getSelector(Ctx); + + SelectorMap &SelMap = TU->getSelectorMap(); + for (SelectorMap::astlocation_iterator + I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) { + if (ValidReference(*I, IFace)) + TULocHandler.Handle(TULocation(TU, *I)); + } + } + + /// \brief Determines whether the given message expression is likely to end + /// up at the given interface decl. + /// + /// It returns true "eagerly", meaning it will return false only if it can + /// "prove" statically that the interface cannot accept this message. + bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) { + assert(ASTLoc.isStmt()); + + // FIXME: Finding @selector references should be through another Analyzer + // method, like FindSelectors. + if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt())) + return false; + + ObjCInterfaceDecl *MsgD = 0; + ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt()); + + switch (Msg->getReceiverKind()) { + case ObjCMessageExpr::Instance: { + const ObjCObjectPointerType *OPT = + Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType(); + + // Can be anything! Accept it as a possibility.. + if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) + return true; + + // Expecting class method. + if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) + return !IsInstanceMethod; + + MsgD = OPT->getInterfaceDecl(); + assert(MsgD); + + // Should be an instance method. + if (!IsInstanceMethod) + return false; + break; + } + + case ObjCMessageExpr::Class: { + // Expecting class method. + if (IsInstanceMethod) + return false; + + MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); + break; + } + + case ObjCMessageExpr::SuperClass: + // Expecting class method. + if (IsInstanceMethod) + return false; + + MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface(); + break; + + case ObjCMessageExpr::SuperInstance: + // Expecting instance method. + if (!IsInstanceMethod) + return false; + + MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl(); + break; + } + + assert(MsgD); + + // Same interface ? We have a winner! + if (MsgD == IFace) + return true; + + // If the message interface is a superclass of the original interface, + // accept this message as a possibility. + if (HierarchyEntities.count(Entity::get(MsgD, Prog))) + return true; + + // If the message interface is a subclass of the original interface, accept + // the message unless there is a subclass in the hierarchy that will + // "steal" the message (thus the message "will go" to the subclass and not + /// the original interface). + if (IFace) { + Selector Sel = Msg->getSelector(); + for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) { + if (Cls == IFace) + return true; + if (Cls->getMethod(Sel, IsInstanceMethod)) + return false; + } + } + + // The interfaces are unrelated, don't accept the message. + return false; + } +}; + +//===----------------------------------------------------------------------===// +// MessageAnalyzer Implementation +//===----------------------------------------------------------------------===// + +/// \brief Accepts an ObjC message expression and finds all methods that may +/// respond to it. +class MessageAnalyzer : public TranslationUnitHandler { + Program &Prog; + TULocationHandler &TULocHandler; + + // The ObjCInterface associated with the message. Can be null/invalid. + Entity MsgIFaceEnt; + GlobalSelector GlobSel; + bool CanBeInstanceMethod; + bool CanBeClassMethod; + + /// \brief Super classes of the ObjCInterface. + typedef llvm::SmallSet<Entity, 16> EntitiesSetTy; + EntitiesSetTy HierarchyEntities; + + /// \brief The interface in the message interface hierarchy that "intercepts" + /// the selector. + Entity ReceiverIFaceEnt; + +public: + MessageAnalyzer(ObjCMessageExpr *Msg, + Program &prog, TULocationHandler &handler) + : Prog(prog), TULocHandler(handler), + CanBeInstanceMethod(false), + CanBeClassMethod(false) { + + assert(Msg); + + ObjCInterfaceDecl *MsgD = 0; + + while (true) { + switch (Msg->getReceiverKind()) { + case ObjCMessageExpr::Instance: { + const ObjCObjectPointerType *OPT = + Msg->getInstanceReceiver()->getType() + ->getAsObjCInterfacePointerType(); + + if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) { + CanBeInstanceMethod = CanBeClassMethod = true; + break; + } + + if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) { + CanBeClassMethod = true; + break; + } + + MsgD = OPT->getInterfaceDecl(); + assert(MsgD); + CanBeInstanceMethod = true; + break; + } + + case ObjCMessageExpr::Class: + CanBeClassMethod = true; + MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); + break; + + case ObjCMessageExpr::SuperClass: + CanBeClassMethod = true; + MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface(); + break; + + case ObjCMessageExpr::SuperInstance: + CanBeInstanceMethod = true; + MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl(); + break; + } + } + + assert(CanBeInstanceMethod || CanBeClassMethod); + + Selector sel = Msg->getSelector(); + assert(!sel.isNull()); + + MsgIFaceEnt = Entity::get(MsgD, Prog); + GlobSel = GlobalSelector::get(sel, Prog); + + if (MsgD) { + for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass(); + Cls; Cls = Cls->getSuperClass()) + HierarchyEntities.insert(Entity::get(Cls, Prog)); + + // Find the interface in the hierarchy that "receives" the message. + for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) { + bool isReceiver = false; + + ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd; + for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel); + Meth != MethEnd; ++Meth) { + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth)) + if ((MD->isInstanceMethod() && CanBeInstanceMethod) || + (MD->isClassMethod() && CanBeClassMethod)) { + isReceiver = true; + break; + } + } + + if (isReceiver) { + ReceiverIFaceEnt = Entity::get(Cls, Prog); + break; + } + } + } + } + + virtual void Handle(TranslationUnit *TU) { + assert(TU && "Passed null translation unit"); + ASTContext &Ctx = TU->getASTContext(); + + // Null means it doesn't exist in this translation unit or there was no + // interface that was determined to receive the original message. + ObjCInterfaceDecl *ReceiverIFace = + cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx)); + + // No subclass for the original receiver interface, so it remains the + // receiver. + if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0) + return; + + // Null means it doesn't exist in this translation unit or there was no + // interface associated with the message in the first place. + ObjCInterfaceDecl *MsgIFace = + cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx)); + + Selector Sel = GlobSel.getSelector(Ctx); + SelectorMap &SelMap = TU->getSelectorMap(); + for (SelectorMap::method_iterator + I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel); + I != E; ++I) { + ObjCMethodDecl *D = *I; + if (ValidMethod(D, MsgIFace, ReceiverIFace)) { + for (ObjCMethodDecl::redecl_iterator + RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI) + TULocHandler.Handle(TULocation(TU, ASTLocation(*RI))); + } + } + } + + /// \brief Determines whether the given method is likely to accept the + /// original message. + /// + /// It returns true "eagerly", meaning it will return false only if it can + /// "prove" statically that the method cannot accept the original message. + bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace, + ObjCInterfaceDecl *ReceiverIFace) { + assert(D); + + // FIXME: Protocol methods ? + if (isa<ObjCProtocolDecl>(D->getDeclContext())) + return false; + + // No specific interface associated with the message. Can be anything. + if (MsgIFaceEnt.isInvalid()) + return true; + + if ((!CanBeInstanceMethod && D->isInstanceMethod()) || + (!CanBeClassMethod && D->isClassMethod())) + return false; + + ObjCInterfaceDecl *IFace = D->getClassInterface(); + assert(IFace); + + // If the original message interface is the same or a superclass of the + // given interface, accept the method as a possibility. + if (MsgIFace && MsgIFace->isSuperClassOf(IFace)) + return true; + + if (ReceiverIFace) { + // The given interface, "overrides" the receiver. + if (ReceiverIFace->isSuperClassOf(IFace)) + return true; + } else { + // No receiver was found for the original message. + assert(ReceiverIFaceEnt.isInvalid()); + + // If the original message interface is a subclass of the given interface, + // accept the message. + if (HierarchyEntities.count(Entity::get(IFace, Prog))) + return true; + } + + // The interfaces are unrelated, or the receiver interface wasn't + // "overriden". + return false; + } +}; + +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Analyzer Implementation +//===----------------------------------------------------------------------===// + +void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) { + assert(D && "Passed null declaration"); + Entity Ent = Entity::get(D, Prog); + if (Ent.isInvalid()) + return; + + DeclEntityAnalyzer DEA(Ent, Handler); + Idxer.GetTranslationUnitsFor(Ent, DEA); +} + +void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) { + assert(D && "Passed null declaration"); + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { + RefSelectorAnalyzer RSA(MD, Prog, Handler); + GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog); + Idxer.GetTranslationUnitsFor(Sel, RSA); + return; + } + + Entity Ent = Entity::get(D, Prog); + if (Ent.isInvalid()) + return; + + RefEntityAnalyzer REA(Ent, Handler); + Idxer.GetTranslationUnitsFor(Ent, REA); +} + +/// \brief Find methods that may respond to the given message and pass them +/// to Handler. +void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg, + TULocationHandler &Handler) { + assert(Msg); + MessageAnalyzer MsgAnalyz(Msg, Prog, Handler); + GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog); + Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz); +} diff --git a/contrib/llvm/tools/clang/lib/Index/CallGraph.cpp b/contrib/llvm/tools/clang/lib/Index/CallGraph.cpp new file mode 100644 index 0000000..741e781 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/CallGraph.cpp @@ -0,0 +1,150 @@ +//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the CallGraph and CGBuilder classes. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/CallGraph.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/StmtVisitor.h" + +#include "llvm/Support/GraphWriter.h" + +using namespace clang; +using namespace idx; + +namespace { +class CGBuilder : public StmtVisitor<CGBuilder> { + + CallGraph &G; + FunctionDecl *FD; + + Entity CallerEnt; + + CallGraphNode *CallerNode; + +public: + CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N) + : G(g), FD(fd), CallerEnt(E), CallerNode(N) {} + + void VisitStmt(Stmt *S) { VisitChildren(S); } + + void VisitCallExpr(CallExpr *CE); + + void VisitChildren(Stmt *S) { + for (Stmt::child_range I = S->children(); I; ++I) + if (*I) + static_cast<CGBuilder*>(this)->Visit(*I); + } +}; +} + +void CGBuilder::VisitCallExpr(CallExpr *CE) { + if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) { + Entity Ent = Entity::get(CalleeDecl, G.getProgram()); + CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent); + CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode); + } +} + +CallGraph::CallGraph(Program &P) : Prog(P), Root(0) { + ExternalCallingNode = getOrInsertFunction(Entity()); +} + +CallGraph::~CallGraph() { + if (!FunctionMap.empty()) { + for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); + I != E; ++I) + delete I->second; + FunctionMap.clear(); + } +} + +void CallGraph::addTU(ASTContext& Ctx) { + DeclContext *DC = Ctx.getTranslationUnitDecl(); + for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); + I != E; ++I) { + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { + if (FD->doesThisDeclarationHaveABody()) { + // Set caller's ASTContext. + Entity Ent = Entity::get(FD, Prog); + CallGraphNode *Node = getOrInsertFunction(Ent); + CallerCtx[Node] = &Ctx; + + // If this function has external linkage, anything could call it. + if (FD->isGlobal()) + ExternalCallingNode->addCallee(idx::ASTLocation(), Node); + + // Set root node to 'main' function. + if (FD->getNameAsString() == "main") + Root = Node; + + CGBuilder builder(*this, FD, Ent, Node); + builder.Visit(FD->getBody()); + } + } + } +} + +CallGraphNode *CallGraph::getOrInsertFunction(Entity F) { + CallGraphNode *&Node = FunctionMap[F]; + if (Node) + return Node; + + return Node = new CallGraphNode(F); +} + +Decl *CallGraph::getDecl(CallGraphNode *Node) { + // Get the function's context. + ASTContext *Ctx = CallerCtx[Node]; + + return Node->getDecl(*Ctx); +} + +void CallGraph::print(raw_ostream &os) { + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I->second->hasCallee()) { + os << "function: " << I->first.getPrintableName() + << " calls:\n"; + for (CallGraphNode::iterator CI = I->second->begin(), + CE = I->second->end(); CI != CE; ++CI) { + os << " " << CI->second->getName(); + } + os << '\n'; + } + } +} + +void CallGraph::dump() { + print(llvm::errs()); +} + +void CallGraph::ViewCallGraph() const { + llvm::ViewGraph(*this, "CallGraph"); +} + +namespace llvm { + +template <> +struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + static std::string getNodeLabel(const CallGraphNode *Node, + const CallGraph &CG) { + return Node->getName(); + + } + +}; + +} diff --git a/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp b/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp new file mode 100644 index 0000000..3fd4336 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp @@ -0,0 +1,90 @@ +//===--- DeclReferenceMap.cpp - Map Decls to their references -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// DeclReferenceMap creates a mapping from Decls to the ASTLocations that +// reference them. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/DeclReferenceMap.h" +#include "clang/Index/ASTLocation.h" +#include "ASTVisitor.h" +using namespace clang; +using namespace idx; + +namespace { + +class RefMapper : public ASTVisitor<RefMapper> { + DeclReferenceMap::MapTy ⤅ + +public: + RefMapper(DeclReferenceMap::MapTy &map) : Map(map) { } + + void VisitDeclRefExpr(DeclRefExpr *Node); + void VisitMemberExpr(MemberExpr *Node); + void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); + + void VisitTypedefTypeLoc(TypedefTypeLoc TL); + void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); +}; + +} // anonymous namespace + +//===----------------------------------------------------------------------===// +// RefMapper Implementation +//===----------------------------------------------------------------------===// + +void RefMapper::VisitDeclRefExpr(DeclRefExpr *Node) { + NamedDecl *PrimD = cast<NamedDecl>(Node->getDecl()->getCanonicalDecl()); + Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node))); +} + +void RefMapper::VisitMemberExpr(MemberExpr *Node) { + NamedDecl *PrimD = cast<NamedDecl>(Node->getMemberDecl()->getCanonicalDecl()); + Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node))); +} + +void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { + Map.insert(std::make_pair(Node->getDecl(), ASTLocation(CurrentDecl, Node))); +} + +void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) { + NamedDecl *ND = TL.getTypedefNameDecl(); + Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc()))); +} + +void RefMapper::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { + NamedDecl *ND = TL.getIFaceDecl(); + Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc()))); +} + +//===----------------------------------------------------------------------===// +// DeclReferenceMap Implementation +//===----------------------------------------------------------------------===// + +DeclReferenceMap::DeclReferenceMap(ASTContext &Ctx) { + RefMapper(Map).Visit(Ctx.getTranslationUnitDecl()); +} + +DeclReferenceMap::astlocation_iterator +DeclReferenceMap::refs_begin(NamedDecl *D) const { + NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl()); + return astlocation_iterator(Map.lower_bound(Prim)); +} + +DeclReferenceMap::astlocation_iterator +DeclReferenceMap::refs_end(NamedDecl *D) const { + NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl()); + return astlocation_iterator(Map.upper_bound(Prim)); +} + +bool DeclReferenceMap::refs_empty(NamedDecl *D) const { + NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl()); + return refs_begin(Prim) == refs_end(Prim); +} diff --git a/contrib/llvm/tools/clang/lib/Index/Entity.cpp b/contrib/llvm/tools/clang/lib/Index/Entity.cpp new file mode 100644 index 0000000..fbab6d8 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/Entity.cpp @@ -0,0 +1,270 @@ +//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Entity is a ASTContext-independent way to refer to declarations that are +// visible across translation units. +// +//===----------------------------------------------------------------------===// + +#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" +using namespace clang; +using namespace idx; + +// FIXME: Entity is really really basic currently, mostly written to work +// on variables and functions. Should support types and other decls eventually.. + + +//===----------------------------------------------------------------------===// +// EntityGetter +//===----------------------------------------------------------------------===// + +namespace clang { +namespace idx { + +/// \brief Gets the Entity associated with a Decl. +class EntityGetter : public DeclVisitor<EntityGetter, Entity> { + Program &Prog; + ProgramImpl &ProgImpl; + +public: + EntityGetter(Program &prog, ProgramImpl &progImpl) + : Prog(prog), ProgImpl(progImpl) { } + + // Get an Entity. + Entity getEntity(Entity Parent, DeclarationName Name, + unsigned IdNS, bool isObjCInstanceMethod); + + // Get an Entity associated with the name in the global namespace. + Entity getGlobalEntity(StringRef Name); + + Entity VisitNamedDecl(NamedDecl *D); + Entity VisitVarDecl(VarDecl *D); + Entity VisitFieldDecl(FieldDecl *D); + Entity VisitFunctionDecl(FunctionDecl *D); + Entity VisitTypeDecl(TypeDecl *D); +}; + +} +} + +Entity EntityGetter::getEntity(Entity Parent, DeclarationName Name, + unsigned IdNS, bool isObjCInstanceMethod) { + llvm::FoldingSetNodeID ID; + EntityImpl::Profile(ID, Parent, Name, IdNS, isObjCInstanceMethod); + + ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities(); + void *InsertPos = 0; + if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos)) + return Entity(Ent); + + void *Buf = ProgImpl.Allocate(sizeof(EntityImpl)); + EntityImpl *New = + new (Buf) EntityImpl(Parent, Name, IdNS, isObjCInstanceMethod); + Entities.InsertNode(New, InsertPos); + + return Entity(New); +} + +Entity EntityGetter::getGlobalEntity(StringRef Name) { + IdentifierInfo *II = &ProgImpl.getIdents().get(Name); + DeclarationName GlobName(II); + unsigned IdNS = Decl::IDNS_Ordinary; + return getEntity(Entity(), GlobName, IdNS, false); +} + +Entity EntityGetter::VisitNamedDecl(NamedDecl *D) { + Entity Parent; + if (!D->getDeclContext()->isTranslationUnit()) { + Parent = Visit(cast<Decl>(D->getDeclContext())); + // FIXME: Anonymous structs ? + if (Parent.isInvalid()) + return Entity(); + } + if (Parent.isValid() && Parent.isInternalToTU()) + return Entity(D); + + // FIXME: Only works for DeclarationNames that are identifiers and selectors. + // Treats other DeclarationNames as internal Decls for now.. + + DeclarationName LocalName = D->getDeclName(); + if (!LocalName) + return Entity(D); + + DeclarationName GlobName; + + if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) { + IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName()); + 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); + + unsigned IdNS = D->getIdentifierNamespace(); + + ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D); + bool isObjCInstanceMethod = MD && MD->isInstanceMethod(); + return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod); +} + +Entity EntityGetter::VisitVarDecl(VarDecl *D) { + // Local variables have no linkage, make invalid Entities. + if (D->hasLocalStorage()) + return Entity(); + + // If it's static it cannot be referred to by another translation unit. + if (D->getStorageClass() == SC_Static) + return Entity(D); + + return VisitNamedDecl(D); +} + +Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) { + // If it's static it cannot be referred to by another translation unit. + if (D->getStorageClass() == SC_Static) + return Entity(D); + + return VisitNamedDecl(D); +} + +Entity EntityGetter::VisitFieldDecl(FieldDecl *D) { + // Make FieldDecl an invalid Entity since it has no linkage. + return Entity(); +} + +Entity EntityGetter::VisitTypeDecl(TypeDecl *D) { + // Although in C++ class name has external linkage, usually the definition of + // the class is available in the same translation unit when it's needed. So we + // make all of them invalid Entity. + return Entity(); +} + +//===----------------------------------------------------------------------===// +// EntityImpl Implementation +//===----------------------------------------------------------------------===// + +Decl *EntityImpl::getDecl(ASTContext &AST) { + DeclContext *DC = + Parent.isInvalid() ? AST.getTranslationUnitDecl() + : cast<DeclContext>(Parent.getDecl(AST)); + if (!DC) + return 0; // Couldn't get the parent context. + + DeclarationName LocalName; + + if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) { + IdentifierInfo &II = AST.Idents.get(GlobII->getName()); + 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) { + Decl *D = *I; + if (D->getIdentifierNamespace() == IdNS) { + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { + if (MD->isInstanceMethod() == IsObjCInstanceMethod) + return MD; + } else + return D; + } + } + + return 0; // Failed to find a decl using this Entity. +} + +/// \brief Get an Entity associated with the given Decl. +/// \returns Null if an Entity cannot refer to this Decl. +Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) { + assert(D && "Passed null Decl"); + return EntityGetter(Prog, ProgImpl).Visit(D); +} + +/// \brief Get an Entity associated with a global name. +Entity EntityImpl::get(StringRef Name, Program &Prog, + ProgramImpl &ProgImpl) { + return EntityGetter(Prog, ProgImpl).getGlobalEntity(Name); +} + +std::string EntityImpl::getPrintableName() { + return Name.getAsString(); +} + +//===----------------------------------------------------------------------===// +// Entity Implementation +//===----------------------------------------------------------------------===// + +Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { } + +/// \brief Find the Decl that can be referred to by this entity. +Decl *Entity::getDecl(ASTContext &AST) const { + if (isInvalid()) + return 0; + + if (Decl *D = Val.dyn_cast<Decl *>()) + // Check that the passed AST is actually the one that this Decl belongs to. + return (&D->getASTContext() == &AST) ? D : 0; + + return Val.get<EntityImpl *>()->getDecl(AST); +} + +std::string Entity::getPrintableName() const { + if (isInvalid()) + return "<< Invalid >>"; + + if (Decl *D = Val.dyn_cast<Decl *>()) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) + return ND->getNameAsString(); + else + return std::string(); + } + + return Val.get<EntityImpl *>()->getPrintableName(); +} + +/// \brief Get an Entity associated with the given Decl. +/// \returns Null if an Entity cannot refer to this Decl. +Entity Entity::get(Decl *D, Program &Prog) { + if (D == 0) + return Entity(); + ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl); + return EntityImpl::get(D, Prog, ProgImpl); +} + +Entity Entity::get(StringRef Name, Program &Prog) { + ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl); + return EntityImpl::get(Name, Prog, ProgImpl); +} + +unsigned +llvm::DenseMapInfo<Entity>::getHashValue(Entity E) { + return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr()); +} diff --git a/contrib/llvm/tools/clang/lib/Index/EntityImpl.h b/contrib/llvm/tools/clang/lib/Index/EntityImpl.h new file mode 100644 index 0000000..6d6a0c6 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/EntityImpl.h @@ -0,0 +1,71 @@ +//===--- EntityImpl.h - Internal Entity implementation---------*- C++ -*-=====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Internal implementation for the Entity class +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_ENTITYIMPL_H +#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 { + +namespace idx { + class ProgramImpl; + +class EntityImpl : public llvm::FoldingSetNode { + Entity Parent; + 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, 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, Program &Prog, ProgramImpl &ProgImpl); + static Entity get(StringRef Name, Program &Prog, ProgramImpl &ProgImpl); + + std::string getPrintableName(); + + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, Parent, Name, IdNS, IsObjCInstanceMethod); + } + static void Profile(llvm::FoldingSetNodeID &ID, Entity Parent, + DeclarationName Name, unsigned IdNS, + bool isObjCInstanceMethod) { + ID.AddPointer(Parent.getAsOpaquePtr()); + ID.AddPointer(Name.getAsOpaquePtr()); + ID.AddInteger(IdNS); + ID.AddBoolean(isObjCInstanceMethod); + } +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp b/contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp new file mode 100644 index 0000000..2fe6f95 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp @@ -0,0 +1,71 @@ +//===-- GlobalSelector.cpp - Cross-translation-unit "token" for selectors -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// GlobalSelector is a ASTContext-independent way to refer to selectors. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/GlobalSelector.h" +#include "ProgramImpl.h" +#include "clang/Index/Program.h" +#include "clang/AST/ASTContext.h" +using namespace clang; +using namespace idx; + +/// \brief Get the ASTContext-specific selector. +Selector GlobalSelector::getSelector(ASTContext &AST) const { + if (isInvalid()) + return Selector(); + + Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val)); + + SmallVector<IdentifierInfo *, 8> Ids; + for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs(); + i != e; ++i) { + IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i); + IdentifierInfo *II = &AST.Idents.get(GlobII->getName()); + Ids.push_back(II); + } + + return AST.Selectors.getSelector(GlobSel.getNumArgs(), Ids.data()); +} + +/// \brief Get a printable name for debugging purpose. +std::string GlobalSelector::getPrintableName() const { + if (isInvalid()) + return "<< Invalid >>"; + + Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val)); + return GlobSel.getAsString(); +} + +/// \brief Get a GlobalSelector for the ASTContext-specific selector. +GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) { + if (Sel.isNull()) + return GlobalSelector(); + + ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl); + + SmallVector<IdentifierInfo *, 8> Ids; + for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs(); + i != e; ++i) { + IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i); + IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName()); + Ids.push_back(GlobII); + } + + Selector GlobSel = ProgImpl.getSelectors().getSelector(Sel.getNumArgs(), + Ids.data()); + return GlobalSelector(GlobSel.getAsOpaquePtr()); +} + +unsigned +llvm::DenseMapInfo<GlobalSelector>::getHashValue(GlobalSelector Sel) { + return DenseMapInfo<void*>::getHashValue(Sel.getAsOpaquePtr()); +} diff --git a/contrib/llvm/tools/clang/lib/Index/Handlers.cpp b/contrib/llvm/tools/clang/lib/Index/Handlers.cpp new file mode 100644 index 0000000..1e9a27d --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/Handlers.cpp @@ -0,0 +1,22 @@ +//===--- Handlers.cpp - Interfaces for receiving information ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Abstract interfaces for receiving information. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/Handlers.h" +#include "clang/Index/Entity.h" +using namespace clang; +using namespace idx; + +// Out-of-line to give the virtual tables a home. +EntityHandler::~EntityHandler() { } +TranslationUnitHandler::~TranslationUnitHandler() { } +TULocationHandler::~TULocationHandler() { } diff --git a/contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp b/contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp new file mode 100644 index 0000000..eea0988 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp @@ -0,0 +1,20 @@ +//===- IndexProvider.cpp - Maps information to translation units -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Maps information to TranslationUnits. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/IndexProvider.h" +#include "clang/Index/Entity.h" +using namespace clang; +using namespace idx; + +// Out-of-line to give the virtual table a home. +IndexProvider::~IndexProvider() { } diff --git a/contrib/llvm/tools/clang/lib/Index/Indexer.cpp b/contrib/llvm/tools/clang/lib/Index/Indexer.cpp new file mode 100644 index 0000000..ebba43c --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/Indexer.cpp @@ -0,0 +1,121 @@ +//===--- Indexer.cpp - IndexProvider implementation -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// IndexProvider implementation. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/Indexer.h" +#include "clang/Index/Program.h" +#include "clang/Index/Handlers.h" +#include "clang/Index/TranslationUnit.h" +#include "ASTVisitor.h" +#include "clang/AST/DeclBase.h" +using namespace clang; +using namespace idx; + +namespace { + +class EntityIndexer : public EntityHandler { + TranslationUnit *TU; + Indexer::MapTy ⤅ + Indexer::DefMapTy &DefMap; + +public: + EntityIndexer(TranslationUnit *tu, Indexer::MapTy &map, + Indexer::DefMapTy &defmap) + : TU(tu), Map(map), DefMap(defmap) { } + + virtual void Handle(Entity Ent) { + if (Ent.isInternalToTU()) + return; + Map[Ent].insert(TU); + + Decl *D = Ent.getDecl(TU->getASTContext()); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->doesThisDeclarationHaveABody()) + DefMap[Ent] = std::make_pair(FD, TU); + } +}; + +class SelectorIndexer : public ASTVisitor<SelectorIndexer> { + Program &Prog; + TranslationUnit *TU; + Indexer::SelMapTy ⤅ + +public: + SelectorIndexer(Program &prog, TranslationUnit *tu, Indexer::SelMapTy &map) + : Prog(prog), TU(tu), Map(map) { } + + void VisitObjCMethodDecl(ObjCMethodDecl *D) { + Map[GlobalSelector::get(D->getSelector(), Prog)].insert(TU); + Base::VisitObjCMethodDecl(D); + } + + void VisitObjCMessageExpr(ObjCMessageExpr *Node) { + Map[GlobalSelector::get(Node->getSelector(), Prog)].insert(TU); + Base::VisitObjCMessageExpr(Node); + } +}; + +} // anonymous namespace + +void Indexer::IndexAST(TranslationUnit *TU) { + assert(TU && "Passed null TranslationUnit"); + ASTContext &Ctx = TU->getASTContext(); + CtxTUMap[&Ctx] = TU; + EntityIndexer Idx(TU, Map, DefMap); + Prog.FindEntities(Ctx, Idx); + + SelectorIndexer SelIdx(Prog, TU, SelMap); + SelIdx.Visit(Ctx.getTranslationUnitDecl()); +} + +void Indexer::GetTranslationUnitsFor(Entity Ent, + TranslationUnitHandler &Handler) { + assert(Ent.isValid() && "Expected valid Entity"); + + if (Ent.isInternalToTU()) { + Decl *D = Ent.getInternalDecl(); + CtxTUMapTy::iterator I = CtxTUMap.find(&D->getASTContext()); + if (I != CtxTUMap.end()) + Handler.Handle(I->second); + return; + } + + MapTy::iterator I = Map.find(Ent); + if (I == Map.end()) + return; + + TUSetTy &Set = I->second; + for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I) + Handler.Handle(*I); +} + +void Indexer::GetTranslationUnitsFor(GlobalSelector Sel, + TranslationUnitHandler &Handler) { + assert(Sel.isValid() && "Expected valid GlobalSelector"); + + SelMapTy::iterator I = SelMap.find(Sel); + if (I == SelMap.end()) + return; + + TUSetTy &Set = I->second; + for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I) + Handler.Handle(*I); +} + +std::pair<FunctionDecl *, TranslationUnit *> +Indexer::getDefinitionFor(Entity Ent) { + DefMapTy::iterator I = DefMap.find(Ent); + if (I == DefMap.end()) + return std::make_pair((FunctionDecl *)0, (TranslationUnit *)0); + else + return I->second; +} diff --git a/contrib/llvm/tools/clang/lib/Index/Program.cpp b/contrib/llvm/tools/clang/lib/Index/Program.cpp new file mode 100644 index 0000000..4efad2c --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/Program.cpp @@ -0,0 +1,50 @@ +//===--- Program.cpp - Entity originator and misc -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Storage for Entities and utility functions +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/Program.h" +#include "ProgramImpl.h" +#include "clang/Index/Handlers.h" +#include "clang/Index/TranslationUnit.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/ASTContext.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; +using namespace idx; + +// Out-of-line to give the virtual tables a home. +TranslationUnit::~TranslationUnit() { } + +Program::Program() : Impl(new ProgramImpl()) { } + +Program::~Program() { + delete static_cast<ProgramImpl *>(Impl); +} + +static void FindEntitiesInDC(DeclContext *DC, Program &Prog, + EntityHandler &Handler) { + for (DeclContext::decl_iterator + I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { + if (I->getLocation().isInvalid()) + continue; + Entity Ent = Entity::get(*I, Prog); + if (Ent.isValid()) + Handler.Handle(Ent); + if (DeclContext *SubDC = dyn_cast<DeclContext>(*I)) + FindEntitiesInDC(SubDC, Prog, Handler); + } +} + +/// \brief Traverses the AST and passes all the entities to the Handler. +void Program::FindEntities(ASTContext &Ctx, EntityHandler &Handler) { + FindEntitiesInDC(Ctx.getTranslationUnitDecl(), *this, Handler); +} diff --git a/contrib/llvm/tools/clang/lib/Index/ProgramImpl.h b/contrib/llvm/tools/clang/lib/Index/ProgramImpl.h new file mode 100644 index 0000000..57b9ce3 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/ProgramImpl.h @@ -0,0 +1,56 @@ +//===--- ProgramImpl.h - Internal Program implementation---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Internal implementation for the Program class +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_PROGRAMIMPL_H +#define LLVM_CLANG_INDEX_PROGRAMIMPL_H + +#include "EntityImpl.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" + +namespace clang { + +namespace idx { + class EntityListener; + +class ProgramImpl { +public: + typedef llvm::FoldingSet<EntityImpl> EntitySetTy; + +private: + EntitySetTy Entities; + llvm::BumpPtrAllocator BumpAlloc; + + IdentifierTable Identifiers; + SelectorTable Selectors; + + ProgramImpl(const ProgramImpl&); // do not implement + ProgramImpl &operator=(const ProgramImpl &); // do not implement + +public: + ProgramImpl() : Identifiers(LangOptions()) { } + + EntitySetTy &getEntities() { return Entities; } + IdentifierTable &getIdents() { return Identifiers; } + SelectorTable &getSelectors() { return Selectors; } + + void *Allocate(unsigned Size, unsigned Align = 8) { + return BumpAlloc.Allocate(Size, Align); + } +}; + +} // namespace idx + +} // namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp b/contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp new file mode 100644 index 0000000..0f11e31 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp @@ -0,0 +1,84 @@ +//===- SelectorMap.cpp - Maps selectors to methods and messages -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// SelectorMap creates a mapping from selectors to ObjC method declarations +// and ObjC message expressions. +// +//===----------------------------------------------------------------------===// + +#include "clang/Index/SelectorMap.h" +#include "ASTVisitor.h" +using namespace clang; +using namespace idx; + +namespace { + +class SelMapper : public ASTVisitor<SelMapper> { + SelectorMap::SelMethMapTy &SelMethMap; + SelectorMap::SelRefMapTy &SelRefMap; + +public: + SelMapper(SelectorMap::SelMethMapTy &MethMap, + SelectorMap::SelRefMapTy &RefMap) + : SelMethMap(MethMap), SelRefMap(RefMap) { } + + void VisitObjCMethodDecl(ObjCMethodDecl *D); + void VisitObjCMessageExpr(ObjCMessageExpr *Node); + void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); +}; + +} // anonymous namespace + +//===----------------------------------------------------------------------===// +// SelMapper Implementation +//===----------------------------------------------------------------------===// + +void SelMapper::VisitObjCMethodDecl(ObjCMethodDecl *D) { + if (D->getCanonicalDecl() == D) + SelMethMap.insert(std::make_pair(D->getSelector(), D)); + Base::VisitObjCMethodDecl(D); +} + +void SelMapper::VisitObjCMessageExpr(ObjCMessageExpr *Node) { + ASTLocation ASTLoc(CurrentDecl, Node); + SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc)); +} + +void SelMapper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { + ASTLocation ASTLoc(CurrentDecl, Node); + SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc)); +} + +//===----------------------------------------------------------------------===// +// SelectorMap Implementation +//===----------------------------------------------------------------------===// + +SelectorMap::SelectorMap(ASTContext &Ctx) { + SelMapper(SelMethMap, SelRefMap).Visit(Ctx.getTranslationUnitDecl()); +} + +SelectorMap::method_iterator +SelectorMap::methods_begin(Selector Sel) const { + return method_iterator(SelMethMap.lower_bound(Sel)); +} + +SelectorMap::method_iterator +SelectorMap::methods_end(Selector Sel) const { + return method_iterator(SelMethMap.upper_bound(Sel)); +} + +SelectorMap::astlocation_iterator +SelectorMap::refs_begin(Selector Sel) const { + return astlocation_iterator(SelRefMap.lower_bound(Sel)); +} + +SelectorMap::astlocation_iterator +SelectorMap::refs_end(Selector Sel) const { + return astlocation_iterator(SelRefMap.upper_bound(Sel)); +} |