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