llvm/clang/include/clang/AST/ExprCXX.h

//===- ExprCXX.h - Classes for representing expressions ---------*- 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
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Defines the clang::Expr interface and subclasses for C++ expressions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H

#include "clang/AST/ASTConcept.h"
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/ExpressionTraits.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Lambda.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>

namespace clang {

class ASTContext;
class DeclAccessPair;
class IdentifierInfo;
class LambdaCapture;
class NonTypeTemplateParmDecl;
class TemplateParameterList;

//===--------------------------------------------------------------------===//
// C++ Expressions.
//===--------------------------------------------------------------------===//

/// A call to an overloaded operator written using operator
/// syntax.
///
/// Represents a call to an overloaded operator written using operator
/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a
/// normal call, this AST node provides better information about the
/// syntactic representation of the call.
///
/// In a C++ template, this expression node kind will be used whenever
/// any of the arguments are type-dependent. In this case, the
/// function itself will be a (possibly empty) set of functions and
/// function templates that were found by name lookup at template
/// definition time.
class CXXOperatorCallExpr final : public CallExpr {};

/// Represents a call to a member function that
/// may be written either with member call syntax (e.g., "obj.func()"
/// or "objptr->func()") or with normal function-call syntax
/// ("func()") within a member function that ends up calling a member
/// function. The callee in either case is a MemberExpr that contains
/// both the object argument and the member function, while the
/// arguments are the arguments within the parentheses (not including
/// the object argument).
class CXXMemberCallExpr final : public CallExpr {};

/// Represents a call to a CUDA kernel function.
class CUDAKernelCallExpr final : public CallExpr {};

/// A rewritten comparison expression that was originally written using
/// operator syntax.
///
/// In C++20, the following rewrites are performed:
/// - <tt>a == b</tt> -> <tt>b == a</tt>
/// - <tt>a != b</tt> -> <tt>!(a == b)</tt>
/// - <tt>a != b</tt> -> <tt>!(b == a)</tt>
/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>:
///   - <tt>a @ b</tt> -> <tt>(a <=> b) @ 0</tt>
///   - <tt>a @ b</tt> -> <tt>0 @ (b <=> a)</tt>
///
/// This expression provides access to both the original syntax and the
/// rewritten expression.
///
/// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically
/// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators.
class CXXRewrittenBinaryOperator : public Expr {};

/// Abstract class common to all of the C++ "named"/"keyword" casts.
///
/// This abstract class is inherited by all of the classes
/// representing "named" casts: CXXStaticCastExpr for \c static_cast,
/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for
/// reinterpret_cast, CXXConstCastExpr for \c const_cast and
/// CXXAddrspaceCastExpr for addrspace_cast (in OpenCL).
class CXXNamedCastExpr : public ExplicitCastExpr {};

/// A C++ \c static_cast expression (C++ [expr.static.cast]).
///
/// This expression node represents a C++ static cast, e.g.,
/// \c static_cast<int>(1.0).
class CXXStaticCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *,
                                    FPOptionsOverride> {};

/// A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
///
/// This expression node represents a dynamic cast, e.g.,
/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time
/// check to determine how to perform the type conversion.
class CXXDynamicCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {};

/// A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
///
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
///
/// A reinterpret_cast provides a differently-typed view of a value but
/// (in Clang, as in most C++ implementations) performs no actual work at
/// run time.
class CXXReinterpretCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXReinterpretCastExpr,
                                    CXXBaseSpecifier *> {};

/// A C++ \c const_cast expression (C++ [expr.const.cast]).
///
/// This expression node represents a const cast, e.g.,
/// \c const_cast<char*>(PtrToConstChar).
///
/// A const_cast can remove type qualifiers but does not change the underlying
/// value.
class CXXConstCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> {};

/// A C++ addrspace_cast expression (currently only enabled for OpenCL).
///
/// This expression node represents a cast between pointers to objects in
/// different address spaces e.g.,
/// \c addrspace_cast<global int*>(PtrToGenericInt).
///
/// A addrspace_cast can cast address space type qualifiers but does not change
/// the underlying value.
class CXXAddrspaceCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXAddrspaceCastExpr, CXXBaseSpecifier *> {};

/// A call to a literal operator (C++11 [over.literal])
/// written as a user-defined literal (C++11 [lit.ext]).
///
/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this
/// is semantically equivalent to a normal call, this AST node provides better
/// information about the syntactic representation of the literal.
///
/// Since literal operators are never found by ADL and can only be declared at
/// namespace scope, a user-defined literal is never dependent.
class UserDefinedLiteral final : public CallExpr {};

/// A boolean literal, per ([C++ lex.bool] Boolean literals).
class CXXBoolLiteralExpr : public Expr {};

/// The null pointer literal (C++11 [lex.nullptr])
///
/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
/// This also implements the null pointer literal in C23 (C23 6.4.1) which is
/// intended to have the same semantics as the feature in C++.
class CXXNullPtrLiteralExpr : public Expr {};

/// Implicit construction of a std::initializer_list<T> object from an
/// array temporary within list-initialization (C++11 [dcl.init.list]p5).
class CXXStdInitializerListExpr : public Expr {};

/// A C++ \c typeid expression (C++ [expr.typeid]), which gets
/// the \c type_info that corresponds to the supplied type, or the (possibly
/// dynamic) type of the supplied expression.
///
/// This represents code like \c typeid(int) or \c typeid(*objPtr)
class CXXTypeidExpr : public Expr {};

/// A member reference to an MSPropertyDecl.
///
/// This expression always has pseudo-object type, and therefore it is
/// typically not encountered in a fully-typechecked expression except
/// within the syntactic form of a PseudoObjectExpr.
class MSPropertyRefExpr : public Expr {};

/// MS property subscript expression.
/// MSVC supports 'property' attribute and allows to apply it to the
/// declaration of an empty array in a class or structure definition.
/// For example:
/// \code
/// __declspec(property(get=GetX, put=PutX)) int x[];
/// \endcode
/// The above statement indicates that x[] can be used with one or more array
/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and
/// p->x[a][b] = i will be turned into p->PutX(a, b, i).
/// This is a syntactic pseudo-object expression.
class MSPropertySubscriptExpr : public Expr {};

/// A Microsoft C++ @c __uuidof expression, which gets
/// the _GUID that corresponds to the supplied type or expression.
///
/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr)
class CXXUuidofExpr : public Expr {};

