//===- DeclarationName.h - Representation of declaration names --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the DeclarationName and DeclarationNameTable classes.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
#define LLVM_CLANG_AST_DECLARATIONNAME_H

#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
#include <cstdint>
#include <cstring>
#include <string>

namespace clang {

class ASTContext;
template <typename> class CanQual;
class DeclarationName;
class DeclarationNameTable;
class MultiKeywordSelector;
struct PrintingPolicy;
class TemplateDecl;
class TypeSourceInfo;
class UsingDirectiveDecl;

using CanQualType = CanQual<Type>;

namespace detail {

/// CXXSpecialNameExtra records the type associated with one of the "special"
/// kinds of declaration names in C++, e.g., constructors, destructors, and
/// conversion functions. Note that CXXSpecialName is used for C++ constructor,
/// destructor and conversion functions, but the actual kind is not stored in
/// CXXSpecialName. Instead we use three different FoldingSet<CXXSpecialName>
/// in DeclarationNameTable.
class alignas(IdentifierInfoAlignment) CXXSpecialNameExtra
    : public llvm::FoldingSetNode {
  friend class clang::DeclarationName;
  friend class clang::DeclarationNameTable;

  /// The type associated with this declaration name.
  QualType Type;

  /// Extra information associated with this declaration name that
  /// can be used by the front end. All bits are really needed
  /// so it is not possible to stash something in the low order bits.
  void *FETokenInfo;

  CXXSpecialNameExtra(QualType QT) : Type(QT), FETokenInfo(nullptr) {}

public:
  void Profile(llvm::FoldingSetNodeID &ID) {
    ID.AddPointer(Type.getAsOpaquePtr());
  }
};

/// Contains extra information for the name of a C++ deduction guide.
class alignas(IdentifierInfoAlignment) CXXDeductionGuideNameExtra
    : public detail::DeclarationNameExtra,
      public llvm::FoldingSetNode {
  friend class clang::DeclarationName;
  friend class clang::DeclarationNameTable;

  /// The template named by the deduction guide.
  TemplateDecl *Template;

  /// Extra information associated with this operator name that
  /// can be used by the front end. All bits are really needed
  /// so it is not possible to stash something in the low order bits.
  void *FETokenInfo;

  CXXDeductionGuideNameExtra(TemplateDecl *TD)
      : DeclarationNameExtra(CXXDeductionGuideName), Template(TD),
        FETokenInfo(nullptr) {}

public:
  void Profile(llvm::FoldingSetNodeID &ID) { ID.AddPointer(Template); }
};

/// Contains extra information for the name of an overloaded operator
/// in C++, such as "operator+. This do not includes literal or conversion
/// operators. For literal operators see CXXLiteralOperatorIdName and for
/// conversion operators see CXXSpecialNameExtra.
class alignas(IdentifierInfoAlignment) CXXOperatorIdName {
  friend class clang::DeclarationName;
  friend class clang::DeclarationNameTable;

  /// The kind of this operator.
  OverloadedOperatorKind Kind = OO_None;

  /// Extra information associated with this operator name that
  /// can be used by the front end. All bits are really needed
  /// so it is not possible to stash something in the low order bits.
  void *FETokenInfo = nullptr;
};

/// Contains the actual identifier that makes up the
/// name of a C++ literal operator.
class alignas(IdentifierInfoAlignment) CXXLiteralOperatorIdName
    : public detail::DeclarationNameExtra,
      public llvm::FoldingSetNode {
  friend class clang::DeclarationName;
  friend class clang::DeclarationNameTable;

  IdentifierInfo *ID;

  /// Extra information associated with this operator name that
  /// can be used by the front end. All bits are really needed
  /// so it is not possible to stash something in the low order bits.
  void *FETokenInfo;

  CXXLiteralOperatorIdName(IdentifierInfo *II)
      : DeclarationNameExtra(CXXLiteralOperatorName), ID(II),
        FETokenInfo(nullptr) {}

public:
  void Profile(llvm::FoldingSetNodeID &FSID) { FSID.AddPointer(ID); }
};

} // namespace detail

/// The name of a declaration. In the common case, this just stores
/// an IdentifierInfo pointer to a normal name. However, it also provides
/// encodings for Objective-C selectors (optimizing zero- and one-argument
/// selectors, which make up 78% percent of all selectors in Cocoa.h),
/// special C++ names for constructors, destructors, and conversion functions,
/// and C++ overloaded operators.
class DeclarationName {
  friend class DeclarationNameTable;
  friend class NamedDecl;

