//===- 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/ADT/STLExtras.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;
struct PrintingPolicy;
class TemplateDecl;
class TypeSourceInfo;

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!");

  static_assert(
      std::is_same<std::underlying_type_t<StoredNameKind>,
                   std::underlying_type_t<
                       detail::DeclarationNameExtra::ExtraKind>>::value,
      "The various enums used to compute values for NameKind should "
      "all have the same underlying type");

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 = llvm::addEnumValues(
        UncommonNameKindOffset,
        detail::DeclarationNameExtra::CXXDeductionGuideName),
    CXXLiteralOperatorName = llvm::addEnumValues(
        UncommonNameKindOffset,
        detail::DeclarationNameExtra::CXXLiteralOperatorName),
    CXXUsingDirective =
        llvm::addEnumValues(UncommonNameKindOffset,
                            detail::DeclarationNameExtra::CXXUsingDirective),
    ObjCMultiArgSelector =
        llvm::addEnumValues(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) const;

  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.
class 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 {
    SourceLocation::UIntTy BeginOpNameLoc;
    SourceLocation::UIntTy EndOpNameLoc;
  };

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

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

  void setNamedTypeLoc(TypeSourceInfo *TInfo) { NamedType.TInfo = TInfo; }

  void setCXXOperatorNameRange(SourceRange Range) {
    CXXOperatorName.BeginOpNameLoc = Range.getBegin().getRawEncoding();
    CXXOperatorName.EndOpNameLoc = Range.getEnd().getRawEncoding();
  }

  void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
    CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
  }

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

  /// Returns the source type info. Assumes that the object stores location
  /// information of a constructor, destructor or conversion operator.
  TypeSourceInfo *getNamedTypeInfo() const { return NamedType.TInfo; }

  /// Return the beginning location of the getCXXOperatorNameRange() range.
  SourceLocation getCXXOperatorNameBeginLoc() const {
    return SourceLocation::getFromRawEncoding(CXXOperatorName.BeginOpNameLoc);
  }

  /// Return the end location of the getCXXOperatorNameRange() range.
  SourceLocation getCXXOperatorNameEndLoc() const {
    return SourceLocation::getFromRawEncoding(CXXOperatorName.EndOpNameLoc);
  }

  /// Return the range of the operator name (without the operator keyword).
  /// Assumes that the object stores location information of a (non-literal)
  /// operator.
  SourceRange getCXXOperatorNameRange() const {
    return SourceRange(getCXXOperatorNameBeginLoc(),
                       getCXXOperatorNameEndLoc());
  }

  /// Return the location of the literal operator name (without the operator
  /// keyword). Assumes that the object stores location information of a literal
  /// operator.
  SourceLocation getCXXLiteralOperatorNameLoc() const {
    return SourceLocation::getFromRawEncoding(CXXLiteralOperatorName.OpNameLoc);
  }

  /// Construct location information for a constructor, destructor or conversion
  /// operator.
  static DeclarationNameLoc makeNamedTypeLoc(TypeSourceInfo *TInfo) {
    DeclarationNameLoc DNL;
    DNL.setNamedTypeLoc(TInfo);
    return DNL;
  }

  /// Construct location information for a non-literal C++ operator.
  static DeclarationNameLoc makeCXXOperatorNameLoc(SourceLocation BeginLoc,
                                                   SourceLocation EndLoc) {
    return makeCXXOperatorNameLoc(SourceRange(BeginLoc, EndLoc));
  }

  /// Construct location information for a non-literal C++ operator.
  static DeclarationNameLoc makeCXXOperatorNameLoc(SourceRange Range) {
    DeclarationNameLoc DNL;
    DNL.setCXXOperatorNameRange(Range);
    return DNL;
  }

  /// Construct location information for a literal C++ operator.
  static DeclarationNameLoc makeCXXLiteralOperatorNameLoc(SourceLocation Loc) {
    DeclarationNameLoc DNL;
    DNL.setCXXLiteralOperatorNameLoc(Loc);
    return DNL;
  }
};

/// 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; }
  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.getNamedTypeInfo();
  }

  /// 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 = DeclarationNameLoc::makeNamedTypeLoc(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 LocInfo.getCXXOperatorNameRange();
  }

  /// 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 = DeclarationNameLoc::makeCXXOperatorNameLoc(R);
  }

  /// 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 LocInfo.getCXXLiteralOperatorNameLoc();
  }

  /// 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 = DeclarationNameLoc::makeCXXLiteralOperatorNameLoc(Loc);
  }

  /// 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, PrintingPolicy Policy) 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 partial diagnostics.  This allows binding
/// DeclarationName's into a partial diagnostic with <<.
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,
                                             DeclarationName N) {
  PD.AddTaggedVal(N.getAsOpaqueInteger(),
                  DiagnosticsEngine::ak_declarationname);
  return PD;
}

raw_ostream &operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo);

} // 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;
  }
};

template <> struct PointerLikeTypeTraits<clang::DeclarationName> {
  static inline void *getAsVoidPointer(clang::DeclarationName P) {
    return P.getAsOpaquePtr();
  }
  static inline clang::DeclarationName getFromVoidPointer(void *P) {
    return clang::DeclarationName::getFromOpaquePtr(P);
  }
  static constexpr int NumLowBitsAvailable = 0;
};

} // namespace llvm

// The definition of AssumedTemplateStorage is factored out of TemplateName to
// resolve a cyclic dependency between it and DeclarationName (via Type).
namespace clang {

/// A structure for storing the information associated with a name that has
/// been assumed to be a template name (despite finding no TemplateDecls).
class AssumedTemplateStorage : public UncommonTemplateNameStorage {
  friend class ASTContext;

  AssumedTemplateStorage(DeclarationName Name)
      : UncommonTemplateNameStorage(Assumed, 0), Name(Name) {}
  DeclarationName Name;

public:
  /// Get the name of the template.
  DeclarationName getDeclName() const { return Name; }
};

} // namespace clang

#endif // LLVM_CLANG_AST_DECLARATIONNAME_H
