Unary and Binary Expressions (GNU Compiler Collection (GCC) Internals)

#### 11.6.3 Unary and Binary Expressions ¶

`NEGATE_EXPR`

  These nodes represent unary negation of the single operand, for both integer and floating-point types. The type of negation can be determined by looking at the type of the expression.

  The behavior of this operation on signed arithmetic overflow is controlled by the `flag_wrapv` and `flag_trapv` variables.

`ABS_EXPR`

  These nodes represent the absolute value of the single operand, for both integer and floating-point types. This is typically used to implement the `abs`, `labs` and `llabs` builtins for integer types, and the `fabs`, `fabsf` and `fabsl` builtins for floating point types. The type of abs operation can be determined by looking at the type of the expression.

  This node is not used for complex types. To represent the modulus or complex abs of a complex value, use the `BUILT_IN_CABS`, `BUILT_IN_CABSF` or `BUILT_IN_CABSL` builtins, as used to implement the C99 `cabs`, `cabsf` and `cabsl` built-in functions.

`ABSU_EXPR`

  These nodes represent the absolute value of the single operand in equivalent unsigned type such that `ABSU_EXPR` of `TYPE_MIN` is well defined.

`BIT_NOT_EXPR`

  These nodes represent bitwise complement, and will always have integral type. The only operand is the value to be complemented.

`TRUTH_NOT_EXPR`

  These nodes represent logical negation, and will always have integral (or boolean) type. The operand is the value being negated. The type of the operand and that of the result are always of `BOOLEAN_TYPE` or `INTEGER_TYPE`.

`PREDECREMENT_EXPR`
`PREINCREMENT_EXPR`
`POSTDECREMENT_EXPR`
`POSTINCREMENT_EXPR`

  These nodes represent increment and decrement expressions. The value of the single operand is computed, and the operand incremented or decremented. In the case of `PREDECREMENT_EXPR` and `PREINCREMENT_EXPR`, the value of the expression is the value resulting after the increment or decrement; in the case of `POSTDECREMENT_EXPR` and `POSTINCREMENT_EXPR` is the value before the increment or decrement occurs. The type of the operand, like that of the result, will be either integral, boolean, or floating-point.

`FIX_TRUNC_EXPR`

  These nodes represent conversion of a floating-point value to an integer. The single operand will have a floating-point type, while the complete expression will have an integral (or boolean) type. The operand is rounded towards zero.

`FLOAT_EXPR`

  These nodes represent conversion of an integral (or boolean) value to a floating-point value. The single operand will have integral type, while the complete expression will have a floating-point type.

  FIXME: How is the operand supposed to be rounded? Is this dependent on `-mieee`?

`COMPLEX_EXPR`

  These nodes are used to represent complex numbers constructed from two expressions of the same (integer or real) type. The first operand is the real part and the second operand is the imaginary part.

`CONJ_EXPR`

  These nodes represent the conjugate of their operand.

`REALPART_EXPR`
`IMAGPART_EXPR`

  These nodes represent respectively the real and the imaginary parts of complex numbers (their sole argument).

`NON_LVALUE_EXPR`

  These nodes indicate that their one and only operand is not an lvalue. A back end can treat these identically to the single operand.

`NOP_EXPR`

  These nodes are used to represent conversions that do not require any code-generation. For example, conversion of a `char*` to an `int*` does not require any code be generated; such a conversion is represented by a `NOP_EXPR`. The single operand is the expression to be converted. The conversion from a pointer to a reference is also represented with a `NOP_EXPR`.

`CONVERT_EXPR`

  These nodes are similar to `NOP_EXPR`s, but are used in those situations where code may need to be generated. For example, if an `int*` is converted to an `int` code may need to be generated on some platforms. These nodes are never used for C++-specific conversions, like conversions between pointers to different classes in an inheritance hierarchy. Any adjustments that need to be made in such cases are always indicated explicitly. Similarly, a user-defined conversion is never represented by a `CONVERT_EXPR`; instead, the function calls are made explicit.

`FIXED_CONVERT_EXPR`

  These nodes are used to represent conversions that involve fixed-point values. For example, from a fixed-point value to another fixed-point value, from an integer to a fixed-point value, from a fixed-point value to an integer, from a floating-point value to a fixed-point value, or from a fixed-point value to a floating-point value.