  /// StoredNameKind represent the kind of name that is actually stored in the
  /// upper bits of the Ptr field. This is only used internally.
  ///
  /// NameKind, StoredNameKind, and DeclarationNameExtra::ExtraKind
  /// must satisfy the following properties. These properties enable
  /// efficient conversion between the various kinds.
  ///
  /// * The first seven enumerators of StoredNameKind must have the same
  ///   numerical value as the first seven enumerators of NameKind.
  ///   This enable efficient conversion between the two enumerations
  ///   in the usual case.
  ///
  /// * The enumerations values of DeclarationNameExtra::ExtraKind must start
  ///   at zero, and correspond to the numerical value of the first non-inline
  ///   enumeration values of NameKind minus an offset. This makes conversion
  ///   between DeclarationNameExtra::ExtraKind and NameKind possible with
  ///   a single addition/substraction.
  ///
  /// * The enumeration values of Selector::IdentifierInfoFlag must correspond
  ///   to the relevant enumeration values of StoredNameKind.
  ///   More specifically:
  ///    * ZeroArg == StoredObjCZeroArgSelector,
  ///    * OneArg == StoredObjCOneArgSelector,
  ///    * MultiArg == StoredDeclarationNameExtra
  ///
  /// * PtrMask must mask the low 3 bits of Ptr.
  enum StoredNameKind {
    StoredIdentifier = 0,
    StoredObjCZeroArgSelector = Selector::ZeroArg,
    StoredObjCOneArgSelector = Selector::OneArg,
    StoredCXXConstructorName = 3,
    StoredCXXDestructorName = 4,
    StoredCXXConversionFunctionName = 5,
    StoredCXXOperatorName = 6,
    StoredDeclarationNameExtra = Selector::MultiArg,
    PtrMask = 7,
    UncommonNameKindOffset = 8
  };

  static_assert(alignof(IdentifierInfo) >= 8 &&
                    alignof(detail::DeclarationNameExtra) >= 8 &&
                    alignof(detail::CXXSpecialNameExtra) >= 8 &&
                    alignof(detail::CXXOperatorIdName) >= 8 &&
                    alignof(detail::CXXDeductionGuideNameExtra) >= 8 &&
                    alignof(detail::CXXLiteralOperatorIdName) >= 8,
                "The various classes that DeclarationName::Ptr can point to"
                " must be at least aligned to 8 bytes!");

public:
  /// The kind of the name stored in this DeclarationName.
  /// The first 7 enumeration values are stored inline and correspond
  /// to frequently used kinds. The rest is stored in DeclarationNameExtra
  /// and correspond to infrequently used kinds.
  enum NameKind {
    Identifier = StoredIdentifier,
    ObjCZeroArgSelector = StoredObjCZeroArgSelector,
    ObjCOneArgSelector = StoredObjCOneArgSelector,
    CXXConstructorName = StoredCXXConstructorName,
    CXXDestructorName = StoredCXXDestructorName,
    CXXConversionFunctionName = StoredCXXConversionFunctionName,
    CXXOperatorName = StoredCXXOperatorName,
    CXXDeductionGuideName = UncommonNameKindOffset +
                            detail::DeclarationNameExtra::CXXDeductionGuideName,
    CXXLiteralOperatorName =
        UncommonNameKindOffset +
        detail::DeclarationNameExtra::CXXLiteralOperatorName,
    CXXUsingDirective = UncommonNameKindOffset +
                        detail::DeclarationNameExtra::CXXUsingDirective,
    ObjCMultiArgSelector = UncommonNameKindOffset +
                           detail::DeclarationNameExtra::ObjCMultiArgSelector
  };

private:
  /// The lowest three bits of Ptr are used to express what kind of name
  /// we're actually storing, using the values of StoredNameKind. Depending
  /// on the kind of name this is, the upper bits of Ptr may have one
  /// of several different meanings:
  ///
  ///   StoredIdentifier - The name is a normal identifier, and Ptr is
  ///   a normal IdentifierInfo pointer.
  ///
  ///   StoredObjCZeroArgSelector - The name is an Objective-C
  ///   selector with zero arguments, and Ptr is an IdentifierInfo
  ///   pointer pointing to the selector name.
  ///
  ///   StoredObjCOneArgSelector - The name is an Objective-C selector
  ///   with one argument, and Ptr is an IdentifierInfo pointer
  ///   pointing to the selector name.
  ///
  ///   StoredCXXConstructorName - The name of a C++ constructor,
  ///   Ptr points to a CXXSpecialNameExtra.
  ///
  ///   StoredCXXDestructorName - The name of a C++ destructor,
  ///   Ptr points to a CXXSpecialNameExtra.
  ///
  ///   StoredCXXConversionFunctionName - The name of a C++ conversion function,
  ///   Ptr points to a CXXSpecialNameExtra.
  ///
  ///   StoredCXXOperatorName - The name of an overloaded C++ operator,
  ///   Ptr points to a CXXOperatorIdName.
  ///
  ///   StoredDeclarationNameExtra - Ptr is actually a pointer to a
  ///   DeclarationNameExtra structure, whose first value will tell us
  ///   whether this is an Objective-C selector, C++ deduction guide,
  ///   C++ literal operator, or C++ using directive.
  uintptr_t Ptr = 0;