/// Represents the \c this expression in C++.
///
/// This is a pointer to the object on which the current member function is
/// executing (C++ [expr.prim]p3). Example:
///
/// \code
/// class Foo {
/// public:
///   void bar();
///   void test() { this->bar(); }
/// };
/// \endcode
class CXXThisExpr : public Expr {};

/// A C++ throw-expression (C++ [except.throw]).
///
/// This handles 'throw' (for re-throwing the current exception) and
/// 'throw' assignment-expression.  When assignment-expression isn't
/// present, Op will be null.
class CXXThrowExpr : public Expr {};

/// A default argument (C++ [dcl.fct.default]).
///
/// This wraps up a function call argument that was created from the
/// corresponding parameter's default argument, when the call did not
/// explicitly supply arguments for all of the parameters.
class CXXDefaultArgExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXDefaultArgExpr, Expr *> {};

/// A use of a default initializer in a constructor or in aggregate
/// initialization.
///
/// This wraps a use of a C++ default initializer (technically,
/// a brace-or-equal-initializer for a non-static data member) when it
/// is implicitly used in a mem-initializer-list in a constructor
/// (C++11 [class.base.init]p8) or in aggregate initialization
/// (C++1y [dcl.init.aggr]p7).
class CXXDefaultInitExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXDefaultInitExpr, Expr *> {};

/// Represents a C++ temporary.
class CXXTemporary {};