`LSHIFT_EXPR`
`RSHIFT_EXPR`
`LROTATE_EXPR`
`RROTATE_EXPR`

  These nodes represent left and right shifts and rotates, respectively. The first operand is the value to shift or rotate; it will always be of integral type. The second operand is an expression for the number of bits by which to shift or rotate. Right shift should be treated as arithmetic, i.e., the high-order bits should be zero-filled when the expression has unsigned type and filled with the sign bit when the expression has signed type. All other operations are logical, operating on the bit representation. Note that the result is undefined if the second operand is larger than or equal to the first operand’s type size. Unlike most nodes, these can have a vector as first operand and a scalar as second operand.

`BIT_IOR_EXPR`
`BIT_XOR_EXPR`
`BIT_AND_EXPR`

  These nodes represent bitwise inclusive or, bitwise exclusive or, and bitwise and, respectively. Both operands will always have integral type.

`TRUTH_ANDIF_EXPR`
`TRUTH_ORIF_EXPR`

  These nodes represent logical “and” and logical “or”, respectively. These operators are not strict; i.e., the second operand is evaluated only if the value of the expression is not determined by evaluation of the first operand. The type of the operands and that of the result are always of `BOOLEAN_TYPE` or `INTEGER_TYPE`.

`TRUTH_AND_EXPR`
`TRUTH_OR_EXPR`
`TRUTH_XOR_EXPR`

  These nodes represent logical and, logical or, and logical exclusive or. They are strict; both arguments are always evaluated. There are no corresponding operators in C or C++, but the front end will sometimes generate these expressions anyhow, if it can tell that strictness does not matter. The type of the operands and that of the result are always of `BOOLEAN_TYPE` or `INTEGER_TYPE`.

`POINTER_PLUS_EXPR`

  This node represents pointer arithmetic. The first operand is always a pointer/reference type. The second operand is always an unsigned integer type compatible with sizetype. This and POINTER_DIFF_EXPR are the only binary arithmetic operators that can operate on pointer types.

`POINTER_DIFF_EXPR`

  This node represents pointer subtraction. The two operands always have pointer/reference type. It returns a signed integer of the same precision as the pointers. The behavior is undefined if the difference of the two pointers, seen as infinite precision non-negative integers, does not fit in the result type. The result does not depend on the pointer type, it is not divided by the size of the pointed-to type.

`PLUS_EXPR`
`MINUS_EXPR`
`MULT_EXPR`

  These nodes represent various binary arithmetic operations. Respectively, these operations are addition, subtraction (of the second operand from the first) and multiplication. Their operands may have either integral or floating type, but there will never be case in which one operand is of floating type and the other is of integral type.

  The behavior of these operations on signed arithmetic overflow is controlled by the `flag_wrapv` and `flag_trapv` variables.

`WIDEN_MULT_EXPR`

  This node represents a widening multiplication. The operands have integral types with same b bits of precision, producing an integral type result with at least 2b bits of precision. The behaviour is equivalent to extending both operands, possibly of different signedness, to the result type, then multiplying them.

`MULT_HIGHPART_EXPR`

  This node represents the “high-part” of a widening multiplication. For an integral type with b bits of precision, the result is the most significant b bits of the full 2b product. Both operands must have the same precision and same signedness.

`RDIV_EXPR`

  This node represents a floating point division operation.

`TRUNC_DIV_EXPR`
`FLOOR_DIV_EXPR`
`CEIL_DIV_EXPR`
`ROUND_DIV_EXPR`

  These nodes represent integer division operations that return an integer result. `TRUNC_DIV_EXPR` rounds towards zero, `FLOOR_DIV_EXPR` rounds towards negative infinity, `CEIL_DIV_EXPR` rounds towards positive infinity and `ROUND_DIV_EXPR` rounds to the closest integer. Integer division in C and C++ is truncating, i.e. `TRUNC_DIV_EXPR`.

  The behavior of these operations on signed arithmetic overflow, when dividing the minimum signed integer by minus one, is controlled by the `flag_wrapv` and `flag_trapv` variables.

`TRUNC_MOD_EXPR`
`FLOOR_MOD_EXPR`
`CEIL_MOD_EXPR`
`ROUND_MOD_EXPR`

  These nodes represent the integer remainder or modulus operation. The integer modulus of two operands `a` and `b` is defined as `a - (a/b)*b` where the division calculated using the corresponding division operator. Hence for `TRUNC_MOD_EXPR` this definition assumes division using truncation towards zero, i.e. `TRUNC_DIV_EXPR`. Integer remainder in C and C++ uses truncating division, i.e. `TRUNC_MOD_EXPR`.

`EXACT_DIV_EXPR`

  The `EXACT_DIV_EXPR` code is used to represent integer divisions where the numerator is known to be an exact multiple of the denominator. This allows the backend to choose between the faster of `TRUNC_DIV_EXPR`, `CEIL_DIV_EXPR` and `FLOOR_DIV_EXPR` for the current target.