  StoredNameKind getStoredNameKind() const {
    return static_cast<StoredNameKind>(Ptr & PtrMask);
  }

  void *getPtr() const { return reinterpret_cast<void *>(Ptr & ~PtrMask); }

  void setPtrAndKind(const void *P, StoredNameKind Kind) {
    uintptr_t PAsInteger = reinterpret_cast<uintptr_t>(P);
    assert((Kind & ~PtrMask) == 0 &&
           "Invalid StoredNameKind in setPtrAndKind!");
    assert((PAsInteger & PtrMask) == 0 &&
           "Improperly aligned pointer in setPtrAndKind!");
    Ptr = PAsInteger | Kind;
  }

  /// Construct a declaration name from a DeclarationNameExtra.
  DeclarationName(detail::DeclarationNameExtra *Name) {
    setPtrAndKind(Name, StoredDeclarationNameExtra);
  }

  /// Construct a declaration name from a CXXSpecialNameExtra.
  DeclarationName(detail::CXXSpecialNameExtra *Name,
                  StoredNameKind StoredKind) {
    assert((StoredKind == StoredCXXConstructorName ||
           StoredKind == StoredCXXDestructorName ||
           StoredKind == StoredCXXConversionFunctionName) &&
               "Invalid StoredNameKind when constructing a DeclarationName"
               " from a CXXSpecialNameExtra!");
    setPtrAndKind(Name, StoredKind);
  }

  /// Construct a DeclarationName from a CXXOperatorIdName.
  DeclarationName(detail::CXXOperatorIdName *Name) {
    setPtrAndKind(Name, StoredCXXOperatorName);
  }

  /// Assert that the stored pointer points to an IdentifierInfo and return it.
  IdentifierInfo *castAsIdentifierInfo() const {
    assert((getStoredNameKind() == StoredIdentifier) &&
           "DeclarationName does not store an IdentifierInfo!");
    return static_cast<IdentifierInfo *>(getPtr());
  }

  /// Assert that the stored pointer points to a DeclarationNameExtra
  /// and return it.
  detail::DeclarationNameExtra *castAsExtra() const {
    assert((getStoredNameKind() == StoredDeclarationNameExtra) &&
           "DeclarationName does not store an Extra structure!");
    return static_cast<detail::DeclarationNameExtra *>(getPtr());
  }

