From d219a9a763a6e4fd3317f5bef2a09828a1d0af97 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 29 Jul 2009 23:40:32 +0000 Subject: [PATCH] Introduce the GlobalSelector class in the Indexing library. GlobalSelector is an ASTContext-independent way to refer to Objective C selectors. llvm-svn: 77538 --- clang/include/clang/Index/GlobalSelector.h | 95 ++++++++++++++++++++++ clang/include/clang/Index/Program.h | 1 + clang/lib/Index/GlobalSelector.cpp | 72 ++++++++++++++++ clang/lib/Index/ProgramImpl.h | 2 + 4 files changed, 170 insertions(+) create mode 100644 clang/include/clang/Index/GlobalSelector.h create mode 100644 clang/lib/Index/GlobalSelector.cpp diff --git a/clang/include/clang/Index/GlobalSelector.h b/clang/include/clang/Index/GlobalSelector.h new file mode 100644 index 000000000000..7bbd30326218 --- /dev/null +++ b/clang/include/clang/Index/GlobalSelector.h @@ -0,0 +1,95 @@ +//===--- GlobalSelector.h - 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_GLOBALSELECTOR_H +#define LLVM_CLANG_INDEX_GLOBALSELECTOR_H + +#include "llvm/ADT/DenseMap.h" +#include + +namespace clang { + class ASTContext; + class Selector; + +namespace idx { + class Program; + +/// \brief A ASTContext-independent way to refer to selectors. +class GlobalSelector { + void *Val; + + explicit GlobalSelector(void *val) : Val(val) { } + +public: + GlobalSelector() : Val(0) { } + + /// \brief Get the ASTContext-specific selector. + Selector getSelector(ASTContext &AST) const; + + bool isValid() const { return Val != 0; } + bool isInvalid() const { return !isValid(); } + + /// \brief Get a printable name for debugging purpose. + std::string getPrintableName() const; + + /// \brief Get a GlobalSelector for the ASTContext-specific selector. + static GlobalSelector get(Selector Sel, Program &Prog); + + void *getAsOpaquePtr() const { return Val; } + + friend bool operator==(const GlobalSelector &LHS, const GlobalSelector &RHS) { + return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr(); + } + + // For use in a std::map. + friend bool operator< (const GlobalSelector &LHS, const GlobalSelector &RHS) { + return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr(); + } + + // For use in DenseMap/DenseSet. + static GlobalSelector getEmptyMarker() { return GlobalSelector((void*)-1); } + static GlobalSelector getTombstoneMarker() { + return GlobalSelector((void*)-2); + } +}; + +} // namespace idx + +} // namespace clang + +namespace llvm { +/// Define DenseMapInfo so that GlobalSelectors can be used as keys in DenseMap +/// and DenseSets. +template<> +struct DenseMapInfo { + static inline clang::idx::GlobalSelector getEmptyKey() { + return clang::idx::GlobalSelector::getEmptyMarker(); + } + + static inline clang::idx::GlobalSelector getTombstoneKey() { + return clang::idx::GlobalSelector::getTombstoneMarker(); + } + + static unsigned getHashValue(clang::idx::GlobalSelector); + + static inline bool + isEqual(clang::idx::GlobalSelector LHS, clang::idx::GlobalSelector RHS) { + return LHS == RHS; + } + + static inline bool isPod() { return true; } +}; + +} // end namespace llvm + +#endif diff --git a/clang/include/clang/Index/Program.h b/clang/include/clang/Index/Program.h index b2bdaa6c2e24..a9e0b878d776 100644 --- a/clang/include/clang/Index/Program.h +++ b/clang/include/clang/Index/Program.h @@ -28,6 +28,7 @@ class Program { Program(const Program&); // do not implement Program &operator=(const Program &); // do not implement friend class Entity; + friend class GlobalSelector; public: Program(); diff --git a/clang/lib/Index/GlobalSelector.cpp b/clang/lib/Index/GlobalSelector.cpp new file mode 100644 index 000000000000..9b18741427a9 --- /dev/null +++ b/clang/lib/Index/GlobalSelector.cpp @@ -0,0 +1,72 @@ +//===-- 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(Val)); + + llvm::SmallVector 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(), + GlobII->getName() + GlobII->getLength()); + Ids.push_back(II); + } + + return AST.Selectors.getSelector(Ids.size(), Ids.data()); +} + +/// \brief Get a printable name for debugging purpose. +std::string GlobalSelector::getPrintableName() const { + if (isInvalid()) + return "<< Invalid >>"; + + Selector GlobSel = Selector(reinterpret_cast(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(Prog.Impl); + + llvm::SmallVector 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(), + II->getName() + II->getLength()); + Ids.push_back(GlobII); + } + + Selector GlobSel = ProgImpl.getSelectors().getSelector(Ids.size(),Ids.data()); + return GlobalSelector(GlobSel.getAsOpaquePtr()); +} + +unsigned +llvm::DenseMapInfo::getHashValue(GlobalSelector Sel) { + return DenseMapInfo::getHashValue(Sel.getAsOpaquePtr()); +} diff --git a/clang/lib/Index/ProgramImpl.h b/clang/lib/Index/ProgramImpl.h index b962a2d32754..1fbff9b32560 100644 --- a/clang/lib/Index/ProgramImpl.h +++ b/clang/lib/Index/ProgramImpl.h @@ -32,6 +32,7 @@ private: llvm::BumpPtrAllocator BumpAlloc; IdentifierTable Identifiers; + SelectorTable Selectors; ProgramImpl(const ProgramImpl&); // do not implement ProgramImpl &operator=(const ProgramImpl &); // do not implement @@ -41,6 +42,7 @@ public: EntitySetTy &getEntities() { return Entities; } IdentifierTable &getIdents() { return Identifiers; } + SelectorTable &getSelectors() { return Selectors; } void *Allocate(unsigned Size, unsigned Align = 8) { return BumpAlloc.Allocate(Size, Align);