`LT_EXPR`
`LE_EXPR`
`GT_EXPR`
`GE_EXPR`
`LTGT_EXPR`
`EQ_EXPR`
`NE_EXPR`

  These nodes represent the less than, less than or equal to, greater than, greater than or equal to, less or greater than, equal, and not equal comparison operators. The first and second operands will either be both of integral type, both of floating type or both of vector type, except for LTGT_EXPR where they will only be both of floating type. The result type of these expressions will always be of integral, boolean or signed integral vector type. These operations return the result type’s zero value for false, the result type’s one value for true, and a vector whose elements are zero (false) or minus one (true) for vectors.

  For floating point comparisons, if we honor IEEE NaNs and either operand is NaN, then `NE_EXPR` always returns true and the remaining operators always return false. On some targets, comparisons against an IEEE NaN, other than equality and inequality, may generate a floating-point exception.

`ORDERED_EXPR`
`UNORDERED_EXPR`

  These nodes represent non-trapping ordered and unordered comparison operators. These operations take two floating point operands and determine whether they are ordered or unordered relative to each other. If either operand is an IEEE NaN, their comparison is defined to be unordered, otherwise the comparison is defined to be ordered. The result type of these expressions will always be of integral or boolean type. These operations return the result type’s zero value for false, and the result type’s one value for true.

`UNLT_EXPR`
`UNLE_EXPR`
`UNGT_EXPR`
`UNGE_EXPR`
`UNEQ_EXPR`

  These nodes represent the unordered comparison operators. These operations take two floating point operands and determine whether the operands are unordered or are less than, less than or equal to, greater than, greater than or equal to, or equal respectively. For example, `UNLT_EXPR` returns true if either operand is an IEEE NaN or the first operand is less than the second. All these operations are guaranteed not to generate a floating point exception. The result type of these expressions will always be of integral or boolean type. These operations return the result type’s zero value for false, and the result type’s one value for true.

`MODIFY_EXPR`

  These nodes represent assignment. The left-hand side is the first operand; the right-hand side is the second operand. The left-hand side will be a `VAR_DECL`, `INDIRECT_REF`, `COMPONENT_REF`, or other lvalue.

  These nodes are used to represent not only assignment with ‘`=`’ but also compound assignments (like ‘`+=`’), by reduction to ‘`=`’ assignment. In other words, the representation for ‘`i += 3`’ looks just like that for ‘`i = i + 3`’.

`INIT_EXPR`

  These nodes are just like `MODIFY_EXPR`, but are used only when a variable is initialized, rather than assigned to subsequently. This means that we can assume that the target of the initialization is not used in computing its own value; any reference to the lhs in computing the rhs is undefined.

`COMPOUND_EXPR`

  These nodes represent comma-expressions. The first operand is an expression whose value is computed and thrown away prior to the evaluation of the second operand. The value of the entire expression is the value of the second operand.

`COND_EXPR`

  These nodes represent `?:` expressions. The first operand is of boolean or integral type. If it evaluates to a nonzero value, the second operand should be evaluated, and returned as the value of the expression. Otherwise, the third operand is evaluated, and returned as the value of the expression.

  The second operand must have the same type as the entire expression, unless it unconditionally throws an exception or calls a noreturn function, in which case it should have void type. The same constraints apply to the third operand. This allows array bounds checks to be represented conveniently as `(i >= 0 && i < 10) ? i : abort()`.

  As a GNU extension, the C language front-ends allow the second operand of the `?:` operator may be omitted in the source. For example, `x ? : 3` is equivalent to `x ? x : 3`, assuming that `x` is an expression without side effects. In the tree representation, however, the second operand is always present, possibly protected by `SAVE_EXPR` if the first argument does cause side effects.

`CALL_EXPR`

  These nodes are used to represent calls to functions, including non-static member functions. `CALL_EXPR`s are implemented as expression nodes with a variable number of operands. Rather than using `TREE_OPERAND` to extract them, it is preferable to use the specialized accessor macros and functions that operate specifically on `CALL_EXPR` nodes.

  `CALL_EXPR_FN` returns a pointer to the function to call; it is always an expression whose type is a `POINTER_TYPE`.

  The number of arguments to the call is returned by `call_expr_nargs`, while the arguments themselves can be accessed with the `CALL_EXPR_ARG` macro. The arguments are zero-indexed and numbered left-to-right. You can iterate over the arguments using `FOR_EACH_CALL_EXPR_ARG`, as in:

      tree call, arg;
      call_expr_arg_iterator iter;
      FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
        /* arg is bound to successive arguments of call.  */
        ...;

  For non-static member functions, there will be an operand corresponding to the `this` pointer. There will always be expressions corresponding to all of the arguments, even if the function is declared with default arguments and some arguments are not explicitly provided at the call sites.

  `CALL_EXPR`s also have a `CALL_EXPR_STATIC_CHAIN` operand that is used to implement nested functions. This operand is otherwise null.