  /// Assert that the stored pointer points to a CXXSpecialNameExtra
  /// and return it.
  detail::CXXSpecialNameExtra *castAsCXXSpecialNameExtra() const {
    assert((getStoredNameKind() == StoredCXXConstructorName ||
           getStoredNameKind() == StoredCXXDestructorName ||
           getStoredNameKind() == StoredCXXConversionFunctionName) &&
               "DeclarationName does not store a CXXSpecialNameExtra!");
    return static_cast<detail::CXXSpecialNameExtra *>(getPtr());
  }

  /// Assert that the stored pointer points to a CXXOperatorIdName
  /// and return it.
  detail::CXXOperatorIdName *castAsCXXOperatorIdName() const {
    assert((getStoredNameKind() == StoredCXXOperatorName) &&
           "DeclarationName does not store a CXXOperatorIdName!");
    return static_cast<detail::CXXOperatorIdName *>(getPtr());
  }

  /// Assert that the stored pointer points to a CXXDeductionGuideNameExtra
  /// and return it.
  detail::CXXDeductionGuideNameExtra *castAsCXXDeductionGuideNameExtra() const {
    assert(getNameKind() == CXXDeductionGuideName &&
           "DeclarationName does not store a CXXDeductionGuideNameExtra!");
    return static_cast<detail::CXXDeductionGuideNameExtra *>(getPtr());
  }

  /// Assert that the stored pointer points to a CXXLiteralOperatorIdName
  /// and return it.
  detail::CXXLiteralOperatorIdName *castAsCXXLiteralOperatorIdName() const {
    assert(getNameKind() == CXXLiteralOperatorName &&
           "DeclarationName does not store a CXXLiteralOperatorIdName!");
    return static_cast<detail::CXXLiteralOperatorIdName *>(getPtr());
  }

  /// Get and set the FETokenInfo in the less common cases where the
  /// declaration name do not point to an identifier.
  void *getFETokenInfoSlow() const;
  void setFETokenInfoSlow(void *T);

public:
  /// Construct an empty declaration name.
  DeclarationName() { setPtrAndKind(nullptr, StoredIdentifier); }

  /// Construct a declaration name from an IdentifierInfo *.
  DeclarationName(const IdentifierInfo *II) {
    setPtrAndKind(II, StoredIdentifier);
  }

  /// Construct a declaration name from an Objective-C selector.
  DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) {}

  /// Returns the name for all C++ using-directives.
  static DeclarationName getUsingDirectiveName() {
    // Single instance of DeclarationNameExtra for using-directive
    static detail::DeclarationNameExtra UDirExtra(
        detail::DeclarationNameExtra::CXXUsingDirective);
    return DeclarationName(&UDirExtra);
  }

  /// Evaluates true when this declaration name is non-empty.
  explicit operator bool() const {
    return getPtr() || (getStoredNameKind() != StoredIdentifier);
  }

  /// Evaluates true when this declaration name is empty.
  bool isEmpty() const { return !*this; }

  /// Predicate functions for querying what type of name this is.
  bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
  bool isObjCZeroArgSelector() const {
    return getStoredNameKind() == StoredObjCZeroArgSelector;
  }
  bool isObjCOneArgSelector() const {
    return getStoredNameKind() == StoredObjCOneArgSelector;
  }

  /// Determine what kind of name this is.
  NameKind getNameKind() const {
    // We rely on the fact that the first 7 NameKind and StoredNameKind
    // have the same numerical value. This makes the usual case efficient.
    StoredNameKind StoredKind = getStoredNameKind();
    if (StoredKind != StoredDeclarationNameExtra)
      return static_cast<NameKind>(StoredKind);
    // We have to consult DeclarationNameExtra. We rely on the fact that the
    // enumeration values of ExtraKind correspond to the enumeration values of
    // NameKind minus an offset of UncommonNameKindOffset.
    unsigned ExtraKind = castAsExtra()->getKind();
    return static_cast<NameKind>(UncommonNameKindOffset + ExtraKind);
  }

  /// Determines whether the name itself is dependent, e.g., because it
  /// involves a C++ type that is itself dependent.
  ///
  /// Note that this does not capture all of the notions of "dependent name",
  /// because an identifier can be a dependent name if it is used as the
  /// callee in a call expression with dependent arguments.
  bool isDependentName() const;

  /// Retrieve the human-readable string for this name.
  std::string getAsString() const;

