//===- TemplateName.h - C++ Template Name Representation --------*- 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 defines the TemplateName interface and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
#define LLVM_CLANG_AST_TEMPLATENAME_H

#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>

namespace clang {

class ASTContext;
class DependentTemplateName;
class DiagnosticBuilder;
class IdentifierInfo;
class NamedDecl;
class NestedNameSpecifier;
enum OverloadedOperatorKind : int;
class OverloadedTemplateStorage;
class AssumedTemplateStorage;
class PartialDiagnostic;
struct PrintingPolicy;
class QualifiedTemplateName;
class SubstTemplateTemplateParmPackStorage;
class SubstTemplateTemplateParmStorage;
class TemplateArgument;
class TemplateDecl;
class TemplateTemplateParmDecl;

/// Implementation class used to describe either a set of overloaded
/// template names or an already-substituted template template parameter pack.
class UncommonTemplateNameStorage {
protected:
  enum Kind {
    Overloaded,
    Assumed, // defined in DeclarationName.h
    SubstTemplateTemplateParm,
    SubstTemplateTemplateParmPack
  };

  struct BitsTag {
    /// A Kind.
    unsigned Kind : 2;

    /// The number of stored templates or template arguments,
    /// depending on which subclass we have.
    unsigned Size : 30;
  };

  union {
    struct BitsTag Bits;
    void *PointerAlignment;
  };

  UncommonTemplateNameStorage(Kind kind, unsigned size) {
    Bits.Kind = kind;
    Bits.Size = size;
  }

public:
  unsigned size() const { return Bits.Size; }

  OverloadedTemplateStorage *getAsOverloadedStorage()  {
    return Bits.Kind == Overloaded
             ? reinterpret_cast<OverloadedTemplateStorage *>(this)
             : nullptr;
  }

  AssumedTemplateStorage *getAsAssumedTemplateName()  {
    return Bits.Kind == Assumed
             ? reinterpret_cast<AssumedTemplateStorage *>(this)
             : nullptr;
  }

  SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {
    return Bits.Kind == SubstTemplateTemplateParm
             ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)
             : nullptr;
  }

  SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
    return Bits.Kind == SubstTemplateTemplateParmPack
             ? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this)
             : nullptr;
  }
};

/// A structure for storing the information associated with an
/// overloaded template name.
class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
  friend class ASTContext;

  OverloadedTemplateStorage(unsigned size)
      : UncommonTemplateNameStorage(Overloaded, size) {}

  NamedDecl **getStorage() {
    return reinterpret_cast<NamedDecl **>(this + 1);
  }
  NamedDecl * const *getStorage() const {
    return reinterpret_cast<NamedDecl *const *>(this + 1);
  }

public:
  using iterator = NamedDecl *const *;

  iterator begin() const { return getStorage(); }
  iterator end() const { return getStorage() + size(); }
};

/// A structure for storing an already-substituted template template
/// parameter pack.
///
/// This kind of template names occurs when the parameter pack has been
/// provided with a template template argument pack in a context where its
/// enclosing pack expansion could not be fully expanded.
class SubstTemplateTemplateParmPackStorage
  : public UncommonTemplateNameStorage, public llvm::FoldingSetNode
{
  TemplateTemplateParmDecl *Parameter;
  const TemplateArgument *Arguments;

public:
  SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
                                       unsigned Size,
                                       const TemplateArgument *Arguments)
      : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
        Parameter(Parameter), Arguments(Arguments) {}

  /// Retrieve the template template parameter pack being substituted.
  TemplateTemplateParmDecl *getParameterPack() const {
    return Parameter;
  }

  /// Retrieve the template template argument pack with which this
  /// parameter was substituted.
  TemplateArgument getArgumentPack() const;

  void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);

  static void Profile(llvm::FoldingSetNodeID &ID,
                      ASTContext &Context,
                      TemplateTemplateParmDecl *Parameter,
                      const TemplateArgument &ArgPack);
};

