//===--- Expr.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 // //===----------------------------------------------------------------------===// // // This file defines the Expr interface and subclasses. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXPR_H #define LLVM_CLANG_AST_EXPR_H #include "clang/AST/APNumericStorage.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTVector.h" #include "clang/AST/ComputeDependence.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclAccessPair.h" #include "clang/AST/DependenceFlags.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SyncScope.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" #include <optional> namespace clang { class APValue; class ASTContext; class BlockDecl; class CXXBaseSpecifier; class CXXMemberCallExpr; class CXXOperatorCallExpr; class CastExpr; class Decl; class IdentifierInfo; class MaterializeTemporaryExpr; class NamedDecl; class ObjCPropertyRefExpr; class OpaqueValueExpr; class ParmVarDecl; class StringLiteral; class TargetInfo; class ValueDecl; /// A simple array of base specifiers. CXXCastPath; /// An adjustment to be made to the temporary created when emitting a /// reference binding, which accesses a particular subobject of that temporary. struct SubobjectAdjustment { … }; /// This represents one expression. Note that Expr's are subclasses of Stmt. /// This allows an expression to be transparently used any place a Stmt is /// required. class Expr : public ValueStmt { … }; // PointerLikeTypeTraits is specialized so it can be used with a forward-decl of // Expr. Verify that we got it right. static_assert …; ConstantExprKind; //===----------------------------------------------------------------------===// // Wrapper Expressions. //===----------------------------------------------------------------------===// /// FullExpr - Represents a "full-expression" node. class FullExpr : public Expr { … }; /// Describes the kind of result that can be tail-allocated. enum class ConstantResultStorageKind { … }; /// ConstantExpr - An expression that occurs in a constant context and /// optionally the result of evaluating the expression. class ConstantExpr final : public FullExpr, private llvm::TrailingObjects<ConstantExpr, APValue, uint64_t> { … }; //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// /// OpaqueValueExpr - An expression referring to an opaque object of a /// fixed type and value class. These don't correspond to concrete /// syntax; instead they're used to express operations (usually copy /// operations) on values whose source is generally obvious from /// context. class OpaqueValueExpr : public Expr { … }; /// A reference to a declared variable, function, enum, etc. /// [C99 6.5.1p2] /// /// This encodes all the information about how a declaration is referenced /// within an expression. /// /// There are several optional constructs attached to DeclRefExprs only when /// they apply in order to conserve memory. These are laid out past the end of /// the object, and flags in the DeclRefExprBitfield track whether they exist: /// /// DeclRefExprBits.HasQualifier: /// Specifies when this declaration reference expression has a C++ /// nested-name-specifier. /// DeclRefExprBits.HasFoundDecl: /// Specifies when this declaration reference expression has a record of /// a NamedDecl (different from the referenced ValueDecl) which was found /// during name lookup and/or overload resolution. /// DeclRefExprBits.HasTemplateKWAndArgsInfo: /// Specifies when this declaration reference expression has an explicit /// C++ template keyword and/or template argument list. /// DeclRefExprBits.RefersToEnclosingVariableOrCapture /// Specifies when this declaration reference expression (validly) /// refers to an enclosed local or a captured variable. class DeclRefExpr final : public Expr, private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc, NamedDecl *, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { … }; class IntegerLiteral : public Expr, public APIntStorage { … }; class FixedPointLiteral : public Expr, public APIntStorage { … }; enum class CharacterLiteralKind { … }; class CharacterLiteral : public Expr { … }; class FloatingLiteral : public Expr, private APFloatStorage { … }; /// ImaginaryLiteral - We support imaginary integer and floating point literals, /// like "1.0i". We represent these as a wrapper around FloatingLiteral and /// IntegerLiteral classes. Instances of this class always have a Complex type /// whose element type matches the subexpression. /// class ImaginaryLiteral : public Expr { … }; enum class StringLiteralKind { … }; /// StringLiteral - This represents a string literal expression, e.g. "foo" /// or L"bar" (wide strings). The actual string data can be obtained with /// getBytes() and is NOT null-terminated. The length of the string data is /// determined by calling getByteLength(). /// /// The C type for a string is always a ConstantArrayType. In C++, the char /// type is const qualified, in C it is not. /// /// Note that strings in C can be formed by concatenation of multiple string /// literal pptokens in translation phase #6. This keeps track of the locations /// of each of these pieces. /// /// Strings in C can also be truncated and extended by assigning into arrays, /// e.g. with constructs like: /// char X[2] = "foobar"; /// In this case, getByteLength() will return 6, but the string literal will /// have type "char[2]". class StringLiteral final : public Expr, private llvm::TrailingObjects<StringLiteral, unsigned, SourceLocation, char> { … }; enum class PredefinedIdentKind { … }; /// [C99 6.4.2.2] - A predefined identifier such as __func__. class PredefinedExpr final : public Expr, private llvm::TrailingObjects<PredefinedExpr, Stmt *> { … }; /// This expression type represents an asterisk in an OpenACC Size-Expr, used in /// the 'tile' and 'gang' clauses. It is of 'int' type, but should not be /// evaluated. class OpenACCAsteriskSizeExpr final : public Expr { … }; // This represents a use of the __builtin_sycl_unique_stable_name, which takes a // type-id, and at CodeGen time emits a unique string representation of the // type in a way that permits us to properly encode information about the SYCL // kernels. class SYCLUniqueStableNameExpr final : public Expr { … }; /// ParenExpr - This represents a parenthesized expression, e.g. "(1)". This /// AST node is only formed if full location information is requested. class ParenExpr : public Expr { … }; /// UnaryOperator - This represents the unary-expression's (except sizeof and /// alignof), the postinc/postdec operators from postfix-expression, and various /// extensions. /// /// Notes on various nodes: /// /// Real/Imag - These return the real/imag part of a complex operand. If /// applied to a non-complex value, the former returns its operand and the /// later returns zero in the type of the operand. /// class UnaryOperator final : public Expr, private llvm::TrailingObjects<UnaryOperator, FPOptionsOverride> { … }; /// Helper class for OffsetOfExpr. // __builtin_offsetof(type, identifier(.identifier|[expr])*) class OffsetOfNode { … }; /// OffsetOfExpr - [C99 7.17] - This represents an expression of the form /// offsetof(record-type, member-designator). For example, given: /// @code /// struct S { /// float f; /// double d; /// }; /// struct T { /// int i; /// struct S s[10]; /// }; /// @endcode /// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). class OffsetOfExpr final : public Expr, private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> { … }; /// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) /// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and /// vec_step (OpenCL 1.1 6.11.12). class UnaryExprOrTypeTraitExpr : public Expr { … }; //===----------------------------------------------------------------------===// // Postfix Operators. //===----------------------------------------------------------------------===// /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. class ArraySubscriptExpr : public Expr { … }; /// MatrixSubscriptExpr - Matrix subscript expression for the MatrixType /// extension. /// MatrixSubscriptExpr can be either incomplete (only Base and RowIdx are set /// so far, the type is IncompleteMatrixIdx) or complete (Base, RowIdx and /// ColumnIdx refer to valid expressions). Incomplete matrix expressions only /// exist during the initial construction of the AST. class MatrixSubscriptExpr : public Expr { … }; /// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). /// CallExpr itself represents a normal function call, e.g., "f(x, 2)", /// while its subclasses may represent alternative syntax that (semantically) /// results in a function call. For example, CXXOperatorCallExpr is /// a subclass for overloaded operator calls that use operator syntax, e.g., /// "str1 + str2" to resolve to a function call. class CallExpr : public Expr { … }; /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr final : public Expr, private llvm::TrailingObjects<MemberExpr, NestedNameSpecifierLoc, DeclAccessPair, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { … }; /// CompoundLiteralExpr - [C99 6.5.2.5] /// class CompoundLiteralExpr : public Expr { … }; /// CastExpr - Base class for type casts, including both implicit /// casts (ImplicitCastExpr) and explicit casts that have some /// representation in the source code (ExplicitCastExpr's derived /// classes). class CastExpr : public Expr { … }; /// ImplicitCastExpr - Allows us to explicitly represent implicit type /// conversions, which have no direct representation in the original /// source code. For example: converting T[]->T*, void f()->void /// (*f)(), float->double, short->int, etc. /// /// In C, implicit casts always produce rvalues. However, in C++, an /// implicit cast whose result is being bound to a reference will be /// an lvalue or xvalue. For example: /// /// @code /// class Base { }; /// class Derived : public Base { }; /// Derived &&ref(); /// void f(Derived d) { /// Base& b = d; // initializer is an ImplicitCastExpr /// // to an lvalue of type Base /// Base&& r = ref(); // initializer is an ImplicitCastExpr /// // to an xvalue of type Base /// } /// @endcode class ImplicitCastExpr final : public CastExpr, private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *, FPOptionsOverride> { … }; /// ExplicitCastExpr - An explicit cast written in the source /// code. /// /// This class is effectively an abstract class, because it provides /// the basic representation of an explicitly-written cast without /// specifying which kind of cast (C cast, functional cast, static /// cast, etc.) was written; specific derived classes represent the /// particular style of cast and its location information. /// /// Unlike implicit casts, explicit cast nodes have two different /// types: the type that was written into the source code, and the /// actual type of the expression as determined by semantic /// analysis. These types may differ slightly. For example, in C++ one /// can cast to a reference type, which indicates that the resulting /// expression will be an lvalue or xvalue. The reference type, however, /// will not be used as the type of the expression. class ExplicitCastExpr : public CastExpr { … }; /// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style /// cast in C++ (C++ [expr.cast]), which uses the syntax /// (Type)expr. For example: @c (int)f. class CStyleCastExpr final : public ExplicitCastExpr, private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *, FPOptionsOverride> { … }; /// A builtin binary operation expression such as "x + y" or "x <= y". /// /// This expression node kind describes a builtin binary operation, /// such as "x + y" for integer values "x" and "y". The operands will /// already have been converted to appropriate types (e.g., by /// performing promotions or conversions). /// /// In C++, where operators may be overloaded, a different kind of /// expression node (CXXOperatorCallExpr) is used to express the /// invocation of an overloaded operator with operator syntax. Within /// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is /// used to store an expression "x + y" depends on the subexpressions /// for x and y. If neither x or y is type-dependent, and the "+" /// operator resolves to a built-in operation, BinaryOperator will be /// used to express the computation (x and y may still be /// value-dependent). If either x or y is type-dependent, or if the /// "+" resolves to an overloaded operator, CXXOperatorCallExpr will /// be used to express the computation. class BinaryOperator : public Expr { … }; /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep /// track of the type the operation is performed in. Due to the semantics of /// these operators, the operands are promoted, the arithmetic performed, an /// implicit conversion back to the result type done, then the assignment takes /// place. This captures the intermediate type which the computation is done /// in. class CompoundAssignOperator : public BinaryOperator { … }; inline size_t BinaryOperator::offsetOfTrailingStorage() const { … } /// AbstractConditionalOperator - An abstract base class for /// ConditionalOperator and BinaryConditionalOperator. class AbstractConditionalOperator : public Expr { … }; /// ConditionalOperator - The ?: ternary operator. The GNU "missing /// middle" extension is a BinaryConditionalOperator. class ConditionalOperator : public AbstractConditionalOperator { … }; /// BinaryConditionalOperator - The GNU extension to the conditional /// operator which allows the middle operand to be omitted. /// /// This is a different expression kind on the assumption that almost /// every client ends up needing to know that these are different. class BinaryConditionalOperator : public AbstractConditionalOperator { … }; inline Expr *AbstractConditionalOperator::getCond() const { … } inline Expr *AbstractConditionalOperator::getTrueExpr() const { … } inline Expr *AbstractConditionalOperator::getFalseExpr() const { … } /// AddrLabelExpr - The GNU address of label extension, representing &&label. class AddrLabelExpr : public Expr { … }; /// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}). /// The StmtExpr contains a single CompoundStmt node, which it evaluates and /// takes the value of the last subexpression. /// /// A StmtExpr is always an r-value; values "returned" out of a /// StmtExpr will be copied. class StmtExpr : public Expr { … }; /// ShuffleVectorExpr - clang-specific builtin-in function /// __builtin_shufflevector. /// This AST node represents a operator that does a constant /// shuffle, similar to LLVM's shufflevector instruction. It takes /// two vectors and a variable number of constant indices, /// and returns the appropriately shuffled vector. class ShuffleVectorExpr : public Expr { … }; /// ConvertVectorExpr - Clang builtin function __builtin_convertvector /// This AST node provides support for converting a vector type to another /// vector type of the same arity. class ConvertVectorExpr : public Expr { … }; /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. /// This AST node is similar to the conditional operator (?:) in C, with /// the following exceptions: /// - the test expression must be a integer constant expression. /// - the expression returned acts like the chosen subexpression in every /// visible way: the type is the same as that of the chosen subexpression, /// and all predicates (whether it's an l-value, whether it's an integer /// constant expression, etc.) return the same result as for the chosen /// sub-expression. class ChooseExpr : public Expr { … }; /// GNUNullExpr - Implements the GNU __null extension, which is a name /// for a null pointer constant that has integral type (e.g., int or /// long) and is the same size and alignment as a pointer. The __null /// extension is typically only used by system headers, which define /// NULL as __null in C++ rather than using 0 (which is an integer /// that may not match the size of a pointer). class GNUNullExpr : public Expr { … }; /// Represents a call to the builtin function \c __builtin_va_arg. class VAArgExpr : public Expr { … }; enum class SourceLocIdentKind { … }; /// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(), /// __builtin_FUNCTION(), __builtin_FUNCSIG(), __builtin_FILE(), /// __builtin_FILE_NAME() or __builtin_source_location(). class SourceLocExpr final : public Expr { … }; /// Stores data related to a single #embed directive. struct EmbedDataStorage { … }; /// Represents a reference to #emded data. By default, this references the whole /// range. Otherwise it represents a subrange of data imported by #embed /// directive. Needed to handle nested initializer lists with #embed directives. /// Example: /// struct S { /// int x, y; /// }; /// /// struct T { /// int x[2]; /// struct S s /// }; /// /// struct T t[] = { /// #embed "data" // data contains 10 elements; /// }; /// /// The resulting semantic form of initializer list will contain (EE stands /// for EmbedExpr): /// { {EE(first two data elements), {EE(3rd element), EE(4th element) }}, /// { {EE(5th and 6th element), {EE(7th element), EE(8th element) }}, /// { {EE(9th and 10th element), { zeroinitializer }}} /// /// EmbedExpr inside of a semantic initializer list and referencing more than /// one element can only appear for arrays of scalars. class EmbedExpr final : public Expr { … }; /// Describes an C or C++ initializer list. /// /// InitListExpr describes an initializer list, which can be used to /// initialize objects of different types, including /// struct/class/union types, arrays, and vectors. For example: /// /// @code /// struct foo x = { 1, { 2, 3 } }; /// @endcode /// /// Prior to semantic analysis, an initializer list will represent the /// initializer list as written by the user, but will have the /// placeholder type "void". This initializer list is called the /// syntactic form of the initializer, and may contain C99 designated /// initializers (represented as DesignatedInitExprs), initializations /// of subobject members without explicit braces, and so on. Clients /// interested in the original syntax of the initializer list should /// use the syntactic form of the initializer list. /// /// After semantic analysis, the initializer list will represent the /// semantic form of the initializer, where the initializations of all /// subobjects are made explicit with nested InitListExpr nodes and /// C99 designators have been eliminated by placing the designated /// initializations into the subobject they initialize. Additionally, /// any "holes" in the initialization, where no initializer has been /// specified for a particular subobject, will be replaced with /// implicitly-generated ImplicitValueInitExpr expressions that /// value-initialize the subobjects. Note, however, that the /// initializer lists may still have fewer initializers than there are /// elements to initialize within the object. /// /// After semantic analysis has completed, given an initializer list, /// method isSemanticForm() returns true if and only if this is the /// semantic form of the initializer list (note: the same AST node /// may at the same time be the syntactic form). /// Given the semantic form of the initializer list, one can retrieve /// the syntactic form of that initializer list (when different) /// using method getSyntacticForm(); the method returns null if applied /// to a initializer list which is already in syntactic form. /// Similarly, given the syntactic form (i.e., an initializer list such /// that isSemanticForm() returns false), one can retrieve the semantic /// form using method getSemanticForm(). /// Since many initializer lists have the same syntactic and semantic forms, /// getSyntacticForm() may return NULL, indicating that the current /// semantic initializer list also serves as its syntactic form. class InitListExpr : public Expr { … }; /// Represents a C99 designated initializer expression. /// /// A designated initializer expression (C99 6.7.8) contains one or /// more designators (which can be field designators, array /// designators, or GNU array-range designators) followed by an /// expression that initializes the field or element(s) that the /// designators refer to. For example, given: /// /// @code /// struct point { /// double x; /// double y; /// }; /// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; /// @endcode /// /// The InitListExpr contains three DesignatedInitExprs, the first of /// which covers @c [2].y=1.0. This DesignatedInitExpr will have two /// designators, one array designator for @c [2] followed by one field /// designator for @c .y. The initialization expression will be 1.0. class DesignatedInitExpr final : public Expr, private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> { … }; /// Represents a place-holder for an object not to be initialized by /// anything. /// /// This only makes sense when it appears as part of an updater of a /// DesignatedInitUpdateExpr (see below). The base expression of a DIUE /// initializes a big object, and the NoInitExpr's mark the spots within the /// big object not to be overwritten by the updater. /// /// \see DesignatedInitUpdateExpr class NoInitExpr : public Expr { … }; // In cases like: // struct Q { int a, b, c; }; // Q *getQ(); // void foo() { // struct A { Q q; } a = { *getQ(), .q.b = 3 }; // } // // We will have an InitListExpr for a, with type A, and then a // DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE // is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3" // class DesignatedInitUpdateExpr : public Expr { … }; /// Represents a loop initializing the elements of an array. /// /// The need to initialize the elements of an array occurs in a number of /// contexts: /// /// * in the implicit copy/move constructor for a class with an array member /// * when a lambda-expression captures an array by value /// * when a decomposition declaration decomposes an array /// /// There are two subexpressions: a common expression (the source array) /// that is evaluated once up-front, and a per-element initializer that /// runs once for each array element. /// /// Within the per-element initializer, the common expression may be referenced /// via an OpaqueValueExpr, and the current index may be obtained via an /// ArrayInitIndexExpr. class ArrayInitLoopExpr : public Expr { … }; /// Represents the index of the current element of an array being /// initialized by an ArrayInitLoopExpr. This can only appear within the /// subexpression of an ArrayInitLoopExpr. class ArrayInitIndexExpr : public Expr { … }; /// Represents an implicitly-generated value initialization of /// an object of a given type. /// /// Implicit value initializations occur within semantic initializer /// list expressions (InitListExpr) as placeholders for subobject /// initializations not explicitly specified by the user. /// /// \see InitListExpr class ImplicitValueInitExpr : public Expr { … }; class ParenListExpr final : public Expr, private llvm::TrailingObjects<ParenListExpr, Stmt *> { … }; /// Represents a C11 generic selection. /// /// A generic selection (C11 6.5.1.1) contains an unevaluated controlling /// expression, followed by one or more generic associations. Each generic /// association specifies a type name and an expression, or "default" and an /// expression (in which case it is known as a default generic association). /// The type and value of the generic selection are identical to those of its /// result expression, which is defined as the expression in the generic /// association with a type name that is compatible with the type of the /// controlling expression, or the expression in the default generic association /// if no types are compatible. For example: /// /// @code /// _Generic(X, double: 1, float: 2, default: 3) /// @endcode /// /// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f /// or 3 if "hello". /// /// As an extension, generic selections are allowed in C++, where the following /// additional semantics apply: /// /// Any generic selection whose controlling expression is type-dependent or /// which names a dependent type in its association list is result-dependent, /// which means that the choice of result expression is dependent. /// Result-dependent generic associations are both type- and value-dependent. /// /// We also allow an extended form in both C and C++ where the controlling /// predicate for the selection expression is a type rather than an expression. /// This type argument form does not perform any conversions for the /// controlling type, which makes it suitable for use with qualified type /// associations, which is not possible with the expression form. class GenericSelectionExpr final : public Expr, private llvm::TrailingObjects<GenericSelectionExpr, Stmt *, TypeSourceInfo *> { … }; //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// /// ExtVectorElementExpr - This represents access to specific elements of a /// vector, and may occur on the left hand side or right hand side. For example /// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. /// /// Note that the base may have either vector or pointer to vector type, just /// like a struct field reference. /// class ExtVectorElementExpr : public Expr { … }; /// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } class BlockExpr : public Expr { … }; /// Copy initialization expr of a __block variable and a boolean flag that /// indicates whether the expression can throw. struct BlockVarCopyInit { … }; /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] /// This AST node provides support for reinterpreting a type to another /// type of the same size. class AsTypeExpr : public Expr { … }; /// PseudoObjectExpr - An expression which accesses a pseudo-object /// l-value. A pseudo-object is an abstract object, accesses to which /// are translated to calls. The pseudo-object expression has a /// syntactic form, which shows how the expression was actually /// written in the source code, and a semantic form, which is a series /// of expressions to be executed in order which detail how the /// operation is actually evaluated. Optionally, one of the semantic /// forms may also provide a result value for the expression. /// /// If any of the semantic-form expressions is an OpaqueValueExpr, /// that OVE is required to have a source expression, and it is bound /// to the result of that source expression. Such OVEs may appear /// only in subsequent semantic-form expressions and as /// sub-expressions of the syntactic form. /// /// PseudoObjectExpr should be used only when an operation can be /// usefully described in terms of fairly simple rewrite rules on /// objects and functions that are meant to be used by end-developers. /// For example, under the Itanium ABI, dynamic casts are implemented /// as a call to a runtime function called __dynamic_cast; using this /// class to describe that would be inappropriate because that call is /// not really part of the user-visible semantics, and instead the /// cast is properly reflected in the AST and IR-generation has been /// taught to generate the call as necessary. In contrast, an /// Objective-C property access is semantically defined to be /// equivalent to a particular message send, and this is very much /// part of the user model. The name of this class encourages this /// modelling design. class PseudoObjectExpr final : public Expr, private llvm::TrailingObjects<PseudoObjectExpr, Expr *> { … }; /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the /// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>, /// and corresponding __opencl_atomic_* for OpenCL 2.0. /// All of these instructions take one primary pointer, at least one memory /// order. The instructions for which getScopeModel returns non-null value /// take one synch scope. class AtomicExpr : public Expr { … }; /// TypoExpr - Internal placeholder for expressions where typo correction /// still needs to be performed and/or an error diagnostic emitted. class TypoExpr : public Expr { … }; /// This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', /// with a boolean differentiator. /// OpenMP 5.0 [2.1.5, Array Sections]. /// To specify an array section in an OpenMP construct, array subscript /// expressions are extended with the following syntax: /// \code /// [ lower-bound : length : stride ] /// [ lower-bound : length : ] /// [ lower-bound : length ] /// [ lower-bound : : stride ] /// [ lower-bound : : ] /// [ lower-bound : ] /// [ : length : stride ] /// [ : length : ] /// [ : length ] /// [ : : stride ] /// [ : : ] /// [ : ] /// \endcode /// The array section must be a subset of the original array. /// Array sections are allowed on multidimensional arrays. Base language array /// subscript expressions can be used to specify length-one dimensions of /// multidimensional array sections. /// Each of the lower-bound, length, and stride expressions if specified must be /// an integral type expressions of the base language. When evaluated /// they represent a set of integer values as follows: /// \code /// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... , /// lower-bound + ((length - 1) * stride) } /// \endcode /// The lower-bound and length must evaluate to non-negative integers. /// The stride must evaluate to a positive integer. /// When the size of the array dimension is not known, the length must be /// specified explicitly. /// When the stride is absent it defaults to 1. /// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉, /// where size is the size of the array dimension. When the lower-bound is /// absent it defaults to 0. /// /// /// OpenACC 3.3 [2.7.1 Data Specification in Data Clauses] /// In C and C++, a subarray is an array name followed by an extended array /// range specification in brackets, with start and length, such as /// /// AA[2:n] /// /// If the lower bound is missing, zero is used. If the length is missing and /// the array has known size, the size of the array is used; otherwise the /// length is required. The subarray AA[2:n] means elements AA[2], AA[3], . . . /// , AA[2+n-1]. In C and C++, a two dimensional array may be declared in at /// least four ways: /// /// -Statically-sized array: float AA[100][200]; /// -Pointer to statically sized rows: typedef float row[200]; row* BB; /// -Statically-sized array of pointers: float* CC[200]; /// -Pointer to pointers: float** DD; /// /// Each dimension may be statically sized, or a pointer to dynamically /// allocated memory. Each of these may be included in a data clause using /// subarray notation to specify a rectangular array: /// /// -AA[2:n][0:200] /// -BB[2:n][0:m] /// -CC[2:n][0:m] /// -DD[2:n][0:m] /// /// Multidimensional rectangular subarrays in C and C++ may be specified for any /// array with any combination of statically-sized or dynamically-allocated /// dimensions. For statically sized dimensions, all dimensions except the first /// must specify the whole extent to preserve the contiguous data restriction, /// discussed below. For dynamically allocated dimensions, the implementation /// will allocate pointers in device memory corresponding to the pointers in /// local memory and will fill in those pointers as appropriate. /// /// In Fortran, a subarray is an array name followed by a comma-separated list /// of range specifications in parentheses, with lower and upper bound /// subscripts, such as /// /// arr(1:high,low:100) /// /// If either the lower or upper bounds are missing, the declared or allocated /// bounds of the array, if known, are used. All dimensions except the last must /// specify the whole extent, to preserve the contiguous data restriction, /// discussed below. /// /// Restrictions /// /// -In Fortran, the upper bound for the last dimension of an assumed-size dummy /// array must be specified. /// /// -In C and C++, the length for dynamically allocated dimensions of an array /// must be explicitly specified. /// /// -In C and C++, modifying pointers in pointer arrays during the data /// lifetime, either on the host or on the device, may result in undefined /// behavior. /// /// -If a subarray appears in a data clause, the implementation may choose to /// allocate memory for only that subarray on the accelerator. /// /// -In Fortran, array pointers may appear, but pointer association is not /// preserved in device memory. /// /// -Any array or subarray in a data clause, including Fortran array pointers, /// must be a contiguous section of memory, except for dynamic multidimensional /// C arrays. /// /// -In C and C++, if a variable or array of composite type appears, all the /// data members of the struct or class are allocated and copied, as /// appropriate. If a composite member is a pointer type, the data addressed by /// that pointer are not implicitly copied. /// /// -In Fortran, if a variable or array of composite type appears, all the /// members of that derived type are allocated and copied, as appropriate. If /// any member has the allocatable or pointer attribute, the data accessed /// through that member are not copied. /// /// -If an expression is used in a subscript or subarray expression in a clause /// on a data construct, the same value is used when copying data at the end of /// the data region, even if the values of variables in the expression change /// during the data region. class ArraySectionExpr : public Expr { … }; /// This class represents temporary values used to represent inout and out /// arguments in HLSL. From the callee perspective these parameters are more or /// less __restrict__ T&. They are guaranteed to not alias any memory. inout /// parameters are initialized by the caller, and out parameters are references /// to uninitialized memory. /// /// In the caller, the argument expression creates a temporary in local memory /// and the address of the temporary is passed into the callee. There may be /// implicit conversion sequences to initialize the temporary, and on expiration /// of the temporary an inverse conversion sequence is applied as a write-back /// conversion to the source l-value. /// /// This AST node has three sub-expressions: /// - An OpaqueValueExpr with a source that is the argument lvalue expression. /// - An OpaqueValueExpr with a source that is an implicit conversion /// sequence from the source lvalue to the argument type. /// - An expression that assigns the second expression into the first, /// performing any necessary conversions. class HLSLOutArgExpr : public Expr { … }; /// Frontend produces RecoveryExprs on semantic errors that prevent creating /// other well-formed expressions. E.g. when type-checking of a binary operator /// fails, we cannot produce a BinaryOperator expression. Instead, we can choose /// to produce a recovery expression storing left and right operands. /// /// RecoveryExpr does not have any semantic meaning in C++, it is only useful to /// preserve expressions in AST that would otherwise be dropped. It captures /// subexpressions of some expression that we could not construct and source /// range covered by the expression. /// /// By default, RecoveryExpr uses dependence-bits to take advantage of existing /// machinery to deal with dependent code in C++, e.g. RecoveryExpr is preserved /// in `decltype(<broken-expr>)` as part of the `DependentDecltypeType`. In /// addition to that, clang does not report most errors on dependent /// expressions, so we get rid of bogus errors for free. However, note that /// unlike other dependent expressions, RecoveryExpr can be produced in /// non-template contexts. /// /// We will preserve the type in RecoveryExpr when the type is known, e.g. /// preserving the return type for a broken non-overloaded function call, a /// overloaded call where all candidates have the same return type. In this /// case, the expression is not type-dependent (unless the known type is itself /// dependent) /// /// One can also reliably suppress all bogus errors on expressions containing /// recovery expressions by examining results of Expr::containsErrors(). class RecoveryExpr final : public Expr, private llvm::TrailingObjects<RecoveryExpr, Expr *> { … }; } // end namespace clang #endif // LLVM_CLANG_AST_EXPR_H