  /// Retrieve the IdentifierInfo * stored in this declaration name,
  /// or null if this declaration name isn't a simple identifier.
  IdentifierInfo *getAsIdentifierInfo() const {
    if (isIdentifier())
      return castAsIdentifierInfo();
    return nullptr;
  }

  /// Get the representation of this declaration name as an opaque integer.
  uintptr_t getAsOpaqueInteger() const { return Ptr; }

  /// Get the representation of this declaration name as an opaque pointer.
  void *getAsOpaquePtr() const { return reinterpret_cast<void *>(Ptr); }

  /// Get a declaration name from an opaque pointer returned by getAsOpaquePtr.
  static DeclarationName getFromOpaquePtr(void *P) {
    DeclarationName N;
    N.Ptr = reinterpret_cast<uintptr_t>(P);
    return N;
  }

  /// Get a declaration name from an opaque integer
  /// returned by getAsOpaqueInteger.
  static DeclarationName getFromOpaqueInteger(uintptr_t P) {
    DeclarationName N;
    N.Ptr = P;
    return N;
  }

  /// If this name is one of the C++ names (of a constructor, destructor,
  /// or conversion function), return the type associated with that name.
  QualType getCXXNameType() const {
    if (getStoredNameKind() == StoredCXXConstructorName ||
        getStoredNameKind() == StoredCXXDestructorName ||
        getStoredNameKind() == StoredCXXConversionFunctionName) {
      assert(getPtr() && "getCXXNameType on a null DeclarationName!");
      return castAsCXXSpecialNameExtra()->Type;
    }
    return QualType();
  }

  /// If this name is the name of a C++ deduction guide, return the
  /// template associated with that name.
  TemplateDecl *getCXXDeductionGuideTemplate() const {
    if (getNameKind() == CXXDeductionGuideName) {
      assert(getPtr() &&
             "getCXXDeductionGuideTemplate on a null DeclarationName!");
      return castAsCXXDeductionGuideNameExtra()->Template;
    }
    return nullptr;
  }

  /// If this name is the name of an overloadable operator in C++
  /// (e.g., @c operator+), retrieve the kind of overloaded operator.
  OverloadedOperatorKind getCXXOverloadedOperator() const {
    if (getStoredNameKind() == StoredCXXOperatorName) {
      assert(getPtr() && "getCXXOverloadedOperator on a null DeclarationName!");
      return castAsCXXOperatorIdName()->Kind;
    }
    return OO_None;
  }

  /// If this name is the name of a literal operator,
  /// retrieve the identifier associated with it.
  IdentifierInfo *getCXXLiteralIdentifier() const {
    if (getNameKind() == CXXLiteralOperatorName) {
      assert(getPtr() && "getCXXLiteralIdentifier on a null DeclarationName!");
      return castAsCXXLiteralOperatorIdName()->ID;
    }
    return nullptr;
  }

  /// Get the Objective-C selector stored in this declaration name.
  Selector getObjCSelector() const {
    assert((getNameKind() == ObjCZeroArgSelector ||
            getNameKind() == ObjCOneArgSelector ||
            getNameKind() == ObjCMultiArgSelector || !getPtr()) &&
           "Not a selector!");
    return Selector(Ptr);
  }

  /// Get and set FETokenInfo. The language front-end is allowed to associate
  /// arbitrary metadata with some kinds of declaration names, including normal
  /// identifiers and C++ constructors, destructors, and conversion functions.
  void *getFETokenInfo() const {
    assert(getPtr() && "getFETokenInfo on an empty DeclarationName!");
    if (getStoredNameKind() == StoredIdentifier)
      return castAsIdentifierInfo()->getFETokenInfo();
    return getFETokenInfoSlow();
  }

  void setFETokenInfo(void *T) {
    assert(getPtr() && "setFETokenInfo on an empty DeclarationName!");
    if (getStoredNameKind() == StoredIdentifier)
      castAsIdentifierInfo()->setFETokenInfo(T);
    else
      setFETokenInfoSlow(T);
  }