/// Represents a C++ template name within the type system.
///
/// A C++ template name refers to a template within the C++ type
/// system. In most cases, a template name is simply a reference to a
/// class template, e.g.
///
/// \code
/// template<typename T> class X { };
///
/// X<int> xi;
/// \endcode
///
/// Here, the 'X' in \c X<int> is a template name that refers to the
/// declaration of the class template X, above. Template names can
/// also refer to function templates, C++0x template aliases, etc.
///
/// Some template names are dependent. For example, consider:
///
/// \code
/// template<typename MetaFun, typename T1, typename T2> struct apply2 {
///   typedef typename MetaFun::template apply<T1, T2>::type type;
/// };
/// \endcode
///
/// Here, "apply" is treated as a template name within the typename
/// specifier in the typedef. "apply" is a nested template, and can
/// only be understood in the context of
class TemplateName {
  using StorageType =
      llvm::PointerUnion4<TemplateDecl *, UncommonTemplateNameStorage *,
                          QualifiedTemplateName *, DependentTemplateName *>;

  StorageType Storage;

  explicit TemplateName(void *Ptr);

public:
  // Kind of name that is actually stored.
  enum NameKind {
    /// A single template declaration.
    Template,

    /// A set of overloaded template declarations.
    OverloadedTemplate,

    /// An unqualified-id that has been assumed to name a function template
    /// that will be found by ADL.
    AssumedTemplate,

    /// A qualified template name, where the qualification is kept
    /// to describe the source code as written.
    QualifiedTemplate,

    /// A dependent template name that has not been resolved to a
    /// template (or set of templates).
    DependentTemplate,

    /// A template template parameter that has been substituted
    /// for some other template name.
    SubstTemplateTemplateParm,

    /// A template template parameter pack that has been substituted for
    /// a template template argument pack, but has not yet been expanded into
    /// individual arguments.
    SubstTemplateTemplateParmPack
  };

  TemplateName() = default;
  explicit TemplateName(TemplateDecl *Template);
  explicit TemplateName(OverloadedTemplateStorage *Storage);
  explicit TemplateName(AssumedTemplateStorage *Storage);
  explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
  explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
  explicit TemplateName(QualifiedTemplateName *Qual);
  explicit TemplateName(DependentTemplateName *Dep);

  /// Determine whether this template name is NULL.
  bool isNull() const;

  // Get the kind of name that is actually stored.
  NameKind getKind() const;

  /// Retrieve the underlying template declaration that
  /// this template name refers to, if known.
  ///
  /// \returns The template declaration that this template name refers
  /// to, if any. If the template name does not refer to a specific
  /// declaration because it is a dependent name, or if it refers to a
  /// set of function templates, returns NULL.
  TemplateDecl *getAsTemplateDecl() const;

  /// Retrieve the underlying, overloaded function template
  /// declarations that this template name refers to, if known.
  ///
  /// \returns The set of overloaded function templates that this template
  /// name refers to, if known. If the template name does not refer to a
  /// specific set of function templates because it is a dependent name or
  /// refers to a single template, returns NULL.
  OverloadedTemplateStorage *getAsOverloadedTemplate() const;

  /// Retrieve information on a name that has been assumed to be a
  /// template-name in order to permit a call via ADL.
  AssumedTemplateStorage *getAsAssumedTemplateName() const;

  /// Retrieve the substituted template template parameter, if
  /// known.
  ///
  /// \returns The storage for the substituted template template parameter,
  /// if known. Otherwise, returns NULL.
  SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const;

  /// Retrieve the substituted template template parameter pack, if
  /// known.
  ///
  /// \returns The storage for the substituted template template parameter pack,
  /// if known. Otherwise, returns NULL.
  SubstTemplateTemplateParmPackStorage *
  getAsSubstTemplateTemplateParmPack() const;

  /// Retrieve the underlying qualified template name
  /// structure, if any.
  QualifiedTemplateName *getAsQualifiedTemplateName() const;

  /// Retrieve the underlying dependent template name
  /// structure, if any.
  DependentTemplateName *getAsDependentTemplateName() const;

  TemplateName getUnderlying() const;

  /// Get the template name to substitute when this template name is used as a
  /// template template argument. This refers to the most recent declaration of
  /// the template, including any default template arguments.
  TemplateName getNameToSubstitute() const;

  /// Determines whether this is a dependent template name.
  bool isDependent() const;