/// Represents binding an expression to a temporary.
///
/// This ensures the destructor is called for the temporary. It should only be
/// needed for non-POD, non-trivially destructable class types. For example:
///
/// \code
///   struct S {
///     S() { }  // User defined constructor makes S non-POD.
///     ~S() { } // User defined destructor makes it non-trivial.
///   };
///   void test() {
///     const S &s_ref = S(); // Requires a CXXBindTemporaryExpr.
///   }
/// \endcode
///
/// Destructor might be null if destructor declaration is not valid.
class CXXBindTemporaryExpr : public Expr {};

enum class CXXConstructionKind {};

/// Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr {};

/// Represents a call to an inherited base class constructor from an
/// inheriting constructor. This call implicitly forwards the arguments from
/// the enclosing context (an inheriting constructor) to the specified inherited
/// base class constructor.
class CXXInheritedCtorInitExpr : public Expr {};

/// Represents an explicit C++ type conversion that uses "functional"
/// notation (C++ [expr.type.conv]).
///
/// Example:
/// \code
///   x = int(0.5);
/// \endcode
class CXXFunctionalCastExpr final
    : public ExplicitCastExpr,
      private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *,
                                    FPOptionsOverride> {};

/// Represents a C++ functional cast expression that builds a
/// temporary object.
///
/// This expression type represents a C++ "functional" cast
/// (C++[expr.type.conv]) with N != 1 arguments that invokes a
/// constructor to build a temporary object. With N == 1 arguments the
/// functional cast expression will be represented by CXXFunctionalCastExpr.
/// Example:
/// \code
/// struct X { X(int, float); }
///
/// X create_X() {
///   return X(1, 3.14f); // creates a CXXTemporaryObjectExpr
/// };
/// \endcode
class CXXTemporaryObjectExpr final : public CXXConstructExpr {};

Stmt **CXXConstructExpr::getTrailingArgs() {}

/// A C++ lambda expression, which produces a function object
/// (of unspecified type) that can be invoked later.
///
/// Example:
/// \code
/// void low_pass_filter(std::vector<double> &values, double cutoff) {
///   values.erase(std::remove_if(values.begin(), values.end(),
///                               [=](double value) { return value > cutoff; });
/// }
/// \endcode
///
/// C++11 lambda expressions can capture local variables, either by copying
/// the values of those local variables at the time the function
/// object is constructed (not when it is called!) or by holding a
/// reference to the local variable. These captures can occur either
/// implicitly or can be written explicitly between the square
/// brackets ([...]) that start the lambda expression.
///
/// C++1y introduces a new form of "capture" called an init-capture that
/// includes an initializing expression (rather than capturing a variable),
/// and which can never occur implicitly.
class LambdaExpr final : public Expr,
                         private llvm::TrailingObjects<LambdaExpr, Stmt *> {};

/// An expression "T()" which creates an rvalue of a non-class type T.
/// For non-void T, the rvalue is value-initialized.
/// See (C++98 [5.2.3p2]).
class CXXScalarValueInitExpr : public Expr {};

enum class CXXNewInitializationStyle {};

/// Represents a new-expression for memory allocation and constructor
/// calls, e.g: "new CXXNewExpr(foo)".
class CXXNewExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXNewExpr, Stmt *, SourceRange> {};

/// Represents a \c delete expression for memory deallocation and
/// destructor calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {};

/// Stores the type being destroyed by a pseudo-destructor expression.
class PseudoDestructorTypeStorage {};

/// Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
///
/// A pseudo-destructor is an expression that looks like a member access to a
/// destructor of a scalar type, except that scalar types don't have
/// destructors. For example:
///
/// \code
/// typedef int T;
/// void f(int *p) {
///   p->T::~T();
/// }
/// \endcode
///
/// Pseudo-destructors typically occur when instantiating templates such as:
///
/// \code
/// template<typename T>
/// void destroy(T* ptr) {
///   ptr->T::~T();
/// }
/// \endcode
///
/// for scalar types. A pseudo-destructor expression has no run-time semantics
/// beyond evaluating the base expression.
class CXXPseudoDestructorExpr : public Expr {};