`CLEANUP_POINT_EXPR`

  These nodes represent full-expressions. The single operand is an expression to evaluate. Any destructor calls engendered by the creation of temporaries during the evaluation of that expression should be performed immediately after the expression is evaluated.

`CONSTRUCTOR`

  These nodes represent the brace-enclosed initializers for a structure or an array. They contain a sequence of component values made out of a vector of constructor_elt, which is a (`INDEX`, `VALUE`) pair.

  If the `TREE_TYPE` of the `CONSTRUCTOR` is a `RECORD_TYPE`, `UNION_TYPE` or `QUAL_UNION_TYPE` then the `INDEX` of each node in the sequence will be a `FIELD_DECL` and the `VALUE` will be the expression used to initialize that field.

  If the `TREE_TYPE` of the `CONSTRUCTOR` is an `ARRAY_TYPE`, then the `INDEX` of each node in the sequence will be an `INTEGER_CST` or a `RANGE_EXPR` of two `INTEGER_CST`s. A single `INTEGER_CST` indicates which element of the array is being assigned to. A `RANGE_EXPR` indicates an inclusive range of elements to initialize. In both cases the `VALUE` is the corresponding initializer. It is re-evaluated for each element of a `RANGE_EXPR`. If the `INDEX` is `NULL_TREE`, then the initializer is for the next available array element.

  In the front end, you should not depend on the fields appearing in any particular order. However, in the middle end, fields must appear in declaration order. You should not assume that all fields will be represented. Unrepresented fields will be cleared (zeroed), unless the CONSTRUCTOR_NO_CLEARING flag is set, in which case their value becomes undefined.

`COMPOUND_LITERAL_EXPR` ¶

  These nodes represent ISO C99 compound literals. The `COMPOUND_LITERAL_EXPR_DECL_EXPR` is a `DECL_EXPR` containing an anonymous `VAR_DECL` for the unnamed object represented by the compound literal; the `DECL_INITIAL` of that `VAR_DECL` is a `CONSTRUCTOR` representing the brace-enclosed list of initializers in the compound literal. That anonymous `VAR_DECL` can also be accessed directly by the `COMPOUND_LITERAL_EXPR_DECL` macro.

`SAVE_EXPR`

  A `SAVE_EXPR` represents an expression (possibly involving side effects) that is used more than once. The side effects should occur only the first time the expression is evaluated. Subsequent uses should just reuse the computed value. The first operand to the `SAVE_EXPR` is the expression to evaluate. The side effects should be executed where the `SAVE_EXPR` is first encountered in a depth-first preorder traversal of the expression tree.

`TARGET_EXPR`

  A `TARGET_EXPR` represents a temporary object. The first operand is a `VAR_DECL` for the temporary variable. The second operand is the initializer for the temporary. The initializer is evaluated and, if non-void, copied (bitwise) into the temporary. If the initializer is void, that means that it will perform the initialization itself.

  Often, a `TARGET_EXPR` occurs on the right-hand side of an assignment, or as the second operand to a comma-expression which is itself the right-hand side of an assignment, etc. In this case, we say that the `TARGET_EXPR` is “normal”; otherwise, we say it is “orphaned”. For a normal `TARGET_EXPR` the temporary variable should be treated as an alias for the left-hand side of the assignment, rather than as a new temporary variable.

  The third operand to the `TARGET_EXPR`, if present, is a cleanup-expression (i.e., destructor call) for the temporary. If this expression is orphaned, then this expression must be executed when the statement containing this expression is complete. These cleanups must always be executed in the order opposite to that in which they were encountered. Note that if a temporary is created on one branch of a conditional operator (i.e., in the second or third operand to a `COND_EXPR`), the cleanup must be run only if that branch is actually executed.

`VA_ARG_EXPR`

  This node is used to implement support for the C/C++ variable argument-list mechanism. It represents expressions like `va_arg (ap, type)`. Its `TREE_TYPE` yields the tree representation for `type` and its sole argument yields the representation for `ap`.

`ANNOTATE_EXPR`

  This node is used to attach markers to an expression. The first operand is the annotated expression, the second is an `INTEGER_CST` with a value from `enum annot_expr_kind`, the third is an `INTEGER_CST`.