  /// Determines whether this is a template name that somehow
  /// depends on a template parameter.
  bool isInstantiationDependent() const;

  /// Determines whether this template name contains an
  /// unexpanded parameter pack (for C++0x variadic templates).
  bool containsUnexpandedParameterPack() const;

  /// Print the template name.
  ///
  /// \param OS the output stream to which the template name will be
  /// printed.
  ///
  /// \param SuppressNNS if true, don't print the
  /// nested-name-specifier that precedes the template name (if it has
  /// one).
  void print(raw_ostream &OS, const PrintingPolicy &Policy,
             bool SuppressNNS = false) const;

  /// Debugging aid that dumps the template name.
  void dump(raw_ostream &OS) const;

  /// Debugging aid that dumps the template name to standard
  /// error.
  void dump() const;

  void Profile(llvm::FoldingSetNodeID &ID) {
    ID.AddPointer(Storage.getOpaqueValue());
  }

  /// Retrieve the template name as a void pointer.
  void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }

  /// Build a template name from a void pointer.
  static TemplateName getFromVoidPointer(void *Ptr) {
    return TemplateName(Ptr);
  }
};

/// Insertion operator for diagnostics.  This allows sending TemplateName's
/// into a diagnostic with <<.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                    TemplateName N);
const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
                                    TemplateName N);

/// A structure for storing the information associated with a
/// substituted template template parameter.
class SubstTemplateTemplateParmStorage
  : public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
  friend class ASTContext;

  TemplateTemplateParmDecl *Parameter;
  TemplateName Replacement;

  SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter,
                                   TemplateName replacement)
      : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
        Parameter(parameter), Replacement(replacement) {}

public:
  TemplateTemplateParmDecl *getParameter() const { return Parameter; }
  TemplateName getReplacement() const { return Replacement; }

  void Profile(llvm::FoldingSetNodeID &ID);

  static void Profile(llvm::FoldingSetNodeID &ID,
                      TemplateTemplateParmDecl *parameter,
                      TemplateName replacement);
};

inline TemplateName TemplateName::getUnderlying() const {
  if (SubstTemplateTemplateParmStorage *subst
        = getAsSubstTemplateTemplateParm())
    return subst->getReplacement().getUnderlying();
  return *this;
}

/// Represents a template name that was expressed as a
/// qualified name.
///
/// This kind of template name refers to a template name that was
/// preceded by a nested name specifier, e.g., \c std::vector. Here,
/// the nested name specifier is "std::" and the template name is the
/// declaration for "vector". The QualifiedTemplateName class is only
/// used to provide "sugar" for template names that were expressed
/// with a qualified name, and has no semantic meaning. In this
/// manner, it is to TemplateName what ElaboratedType is to Type,
/// providing extra syntactic sugar for downstream clients.
class QualifiedTemplateName : public llvm::FoldingSetNode {
  friend class ASTContext;

  /// The nested name specifier that qualifies the template name.
  ///
  /// The bit is used to indicate whether the "template" keyword was
  /// present before the template name itself. Note that the
  /// "template" keyword is always redundant in this case (otherwise,
  /// the template name would be a dependent name and we would express
  /// this name with DependentTemplateName).
  llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;

  /// The template declaration or set of overloaded function templates
  /// that this qualified name refers to.
  TemplateDecl *Template;

  QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
                        TemplateDecl *Template)
      : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {}

public:
  /// Return the nested name specifier that qualifies this name.
  NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }

  /// Whether the template name was prefixed by the "template"
  /// keyword.
  bool hasTemplateKeyword() const { return Qualifier.getInt(); }

  /// The template declaration that this qualified name refers
  /// to.
  TemplateDecl *getDecl() const { return Template; }

  /// The template declaration to which this qualified name
  /// refers.
  TemplateDecl *getTemplateDecl() const { return Template; }

  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
  }

  static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
                      bool TemplateKeyword, TemplateDecl *Template) {
    ID.AddPointer(NNS);
    ID.AddBoolean(TemplateKeyword);
    ID.AddPointer(Template);
  }
};