/// A type trait used in the implementation of various C++11 and
/// Library TR1 trait templates.
///
/// \code
///   __is_pod(int) == true
///   __is_enum(std::string) == false
///   __is_trivially_constructible(vector<int>, int*, int*)
/// \endcode
class TypeTraitExpr final
    : public Expr,
      private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> {};

/// An Embarcadero array type trait, as used in the implementation of
/// __array_rank and __array_extent.
///
/// Example:
/// \code
///   __array_rank(int[10][20]) == 2
///   __array_extent(int, 1)    == 20
/// \endcode
class ArrayTypeTraitExpr : public Expr {};

/// An expression trait intrinsic.
///
/// Example:
/// \code
///   __is_lvalue_expr(std::cout) == true
///   __is_lvalue_expr(1) == false
/// \endcode
class ExpressionTraitExpr : public Expr {};

/// A reference to an overloaded function set, either an
/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
class OverloadExpr : public Expr {};

/// A reference to a name which we were able to look up during
/// parsing but could not resolve to a specific declaration.
///
/// This arises in several ways:
///   * we might be waiting for argument-dependent lookup;
///   * the name might resolve to an overloaded function;
///   * the name might resolve to a non-function template; for example, in the
///   following snippet, the return expression of the member function
///   'foo()' might remain unresolved until instantiation:
///
/// \code
/// struct P {
///   template <class T> using I = T;
/// };
///
/// struct Q {
///   template <class T> int foo() {
///     return T::template I<int>;
///   }
/// };
/// \endcode
///
/// ...which is distinct from modeling function overloads, and therefore we use
/// a different builtin type 'UnresolvedTemplate' to avoid confusion. This is
/// done in Sema::BuildTemplateIdExpr.
///
/// and eventually:
///   * the lookup might have included a function template.
///   * the unresolved template gets transformed in an instantiation or gets
///   diagnosed for its direct use.
///
/// These never include UnresolvedUsingValueDecls, which are always class
/// members and therefore appear only in UnresolvedMemberLookupExprs.
class UnresolvedLookupExpr final
    : public OverloadExpr,
      private llvm::TrailingObjects<UnresolvedLookupExpr, DeclAccessPair,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {};

/// A qualified reference to a name whose declaration cannot
/// yet be resolved.
///
/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that
/// it expresses a reference to a declaration such as
/// X<T>::value. The difference, however, is that an
/// DependentScopeDeclRefExpr node is used only within C++ templates when
/// the qualification (e.g., X<T>::) refers to a dependent type. In
/// this case, X<T>::value cannot resolve to a declaration because the
/// declaration will differ from one instantiation of X<T> to the
/// next. Therefore, DependentScopeDeclRefExpr keeps track of the
/// qualifier (X<T>::) and the name of the entity being referenced
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
/// declaration can be found.
class DependentScopeDeclRefExpr final
    : public Expr,
      private llvm::TrailingObjects<DependentScopeDeclRefExpr,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {};

/// Represents an expression -- generally a full-expression -- that
/// introduces cleanups to be run at the end of the sub-expression's
/// evaluation.  The most common source of expression-introduced
/// cleanups is temporary objects in C++, but several other kinds of
/// expressions can create cleanups, including basically every
/// call in ARC that returns an Objective-C pointer.
///
/// This expression also tracks whether the sub-expression contains a
/// potentially-evaluated block literal.  The lifetime of a block
/// literal is the extent of the enclosing scope.
class ExprWithCleanups final
    : public FullExpr,
      private llvm::TrailingObjects<
          ExprWithCleanups,
          llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>> {};

