text: //===--- Identifier.h - Uniqued Identifier ----------------------*- C++ -*-===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See https://swift.org/LICENSE.txt for license information
  // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  //
  // This file defines the Identifier interface.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_AST_IDENTIFIER_H
  #define SWIFT_AST_IDENTIFIER_H
  
  #include "swift/Basic/EditorPlaceholder.h"
  #include "swift/Basic/LLVM.h"
  #include "llvm/ADT/FoldingSet.h"
  #include "llvm/ADT/PointerUnion.h"
  #include "llvm/Support/TrailingObjects.h"
  
  namespace llvm {
    class raw_ostream;
  }
  
  namespace swift {
    class ASTContext;
    class ParameterList;
  
  /// DeclRefKind - The kind of reference to an identifier.
  enum class DeclRefKind {
    /// An ordinary reference to an identifier, e.g. 'foo'.
    Ordinary,
  
    /// A reference to an identifier as a binary operator, e.g. '+' in 'a+b'.
    BinaryOperator,
  
    /// A reference to an identifier as a postfix unary operator, e.g. '++' in
    /// 'a++'.
    PostfixOperator,
  
    /// A reference to an identifier as a prefix unary operator, e.g. '--' in
    /// '--a'.
    PrefixOperator
  };
  
  /// Identifier - This is an instance of a uniqued identifier created by
  /// ASTContext.  It just wraps a nul-terminated "const char*".
  class Identifier {
    friend class ASTContext;
    friend class DeclBaseName;
  
    const char *Pointer;
    
    /// Constructor, only accessible by ASTContext, which handles the uniquing.
    explicit Identifier(const char *Ptr) : Pointer(Ptr) {}
  public:
    explicit Identifier() : Pointer(nullptr) {}
    
    const char *get() const { return Pointer; }
    
    StringRef str() const { return Pointer; }
    
    unsigned getLength() const {
      assert(Pointer != nullptr && "Tried getting length of empty identifier");
      return ::strlen(Pointer);
    }
    
    bool empty() const { return Pointer == nullptr; }
  
    bool is(StringRef string) const { return str().equals(string); }
    
    /// isOperator - Return true if this identifier is an operator, false if it is
    /// a normal identifier.
    /// FIXME: We should maybe cache this.
    bool isOperator() const {
      if (empty())
        return false;
      if (isEditorPlaceholder())
        return false;
      if ((unsigned char)Pointer[0] < 0x80)
        return isOperatorStartCodePoint((unsigned char)Pointer[0]);
  
      // Handle the high unicode case out of line.
      return isOperatorSlow();
    }
    
    /// isOperatorStartCodePoint - Return true if the specified code point is a
    /// valid start of an operator.
    static bool isOperatorStartCodePoint(uint32_t C) {
      // ASCII operator chars.
      static const char OpChars[] = "/=-+*%<>!&|^~.?";
      if (C < 0x80)
        return memchr(OpChars, C, sizeof(OpChars) - 1) != 0;
      
      // Unicode math, symbol, arrow, dingbat, and line/box drawing chars.
      return (C >= 0x00A1 && C <= 0x00A7)
          || C == 0x00A9 || C == 0x00AB || C == 0x00AC || C == 0x00AE
          || C == 0x00B0 || C == 0x00B1 || C == 0x00B6 || C == 0x00BB
          || C == 0x00BF || C == 0x00D7 || C == 0x00F7
          || C == 0x2016 || C == 0x2017 || (C >= 0x2020 && C <= 0x2027)
          || (C >= 0x2030 && C <= 0x203E) || (C >= 0x2041 && C <= 0x2053)
          || (C >= 0x2055 && C <= 0x205E) || (C >= 0x2190 && C <= 0x23FF)
          || (C >= 0x2500 && C <= 0x2775) || (C >= 0x2794 && C <= 0x2BFF)
          || (C >= 0x2E00 && C <= 0x2E7F) || (C >= 0x3001 && C <= 0x3003)
          || (C >= 0x3008 && C <= 0x3030);
    }
    
    /// isOperatorContinuationCodePoint - Return true if the specified code point
    /// is a valid operator code point.
    static bool isOperatorContinuationCodePoint(uint32_t C) {
      if (isOperatorStartCodePoint(C))
        return true;
  
      // Unicode combining characters and variation selectors.
      return (C >= 0x0300 && C <= 0x036F)
          || (C >= 0x1DC0 && C <= 0x1DFF)
          || (C >= 0x20D0 && C <= 0x20FF)
          || (C >= 0xFE00 && C <= 0xFE0F)
          || (C >= 0xFE20 && C <= 0xFE2F)
          || (C >= 0xE0100 && C <= 0xE01EF);
    }
  
    static bool isEditorPlaceholder(StringRef name) {
      return swift::isEditorPlaceholder(name);
    }
  
    bool isEditorPlaceholder() const {
      return !empty() && isEditorPlaceholder(str());
    }
    
    const void *getAsOpaquePointer() const {
        return static_cast<const void *>(Pointer);
    }
    
    static Identifier getFromOpaquePointer(void *P) {
      return Identifier((const char*)P);
    }
  
    /// Compare two identifiers, producing -1 if \c *this comes before \c other,
    /// 1 if \c *this comes after \c other, and 0 if they are equal.
    ///
    /// Null identifiers come after all other identifiers.
    int compare(Identifier other) const;
  
    bool operator==(Identifier RHS) const { return Pointer == RHS.Pointer; }
    bool operator!=(Identifier RHS) const { return !(*this==RHS); }
  
    bool operator<(Identifier RHS) const { return Pointer < RHS.Pointer; }
    
    static Identifier getEmptyKey() {
      return Identifier((const char*)
                        llvm::DenseMapInfo<const void*>::getEmptyKey());
    }
    static Identifier getTombstoneKey() {
      return Identifier((const char*)
                        llvm::DenseMapInfo<const void*>::getTombstoneKey());
    }
  
  private:
    bool isOperatorSlow() const;
  };
    
  class DeclName;
  class ObjCSelector;
  
  } // end namespace swift
  
  namespace llvm {
    raw_ostream &operator<<(raw_ostream &OS, swift::Identifier I);
    raw_ostream &operator<<(raw_ostream &OS, swift::DeclName I);
    raw_ostream &operator<<(raw_ostream &OS, swift::ObjCSelector S);
  
    // Identifiers hash just like pointers.
    template<> struct DenseMapInfo<swift::Identifier> {
      static swift::Identifier getEmptyKey() {
        return swift::Identifier::getEmptyKey();
      }
      static swift::Identifier getTombstoneKey() {
        return swift::Identifier::getTombstoneKey();
      }
      static unsigned getHashValue(swift::Identifier Val) {
        return DenseMapInfo<const void*>::getHashValue(Val.get());
      }
      static bool isEqual(swift::Identifier LHS, swift::Identifier RHS) {
        return LHS == RHS;
      }
    };
    
    // An Identifier is "pointer like".
    template<typename T> struct PointerLikeTypeTraits;
    template<>
    struct PointerLikeTypeTraits<swift::Identifier> {
    public:
      static inline void *getAsVoidPointer(swift::Identifier I) {
        return const_cast<void *>(I.getAsOpaquePointer());
      }
      static inline swift::Identifier getFromVoidPointer(void *P) {
        return swift::Identifier::getFromOpaquePointer(P);
      }
      enum { NumLowBitsAvailable = 2 };
    };
    
  } // end namespace llvm
  
  namespace swift {
  
  /// Wrapper that may either be an Identifier or a special name
  /// (e.g. for subscripts)
  class DeclBaseName {
  public:
    enum class Kind: uint8_t {
      Normal,
      Subscript,
      Constructor,
      Destructor
    };
    
  private:
    /// In a special DeclName represenenting a subscript, this opaque pointer
    /// is used as the data of the base name identifier.
    /// This is an implementation detail that should never leak outside of
    /// DeclName.
    static void *SubscriptIdentifierData;
    /// As above, for special constructor DeclNames.
    static void *ConstructorIdentifierData;
    /// As above, for special destructor DeclNames.
    static void *DestructorIdentifierData;
  
    Identifier Ident;
  
  public:
    DeclBaseName() : DeclBaseName(Identifier()) {}
  
    DeclBaseName(Identifier I) : Ident(I) {}
  
    static DeclBaseName createSubscript() {
      return DeclBaseName(Identifier((const char *)SubscriptIdentifierData));
    }
  
    static DeclBaseName createConstructor() {
      return DeclBaseName(Identifier((const char *)ConstructorIdentifierData));
    }
  
    static DeclBaseName createDestructor() {
      return DeclBaseName(Identifier((const char *)DestructorIdentifierData));
    }
  
    Kind getKind() const {
      if (Ident.get() == SubscriptIdentifierData) {
        return Kind::Subscript;
      } else if (Ident.get() == ConstructorIdentifierData) {
        return Kind::Constructor;
      } else if (Ident.get() == DestructorIdentifierData) {
          return Kind::Destructor;
      } else {
        return Kind::Normal;
      }
    }
  
    bool isSpecial() const { return getKind() != Kind::Normal; }
  
    /// Return the identifier backing the name. Assumes that the name is not
    /// special.
    Identifier getIdentifier() const {
      assert(!isSpecial() && "Cannot retrieve identifier from special names");
      return Ident;
    }
  
    bool empty() const { return !isSpecial() && getIdentifier().empty(); }
  
    bool isOperator() const {
      return !isSpecial() && getIdentifier().isOperator();
    }
  
    bool isEditorPlaceholder() const {
      return !isSpecial() && getIdentifier().isEditorPlaceholder();
    }
  
    /// A representation of the name to be displayed to users. May be ambiguous
    /// between identifiers and special names.
    StringRef userFacingName() const {
      if (empty())
        return "_";
  
      switch (getKind()) {
      case Kind::Normal:
        return getIdentifier().str();
      case Kind::Subscript:
        return "subscript";
      case Kind::Constructor:
        return "init";
      case Kind::Destructor:
        return "deinit";
      }
      llvm_unreachable("unhandled kind");
    }
  
    int compare(DeclBaseName other) const {
      return userFacingName().compare(other.userFacingName());
    }
  
    bool operator==(StringRef Str) const {
      return !isSpecial() && getIdentifier().is(Str);
    }
    bool operator!=(StringRef Str) const { return !(*this == Str); }
  
    bool operator==(DeclBaseName RHS) const { return Ident == RHS.Ident; }
    bool operator!=(DeclBaseName RHS) const { return !(*this == RHS); }
  
    bool operator<(DeclBaseName RHS) const {
      return Ident.get() < RHS.Ident.get();
    }
  
    const void *getAsOpaquePointer() const { return Ident.get(); }
  
    static DeclBaseName getFromOpaquePointer(void *P) {
      return Identifier::getFromOpaquePointer(P);
    }
  };
  
  } // end namespace swift
  
  namespace llvm {
  
  raw_ostream &operator<<(raw_ostream &OS, swift::DeclBaseName D);
  
  // DeclBaseNames hash just like pointers.
  template<> struct DenseMapInfo<swift::DeclBaseName> {
    static swift::DeclBaseName getEmptyKey() {
      return swift::Identifier::getEmptyKey();
    }
    static swift::DeclBaseName getTombstoneKey() {
      return swift::Identifier::getTombstoneKey();
    }
    static unsigned getHashValue(swift::DeclBaseName Val) {
      return DenseMapInfo<const void *>::getHashValue(Val.getAsOpaquePointer());
    }
    static bool isEqual(swift::DeclBaseName LHS, swift::DeclBaseName RHS) {
      return LHS == RHS;
    }
  };
  
  // A DeclBaseName is "pointer like".
  template <typename T> struct PointerLikeTypeTraits;
  template <> struct PointerLikeTypeTraits<swift::DeclBaseName> {
  public:
    static inline void *getAsVoidPointer(swift::DeclBaseName D) {
      return const_cast<void *>(D.getAsOpaquePointer());
    }
    static inline swift::DeclBaseName getFromVoidPointer(void *P) {
      return swift::DeclBaseName::getFromOpaquePointer(P);
    }
    enum { NumLowBitsAvailable = PointerLikeTypeTraits<swift::Identifier>::NumLowBitsAvailable };
  };
  
  } // end namespace llvm
  
  namespace swift {
  
  /// A declaration name, which may comprise one or more identifier pieces.
  class DeclName {
    friend class ASTContext;
  
    /// Represents a compound declaration name.
    struct alignas(Identifier) CompoundDeclName final : llvm::FoldingSetNode,
        private llvm::TrailingObjects<CompoundDeclName, Identifier> {
      friend TrailingObjects;
      friend class DeclName;
  
      DeclBaseName BaseName;
      size_t NumArgs;
  
      explicit CompoundDeclName(DeclBaseName BaseName, size_t NumArgs)
          : BaseName(BaseName), NumArgs(NumArgs) {
        assert(NumArgs > 0 && "Should use IdentifierAndCompound");
      }
      
      ArrayRef<Identifier> getArgumentNames() const {
        return {getTrailingObjects<Identifier>(), NumArgs};
      }
      MutableArrayRef<Identifier> getArgumentNames() {
        return {getTrailingObjects<Identifier>(), NumArgs};
      }
  
      /// Uniquing for the ASTContext.
      static void Profile(llvm::FoldingSetNodeID &id, DeclBaseName baseName,
                          ArrayRef<Identifier> argumentNames);
  
      void Profile(llvm::FoldingSetNodeID &id) {
        Profile(id, BaseName, getArgumentNames());
      }
    };
  
    // A single stored identifier, along with a bit stating whether it is the
    // base name for a zero-argument compound name.
    typedef llvm::PointerIntPair<DeclBaseName, 1, bool> BaseNameAndCompound;
  
    // Either a single identifier piece stored inline (with a bit to say whether
    // it is simple or compound), or a reference to a compound declaration name.
    llvm::PointerUnion<BaseNameAndCompound, CompoundDeclName *> SimpleOrCompound;
  
    DeclName(void *Opaque)
      : SimpleOrCompound(decltype(SimpleOrCompound)::getFromOpaqueValue(Opaque))
    {}
  
    void initialize(ASTContext &C, DeclBaseName baseName,
                    ArrayRef<Identifier> argumentNames);
  
  public:
    /// Build a null name.
    DeclName() : SimpleOrCompound(BaseNameAndCompound()) {}
  
    /// Build a simple value name with one component.
    /*implicit*/ DeclName(DeclBaseName simpleName)
        : SimpleOrCompound(BaseNameAndCompound(simpleName, false)) {}
  
    /*implicit*/ DeclName(Identifier simpleName)
        : DeclName(DeclBaseName(simpleName)) {}
  
    /// Build a compound value name given a base name and a set of argument names.
    DeclName(ASTContext &C, DeclBaseName baseName,
             ArrayRef<Identifier> argumentNames) {
      initialize(C, baseName, argumentNames);
    }
  
    /// Build a compound value name given a base name and a set of argument names
    /// extracted from a parameter list.
    DeclName(ASTContext &C, DeclBaseName baseName, ParameterList *paramList);
  
    /// Retrieve the 'base' name, i.e., the name that follows the introducer,
    /// such as the 'foo' in 'func foo(x:Int, y:Int)' or the 'bar' in
    /// 'var bar: Int'.
    DeclBaseName getBaseName() const {
      if (auto compound = SimpleOrCompound.dyn_cast<CompoundDeclName*>())
        return compound->BaseName;
  
      return SimpleOrCompound.get<BaseNameAndCompound>().getPointer();
    }
  
    /// Assert that the base name is not special and return its identifier.
    Identifier getBaseIdentifier() const {
      auto baseName = getBaseName();
      assert(!baseName.isSpecial() &&
             "Can't retrieve the identifier of a special base name");
      return baseName.getIdentifier();
    }
  
    /// Retrieve the names of the arguments, if there are any.
    ArrayRef<Identifier> getArgumentNames() const {
      if (auto compound = SimpleOrCompound.dyn_cast<CompoundDeclName*>())
        return compound->getArgumentNames();
  
      return { };
    }
  
    bool isSpecial() const { return getBaseName().isSpecial(); }
  
    explicit operator bool() const {
      if (SimpleOrCompound.dyn_cast<CompoundDeclName*>())
        return true;
      return !SimpleOrCompound.get<BaseNameAndCompound>().getPointer().empty();
    }
    
    /// True if this is a simple one-component name.
    bool isSimpleName() const {
      if (SimpleOrCompound.dyn_cast<CompoundDeclName*>())
        return false;
  
      return !SimpleOrCompound.get<BaseNameAndCompound>().getInt();
    }
  
    /// True if this is a compound name.
    bool isCompoundName() const {
      if (SimpleOrCompound.dyn_cast<CompoundDeclName*>())
        return true;
  
      return SimpleOrCompound.get<BaseNameAndCompound>().getInt();
    }
    
    /// True if this name is a simple one-component name identical to the
    /// given identifier.
    bool isSimpleName(DeclBaseName name) const {
      return isSimpleName() && getBaseName() == name;
    }
    
    /// True if this name is a simple one-component name equal to the
    /// given string.
    bool isSimpleName(StringRef name) const {
      return isSimpleName() && getBaseName() == name;
    }
  
    /// True if this name is a compound name equal to the given base name and
    /// argument names.
    bool isCompoundName(DeclBaseName base, ArrayRef<StringRef> args) const;
  
    /// True if this name is a compound name equal to the given normal
    /// base name and argument names.
    bool isCompoundName(StringRef base, ArrayRef<StringRef> args) const;
    
    /// True if this name is an operator.
    bool isOperator() const {
      return getBaseName().isOperator();
    }
    
    /// True if this name should be found by a decl ref or member ref under the
    /// name specified by 'refName'.
    ///
    /// We currently match compound names either when their first component
    /// matches a simple name lookup or when the full compound name matches.
    bool matchesRef(DeclName refName) const {
      // Identical names always match.
      if (SimpleOrCompound == refName.SimpleOrCompound)
        return true;
      // If the reference is a simple name, try simple name matching.
      if (refName.isSimpleName())
        return refName.getBaseName() == getBaseName();
      // The names don't match.
      return false;
    }
    
    /// Add a DeclName to a lookup table so that it can be found by its simple
    /// name or its compound name.
    template<typename LookupTable, typename Element>
    void addToLookupTable(LookupTable &table, const Element &elt) {
      table[*this].push_back(elt);
      if (!isSimpleName()) {
        table[getBaseName()].push_back(elt);
      }
    }
  
    /// Compare two declaration names, producing -1 if \c *this comes before
    /// \c other,  1 if \c *this comes after \c other, and 0 if they are equal.
    ///
    /// Null declaration names come after all other declaration names.
    int compare(DeclName other) const;
  
    friend bool operator==(DeclName lhs, DeclName rhs) {
      return lhs.getOpaqueValue() == rhs.getOpaqueValue();
    }
  
    friend bool operator!=(DeclName lhs, DeclName rhs) {
      return !(lhs == rhs);
    }
  
    friend bool operator<(DeclName lhs, DeclName rhs) {
      return lhs.compare(rhs) < 0;
    }
  
    friend bool operator<=(DeclName lhs, DeclName rhs) {
      return lhs.compare(rhs) <= 0;
    }
  
    friend bool operator>(DeclName lhs, DeclName rhs) {
      return lhs.compare(rhs) > 0;
    }
  
    friend bool operator>=(DeclName lhs, DeclName rhs) {
      return lhs.compare(rhs) >= 0;
    }
  
    void *getOpaqueValue() const { return SimpleOrCompound.getOpaqueValue(); }
    static DeclName getFromOpaqueValue(void *p) { return DeclName(p); }
  
    /// Get a string representation of the name,
    ///
    /// \param scratch Scratch space to use.
    StringRef getString(llvm::SmallVectorImpl<char> &scratch,
                        bool skipEmptyArgumentNames = false) const;
  
    /// Print the representation of this declaration name to the given
    /// stream.
    ///
    /// \param skipEmptyArgumentNames When true, don't print the argument labels
    /// if they are all empty.
    llvm::raw_ostream &print(llvm::raw_ostream &os,
                             bool skipEmptyArgumentNames = false) const;
  
    /// Print a "pretty" representation of this declaration name to the given
    /// stream.
    ///
    /// This is the name used for diagnostics; it is not necessarily the
    /// fully-specified name that would be written in the source.
    llvm::raw_ostream &printPretty(llvm::raw_ostream &os) const;
  
    /// Dump this name to standard error.
    LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
                              "only for use within the debugger");
  };
  
  enum class ObjCSelectorFamily : unsigned {
    None,
  #define OBJC_SELECTOR_FAMILY(LABEL, PREFIX) LABEL,
  #include "swift/AST/ObjCSelectorFamily.def"
  };
  
  /// Represents an Objective-C selector.
  class ObjCSelector {
    /// The storage for an Objective-C selector.
    ///
    /// A zero-argument selector is represented as simple name.
    /// A selector with N arguments is represented as a compound name with
    /// N arguments, where the simple name is a placeholder.
    DeclName Storage;
  
    explicit ObjCSelector(DeclName storage) : Storage(storage) { }
  
    friend struct llvm::DenseMapInfo<ObjCSelector>;
  
  public:
    /// Form a selector with the given number of arguments and the given selector
    /// pieces.
    ObjCSelector(ASTContext &ctx, unsigned numArgs, ArrayRef<Identifier> pieces);
  
    /// Construct an invalid ObjCSelector.
    ObjCSelector() : Storage() {}
  
    /// Convert to true if the decl name is valid.
    explicit operator bool() const { return (bool)Storage; }
  
    /// Determine the number of arguments in the selector.
    ///
    /// When this is zero, the number of selector pieces will be one. Otherwise,
    /// it equals the number of selector pieces.
    unsigned getNumArgs() const {
      if (Storage.isSimpleName()) {
        return 0;
      }
  
      return Storage.getArgumentNames().size();
    }
  
    /// Determine the number of selector pieces in the selector.
    ///
    /// When this is one, the number of arguments may either be zero or one.
    /// Otherwise, it equals the number of arguments.
    unsigned getNumSelectorPieces() const {
      return getSelectorPieces().size();
    }
  
    /// Retrieve the pieces in this selector.
    ArrayRef<Identifier> getSelectorPieces() const {
      if (Storage.isSimpleName()) {
        return { reinterpret_cast<const Identifier*>(&Storage), 1 };
      }
  
      return Storage.getArgumentNames();
    }
  
    /// Asserts that this is a nullary selector and returns the single identifier.
    Identifier getSimpleName() const {
      assert(Storage.isSimpleName() && "not a nullary selector");
      return Storage.getBaseIdentifier();
    }
  
    /// Get a string representation of the selector.
    ///
    /// \param scratch Scratch space to use.
    StringRef getString(llvm::SmallVectorImpl<char> &scratch) const;
  
    ObjCSelectorFamily getSelectorFamily() const;
  
    void *getOpaqueValue() const { return Storage.getOpaqueValue(); }
    static ObjCSelector getFromOpaqueValue(void *p) {
      return ObjCSelector(DeclName::getFromOpaqueValue(p));
    }
  
    /// Dump this selector to standard error.
    LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
                              "only for use within the debugger");
  
    /// Compare two Objective-C selectors, producing -1 if \c *this comes before
    /// \c other,  1 if \c *this comes after \c other, and 0 if they are equal.
    int compare(ObjCSelector other) const {
      return Storage.compare(other.Storage);
    }
  
    friend bool operator==(ObjCSelector lhs, ObjCSelector rhs) {
      return lhs.getOpaqueValue() == rhs.getOpaqueValue();
    }
  
    friend bool operator!=(ObjCSelector lhs, ObjCSelector rhs) {
      return !(lhs == rhs);
    }
  
    friend bool operator<(ObjCSelector lhs, ObjCSelector rhs) {
      return lhs.compare(rhs) < 0;
    }
  
    friend bool operator<=(ObjCSelector lhs, ObjCSelector rhs) {
      return lhs.compare(rhs) <= 0;
    }
  
    friend bool operator>(ObjCSelector lhs, ObjCSelector rhs) {
      return lhs.compare(rhs) > 0;
    }
  
    friend bool operator>=(ObjCSelector lhs, ObjCSelector rhs) {
      return lhs.compare(rhs) >= 0;
    }
  };
  
  } // end namespace swift
  
  namespace llvm {
    // A DeclName is "pointer like".
    template<typename T> struct PointerLikeTypeTraits;
    template<>
    struct PointerLikeTypeTraits<swift::DeclName> {
    public:
      static inline void *getAsVoidPointer(swift::DeclName name) {
        return name.getOpaqueValue();
      }
      static inline swift::DeclName getFromVoidPointer(void *ptr) {
        return swift::DeclName::getFromOpaqueValue(ptr);
      }
      enum { NumLowBitsAvailable = 0 };
    };
  
    // DeclNames hash just like pointers.
    template<> struct DenseMapInfo<swift::DeclName> {
      static swift::DeclName getEmptyKey() {
        return swift::Identifier::getEmptyKey();
      }
      static swift::DeclName getTombstoneKey() {
        return swift::Identifier::getTombstoneKey();
      }
      static unsigned getHashValue(swift::DeclName Val) {
        return DenseMapInfo<void*>::getHashValue(Val.getOpaqueValue());
      }
      static bool isEqual(swift::DeclName LHS, swift::DeclName RHS) {
        return LHS.getOpaqueValue() == RHS.getOpaqueValue();
      }
    };
  
    // An ObjCSelector is "pointer like".
    template<typename T> struct PointerLikeTypeTraits;
    template<>
    struct PointerLikeTypeTraits<swift::ObjCSelector> {
    public:
      static inline void *getAsVoidPointer(swift::ObjCSelector name) {
        return name.getOpaqueValue();
      }
      static inline swift::ObjCSelector getFromVoidPointer(void *ptr) {
        return swift::ObjCSelector::getFromOpaqueValue(ptr);
      }
      enum { NumLowBitsAvailable = 0 };
    };
  
    // ObjCSelectors hash just like pointers.
    template<> struct DenseMapInfo<swift::ObjCSelector> {
      static swift::ObjCSelector getEmptyKey() {
        return swift::ObjCSelector(DenseMapInfo<swift::DeclName>::getEmptyKey());
      }
      static swift::ObjCSelector getTombstoneKey() {
        return swift::ObjCSelector(
                 DenseMapInfo<swift::DeclName>::getTombstoneKey());
      }
      static unsigned getHashValue(swift::ObjCSelector Val) {
        return DenseMapInfo<void*>::getHashValue(Val.getOpaqueValue());
      }
      static bool isEqual(swift::ObjCSelector LHS, swift::ObjCSelector RHS) {
        return LHS.getOpaqueValue() == RHS.getOpaqueValue();
      }
    };
  } // end namespace llvm
  
  #endif
  