/// Represents a dependent template name that cannot be
/// resolved prior to template instantiation.
///
/// This kind of template name refers to a dependent template name,
/// including its nested name specifier (if any). For example,
/// DependentTemplateName can refer to "MetaFun::template apply",
/// where "MetaFun::" is the nested name specifier and "apply" is the
/// template name referenced. The "template" keyword is implied.
class DependentTemplateName : public llvm::FoldingSetNode {
  friend class ASTContext;

  /// The nested name specifier that qualifies the template
  /// name.
  ///
  /// The bit stored in this qualifier describes whether the \c Name field
  /// is interpreted as an IdentifierInfo pointer (when clear) or as an
  /// overloaded operator kind (when set).
  llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;

  /// The dependent template name.
  union {
    /// The identifier template name.
    ///
    /// Only valid when the bit on \c Qualifier is clear.
    const IdentifierInfo *Identifier;

    /// The overloaded operator name.
    ///
    /// Only valid when the bit on \c Qualifier is set.
    OverloadedOperatorKind Operator;
  };

  /// The canonical template name to which this dependent
  /// template name refers.
  ///
  /// The canonical template name for a dependent template name is
  /// another dependent template name whose nested name specifier is
  /// canonical.
  TemplateName CanonicalTemplateName;

  DependentTemplateName(NestedNameSpecifier *Qualifier,
                        const IdentifierInfo *Identifier)
      : Qualifier(Qualifier, false), Identifier(Identifier),
        CanonicalTemplateName(this) {}

  DependentTemplateName(NestedNameSpecifier *Qualifier,
                        const IdentifierInfo *Identifier,
                        TemplateName Canon)
      : Qualifier(Qualifier, false), Identifier(Identifier),
        CanonicalTemplateName(Canon) {}

  DependentTemplateName(NestedNameSpecifier *Qualifier,
                        OverloadedOperatorKind Operator)
      : Qualifier(Qualifier, true), Operator(Operator),
        CanonicalTemplateName(this) {}

  DependentTemplateName(NestedNameSpecifier *Qualifier,
                        OverloadedOperatorKind Operator,
                        TemplateName Canon)
       : Qualifier(Qualifier, true), Operator(Operator),
         CanonicalTemplateName(Canon) {}

public:
  /// Return the nested name specifier that qualifies this name.
  NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }

  /// Determine whether this template name refers to an identifier.
  bool isIdentifier() const { return !Qualifier.getInt(); }

  /// Returns the identifier to which this template name refers.
  const IdentifierInfo *getIdentifier() const {
    assert(isIdentifier() && "Template name isn't an identifier?");
    return Identifier;
  }

  /// Determine whether this template name refers to an overloaded
  /// operator.
  bool isOverloadedOperator() const { return Qualifier.getInt(); }

  /// Return the overloaded operator to which this template name refers.
  OverloadedOperatorKind getOperator() const {
    assert(isOverloadedOperator() &&
           "Template name isn't an overloaded operator?");
    return Operator;
  }

  void Profile(llvm::FoldingSetNodeID &ID) {
    if (isIdentifier())
      Profile(ID, getQualifier(), getIdentifier());
    else
      Profile(ID, getQualifier(), getOperator());
  }

  static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
                      const IdentifierInfo *Identifier) {
    ID.AddPointer(NNS);
    ID.AddBoolean(false);
    ID.AddPointer(Identifier);
  }

  static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
                      OverloadedOperatorKind Operator) {
    ID.AddPointer(NNS);
    ID.AddBoolean(true);
    ID.AddInteger(Operator);
  }
};

} // namespace clang.

namespace llvm {

/// The clang::TemplateName class is effectively a pointer.
template<>
struct PointerLikeTypeTraits<clang::TemplateName> {
  static inline void *getAsVoidPointer(clang::TemplateName TN) {
    return TN.getAsVoidPointer();
  }

  static inline clang::TemplateName getFromVoidPointer(void *Ptr) {
    return clang::TemplateName::getFromVoidPointer(Ptr);
  }

  // No bits are available!
  enum { NumLowBitsAvailable = 0 };
};

} // namespace llvm.

#endif // LLVM_CLANG_AST_TEMPLATENAME_H