/// Describes an explicit type conversion that uses functional
/// notion but could not be resolved because one or more arguments are
/// type-dependent.
///
/// The explicit type conversions expressed by
/// CXXUnresolvedConstructExpr have the form <tt>T(a1, a2, ..., aN)</tt>,
/// where \c T is some type and \c a1, \c a2, ..., \c aN are values, and
/// either \c T is a dependent type or one or more of the <tt>a</tt>'s is
/// type-dependent. For example, this would occur in a template such
/// as:
///
/// \code
///   template<typename T, typename A1>
///   inline T make_a(const A1& a1) {
///     return T(a1);
///   }
/// \endcode
///
/// When the returned expression is instantiated, it may resolve to a
/// constructor call, conversion function call, or some kind of type
/// conversion.
class CXXUnresolvedConstructExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXUnresolvedConstructExpr, Expr *> {};

/// Represents a C++ member access expression where the actual
/// member referenced could not be resolved because the base
/// expression or the member name was dependent.
///
/// Like UnresolvedMemberExprs, these can be either implicit or
/// explicit accesses.  It is only possible to get one of these with
/// an implicit access if a qualifier is provided.
class CXXDependentScopeMemberExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc, NamedDecl *> {};

/// Represents a C++ member access expression for which lookup
/// produced a set of overloaded functions.
///
/// The member access may be explicit or implicit:
/// \code
///    struct A {
///      int a, b;
///      int explicitAccess() { return this->a + this->A::b; }
///      int implicitAccess() { return a + A::b; }
///    };
/// \endcode
///
/// In the final AST, an explicit access always becomes a MemberExpr.
/// An implicit access may become either a MemberExpr or a
/// DeclRefExpr, depending on whether the member is static.
class UnresolvedMemberExpr final
    : public OverloadExpr,
      private llvm::TrailingObjects<UnresolvedMemberExpr, DeclAccessPair,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {};

DeclAccessPair *OverloadExpr::getTrailingResults() {}

ASTTemplateKWAndArgsInfo *OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() {}

TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {}

CXXRecordDecl *OverloadExpr::getNamingClass() {}

/// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
///
/// The noexcept expression tests whether a given expression might throw. Its
/// result is a boolean constant.
class CXXNoexceptExpr : public Expr {};

/// Represents a C++11 pack expansion that produces a sequence of
/// expressions.
///
/// A pack expansion expression contains a pattern (which itself is an
/// expression) followed by an ellipsis. For example:
///
/// \code
/// template<typename F, typename ...Types>
/// void forward(F f, Types &&...args) {
///   f(static_cast<Types&&>(args)...);
/// }
/// \endcode
///
/// Here, the argument to the function object \c f is a pack expansion whose
/// pattern is \c static_cast<Types&&>(args). When the \c forward function
/// template is instantiated, the pack expansion will instantiate to zero or
/// or more function arguments to the function object \c f.
class PackExpansionExpr : public Expr {};

/// Represents an expression that computes the length of a parameter
/// pack.
///
/// \code
/// template<typename ...Types>
/// struct count {
///   static const unsigned value = sizeof...(Types);
/// };
/// \endcode
class SizeOfPackExpr final
    : public Expr,
      private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> {};

class PackIndexingExpr final
    : public Expr,
      private llvm::TrailingObjects<PackIndexingExpr, Expr *> {};

/// Represents a reference to a non-type template parameter
/// that has been substituted with a template argument.
class SubstNonTypeTemplateParmExpr : public Expr {};

/// Represents a reference to a non-type template parameter pack that
/// has been substituted with a non-template argument pack.
///
/// When a pack expansion in the source code contains multiple parameter packs
/// and those parameter packs correspond to different levels of template
/// parameter lists, this node is used to represent a non-type template
/// parameter pack from an outer level, which has already had its argument pack
/// substituted but that still lives within a pack expansion that itself
/// could not be instantiated. When actually performing a substitution into
/// that pack expansion (e.g., when all template parameters have corresponding
/// arguments), this type will be replaced with the appropriate underlying
/// expression at the current pack substitution index.
class SubstNonTypeTemplateParmPackExpr : public Expr {};

