//===- 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) 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