  /// Determine whether the specified names are identical.
  friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
    return LHS.Ptr == RHS.Ptr;
  }

  /// Determine whether the specified names are different.
  friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
    return LHS.Ptr != RHS.Ptr;
  }

  static DeclarationName getEmptyMarker() {
    DeclarationName Name;
    Name.Ptr = uintptr_t(-1);
    return Name;
  }

  static DeclarationName getTombstoneMarker() {
    DeclarationName Name;
    Name.Ptr = uintptr_t(-2);
    return Name;
  }

  static int compare(DeclarationName LHS, DeclarationName RHS);

  void print(raw_ostream &OS, const PrintingPolicy &Policy);

  void dump() const;
};

raw_ostream &operator<<(raw_ostream &OS, DeclarationName N);

/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator<(DeclarationName LHS, DeclarationName RHS) {
  return DeclarationName::compare(LHS, RHS) < 0;
}

/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator>(DeclarationName LHS, DeclarationName RHS) {
  return DeclarationName::compare(LHS, RHS) > 0;
}

/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator<=(DeclarationName LHS, DeclarationName RHS) {
  return DeclarationName::compare(LHS, RHS) <= 0;
}

/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
  return DeclarationName::compare(LHS, RHS) >= 0;
}

/// DeclarationNameTable is used to store and retrieve DeclarationName
/// instances for the various kinds of declaration names, e.g., normal
/// identifiers, C++ constructor names, etc. This class contains
/// uniqued versions of each of the C++ special names, which can be
/// retrieved using its member functions (e.g., getCXXConstructorName).
class DeclarationNameTable {
  /// Used to allocate elements in the FoldingSets below.
  const ASTContext &Ctx;

  /// Manage the uniqued CXXSpecialNameExtra representing C++ constructors.
  /// getCXXConstructorName and getCXXSpecialName can be used to obtain
  /// a DeclarationName from the corresponding type of the constructor.
  llvm::FoldingSet<detail::CXXSpecialNameExtra> CXXConstructorNames;

  /// Manage the uniqued CXXSpecialNameExtra representing C++ destructors.
  /// getCXXDestructorName and getCXXSpecialName can be used to obtain
  /// a DeclarationName from the corresponding type of the destructor.
  llvm::FoldingSet<detail::CXXSpecialNameExtra> CXXDestructorNames;

  /// Manage the uniqued CXXSpecialNameExtra representing C++ conversion
  /// functions. getCXXConversionFunctionName and getCXXSpecialName can be
  /// used to obtain a DeclarationName from the corresponding type of the
  /// conversion function.
  llvm::FoldingSet<detail::CXXSpecialNameExtra> CXXConversionFunctionNames;

  /// Manage the uniqued CXXOperatorIdName, which contain extra information
  /// for the name of overloaded C++ operators. getCXXOperatorName
  /// can be used to obtain a DeclarationName from the operator kind.
  detail::CXXOperatorIdName CXXOperatorNames[NUM_OVERLOADED_OPERATORS];

  /// Manage the uniqued CXXLiteralOperatorIdName, which contain extra
  /// information for the name of C++ literal operators.
  /// getCXXLiteralOperatorName can be used to obtain a DeclarationName
  /// from the corresponding IdentifierInfo.
  llvm::FoldingSet<detail::CXXLiteralOperatorIdName> CXXLiteralOperatorNames;

  /// Manage the uniqued CXXDeductionGuideNameExtra, which contain
  /// extra information for the name of a C++ deduction guide.
  /// getCXXDeductionGuideName can be used to obtain a DeclarationName
  /// from the corresponding template declaration.
  llvm::FoldingSet<detail::CXXDeductionGuideNameExtra> CXXDeductionGuideNames;

public:
  DeclarationNameTable(const ASTContext &C);
  DeclarationNameTable(const DeclarationNameTable &) = delete;
  DeclarationNameTable &operator=(const DeclarationNameTable &) = delete;
  DeclarationNameTable(DeclarationNameTable &&) = delete;
  DeclarationNameTable &operator=(DeclarationNameTable &&) = delete;
  ~DeclarationNameTable() = default;

  /// Create a declaration name that is a simple identifier.
  DeclarationName getIdentifier(const IdentifierInfo *ID) {
    return DeclarationName(ID);
  }