/// Represents a reference to a function parameter pack or init-capture pack
/// that has been substituted but not yet expanded.
///
/// When a pack expansion contains multiple parameter packs at different levels,
/// this node is used to represent a function parameter pack at an outer level
/// which we have already substituted to refer to expanded parameters, but where
/// the containing pack expansion cannot yet be expanded.
///
/// \code
/// template<typename...Ts> struct S {
///   template<typename...Us> auto f(Ts ...ts) -> decltype(g(Us(ts)...));
/// };
/// template struct S<int, int>;
/// \endcode
class FunctionParmPackExpr final
    : public Expr,
      private llvm::TrailingObjects<FunctionParmPackExpr, VarDecl *> {};

/// Represents a prvalue temporary that is written into memory so that
/// a reference can bind to it.
///
/// Prvalue expressions are materialized when they need to have an address
/// in memory for a reference to bind to. This happens when binding a
/// reference to the result of a conversion, e.g.,
///
/// \code
/// const int &r = 1.0;
/// \endcode
///
/// Here, 1.0 is implicitly converted to an \c int. That resulting \c int is
/// then materialized via a \c MaterializeTemporaryExpr, and the reference
/// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues
/// (either an lvalue or an xvalue, depending on the kind of reference binding
/// to it), maintaining the invariant that references always bind to glvalues.
///
/// Reference binding and copy-elision can both extend the lifetime of a
/// temporary. When either happens, the expression will also track the
/// declaration which is responsible for the lifetime extension.
class MaterializeTemporaryExpr : public Expr {};

/// Represents a folding of a pack over an operator.
///
/// This expression is always dependent and represents a pack expansion of the
/// forms:
///
///    ( expr op ... )
///    ( ... op expr )
///    ( expr op ... op expr )
class CXXFoldExpr : public Expr {};

/// Represents a list-initialization with parenthesis.
///
/// As per P0960R3, this is a C++20 feature that allows aggregate to
/// be initialized with a parenthesized list of values:
/// ```
/// struct A {
///   int a;
///   double b;
/// };
///
/// void foo() {
///   A a1(0);        // Well-formed in C++20
///   A a2(1.5, 1.0); // Well-formed in C++20
/// }
/// ```
/// It has some sort of similiarity to braced
/// list-initialization, with some differences such as
/// it allows narrowing conversion whilst braced
/// list-initialization doesn't.
/// ```
/// struct A {
///   char a;
/// };
/// void foo() {
///   A a(1.5); // Well-formed in C++20
///   A b{1.5}; // Ill-formed !
/// }
/// ```
class CXXParenListInitExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXParenListInitExpr, Expr *> {};

/// Represents an expression that might suspend coroutine execution;
/// either a co_await or co_yield expression.
///
/// Evaluation of this expression first evaluates its 'ready' expression. If
/// that returns 'false':
///  -- execution of the coroutine is suspended
///  -- the 'suspend' expression is evaluated
///     -- if the 'suspend' expression returns 'false', the coroutine is
///        resumed
///     -- otherwise, control passes back to the resumer.
/// If the coroutine is not suspended, or when it is resumed, the 'resume'
/// expression is evaluated, and its result is the result of the overall
/// expression.
class CoroutineSuspendExpr : public Expr {};

/// Represents a 'co_await' expression.
class CoawaitExpr : public CoroutineSuspendExpr {};

/// Represents a 'co_await' expression while the type of the promise
/// is dependent.
class DependentCoawaitExpr : public Expr {};

/// Represents a 'co_yield' expression.
class CoyieldExpr : public CoroutineSuspendExpr {};

/// Represents a C++2a __builtin_bit_cast(T, v) expression. Used to implement
/// std::bit_cast. These can sometimes be evaluated as part of a constant
/// expression, but otherwise CodeGen to a simple memcpy in general.
class BuiltinBitCastExpr final
    : public ExplicitCastExpr,
      private llvm::TrailingObjects<BuiltinBitCastExpr, CXXBaseSpecifier *> {};

} // namespace clang

#endif // LLVM_CLANG_AST_EXPRCXX_H