  /// Returns the name of a C++ constructor for the given Type.
  DeclarationName getCXXConstructorName(CanQualType Ty);

  /// Returns the name of a C++ destructor for the given Type.
  DeclarationName getCXXDestructorName(CanQualType Ty);

  /// Returns the name of a C++ deduction guide for the given template.
  DeclarationName getCXXDeductionGuideName(TemplateDecl *TD);

  /// Returns the name of a C++ conversion function for the given Type.
  DeclarationName getCXXConversionFunctionName(CanQualType Ty);

  /// Returns a declaration name for special kind of C++ name,
  /// e.g., for a constructor, destructor, or conversion function.
  /// Kind must be one of:
  ///   * DeclarationName::CXXConstructorName,
  ///   * DeclarationName::CXXDestructorName or
  ///   * DeclarationName::CXXConversionFunctionName
  DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
                                    CanQualType Ty);

  /// Get the name of the overloadable C++ operator corresponding to Op.
  DeclarationName getCXXOperatorName(OverloadedOperatorKind Op) {
    return DeclarationName(&CXXOperatorNames[Op]);
  }

  /// Get the name of the literal operator function with II as the identifier.
  DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
};

/// DeclarationNameLoc - Additional source/type location info
/// for a declaration name. Needs a DeclarationName in order
/// to be interpreted correctly.
struct DeclarationNameLoc {
  // The source location for identifier stored elsewhere.
  // struct {} Identifier;

  // Type info for constructors, destructors and conversion functions.
  // Locations (if any) for the tilde (destructor) or operator keyword
  // (conversion) are stored elsewhere.
  struct NT {
    TypeSourceInfo *TInfo;
  };

  // The location (if any) of the operator keyword is stored elsewhere.
  struct CXXOpName {
    unsigned BeginOpNameLoc;
    unsigned EndOpNameLoc;
  };

  // The location (if any) of the operator keyword is stored elsewhere.
  struct CXXLitOpName {
    unsigned OpNameLoc;
  };

  // struct {} CXXUsingDirective;
  // struct {} ObjCZeroArgSelector;
  // struct {} ObjCOneArgSelector;
  // struct {} ObjCMultiArgSelector;
  union {
    struct NT NamedType;
    struct CXXOpName CXXOperatorName;
    struct CXXLitOpName CXXLiteralOperatorName;
  };

  DeclarationNameLoc(DeclarationName Name);

  // FIXME: this should go away once all DNLocs are properly initialized.
  DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); }
};

/// DeclarationNameInfo - A collector data type for bundling together
/// a DeclarationName and the correspnding source/type location info.
struct DeclarationNameInfo {
private:
  /// Name - The declaration name, also encoding name kind.
  DeclarationName Name;

  /// Loc - The main source location for the declaration name.
  SourceLocation NameLoc;

  /// Info - Further source/type location info for special kinds of names.
  DeclarationNameLoc LocInfo;

public:
  // FIXME: remove it.
  DeclarationNameInfo() = default;

  DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
      : Name(Name), NameLoc(NameLoc), LocInfo(Name) {}

  DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
                      DeclarationNameLoc LocInfo)
      : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}

  /// getName - Returns the embedded declaration name.
  DeclarationName getName() const { return Name; }

  /// setName - Sets the embedded declaration name.
  void setName(DeclarationName N) { Name = N; }

  /// getLoc - Returns the main location of the declaration name.
  SourceLocation getLoc() const { return NameLoc; }

  /// setLoc - Sets the main location of the declaration name.
  void setLoc(SourceLocation L) { NameLoc = L; }

  const DeclarationNameLoc &getInfo() const { return LocInfo; }
  DeclarationNameLoc &getInfo() { return LocInfo; }
  void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }

  /// getNamedTypeInfo - Returns the source type info associated to
  /// the name. Assumes it is a constructor, destructor or conversion.
  TypeSourceInfo *getNamedTypeInfo() const {
    if (Name.getNameKind() != DeclarationName::CXXConstructorName &&
        Name.getNameKind() != DeclarationName::CXXDestructorName &&
        Name.getNameKind() != DeclarationName::CXXConversionFunctionName)
      return nullptr;
    return LocInfo.NamedType.TInfo;
  }

  /// setNamedTypeInfo - Sets the source type info associated to
  /// the name. Assumes it is a constructor, destructor or conversion.
  void setNamedTypeInfo(TypeSourceInfo *TInfo) {
    assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
           Name.getNameKind() == DeclarationName::CXXDestructorName ||
           Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
    LocInfo.NamedType.TInfo = TInfo;
  }

  /// getCXXOperatorNameRange - Gets the range of the operator name
  /// (without the operator keyword). Assumes it is a (non-literal) operator.
  SourceRange getCXXOperatorNameRange() const {
    if (Name.getNameKind() != DeclarationName::CXXOperatorName)
      return SourceRange();
    return SourceRange(
     SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
     SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
                       );
  }

  /// setCXXOperatorNameRange - Sets the range of the operator name
  /// (without the operator keyword). Assumes it is a C++ operator.
  void setCXXOperatorNameRange(SourceRange R) {
    assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
    LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding();
    LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding();
  }

  /// getCXXLiteralOperatorNameLoc - Returns the location of the literal
  /// operator name (not the operator keyword).
  /// Assumes it is a literal operator.
  SourceLocation getCXXLiteralOperatorNameLoc() const {
    if (Name.getNameKind() != DeclarationName::CXXLiteralOperatorName)
      return SourceLocation();
    return SourceLocation::
      getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
  }

  /// setCXXLiteralOperatorNameLoc - Sets the location of the literal
  /// operator name (not the operator keyword).
  /// Assumes it is a literal operator.
  void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
    assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
    LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
  }

  /// Determine whether this name involves a template parameter.
  bool isInstantiationDependent() const;

  /// Determine whether this name contains an unexpanded
  /// parameter pack.
  bool containsUnexpandedParameterPack() const;

  /// getAsString - Retrieve the human-readable string for this name.
  std::string getAsString() const;

  /// printName - Print the human-readable name to a stream.
  void printName(raw_ostream &OS) const;

  /// getBeginLoc - Retrieve the location of the first token.
  SourceLocation getBeginLoc() const { return NameLoc; }

  /// getSourceRange - The range of the declaration name.
  SourceRange getSourceRange() const LLVM_READONLY {
    return SourceRange(getBeginLoc(), getEndLoc());
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    SourceLocation EndLoc = getEndLocPrivate();
    return EndLoc.isValid() ? EndLoc : getBeginLoc();
  }

private:
  SourceLocation getEndLocPrivate() const;
};

/// Insertion operator for diagnostics.  This allows sending DeclarationName's
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                           DeclarationName N) {
  DB.AddTaggedVal(N.getAsOpaqueInteger(),
                  DiagnosticsEngine::ak_declarationname);
  return DB;
}

/// Insertion operator for partial diagnostics.  This allows binding
/// DeclarationName's into a partial diagnostic with <<.
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
                                           DeclarationName N) {
  PD.AddTaggedVal(N.getAsOpaqueInteger(),
                  DiagnosticsEngine::ak_declarationname);
  return PD;
}

inline raw_ostream &operator<<(raw_ostream &OS,
                                     DeclarationNameInfo DNInfo) {
  DNInfo.printName(OS);
  return OS;
}

} // namespace clang

namespace llvm {

/// Define DenseMapInfo so that DeclarationNames can be used as keys
/// in DenseMap and DenseSets.
template<>
struct DenseMapInfo<clang::DeclarationName> {
  static inline clang::DeclarationName getEmptyKey() {
    return clang::DeclarationName::getEmptyMarker();
  }

  static inline clang::DeclarationName getTombstoneKey() {
    return clang::DeclarationName::getTombstoneMarker();
  }

  static unsigned getHashValue(clang::DeclarationName Name) {
    return DenseMapInfo<void*>::getHashValue(Name.getAsOpaquePtr());
  }

  static inline bool
  isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
    return LHS == RHS;
  }
};

} // namespace llvm

#endif // LLVM_CLANG_AST_DECLARATIONNAME_H
