From: Roger Sayle Date: Fri, 18 Jul 2003 00:26:51 +0000 (+0000) Subject: fold-const.c (const_binop): Avoid performing the FP operation at compile-time... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3e4093b64f2e2623bba32e733e7e8f08efc700ac;p=gcc.git fold-const.c (const_binop): Avoid performing the FP operation at compile-time... * fold-const.c (const_binop): Avoid performing the FP operation at compile-time, if either operand is NaN and we honor signaling NaNs, or if we're dividing by zero and either flag_trapping_math is set or the desired mode doesn't support infinities. (fold_initializer): New function to fold an expression ignoring any potential run-time exceptions or traps. * tree.h (fold_initializer): Prototype here. * c-typeck.c (build_binary_op): Move to the end of the file so that intializer_stack is in scope. If constructing an initializer, i.e. when initializer_stack is not NULL, use fold_initializer to fold expressions. * simplify-rtx.c (simplify_binary_operation): Likewise, avoid performing FP operations at compile-time, if they would raise an exception at run-time. From-SVN: r69533 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fea6e3b6be5..dfff20cdaa4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2003-07-17 Roger Sayle + + * fold-const.c (const_binop): Avoid performing the FP operation at + compile-time, if either operand is NaN and we honor signaling NaNs, + or if we're dividing by zero and either flag_trapping_math is set + or the desired mode doesn't support infinities. + (fold_initializer): New function to fold an expression ignoring any + potential run-time exceptions or traps. + * tree.h (fold_initializer): Prototype here. + * c-typeck.c (build_binary_op): Move to the end of the file so + that intializer_stack is in scope. If constructing an initializer, + i.e. when initializer_stack is not NULL, use fold_initializer to + fold expressions. + * simplify-rtx.c (simplify_binary_operation): Likewise, avoid + performing FP operations at compile-time, if they would raise an + exception at run-time. + 2003-07-17 Geoffrey Keating PR 11498 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 43b5797b7a7..c4154deb833 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2008,5196 +2008,5199 @@ parser_build_binary_op (enum tree_code code, tree arg1, tree arg2) return result; } + -/* Build a binary-operation expression without default conversions. - CODE is the kind of expression to build. - This function differs from `build' in several ways: - the data type of the result is computed and recorded in it, - warnings are generated if arg data types are invalid, - special handling for addition and subtraction of pointers is known, - and some optimization is done (operations on narrow ints - are done in the narrower type when that gives the same result). - Constant folding is also done before the result is returned. - - Note that the operands will never have enumeral types, or function - or array types, because either they will have the default conversions - performed or they have both just been converted to some other type in which - the arithmetic is to be done. */ +/* Return true if `t' is known to be non-negative. */ -tree -build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, - int convert_p) +int +c_tree_expr_nonnegative_p (tree t) { - tree type0, type1; - enum tree_code code0, code1; - tree op0, op1; - - /* Expression code to give to the expression when it is built. - Normally this is CODE, which is what the caller asked for, - but in some special cases we change it. */ - enum tree_code resultcode = code; - - /* Data type in which the computation is to be performed. - In the simplest cases this is the common type of the arguments. */ - tree result_type = NULL; + if (TREE_CODE (t) == STMT_EXPR) + { + t = COMPOUND_BODY (STMT_EXPR_STMT (t)); - /* Nonzero means operands have already been type-converted - in whatever way is necessary. - Zero means they need to be converted to RESULT_TYPE. */ - int converted = 0; + /* Find the last statement in the chain, ignoring the final + * scope statement */ + while (TREE_CHAIN (t) != NULL_TREE + && TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT) + t = TREE_CHAIN (t); + return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); + } + return tree_expr_nonnegative_p (t); +} - /* Nonzero means create the expression with this type, rather than - RESULT_TYPE. */ - tree build_type = 0; +/* Return a tree for the difference of pointers OP0 and OP1. + The resulting tree has type int. */ - /* Nonzero means after finally constructing the expression - convert it to this type. */ - tree final_type = 0; +static tree +pointer_diff (tree op0, tree op1) +{ + tree result, folded; + tree restype = ptrdiff_type_node; - /* Nonzero if this is an operation like MIN or MAX which can - safely be computed in short if both args are promoted shorts. - Also implies COMMON. - -1 indicates a bitwise operation; this makes a difference - in the exact conditions for when it is safe to do the operation - in a narrower mode. */ - int shorten = 0; + tree target_type = TREE_TYPE (TREE_TYPE (op0)); + tree con0, con1, lit0, lit1; + tree orig_op1 = op1; - /* Nonzero if this is a comparison operation; - if both args are promoted shorts, compare the original shorts. - Also implies COMMON. */ - int short_compare = 0; + if (pedantic || warn_pointer_arith) + { + if (TREE_CODE (target_type) == VOID_TYPE) + pedwarn ("pointer of type `void *' used in subtraction"); + if (TREE_CODE (target_type) == FUNCTION_TYPE) + pedwarn ("pointer to a function used in subtraction"); + } - /* Nonzero if this is a right-shift operation, which can be computed on the - original short and then promoted if the operand is a promoted short. */ - int short_shift = 0; + /* If the conversion to ptrdiff_type does anything like widening or + converting a partial to an integral mode, we get a convert_expression + that is in the way to do any simplifications. + (fold-const.c doesn't know that the extra bits won't be needed. + split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a + different mode in place.) + So first try to find a common term here 'by hand'; we want to cover + at least the cases that occur in legal static initializers. */ + con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0; + con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1; - /* Nonzero means set RESULT_TYPE to the common type of the args. */ - int common = 0; + if (TREE_CODE (con0) == PLUS_EXPR) + { + lit0 = TREE_OPERAND (con0, 1); + con0 = TREE_OPERAND (con0, 0); + } + else + lit0 = integer_zero_node; - if (convert_p) + if (TREE_CODE (con1) == PLUS_EXPR) { - op0 = default_conversion (orig_op0); - op1 = default_conversion (orig_op1); + lit1 = TREE_OPERAND (con1, 1); + con1 = TREE_OPERAND (con1, 0); } else + lit1 = integer_zero_node; + + if (operand_equal_p (con0, con1, 0)) { - op0 = orig_op0; - op1 = orig_op1; + op0 = lit0; + op1 = lit1; } - type0 = TREE_TYPE (op0); - type1 = TREE_TYPE (op1); - /* The expression codes of the data types of the arguments tell us - whether the arguments are integers, floating, pointers, etc. */ - code0 = TREE_CODE (type0); - code1 = TREE_CODE (type1); + /* First do the subtraction as integers; + then drop through to build the divide operator. + Do not do default conversions on the minus operator + in case restype is a short type. */ - /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ - STRIP_TYPE_NOPS (op0); - STRIP_TYPE_NOPS (op1); + op0 = build_binary_op (MINUS_EXPR, convert (restype, op0), + convert (restype, op1), 0); + /* This generates an error if op1 is pointer to incomplete type. */ + if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) + error ("arithmetic on pointer to an incomplete type"); - /* If an error was already reported for one of the arguments, - avoid reporting another error. */ + /* This generates an error if op0 is pointer to incomplete type. */ + op1 = c_size_in_bytes (target_type); - if (code0 == ERROR_MARK || code1 == ERROR_MARK) - return error_mark_node; + /* Divide by the size, in easiest possible way. */ - switch (code) - { - case PLUS_EXPR: - /* Handle the pointer + int case. */ - if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) - return pointer_int_sum (PLUS_EXPR, op0, op1); - else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE) - return pointer_int_sum (PLUS_EXPR, op1, op0); - else - common = 1; - break; + result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)); - case MINUS_EXPR: - /* Subtraction of two similar pointers. - We must subtract them as integers, then divide by object size. */ - if (code0 == POINTER_TYPE && code1 == POINTER_TYPE - && comp_target_types (type0, type1, 1)) - return pointer_diff (op0, op1); - /* Handle pointer minus int. Just like pointer plus int. */ - else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) - return pointer_int_sum (MINUS_EXPR, op0, op1); - else - common = 1; - break; + folded = fold (result); + if (folded == result) + TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1); + return folded; +} + +/* Construct and perhaps optimize a tree representation + for a unary operation. CODE, a tree_code, specifies the operation + and XARG is the operand. + For any CODE other than ADDR_EXPR, FLAG nonzero suppresses + the default promotions (such as from short to int). + For ADDR_EXPR, the default promotions are not applied; FLAG nonzero + allows non-lvalues; this is only used to handle conversion of non-lvalue + arrays to pointers in C99. */ - case MULT_EXPR: - common = 1; - break; +tree +build_unary_op (enum tree_code code, tree xarg, int flag) +{ + /* No default_conversion here. It causes trouble for ADDR_EXPR. */ + tree arg = xarg; + tree argtype = 0; + enum tree_code typecode = TREE_CODE (TREE_TYPE (arg)); + tree val; + int noconvert = flag; - case TRUNC_DIV_EXPR: - case CEIL_DIV_EXPR: - case FLOOR_DIV_EXPR: - case ROUND_DIV_EXPR: - case EXACT_DIV_EXPR: - /* Floating point division by zero is a legitimate way to obtain - infinities and NaNs. */ - if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1)) - warning ("division by zero"); + if (typecode == ERROR_MARK) + return error_mark_node; + if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE) + typecode = INTEGER_TYPE; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) + switch (code) + { + case CONVERT_EXPR: + /* This is used for unary plus, because a CONVERT_EXPR + is enough to prevent anybody from looking inside for + associativity, but won't generate any code. */ + if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE + || typecode == COMPLEX_TYPE)) { - if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)) - resultcode = RDIV_EXPR; - else - /* Although it would be tempting to shorten always here, that - loses on some targets, since the modulo instruction is - undefined if the quotient can't be represented in the - computation mode. We shorten only if unsigned or if - dividing by something we know != -1. */ - shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0)) - || (TREE_CODE (op1) == INTEGER_CST - && ! integer_all_onesp (op1))); - common = 1; + error ("wrong type argument to unary plus"); + return error_mark_node; } + else if (!noconvert) + arg = default_conversion (arg); + arg = non_lvalue (arg); break; - case BIT_AND_EXPR: - case BIT_ANDTC_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) - shorten = -1; - else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) - common = 1; + case NEGATE_EXPR: + if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE + || typecode == COMPLEX_TYPE + || typecode == VECTOR_TYPE)) + { + error ("wrong type argument to unary minus"); + return error_mark_node; + } + else if (!noconvert) + arg = default_conversion (arg); break; - case TRUNC_MOD_EXPR: - case FLOOR_MOD_EXPR: - if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1)) - warning ("division by zero"); - - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + case BIT_NOT_EXPR: + if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE) { - /* Although it would be tempting to shorten always here, that loses - on some targets, since the modulo instruction is undefined if the - quotient can't be represented in the computation mode. We shorten - only if unsigned or if dividing by something we know != -1. */ - shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0)) - || (TREE_CODE (op1) == INTEGER_CST - && ! integer_all_onesp (op1))); - common = 1; + if (!noconvert) + arg = default_conversion (arg); } - break; - - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: - if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE - || code0 == REAL_TYPE || code0 == COMPLEX_TYPE) - && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE - || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) + else if (typecode == COMPLEX_TYPE) { - /* Result of these operations is always an int, - but that does not mean the operands should be - converted to ints! */ - result_type = integer_type_node; - op0 = c_common_truthvalue_conversion (op0); - op1 = c_common_truthvalue_conversion (op1); - converted = 1; + code = CONJ_EXPR; + if (pedantic) + pedwarn ("ISO C does not support `~' for complex conjugation"); + if (!noconvert) + arg = default_conversion (arg); + } + else + { + error ("wrong type argument to bit-complement"); + return error_mark_node; } break; - /* Shift operations: result has same type as first operand; - always convert second operand to int. - Also set SHORT_SHIFT if shifting rightward. */ - - case RSHIFT_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + case ABS_EXPR: + if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE + || typecode == COMPLEX_TYPE)) { - if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) - { - if (tree_int_cst_sgn (op1) < 0) - warning ("right shift count is negative"); - else - { - if (! integer_zerop (op1)) - short_shift = 1; - - if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - warning ("right shift count >= width of type"); - } - } - - /* Use the type of the value to be shifted. */ - result_type = type0; - /* Convert the shift-count to an integer, regardless of size - of value being shifted. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); - /* Avoid converting op1 to result_type later. */ - converted = 1; + error ("wrong type argument to abs"); + return error_mark_node; } + else if (!noconvert) + arg = default_conversion (arg); break; - case LSHIFT_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + case CONJ_EXPR: + /* Conjugating a real value is a no-op, but allow it anyway. */ + if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE + || typecode == COMPLEX_TYPE)) { - if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) - { - if (tree_int_cst_sgn (op1) < 0) - warning ("left shift count is negative"); - - else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - warning ("left shift count >= width of type"); - } - - /* Use the type of the value to be shifted. */ - result_type = type0; - /* Convert the shift-count to an integer, regardless of size - of value being shifted. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); - /* Avoid converting op1 to result_type later. */ - converted = 1; + error ("wrong type argument to conjugation"); + return error_mark_node; } + else if (!noconvert) + arg = default_conversion (arg); break; - case RROTATE_EXPR: - case LROTATE_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + case TRUTH_NOT_EXPR: + if (typecode != INTEGER_TYPE + && typecode != REAL_TYPE && typecode != POINTER_TYPE + && typecode != COMPLEX_TYPE + /* These will convert to a pointer. */ + && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE) { - if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) - { - if (tree_int_cst_sgn (op1) < 0) - warning ("shift count is negative"); - else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - warning ("shift count >= width of type"); - } - - /* Use the type of the value to be shifted. */ - result_type = type0; - /* Convert the shift-count to an integer, regardless of size - of value being shifted. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); - /* Avoid converting op1 to result_type later. */ - converted = 1; + error ("wrong type argument to unary exclamation mark"); + return error_mark_node; } + arg = c_common_truthvalue_conversion (arg); + return invert_truthvalue (arg); + + case NOP_EXPR: break; - case EQ_EXPR: - case NE_EXPR: - if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE)) - warning ("comparing floating point with == or != is unsafe"); - /* Result of comparison is always int, - but don't convert the args to int! */ - build_type = integer_type_node; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == COMPLEX_TYPE - || code0 == VECTOR_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE - || code1 == VECTOR_TYPE)) - short_compare = 1; - else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - { - tree tt0 = TREE_TYPE (type0); - tree tt1 = TREE_TYPE (type1); - /* Anything compares with void *. void * compares with anything. - Otherwise, the targets must be compatible - and both must be object or both incomplete. */ - if (comp_target_types (type0, type1, 1)) - result_type = common_type (type0, type1); - else if (VOID_TYPE_P (tt0)) - { - /* op0 != orig_op0 detects the case of something - whose value is 0 but which isn't a valid null ptr const. */ - if (pedantic && (!integer_zerop (op0) || op0 != orig_op0) - && TREE_CODE (tt1) == FUNCTION_TYPE) - pedwarn ("ISO C forbids comparison of `void *' with function pointer"); - } - else if (VOID_TYPE_P (tt1)) - { - if (pedantic && (!integer_zerop (op1) || op1 != orig_op1) - && TREE_CODE (tt0) == FUNCTION_TYPE) - pedwarn ("ISO C forbids comparison of `void *' with function pointer"); - } - else - pedwarn ("comparison of distinct pointer types lacks a cast"); + case REALPART_EXPR: + if (TREE_CODE (arg) == COMPLEX_CST) + return TREE_REALPART (arg); + else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) + return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); + else + return arg; - if (result_type == NULL_TREE) - result_type = ptr_type_node; - } - else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST - && integer_zerop (op1)) - result_type = type0; - else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST - && integer_zerop (op0)) - result_type = type1; - else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) + case IMAGPART_EXPR: + if (TREE_CODE (arg) == COMPLEX_CST) + return TREE_IMAGPART (arg); + else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) + return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); + else + return convert (TREE_TYPE (arg), integer_zero_node); + + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + /* Handle complex lvalues (when permitted) + by reduction to simpler cases. */ + + val = unary_complex_lvalue (code, arg, 0); + if (val != 0) + return val; + + /* Increment or decrement the real part of the value, + and don't change the imaginary part. */ + if (typecode == COMPLEX_TYPE) { - result_type = type0; - pedwarn ("comparison between pointer and integer"); + tree real, imag; + + if (pedantic) + pedwarn ("ISO C does not support `++' and `--' on complex types"); + + arg = stabilize_reference (arg); + real = build_unary_op (REALPART_EXPR, arg, 1); + imag = build_unary_op (IMAGPART_EXPR, arg, 1); + return build (COMPLEX_EXPR, TREE_TYPE (arg), + build_unary_op (code, real, 1), imag); } - else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) + + /* Report invalid types. */ + + if (typecode != POINTER_TYPE + && typecode != INTEGER_TYPE && typecode != REAL_TYPE) { - result_type = type1; - pedwarn ("comparison between pointer and integer"); + if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + error ("wrong type argument to increment"); + else + error ("wrong type argument to decrement"); + + return error_mark_node; } - break; - case MAX_EXPR: - case MIN_EXPR: - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) - shorten = 1; - else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - { - if (comp_target_types (type0, type1, 1)) - { - result_type = common_type (type0, type1); - if (pedantic - && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids ordered comparisons of pointers to functions"); - } - else - { - result_type = ptr_type_node; - pedwarn ("comparison of distinct pointer types lacks a cast"); - } - } - break; + { + tree inc; + tree result_type = TREE_TYPE (arg); - case LE_EXPR: - case GE_EXPR: - case LT_EXPR: - case GT_EXPR: - build_type = integer_type_node; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) - short_compare = 1; - else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - { - if (comp_target_types (type0, type1, 1)) - { - result_type = common_type (type0, type1); - if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) - != !COMPLETE_TYPE_P (TREE_TYPE (type1))) - pedwarn ("comparison of complete and incomplete pointers"); - else if (pedantic - && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids ordered comparisons of pointers to functions"); - } - else + arg = get_unwidened (arg, 0); + argtype = TREE_TYPE (arg); + + /* Compute the increment. */ + + if (typecode == POINTER_TYPE) + { + /* If pointer target is an undefined struct, + we just cannot know how to do the arithmetic. */ + if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type))) + { + if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + error ("increment of pointer to unknown structure"); + else + error ("decrement of pointer to unknown structure"); + } + else if ((pedantic || warn_pointer_arith) + && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)) + { + if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + pedwarn ("wrong type argument to increment"); + else + pedwarn ("wrong type argument to decrement"); + } + + inc = c_size_in_bytes (TREE_TYPE (result_type)); + } + else + inc = integer_one_node; + + inc = convert (argtype, inc); + + /* Handle incrementing a cast-expression. */ + + while (1) + switch (TREE_CODE (arg)) { - result_type = ptr_type_node; - pedwarn ("comparison of distinct pointer types lacks a cast"); + case NOP_EXPR: + case CONVERT_EXPR: + case FLOAT_EXPR: + case FIX_TRUNC_EXPR: + case FIX_FLOOR_EXPR: + case FIX_ROUND_EXPR: + case FIX_CEIL_EXPR: + pedantic_lvalue_warning (CONVERT_EXPR); + /* If the real type has the same machine representation + as the type it is cast to, we can make better output + by adding directly to the inside of the cast. */ + if ((TREE_CODE (TREE_TYPE (arg)) + == TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0)))) + && (TYPE_MODE (TREE_TYPE (arg)) + == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0))))) + arg = TREE_OPERAND (arg, 0); + else + { + tree incremented, modify, value; + if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) + value = boolean_increment (code, arg); + else + { + arg = stabilize_reference (arg); + if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR) + value = arg; + else + value = save_expr (arg); + incremented = build (((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? PLUS_EXPR : MINUS_EXPR), + argtype, value, inc); + TREE_SIDE_EFFECTS (incremented) = 1; + modify = build_modify_expr (arg, NOP_EXPR, incremented); + value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value); + } + TREE_USED (value) = 1; + return value; + } + break; + + default: + goto give_up; } - } - else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST - && integer_zerop (op1)) - { - result_type = type0; - if (pedantic || extra_warnings) - pedwarn ("ordered comparison of pointer with integer zero"); - } - else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST - && integer_zerop (op0)) - { - result_type = type1; - if (pedantic) - pedwarn ("ordered comparison of pointer with integer zero"); - } - else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) - { - result_type = type0; - pedwarn ("comparison between pointer and integer"); - } - else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) + give_up: + + /* Complain about anything else that is not a true lvalue. */ + if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? "invalid lvalue in increment" + : "invalid lvalue in decrement"))) + return error_mark_node; + + /* Report a read-only lvalue. */ + if (TREE_READONLY (arg)) + readonly_warning (arg, + ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? "increment" : "decrement")); + + if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) + val = boolean_increment (code, arg); + else + val = build (code, TREE_TYPE (arg), arg, inc); + TREE_SIDE_EFFECTS (val) = 1; + val = convert (result_type, val); + if (TREE_CODE (val) != code) + TREE_NO_UNUSED_WARNING (val) = 1; + return val; + } + + case ADDR_EXPR: + /* Note that this operation never does default_conversion. */ + + /* Let &* cancel out to simplify resulting code. */ + if (TREE_CODE (arg) == INDIRECT_REF) { - result_type = type1; - pedwarn ("comparison between pointer and integer"); + /* Don't let this be an lvalue. */ + if (lvalue_p (TREE_OPERAND (arg, 0))) + return non_lvalue (TREE_OPERAND (arg, 0)); + return TREE_OPERAND (arg, 0); } - break; - case UNORDERED_EXPR: - case ORDERED_EXPR: - case UNLT_EXPR: - case UNLE_EXPR: - case UNGT_EXPR: - case UNGE_EXPR: - case UNEQ_EXPR: - build_type = integer_type_node; - if (code0 != REAL_TYPE || code1 != REAL_TYPE) + /* For &x[y], return x+y */ + if (TREE_CODE (arg) == ARRAY_REF) { - error ("unordered comparison on non-floating point argument"); - return error_mark_node; + if (!c_mark_addressable (TREE_OPERAND (arg, 0))) + return error_mark_node; + return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0), + TREE_OPERAND (arg, 1), 1); } - common = 1; - break; - default: - break; - } + /* Handle complex lvalues (when permitted) + by reduction to simpler cases. */ + val = unary_complex_lvalue (code, arg, flag); + if (val != 0) + return val; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == VECTOR_TYPE) - && - (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE - || code1 == VECTOR_TYPE)) - { - int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE); + /* Anything not already handled and not a true memory reference + or a non-lvalue array is an error. */ + else if (typecode != FUNCTION_TYPE && !flag + && !lvalue_or_else (arg, "invalid lvalue in unary `&'")) + return error_mark_node; - if (shorten || common || short_compare) - result_type = common_type (type0, type1); + /* Ordinary case; arg is a COMPONENT_REF or a decl. */ + argtype = TREE_TYPE (arg); - /* For certain operations (which identify themselves by shorten != 0) - if both args were extended from the same smaller type, - do the arithmetic in that type and then extend. + /* If the lvalue is const or volatile, merge that into the type + to which the address will point. Note that you can't get a + restricted pointer by taking the address of something, so we + only have to deal with `const' and `volatile' here. */ + if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r') + && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) + argtype = c_build_type_variant (argtype, + TREE_READONLY (arg), + TREE_THIS_VOLATILE (arg)); - shorten !=0 and !=1 indicates a bitwise operation. - For them, this optimization is safe only if - both args are zero-extended or both are sign-extended. - Otherwise, we might change the result. - Eg, (short)-1 | (unsigned short)-1 is (int)-1 - but calculated in (unsigned short) it would be (unsigned short)-1. */ + argtype = build_pointer_type (argtype); - if (shorten && none_complex) - { - int unsigned0, unsigned1; - tree arg0 = get_narrower (op0, &unsigned0); - tree arg1 = get_narrower (op1, &unsigned1); - /* UNS is 1 if the operation to be done is an unsigned one. */ - int uns = TREE_UNSIGNED (result_type); - tree type; + if (!c_mark_addressable (arg)) + return error_mark_node; - final_type = result_type; + { + tree addr; - /* Handle the case that OP0 (or OP1) does not *contain* a conversion - but it *requires* conversion to FINAL_TYPE. */ + if (TREE_CODE (arg) == COMPONENT_REF) + { + tree field = TREE_OPERAND (arg, 1); - if ((TYPE_PRECISION (TREE_TYPE (op0)) - == TYPE_PRECISION (TREE_TYPE (arg0))) - && TREE_TYPE (op0) != final_type) - unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0)); - if ((TYPE_PRECISION (TREE_TYPE (op1)) - == TYPE_PRECISION (TREE_TYPE (arg1))) - && TREE_TYPE (op1) != final_type) - unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1)); - - /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */ + addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag); - /* For bitwise operations, signedness of nominal type - does not matter. Consider only how operands were extended. */ - if (shorten == -1) - uns = unsigned0; + if (DECL_C_BIT_FIELD (field)) + { + error ("attempt to take address of bit-field structure member `%s'", + IDENTIFIER_POINTER (DECL_NAME (field))); + return error_mark_node; + } - /* Note that in all three cases below we refrain from optimizing - an unsigned operation on sign-extended args. - That would not be valid. */ + addr = fold (build (PLUS_EXPR, argtype, + convert (argtype, addr), + convert (argtype, byte_position (field)))); + } + else + addr = build1 (code, argtype, arg); - /* Both args variable: if both extended in same way - from same width, do it in that width. - Do it unsigned if args were zero-extended. */ - if ((TYPE_PRECISION (TREE_TYPE (arg0)) - < TYPE_PRECISION (result_type)) - && (TYPE_PRECISION (TREE_TYPE (arg1)) - == TYPE_PRECISION (TREE_TYPE (arg0))) - && unsigned0 == unsigned1 - && (unsigned0 || !uns)) - result_type - = c_common_signed_or_unsigned_type - (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); - else if (TREE_CODE (arg0) == INTEGER_CST - && (unsigned1 || !uns) - && (TYPE_PRECISION (TREE_TYPE (arg1)) - < TYPE_PRECISION (result_type)) - && (type - = c_common_signed_or_unsigned_type (unsigned1, - TREE_TYPE (arg1)), - int_fits_type_p (arg0, type))) - result_type = type; - else if (TREE_CODE (arg1) == INTEGER_CST - && (unsigned0 || !uns) - && (TYPE_PRECISION (TREE_TYPE (arg0)) - < TYPE_PRECISION (result_type)) - && (type - = c_common_signed_or_unsigned_type (unsigned0, - TREE_TYPE (arg0)), - int_fits_type_p (arg1, type))) - result_type = type; - } + /* Address of a static or external variable or + file-scope function counts as a constant. */ + if (staticp (arg) + && ! (TREE_CODE (arg) == FUNCTION_DECL + && !C_DECL_FILE_SCOPE (arg))) + TREE_CONSTANT (addr) = 1; + return addr; + } - /* Shifts can be shortened if shifting right. */ + default: + break; + } - if (short_shift) - { - int unsigned_arg; - tree arg0 = get_narrower (op0, &unsigned_arg); + if (argtype == 0) + argtype = TREE_TYPE (arg); + return fold (build1 (code, argtype, arg)); +} - final_type = result_type; +/* Return nonzero if REF is an lvalue valid for this language. + Lvalues can be assigned, unless their type has TYPE_READONLY. + Lvalues can have their address taken, unless they have DECL_REGISTER. */ - if (arg0 == op0 && final_type == TREE_TYPE (op0)) - unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0)); +int +lvalue_p (tree ref) +{ + enum tree_code code = TREE_CODE (ref); - if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type) - /* We can shorten only if the shift count is less than the - number of bits in the smaller type size. */ - && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0 - /* We cannot drop an unsigned shift after sign-extension. */ - && (!TREE_UNSIGNED (final_type) || unsigned_arg)) - { - /* Do an unsigned shift if the operand was zero-extended. */ - result_type - = c_common_signed_or_unsigned_type (unsigned_arg, - TREE_TYPE (arg0)); - /* Convert value-to-be-shifted to that type. */ - if (TREE_TYPE (op0) != result_type) - op0 = convert (result_type, op0); - converted = 1; - } - } + switch (code) + { + case REALPART_EXPR: + case IMAGPART_EXPR: + case COMPONENT_REF: + return lvalue_p (TREE_OPERAND (ref, 0)); - /* Comparison operations are shortened too but differently. - They identify themselves by setting short_compare = 1. */ + case COMPOUND_LITERAL_EXPR: + case STRING_CST: + return 1; - if (short_compare) - { - /* Don't write &op0, etc., because that would prevent op0 - from being kept in a register. - Instead, make copies of the our local variables and - pass the copies by reference, then copy them back afterward. */ - tree xop0 = op0, xop1 = op1, xresult_type = result_type; - enum tree_code xresultcode = resultcode; - tree val - = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); + case INDIRECT_REF: + case ARRAY_REF: + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + case ERROR_MARK: + return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE); - if (val != 0) - return val; + case BIND_EXPR: + case RTL_EXPR: + return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; - op0 = xop0, op1 = xop1; - converted = 1; - resultcode = xresultcode; + default: + return 0; + } +} - if (warn_sign_compare && skip_evaluation == 0) - { - int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0)); - int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1)); - int unsignedp0, unsignedp1; - tree primop0 = get_narrower (op0, &unsignedp0); - tree primop1 = get_narrower (op1, &unsignedp1); +/* Return nonzero if REF is an lvalue valid for this language; + otherwise, print an error message and return zero. */ - xop0 = orig_op0; - xop1 = orig_op1; - STRIP_TYPE_NOPS (xop0); - STRIP_TYPE_NOPS (xop1); +int +lvalue_or_else (tree ref, const char *msgid) +{ + int win = lvalue_p (ref); - /* Give warnings for comparisons between signed and unsigned - quantities that may fail. + if (! win) + error ("%s", msgid); - Do the checking based on the original operand trees, so that - casts will be considered, but default promotions won't be. + return win; +} - Do not warn if the comparison is being done in a signed type, - since the signed type will only be chosen if it can represent - all the values of the unsigned type. */ - if (! TREE_UNSIGNED (result_type)) - /* OK */; - /* Do not warn if both operands are the same signedness. */ - else if (op0_signed == op1_signed) - /* OK */; - else - { - tree sop, uop; +/* Apply unary lvalue-demanding operator CODE to the expression ARG + for certain kinds of expressions which are not really lvalues + but which we can accept as lvalues. If FLAG is nonzero, then + non-lvalues are OK since we may be converting a non-lvalue array to + a pointer in C99. - if (op0_signed) - sop = xop0, uop = xop1; - else - sop = xop1, uop = xop0; + If ARG is not a kind of expression we can handle, return zero. */ - /* Do not warn if the signed quantity is an - unsuffixed integer literal (or some static - constant expression involving such literals or a - conditional expression involving such literals) - and it is non-negative. */ - if (c_tree_expr_nonnegative_p (sop)) - /* OK */; - /* Do not warn if the comparison is an equality operation, - the unsigned quantity is an integral constant, and it - would fit in the result if the result were signed. */ - else if (TREE_CODE (uop) == INTEGER_CST - && (resultcode == EQ_EXPR || resultcode == NE_EXPR) - && int_fits_type_p - (uop, c_common_signed_type (result_type))) - /* OK */; - /* Do not warn if the unsigned quantity is an enumeration - constant and its maximum value would fit in the result - if the result were signed. */ - else if (TREE_CODE (uop) == INTEGER_CST - && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE - && int_fits_type_p - (TYPE_MAX_VALUE (TREE_TYPE(uop)), - c_common_signed_type (result_type))) - /* OK */; - else - warning ("comparison between signed and unsigned"); - } +static tree +unary_complex_lvalue (enum tree_code code, tree arg, int flag) +{ + /* Handle (a, b) used as an "lvalue". */ + if (TREE_CODE (arg) == COMPOUND_EXPR) + { + tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0); - /* Warn if two unsigned values are being compared in a size - larger than their original size, and one (and only one) is the - result of a `~' operator. This comparison will always fail. + /* If this returns a function type, it isn't really being used as + an lvalue, so don't issue a warning about it. */ + if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag) + pedantic_lvalue_warning (COMPOUND_EXPR); - Also warn if one operand is a constant, and the constant - does not have all bits set that are set in the ~ operand - when it is extended. */ + return build (COMPOUND_EXPR, TREE_TYPE (real_result), + TREE_OPERAND (arg, 0), real_result); + } - if ((TREE_CODE (primop0) == BIT_NOT_EXPR) - != (TREE_CODE (primop1) == BIT_NOT_EXPR)) - { - if (TREE_CODE (primop0) == BIT_NOT_EXPR) - primop0 = get_narrower (TREE_OPERAND (primop0, 0), - &unsignedp0); - else - primop1 = get_narrower (TREE_OPERAND (primop1, 0), - &unsignedp1); + /* Handle (a ? b : c) used as an "lvalue". */ + if (TREE_CODE (arg) == COND_EXPR) + { + if (!flag) + pedantic_lvalue_warning (COND_EXPR); + if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag) + pedantic_lvalue_warning (COMPOUND_EXPR); - if (host_integerp (primop0, 0) || host_integerp (primop1, 0)) - { - tree primop; - HOST_WIDE_INT constant, mask; - int unsignedp, bits; - - if (host_integerp (primop0, 0)) - { - primop = primop1; - unsignedp = unsignedp1; - constant = tree_low_cst (primop0, 0); - } - else - { - primop = primop0; - unsignedp = unsignedp0; - constant = tree_low_cst (primop1, 0); - } - - bits = TYPE_PRECISION (TREE_TYPE (primop)); - if (bits < TYPE_PRECISION (result_type) - && bits < HOST_BITS_PER_WIDE_INT && unsignedp) - { - mask = (~ (HOST_WIDE_INT) 0) << bits; - if ((mask & constant) != mask) - warning ("comparison of promoted ~unsigned with constant"); - } - } - else if (unsignedp0 && unsignedp1 - && (TYPE_PRECISION (TREE_TYPE (primop0)) - < TYPE_PRECISION (result_type)) - && (TYPE_PRECISION (TREE_TYPE (primop1)) - < TYPE_PRECISION (result_type))) - warning ("comparison of promoted ~unsigned with unsigned"); - } - } - } - } - - /* At this point, RESULT_TYPE must be nonzero to avoid an error message. - If CONVERTED is zero, both args will be converted to type RESULT_TYPE. - Then the expression will be built. - It will be given type FINAL_TYPE if that is nonzero; - otherwise, it will be given type RESULT_TYPE. */ - - if (!result_type) - { - binary_op_error (code); - return error_mark_node; - } - - if (! converted) - { - if (TREE_TYPE (op0) != result_type) - op0 = convert (result_type, op0); - if (TREE_TYPE (op1) != result_type) - op1 = convert (result_type, op1); + return (build_conditional_expr + (TREE_OPERAND (arg, 0), + build_unary_op (code, TREE_OPERAND (arg, 1), flag), + build_unary_op (code, TREE_OPERAND (arg, 2), flag))); } - if (build_type == NULL_TREE) - build_type = result_type; + return 0; +} - { - tree result = build (resultcode, build_type, op0, op1); - tree folded; +/* If pedantic, warn about improper lvalue. CODE is either COND_EXPR + COMPOUND_EXPR, or CONVERT_EXPR (for casts). */ - folded = fold (result); - if (folded == result) - TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1); - if (final_type != 0) - return convert (final_type, folded); - return folded; - } +static void +pedantic_lvalue_warning (enum tree_code code) +{ + if (pedantic) + switch (code) + { + case COND_EXPR: + pedwarn ("ISO C forbids use of conditional expressions as lvalues"); + break; + case COMPOUND_EXPR: + pedwarn ("ISO C forbids use of compound expressions as lvalues"); + break; + default: + pedwarn ("ISO C forbids use of cast expressions as lvalues"); + break; + } } +/* Warn about storing in something that is `const'. */ -/* Return true if `t' is known to be non-negative. */ - -int -c_tree_expr_nonnegative_p (tree t) +void +readonly_warning (tree arg, const char *msgid) { - if (TREE_CODE (t) == STMT_EXPR) + if (TREE_CODE (arg) == COMPONENT_REF) { - t = COMPOUND_BODY (STMT_EXPR_STMT (t)); - - /* Find the last statement in the chain, ignoring the final - * scope statement */ - while (TREE_CHAIN (t) != NULL_TREE - && TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT) - t = TREE_CHAIN (t); - return tree_expr_nonnegative_p (TREE_OPERAND (t, 0)); + if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) + readonly_warning (TREE_OPERAND (arg, 0), msgid); + else + pedwarn ("%s of read-only member `%s'", _(msgid), + IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1)))); } - return tree_expr_nonnegative_p (t); + else if (TREE_CODE (arg) == VAR_DECL) + pedwarn ("%s of read-only variable `%s'", _(msgid), + IDENTIFIER_POINTER (DECL_NAME (arg))); + else + pedwarn ("%s of read-only location", _(msgid)); } + +/* Mark EXP saying that we need to be able to take the + address of it; it should not be allocated in a register. + Returns true if successful. */ -/* Return a tree for the difference of pointers OP0 and OP1. - The resulting tree has type int. */ - -static tree -pointer_diff (tree op0, tree op1) +bool +c_mark_addressable (tree exp) { - tree result, folded; - tree restype = ptrdiff_type_node; - - tree target_type = TREE_TYPE (TREE_TYPE (op0)); - tree con0, con1, lit0, lit1; - tree orig_op1 = op1; - - if (pedantic || warn_pointer_arith) - { - if (TREE_CODE (target_type) == VOID_TYPE) - pedwarn ("pointer of type `void *' used in subtraction"); - if (TREE_CODE (target_type) == FUNCTION_TYPE) - pedwarn ("pointer to a function used in subtraction"); - } - - /* If the conversion to ptrdiff_type does anything like widening or - converting a partial to an integral mode, we get a convert_expression - that is in the way to do any simplifications. - (fold-const.c doesn't know that the extra bits won't be needed. - split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a - different mode in place.) - So first try to find a common term here 'by hand'; we want to cover - at least the cases that occur in legal static initializers. */ - con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0; - con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1; + tree x = exp; - if (TREE_CODE (con0) == PLUS_EXPR) - { - lit0 = TREE_OPERAND (con0, 1); - con0 = TREE_OPERAND (con0, 0); - } - else - lit0 = integer_zero_node; + while (1) + switch (TREE_CODE (x)) + { + case COMPONENT_REF: + if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) + { + error ("cannot take address of bit-field `%s'", + IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1)))); + return false; + } - if (TREE_CODE (con1) == PLUS_EXPR) - { - lit1 = TREE_OPERAND (con1, 1); - con1 = TREE_OPERAND (con1, 0); - } - else - lit1 = integer_zero_node; + /* ... fall through ... */ - if (operand_equal_p (con0, con1, 0)) - { - op0 = lit0; - op1 = lit1; - } + case ADDR_EXPR: + case ARRAY_REF: + case REALPART_EXPR: + case IMAGPART_EXPR: + x = TREE_OPERAND (x, 0); + break; + case COMPOUND_LITERAL_EXPR: + case CONSTRUCTOR: + TREE_ADDRESSABLE (x) = 1; + return true; - /* First do the subtraction as integers; - then drop through to build the divide operator. - Do not do default conversions on the minus operator - in case restype is a short type. */ + case VAR_DECL: + case CONST_DECL: + case PARM_DECL: + case RESULT_DECL: + if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) + && DECL_NONLOCAL (x)) + { + if (TREE_PUBLIC (x)) + { + error ("global register variable `%s' used in nested function", + IDENTIFIER_POINTER (DECL_NAME (x))); + return false; + } + pedwarn ("register variable `%s' used in nested function", + IDENTIFIER_POINTER (DECL_NAME (x))); + } + else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)) + { + if (TREE_PUBLIC (x)) + { + error ("address of global register variable `%s' requested", + IDENTIFIER_POINTER (DECL_NAME (x))); + return false; + } - op0 = build_binary_op (MINUS_EXPR, convert (restype, op0), - convert (restype, op1), 0); - /* This generates an error if op1 is pointer to incomplete type. */ - if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) - error ("arithmetic on pointer to an incomplete type"); + /* If we are making this addressable due to its having + volatile components, give a different error message. Also + handle the case of an unnamed parameter by not trying + to give the name. */ - /* This generates an error if op0 is pointer to incomplete type. */ - op1 = c_size_in_bytes (target_type); + else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x))) + { + error ("cannot put object with volatile field into register"); + return false; + } - /* Divide by the size, in easiest possible way. */ + pedwarn ("address of register variable `%s' requested", + IDENTIFIER_POINTER (DECL_NAME (x))); + } + put_var_into_stack (x, /*rescan=*/true); - result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)); - - folded = fold (result); - if (folded == result) - TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1); - return folded; -} - -/* Construct and perhaps optimize a tree representation - for a unary operation. CODE, a tree_code, specifies the operation - and XARG is the operand. - For any CODE other than ADDR_EXPR, FLAG nonzero suppresses - the default promotions (such as from short to int). - For ADDR_EXPR, the default promotions are not applied; FLAG nonzero - allows non-lvalues; this is only used to handle conversion of non-lvalue - arrays to pointers in C99. */ + /* drops in */ + case FUNCTION_DECL: + TREE_ADDRESSABLE (x) = 1; + /* drops out */ + default: + return true; + } +} + +/* Build and return a conditional expression IFEXP ? OP1 : OP2. */ tree -build_unary_op (enum tree_code code, tree xarg, int flag) +build_conditional_expr (tree ifexp, tree op1, tree op2) { - /* No default_conversion here. It causes trouble for ADDR_EXPR. */ - tree arg = xarg; - tree argtype = 0; - enum tree_code typecode = TREE_CODE (TREE_TYPE (arg)); - tree val; - int noconvert = flag; + tree type1; + tree type2; + enum tree_code code1; + enum tree_code code2; + tree result_type = NULL; + tree orig_op1 = op1, orig_op2 = op2; - if (typecode == ERROR_MARK) + ifexp = c_common_truthvalue_conversion (default_conversion (ifexp)); + + /* Promote both alternatives. */ + + if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE) + op1 = default_conversion (op1); + if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE) + op2 = default_conversion (op2); + + if (TREE_CODE (ifexp) == ERROR_MARK + || TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK + || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK) return error_mark_node; - if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE) - typecode = INTEGER_TYPE; - switch (code) + type1 = TREE_TYPE (op1); + code1 = TREE_CODE (type1); + type2 = TREE_TYPE (op2); + code2 = TREE_CODE (type2); + + /* Quickly detect the usual case where op1 and op2 have the same type + after promotion. */ + if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) { - case CONVERT_EXPR: - /* This is used for unary plus, because a CONVERT_EXPR - is enough to prevent anybody from looking inside for - associativity, but won't generate any code. */ - if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE - || typecode == COMPLEX_TYPE)) - { - error ("wrong type argument to unary plus"); - return error_mark_node; - } - else if (!noconvert) - arg = default_conversion (arg); - arg = non_lvalue (arg); - break; + if (type1 == type2) + result_type = type1; + else + result_type = TYPE_MAIN_VARIANT (type1); + } + else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == COMPLEX_TYPE) + && (code2 == INTEGER_TYPE || code2 == REAL_TYPE + || code2 == COMPLEX_TYPE)) + { + result_type = common_type (type1, type2); - case NEGATE_EXPR: - if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE - || typecode == COMPLEX_TYPE - || typecode == VECTOR_TYPE)) + /* If -Wsign-compare, warn here if type1 and type2 have + different signedness. We'll promote the signed to unsigned + and later code won't know it used to be different. + Do this check on the original types, so that explicit casts + will be considered, but default promotions won't. */ + if (warn_sign_compare && !skip_evaluation) { - error ("wrong type argument to unary minus"); - return error_mark_node; - } - else if (!noconvert) - arg = default_conversion (arg); - break; + int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1)); + int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2)); - case BIT_NOT_EXPR: - if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE) + if (unsigned_op1 ^ unsigned_op2) + { + /* Do not warn if the result type is signed, since the + signed type will only be chosen if it can represent + all the values of the unsigned type. */ + if (! TREE_UNSIGNED (result_type)) + /* OK */; + /* Do not warn if the signed quantity is an unsuffixed + integer literal (or some static constant expression + involving such literals) and it is non-negative. */ + else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1)) + || (unsigned_op1 && c_tree_expr_nonnegative_p (op2))) + /* OK */; + else + warning ("signed and unsigned type in conditional expression"); + } + } + } + else if (code1 == VOID_TYPE || code2 == VOID_TYPE) + { + if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE)) + pedwarn ("ISO C forbids conditional expr with only one void side"); + result_type = void_type_node; + } + else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) + { + if (comp_target_types (type1, type2, 1)) + result_type = common_type (type1, type2); + else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node + && TREE_CODE (orig_op1) != NOP_EXPR) + result_type = qualify_type (type2, type1); + else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node + && TREE_CODE (orig_op2) != NOP_EXPR) + result_type = qualify_type (type1, type2); + else if (VOID_TYPE_P (TREE_TYPE (type1))) { - if (!noconvert) - arg = default_conversion (arg); + if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) + pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); + result_type = build_pointer_type (qualify_type (TREE_TYPE (type1), + TREE_TYPE (type2))); } - else if (typecode == COMPLEX_TYPE) + else if (VOID_TYPE_P (TREE_TYPE (type2))) { - code = CONJ_EXPR; - if (pedantic) - pedwarn ("ISO C does not support `~' for complex conjugation"); - if (!noconvert) - arg = default_conversion (arg); + if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) + pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); + result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), + TREE_TYPE (type1))); } else { - error ("wrong type argument to bit-complement"); - return error_mark_node; + pedwarn ("pointer type mismatch in conditional expression"); + result_type = build_pointer_type (void_type_node); } - break; - - case ABS_EXPR: - if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE - || typecode == COMPLEX_TYPE)) + } + else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) + { + if (! integer_zerop (op2)) + pedwarn ("pointer/integer type mismatch in conditional expression"); + else { - error ("wrong type argument to abs"); - return error_mark_node; + op2 = null_pointer_node; } - else if (!noconvert) - arg = default_conversion (arg); - break; - - case CONJ_EXPR: - /* Conjugating a real value is a no-op, but allow it anyway. */ - if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE - || typecode == COMPLEX_TYPE)) + result_type = type1; + } + else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) + { + if (!integer_zerop (op1)) + pedwarn ("pointer/integer type mismatch in conditional expression"); + else { - error ("wrong type argument to conjugation"); - return error_mark_node; + op1 = null_pointer_node; } - else if (!noconvert) - arg = default_conversion (arg); - break; + result_type = type2; + } - case TRUTH_NOT_EXPR: - if (typecode != INTEGER_TYPE - && typecode != REAL_TYPE && typecode != POINTER_TYPE - && typecode != COMPLEX_TYPE - /* These will convert to a pointer. */ - && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE) + if (!result_type) + { + if (flag_cond_mismatch) + result_type = void_type_node; + else { - error ("wrong type argument to unary exclamation mark"); + error ("type mismatch in conditional expression"); return error_mark_node; } - arg = c_common_truthvalue_conversion (arg); - return invert_truthvalue (arg); + } - case NOP_EXPR: - break; + /* Merge const and volatile flags of the incoming types. */ + result_type + = build_type_variant (result_type, + TREE_READONLY (op1) || TREE_READONLY (op2), + TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); - case REALPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_REALPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); - else - return arg; + if (result_type != TREE_TYPE (op1)) + op1 = convert_and_check (result_type, op1); + if (result_type != TREE_TYPE (op2)) + op2 = convert_and_check (result_type, op2); - case IMAGPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_IMAGPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); - else - return convert (TREE_TYPE (arg), integer_zero_node); + if (TREE_CODE (ifexp) == INTEGER_CST) + return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1); - case PREINCREMENT_EXPR: - case POSTINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case POSTDECREMENT_EXPR: - /* Handle complex lvalues (when permitted) - by reduction to simpler cases. */ + return fold (build (COND_EXPR, result_type, ifexp, op1, op2)); +} + +/* Given a list of expressions, return a compound expression + that performs them all and returns the value of the last of them. */ - val = unary_complex_lvalue (code, arg, 0); - if (val != 0) - return val; +tree +build_compound_expr (tree list) +{ + return internal_build_compound_expr (list, TRUE); +} - /* Increment or decrement the real part of the value, - and don't change the imaginary part. */ - if (typecode == COMPLEX_TYPE) - { - tree real, imag; - - if (pedantic) - pedwarn ("ISO C does not support `++' and `--' on complex types"); - - arg = stabilize_reference (arg); - real = build_unary_op (REALPART_EXPR, arg, 1); - imag = build_unary_op (IMAGPART_EXPR, arg, 1); - return build (COMPLEX_EXPR, TREE_TYPE (arg), - build_unary_op (code, real, 1), imag); - } - - /* Report invalid types. */ - - if (typecode != POINTER_TYPE - && typecode != INTEGER_TYPE && typecode != REAL_TYPE) - { - if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - error ("wrong type argument to increment"); - else - error ("wrong type argument to decrement"); - - return error_mark_node; - } +static tree +internal_build_compound_expr (tree list, int first_p) +{ + tree rest; - { - tree inc; - tree result_type = TREE_TYPE (arg); + if (TREE_CHAIN (list) == 0) + { + /* Convert arrays and functions to pointers when there + really is a comma operator. */ + if (!first_p) + TREE_VALUE (list) + = default_function_array_conversion (TREE_VALUE (list)); - arg = get_unwidened (arg, 0); - argtype = TREE_TYPE (arg); + /* Don't let (0, 0) be null pointer constant. */ + if (!first_p && integer_zerop (TREE_VALUE (list))) + return non_lvalue (TREE_VALUE (list)); + return TREE_VALUE (list); + } - /* Compute the increment. */ + rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE); - if (typecode == POINTER_TYPE) - { - /* If pointer target is an undefined struct, - we just cannot know how to do the arithmetic. */ - if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type))) - { - if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - error ("increment of pointer to unknown structure"); - else - error ("decrement of pointer to unknown structure"); - } - else if ((pedantic || warn_pointer_arith) - && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)) - { - if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - pedwarn ("wrong type argument to increment"); - else - pedwarn ("wrong type argument to decrement"); - } + if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) + { + /* The left-hand operand of a comma expression is like an expression + statement: with -Wextra or -Wunused, we should warn if it doesn't have + any side-effects, unless it was explicitly cast to (void). */ + if (warn_unused_value + && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR + && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list))))) + warning ("left-hand operand of comma expression has no effect"); - inc = c_size_in_bytes (TREE_TYPE (result_type)); - } - else - inc = integer_one_node; + /* When pedantic, a compound expression can be neither an lvalue + nor an integer constant expression. */ + if (! pedantic) + return rest; + } - inc = convert (argtype, inc); + /* With -Wunused, we should also warn if the left-hand operand does have + side-effects, but computes a value which is not used. For example, in + `foo() + bar(), baz()' the result of the `+' operator is not used, + so we should issue a warning. */ + else if (warn_unused_value) + warn_if_unused_value (TREE_VALUE (list)); - /* Handle incrementing a cast-expression. */ + return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest); +} - while (1) - switch (TREE_CODE (arg)) - { - case NOP_EXPR: - case CONVERT_EXPR: - case FLOAT_EXPR: - case FIX_TRUNC_EXPR: - case FIX_FLOOR_EXPR: - case FIX_ROUND_EXPR: - case FIX_CEIL_EXPR: - pedantic_lvalue_warning (CONVERT_EXPR); - /* If the real type has the same machine representation - as the type it is cast to, we can make better output - by adding directly to the inside of the cast. */ - if ((TREE_CODE (TREE_TYPE (arg)) - == TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0)))) - && (TYPE_MODE (TREE_TYPE (arg)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0))))) - arg = TREE_OPERAND (arg, 0); - else - { - tree incremented, modify, value; - if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) - value = boolean_increment (code, arg); - else - { - arg = stabilize_reference (arg); - if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR) - value = arg; - else - value = save_expr (arg); - incremented = build (((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? PLUS_EXPR : MINUS_EXPR), - argtype, value, inc); - TREE_SIDE_EFFECTS (incremented) = 1; - modify = build_modify_expr (arg, NOP_EXPR, incremented); - value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value); - } - TREE_USED (value) = 1; - return value; - } - break; +/* Build an expression representing a cast to type TYPE of expression EXPR. */ - default: - goto give_up; - } - give_up: +tree +build_c_cast (tree type, tree expr) +{ + tree value = expr; - /* Complain about anything else that is not a true lvalue. */ - if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? "invalid lvalue in increment" - : "invalid lvalue in decrement"))) - return error_mark_node; + if (type == error_mark_node || expr == error_mark_node) + return error_mark_node; - /* Report a read-only lvalue. */ - if (TREE_READONLY (arg)) - readonly_warning (arg, - ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? "increment" : "decrement")); + /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing + only in qualifications. But when constructing cast expressions, + the protocols do matter and must be kept around. */ + if (!c_dialect_objc () || !objc_is_id (type)) + type = TYPE_MAIN_VARIANT (type); - if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) - val = boolean_increment (code, arg); - else - val = build (code, TREE_TYPE (arg), arg, inc); - TREE_SIDE_EFFECTS (val) = 1; - val = convert (result_type, val); - if (TREE_CODE (val) != code) - TREE_NO_UNUSED_WARNING (val) = 1; - return val; - } + if (TREE_CODE (type) == ARRAY_TYPE) + { + error ("cast specifies array type"); + return error_mark_node; + } - case ADDR_EXPR: - /* Note that this operation never does default_conversion. */ + if (TREE_CODE (type) == FUNCTION_TYPE) + { + error ("cast specifies function type"); + return error_mark_node; + } - /* Let &* cancel out to simplify resulting code. */ - if (TREE_CODE (arg) == INDIRECT_REF) + if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value))) + { + if (pedantic) { - /* Don't let this be an lvalue. */ - if (lvalue_p (TREE_OPERAND (arg, 0))) - return non_lvalue (TREE_OPERAND (arg, 0)); - return TREE_OPERAND (arg, 0); + if (TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE) + pedwarn ("ISO C forbids casting nonscalar to the same type"); } + } + else if (TREE_CODE (type) == UNION_TYPE) + { + tree field; + value = default_function_array_conversion (value); - /* For &x[y], return x+y */ - if (TREE_CODE (arg) == ARRAY_REF) + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), + TYPE_MAIN_VARIANT (TREE_TYPE (value)), COMPARE_STRICT)) + break; + + if (field) { - if (!c_mark_addressable (TREE_OPERAND (arg, 0))) - return error_mark_node; - return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0), - TREE_OPERAND (arg, 1), 1); + tree t; + + if (pedantic) + pedwarn ("ISO C forbids casts to union type"); + t = digest_init (type, + build_constructor (type, + build_tree_list (field, value)), + 0); + TREE_CONSTANT (t) = TREE_CONSTANT (value); + return t; } + error ("cast to union type from type not present in union"); + return error_mark_node; + } + else + { + tree otype, ovalue; - /* Handle complex lvalues (when permitted) - by reduction to simpler cases. */ - val = unary_complex_lvalue (code, arg, flag); - if (val != 0) - return val; + /* If casting to void, avoid the error that would come + from default_conversion in the case of a non-lvalue array. */ + if (type == void_type_node) + return build1 (CONVERT_EXPR, type, value); - /* Anything not already handled and not a true memory reference - or a non-lvalue array is an error. */ - else if (typecode != FUNCTION_TYPE && !flag - && !lvalue_or_else (arg, "invalid lvalue in unary `&'")) - return error_mark_node; + /* Convert functions and arrays to pointers, + but don't convert any other types. */ + value = default_function_array_conversion (value); + otype = TREE_TYPE (value); - /* Ordinary case; arg is a COMPONENT_REF or a decl. */ - argtype = TREE_TYPE (arg); + /* Optionally warn about potentially worrisome casts. */ - /* If the lvalue is const or volatile, merge that into the type - to which the address will point. Note that you can't get a - restricted pointer by taking the address of something, so we - only have to deal with `const' and `volatile' here. */ - if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r') - && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) - argtype = c_build_type_variant (argtype, - TREE_READONLY (arg), - TREE_THIS_VOLATILE (arg)); - - argtype = build_pointer_type (argtype); - - if (!c_mark_addressable (arg)) - return error_mark_node; - - { - tree addr; + if (warn_cast_qual + && TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == POINTER_TYPE) + { + tree in_type = type; + tree in_otype = otype; + int added = 0; + int discarded = 0; - if (TREE_CODE (arg) == COMPONENT_REF) - { - tree field = TREE_OPERAND (arg, 1); + /* Check that the qualifiers on IN_TYPE are a superset of + the qualifiers of IN_OTYPE. The outermost level of + POINTER_TYPE nodes is uninteresting and we stop as soon + as we hit a non-POINTER_TYPE node on either type. */ + do + { + in_otype = TREE_TYPE (in_otype); + in_type = TREE_TYPE (in_type); - addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag); + /* GNU C allows cv-qualified function types. 'const' + means the function is very pure, 'volatile' means it + can't return. We need to warn when such qualifiers + are added, not when they're taken away. */ + if (TREE_CODE (in_otype) == FUNCTION_TYPE + && TREE_CODE (in_type) == FUNCTION_TYPE) + added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype)); + else + discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type)); + } + while (TREE_CODE (in_type) == POINTER_TYPE + && TREE_CODE (in_otype) == POINTER_TYPE); - if (DECL_C_BIT_FIELD (field)) - { - error ("attempt to take address of bit-field structure member `%s'", - IDENTIFIER_POINTER (DECL_NAME (field))); - return error_mark_node; - } + if (added) + warning ("cast adds new qualifiers to function type"); - addr = fold (build (PLUS_EXPR, argtype, - convert (argtype, addr), - convert (argtype, byte_position (field)))); - } - else - addr = build1 (code, argtype, arg); + if (discarded) + /* There are qualifiers present in IN_OTYPE that are not + present in IN_TYPE. */ + warning ("cast discards qualifiers from pointer target type"); + } - /* Address of a static or external variable or - file-scope function counts as a constant. */ - if (staticp (arg) - && ! (TREE_CODE (arg) == FUNCTION_DECL - && !C_DECL_FILE_SCOPE (arg))) - TREE_CONSTANT (addr) = 1; - return addr; - } + /* Warn about possible alignment problems. */ + if (STRICT_ALIGNMENT && warn_cast_align + && TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE + && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE + /* Don't warn about opaque types, where the actual alignment + restriction is unknown. */ + && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE + || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) + && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) + && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype))) + warning ("cast increases required alignment of target type"); - default: - break; - } + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (otype) == POINTER_TYPE + && TYPE_PRECISION (type) != TYPE_PRECISION (otype) + && !TREE_CONSTANT (value)) + warning ("cast from pointer to integer of different size"); - if (argtype == 0) - argtype = TREE_TYPE (arg); - return fold (build1 (code, argtype, arg)); -} + if (warn_bad_function_cast + && TREE_CODE (value) == CALL_EXPR + && TREE_CODE (type) != TREE_CODE (otype)) + warning ("cast does not match function type"); -/* Return nonzero if REF is an lvalue valid for this language. - Lvalues can be assigned, unless their type has TYPE_READONLY. - Lvalues can have their address taken, unless they have DECL_REGISTER. */ + if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == INTEGER_TYPE + && TYPE_PRECISION (type) != TYPE_PRECISION (otype) + /* Don't warn about converting any constant. */ + && !TREE_CONSTANT (value)) + warning ("cast to pointer from integer of different size"); -int -lvalue_p (tree ref) -{ - enum tree_code code = TREE_CODE (ref); + if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == POINTER_TYPE + && TREE_CODE (expr) == ADDR_EXPR + && DECL_P (TREE_OPERAND (expr, 0)) + && flag_strict_aliasing && warn_strict_aliasing + && !VOID_TYPE_P (TREE_TYPE (type))) + { + /* Casting the address of a decl to non void pointer. Warn + if the cast breaks type based aliasing. */ + if (!COMPLETE_TYPE_P (TREE_TYPE (type))) + warning ("type-punning to incomplete type might break strict-aliasing rules"); + else if (!alias_sets_conflict_p + (get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))), + get_alias_set (TREE_TYPE (type)))) + warning ("dereferencing type-punned pointer will break strict-aliasing rules"); + } - switch (code) - { - case REALPART_EXPR: - case IMAGPART_EXPR: - case COMPONENT_REF: - return lvalue_p (TREE_OPERAND (ref, 0)); + ovalue = value; + /* Replace a nonvolatile const static variable with its value. */ + if (optimize && TREE_CODE (value) == VAR_DECL) + value = decl_constant_value (value); + value = convert (type, value); - case COMPOUND_LITERAL_EXPR: - case STRING_CST: - return 1; + /* Ignore any integer overflow caused by the cast. */ + if (TREE_CODE (value) == INTEGER_CST) + { + TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); + TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); + } + } - case INDIRECT_REF: - case ARRAY_REF: - case VAR_DECL: - case PARM_DECL: - case RESULT_DECL: - case ERROR_MARK: - return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE - && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE); + /* Pedantically, don't let (void *) (FOO *) 0 be a null pointer constant. */ + if (pedantic && TREE_CODE (value) == INTEGER_CST + && TREE_CODE (expr) == INTEGER_CST + && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE) + value = non_lvalue (value); - case BIND_EXPR: - case RTL_EXPR: - return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; + /* If pedantic, don't let a cast be an lvalue. */ + if (value == expr && pedantic) + value = non_lvalue (value); - default: - return 0; - } + return value; } -/* Return nonzero if REF is an lvalue valid for this language; - otherwise, print an error message and return zero. */ - -int -lvalue_or_else (tree ref, const char *msgid) +/* Interpret a cast of expression EXPR to type TYPE. */ +tree +c_cast_expr (tree type, tree expr) { - int win = lvalue_p (ref); + int saved_wsp = warn_strict_prototypes; - if (! win) - error ("%s", msgid); + /* This avoids warnings about unprototyped casts on + integers. E.g. "#define SIG_DFL (void(*)())0". */ + if (TREE_CODE (expr) == INTEGER_CST) + warn_strict_prototypes = 0; + type = groktypename (type); + warn_strict_prototypes = saved_wsp; - return win; + return build_c_cast (type, expr); } -/* Apply unary lvalue-demanding operator CODE to the expression ARG - for certain kinds of expressions which are not really lvalues - but which we can accept as lvalues. If FLAG is nonzero, then - non-lvalues are OK since we may be converting a non-lvalue array to - a pointer in C99. - - If ARG is not a kind of expression we can handle, return zero. */ + +/* Build an assignment expression of lvalue LHS from value RHS. + MODIFYCODE is the code for a binary operator that we use + to combine the old value of LHS with RHS to get the new value. + Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. */ -static tree -unary_complex_lvalue (enum tree_code code, tree arg, int flag) +tree +build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { - /* Handle (a, b) used as an "lvalue". */ - if (TREE_CODE (arg) == COMPOUND_EXPR) - { - tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0); + tree result; + tree newrhs; + tree lhstype = TREE_TYPE (lhs); + tree olhstype = lhstype; - /* If this returns a function type, it isn't really being used as - an lvalue, so don't issue a warning about it. */ - if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag) - pedantic_lvalue_warning (COMPOUND_EXPR); + /* Types that aren't fully specified cannot be used in assignments. */ + lhs = require_complete_type (lhs); - return build (COMPOUND_EXPR, TREE_TYPE (real_result), - TREE_OPERAND (arg, 0), real_result); - } + /* Avoid duplicate error messages from operands that had errors. */ + if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) + return error_mark_node; - /* Handle (a ? b : c) used as an "lvalue". */ - if (TREE_CODE (arg) == COND_EXPR) - { - if (!flag) - pedantic_lvalue_warning (COND_EXPR); - if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag) - pedantic_lvalue_warning (COMPOUND_EXPR); + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Do not use STRIP_NOPS here. We do not want an enumerator + whose value is 0 to count as a null pointer constant. */ + if (TREE_CODE (rhs) == NON_LVALUE_EXPR) + rhs = TREE_OPERAND (rhs, 0); - return (build_conditional_expr - (TREE_OPERAND (arg, 0), - build_unary_op (code, TREE_OPERAND (arg, 1), flag), - build_unary_op (code, TREE_OPERAND (arg, 2), flag))); - } + newrhs = rhs; - return 0; -} + /* Handle control structure constructs used as "lvalues". */ -/* If pedantic, warn about improper lvalue. CODE is either COND_EXPR - COMPOUND_EXPR, or CONVERT_EXPR (for casts). */ + switch (TREE_CODE (lhs)) + { + /* Handle (a, b) used as an "lvalue". */ + case COMPOUND_EXPR: + pedantic_lvalue_warning (COMPOUND_EXPR); + newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs); + if (TREE_CODE (newrhs) == ERROR_MARK) + return error_mark_node; + return build (COMPOUND_EXPR, lhstype, + TREE_OPERAND (lhs, 0), newrhs); -static void -pedantic_lvalue_warning (enum tree_code code) -{ - if (pedantic) - switch (code) + /* Handle (a ? b : c) used as an "lvalue". */ + case COND_EXPR: + pedantic_lvalue_warning (COND_EXPR); + rhs = save_expr (rhs); { - case COND_EXPR: - pedwarn ("ISO C forbids use of conditional expressions as lvalues"); - break; - case COMPOUND_EXPR: - pedwarn ("ISO C forbids use of compound expressions as lvalues"); - break; - default: - pedwarn ("ISO C forbids use of cast expressions as lvalues"); - break; + /* Produce (a ? (b = rhs) : (c = rhs)) + except that the RHS goes through a save-expr + so the code to compute it is only emitted once. */ + tree cond + = build_conditional_expr (TREE_OPERAND (lhs, 0), + build_modify_expr (TREE_OPERAND (lhs, 1), + modifycode, rhs), + build_modify_expr (TREE_OPERAND (lhs, 2), + modifycode, rhs)); + if (TREE_CODE (cond) == ERROR_MARK) + return cond; + /* Make sure the code to compute the rhs comes out + before the split. */ + return build (COMPOUND_EXPR, TREE_TYPE (lhs), + /* But cast it to void to avoid an "unused" error. */ + convert (void_type_node, rhs), cond); } -} - -/* Warn about storing in something that is `const'. */ + default: + break; + } -void -readonly_warning (tree arg, const char *msgid) -{ - if (TREE_CODE (arg) == COMPONENT_REF) + /* If a binary op has been requested, combine the old LHS value with the RHS + producing the value we should actually store into the LHS. */ + + if (modifycode != NOP_EXPR) { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - readonly_warning (TREE_OPERAND (arg, 0), msgid); - else - pedwarn ("%s of read-only member `%s'", _(msgid), - IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1)))); + lhs = stabilize_reference (lhs); + newrhs = build_binary_op (modifycode, lhs, rhs, 1); } - else if (TREE_CODE (arg) == VAR_DECL) - pedwarn ("%s of read-only variable `%s'", _(msgid), - IDENTIFIER_POINTER (DECL_NAME (arg))); - else - pedwarn ("%s of read-only location", _(msgid)); -} - -/* Mark EXP saying that we need to be able to take the - address of it; it should not be allocated in a register. - Returns true if successful. */ -bool -c_mark_addressable (tree exp) -{ - tree x = exp; + /* Handle a cast used as an "lvalue". + We have already performed any binary operator using the value as cast. + Now convert the result to the cast type of the lhs, + and then true type of the lhs and store it there; + then convert result back to the cast type to be the value + of the assignment. */ - while (1) - switch (TREE_CODE (x)) + switch (TREE_CODE (lhs)) + { + case NOP_EXPR: + case CONVERT_EXPR: + case FLOAT_EXPR: + case FIX_TRUNC_EXPR: + case FIX_FLOOR_EXPR: + case FIX_ROUND_EXPR: + case FIX_CEIL_EXPR: + newrhs = default_function_array_conversion (newrhs); { - case COMPONENT_REF: - if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) - { - error ("cannot take address of bit-field `%s'", - IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1)))); - return false; - } + tree inner_lhs = TREE_OPERAND (lhs, 0); + tree result; + result = build_modify_expr (inner_lhs, NOP_EXPR, + convert (TREE_TYPE (inner_lhs), + convert (lhstype, newrhs))); + if (TREE_CODE (result) == ERROR_MARK) + return result; + pedantic_lvalue_warning (CONVERT_EXPR); + return convert (TREE_TYPE (lhs), result); + } - /* ... fall through ... */ + default: + break; + } - case ADDR_EXPR: - case ARRAY_REF: - case REALPART_EXPR: - case IMAGPART_EXPR: - x = TREE_OPERAND (x, 0); - break; + /* Now we have handled acceptable kinds of LHS that are not truly lvalues. + Reject anything strange now. */ - case COMPOUND_LITERAL_EXPR: - case CONSTRUCTOR: - TREE_ADDRESSABLE (x) = 1; - return true; + if (!lvalue_or_else (lhs, "invalid lvalue in assignment")) + return error_mark_node; - case VAR_DECL: - case CONST_DECL: - case PARM_DECL: - case RESULT_DECL: - if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) - && DECL_NONLOCAL (x)) - { - if (TREE_PUBLIC (x)) - { - error ("global register variable `%s' used in nested function", - IDENTIFIER_POINTER (DECL_NAME (x))); - return false; - } - pedwarn ("register variable `%s' used in nested function", - IDENTIFIER_POINTER (DECL_NAME (x))); - } - else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)) - { - if (TREE_PUBLIC (x)) - { - error ("address of global register variable `%s' requested", - IDENTIFIER_POINTER (DECL_NAME (x))); - return false; - } + /* Warn about storing in something that is `const'. */ - /* If we are making this addressable due to its having - volatile components, give a different error message. Also - handle the case of an unnamed parameter by not trying - to give the name. */ + if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype) + || ((TREE_CODE (lhstype) == RECORD_TYPE + || TREE_CODE (lhstype) == UNION_TYPE) + && C_TYPE_FIELDS_READONLY (lhstype))) + readonly_warning (lhs, "assignment"); - else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x))) - { - error ("cannot put object with volatile field into register"); - return false; - } + /* If storing into a structure or union member, + it has probably been given type `int'. + Compute the type that would go with + the actual amount of storage the member occupies. */ - pedwarn ("address of register variable `%s' requested", - IDENTIFIER_POINTER (DECL_NAME (x))); - } - put_var_into_stack (x, /*rescan=*/true); + if (TREE_CODE (lhs) == COMPONENT_REF + && (TREE_CODE (lhstype) == INTEGER_TYPE + || TREE_CODE (lhstype) == BOOLEAN_TYPE + || TREE_CODE (lhstype) == REAL_TYPE + || TREE_CODE (lhstype) == ENUMERAL_TYPE)) + lhstype = TREE_TYPE (get_unwidened (lhs, 0)); - /* drops in */ - case FUNCTION_DECL: - TREE_ADDRESSABLE (x) = 1; - /* drops out */ - default: - return true; + /* If storing in a field that is in actuality a short or narrower than one, + we must store in the field in its actual type. */ + + if (lhstype != TREE_TYPE (lhs)) + { + lhs = copy_node (lhs); + TREE_TYPE (lhs) = lhstype; } -} - -/* Build and return a conditional expression IFEXP ? OP1 : OP2. */ -tree -build_conditional_expr (tree ifexp, tree op1, tree op2) -{ - tree type1; - tree type2; - enum tree_code code1; - enum tree_code code2; - tree result_type = NULL; - tree orig_op1 = op1, orig_op2 = op2; + /* Convert new value to destination type. */ - ifexp = c_common_truthvalue_conversion (default_conversion (ifexp)); + newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"), + NULL_TREE, NULL_TREE, 0); + if (TREE_CODE (newrhs) == ERROR_MARK) + return error_mark_node; - /* Promote both alternatives. */ + /* Scan operands */ - if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE) - op1 = default_conversion (op1); - if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE) - op2 = default_conversion (op2); + result = build (MODIFY_EXPR, lhstype, lhs, newrhs); + TREE_SIDE_EFFECTS (result) = 1; - if (TREE_CODE (ifexp) == ERROR_MARK - || TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK - || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK) - return error_mark_node; + /* If we got the LHS in a different type for storing in, + convert the result back to the nominal type of LHS + so that the value we return always has the same type + as the LHS argument. */ - type1 = TREE_TYPE (op1); - code1 = TREE_CODE (type1); - type2 = TREE_TYPE (op2); - code2 = TREE_CODE (type2); + if (olhstype == TREE_TYPE (result)) + return result; + return convert_for_assignment (olhstype, result, _("assignment"), + NULL_TREE, NULL_TREE, 0); +} + +/* Convert value RHS to type TYPE as preparation for an assignment + to an lvalue of type TYPE. + The real work of conversion is done by `convert'. + The purpose of this function is to generate error messages + for assignments that are not allowed in C. + ERRTYPE is a string to use in error messages: + "assignment", "return", etc. If it is null, this is parameter passing + for a function call (and different error messages are output). - /* Quickly detect the usual case where op1 and op2 have the same type - after promotion. */ - if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) - { - if (type1 == type2) - result_type = type1; - else - result_type = TYPE_MAIN_VARIANT (type1); - } - else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE) - && (code2 == INTEGER_TYPE || code2 == REAL_TYPE - || code2 == COMPLEX_TYPE)) - { - result_type = common_type (type1, type2); + FUNNAME is the name of the function being called, + as an IDENTIFIER_NODE, or null. + PARMNUM is the number of the argument, for printing in error messages. */ - /* If -Wsign-compare, warn here if type1 and type2 have - different signedness. We'll promote the signed to unsigned - and later code won't know it used to be different. - Do this check on the original types, so that explicit casts - will be considered, but default promotions won't. */ - if (warn_sign_compare && !skip_evaluation) - { - int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1)); - int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2)); +static tree +convert_for_assignment (tree type, tree rhs, const char *errtype, + tree fundecl, tree funname, int parmnum) +{ + enum tree_code codel = TREE_CODE (type); + tree rhstype; + enum tree_code coder; - if (unsigned_op1 ^ unsigned_op2) - { - /* Do not warn if the result type is signed, since the - signed type will only be chosen if it can represent - all the values of the unsigned type. */ - if (! TREE_UNSIGNED (result_type)) - /* OK */; - /* Do not warn if the signed quantity is an unsuffixed - integer literal (or some static constant expression - involving such literals) and it is non-negative. */ - else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1)) - || (unsigned_op1 && c_tree_expr_nonnegative_p (op2))) - /* OK */; - else - warning ("signed and unsigned type in conditional expression"); - } - } - } - else if (code1 == VOID_TYPE || code2 == VOID_TYPE) - { - if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE)) - pedwarn ("ISO C forbids conditional expr with only one void side"); - result_type = void_type_node; - } - else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Do not use STRIP_NOPS here. We do not want an enumerator + whose value is 0 to count as a null pointer constant. */ + if (TREE_CODE (rhs) == NON_LVALUE_EXPR) + rhs = TREE_OPERAND (rhs, 0); + + if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE) + rhs = default_conversion (rhs); + else if (optimize && TREE_CODE (rhs) == VAR_DECL) + rhs = decl_constant_value_for_broken_optimization (rhs); + + rhstype = TREE_TYPE (rhs); + coder = TREE_CODE (rhstype); + + if (coder == ERROR_MARK) + return error_mark_node; + + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) { - if (comp_target_types (type1, type2, 1)) - result_type = common_type (type1, type2); - else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node - && TREE_CODE (orig_op1) != NOP_EXPR) - result_type = qualify_type (type2, type1); - else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node - && TREE_CODE (orig_op2) != NOP_EXPR) - result_type = qualify_type (type1, type2); - else if (VOID_TYPE_P (TREE_TYPE (type1))) - { - if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); - result_type = build_pointer_type (qualify_type (TREE_TYPE (type1), - TREE_TYPE (type2))); - } - else if (VOID_TYPE_P (TREE_TYPE (type2))) - { - if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); - result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), - TREE_TYPE (type1))); - } - else - { - pedwarn ("pointer type mismatch in conditional expression"); - result_type = build_pointer_type (void_type_node); - } + overflow_warning (rhs); + /* Check for Objective-C protocols. This will automatically + issue a warning if there are protocol violations. No need to + use the return value. */ + if (c_dialect_objc ()) + objc_comptypes (type, rhstype, 0); + return rhs; } - else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) + + if (coder == VOID_TYPE) { - if (! integer_zerop (op2)) - pedwarn ("pointer/integer type mismatch in conditional expression"); - else - { - op2 = null_pointer_node; - } - result_type = type1; + error ("void value not ignored as it ought to be"); + return error_mark_node; } - else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) + /* A type converts to a reference to it. + This code doesn't fully support references, it's just for the + special case of va_start and va_copy. */ + if (codel == REFERENCE_TYPE + && comptypes (TREE_TYPE (type), TREE_TYPE (rhs), COMPARE_STRICT) == 1) { - if (!integer_zerop (op1)) - pedwarn ("pointer/integer type mismatch in conditional expression"); - else + if (!lvalue_p (rhs)) { - op1 = null_pointer_node; + error ("cannot pass rvalue to reference parameter"); + return error_mark_node; } - result_type = type2; + if (!c_mark_addressable (rhs)) + return error_mark_node; + rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs); + + /* We already know that these two types are compatible, but they + may not be exactly identical. In fact, `TREE_TYPE (type)' is + likely to be __builtin_va_list and `TREE_TYPE (rhs)' is + likely to be va_list, a typedef to __builtin_va_list, which + is different enough that it will cause problems later. */ + if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type)) + rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs); + + rhs = build1 (NOP_EXPR, type, rhs); + return rhs; } + /* Some types can interconvert without explicit casts. */ + else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE + && ((*targetm.vector_opaque_p) (type) + || (*targetm.vector_opaque_p) (rhstype))) + return convert (type, rhs); + /* Arithmetic types all interconvert, and enum is treated like int. */ + else if ((codel == INTEGER_TYPE || codel == REAL_TYPE + || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE + || codel == BOOLEAN_TYPE) + && (coder == INTEGER_TYPE || coder == REAL_TYPE + || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE + || coder == BOOLEAN_TYPE)) + return convert_and_check (type, rhs); - if (!result_type) + /* Conversion to a transparent union from its member types. + This applies only to function arguments. */ + else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && ! errtype) { - if (flag_cond_mismatch) - result_type = void_type_node; - else + tree memb_types; + tree marginal_memb_type = 0; + + for (memb_types = TYPE_FIELDS (type); memb_types; + memb_types = TREE_CHAIN (memb_types)) { - error ("type mismatch in conditional expression"); - return error_mark_node; - } - } + tree memb_type = TREE_TYPE (memb_types); - /* Merge const and volatile flags of the incoming types. */ - result_type - = build_type_variant (result_type, - TREE_READONLY (op1) || TREE_READONLY (op2), - TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); + if (comptypes (TYPE_MAIN_VARIANT (memb_type), + TYPE_MAIN_VARIANT (rhstype), COMPARE_STRICT)) + break; - if (result_type != TREE_TYPE (op1)) - op1 = convert_and_check (result_type, op1); - if (result_type != TREE_TYPE (op2)) - op2 = convert_and_check (result_type, op2); + if (TREE_CODE (memb_type) != POINTER_TYPE) + continue; - if (TREE_CODE (ifexp) == INTEGER_CST) - return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1); + if (coder == POINTER_TYPE) + { + tree ttl = TREE_TYPE (memb_type); + tree ttr = TREE_TYPE (rhstype); - return fold (build (COND_EXPR, result_type, ifexp, op1, op2)); -} - -/* Given a list of expressions, return a compound expression - that performs them all and returns the value of the last of them. */ + /* Any non-function converts to a [const][volatile] void * + and vice versa; otherwise, targets must be the same. + Meanwhile, the lhs target must have all the qualifiers of + the rhs. */ + if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) + || comp_target_types (memb_type, rhstype, 0)) + { + /* If this type won't generate any warnings, use it. */ + if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr) + || ((TREE_CODE (ttr) == FUNCTION_TYPE + && TREE_CODE (ttl) == FUNCTION_TYPE) + ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) + == TYPE_QUALS (ttr)) + : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) + == TYPE_QUALS (ttl)))) + break; -tree -build_compound_expr (tree list) -{ - return internal_build_compound_expr (list, TRUE); -} + /* Keep looking for a better type, but remember this one. */ + if (! marginal_memb_type) + marginal_memb_type = memb_type; + } + } -static tree -internal_build_compound_expr (tree list, int first_p) -{ - tree rest; + /* Can convert integer zero to any pointer type. */ + if (integer_zerop (rhs) + || (TREE_CODE (rhs) == NOP_EXPR + && integer_zerop (TREE_OPERAND (rhs, 0)))) + { + rhs = null_pointer_node; + break; + } + } - if (TREE_CHAIN (list) == 0) - { - /* Convert arrays and functions to pointers when there - really is a comma operator. */ - if (!first_p) - TREE_VALUE (list) - = default_function_array_conversion (TREE_VALUE (list)); + if (memb_types || marginal_memb_type) + { + if (! memb_types) + { + /* We have only a marginally acceptable member type; + it needs a warning. */ + tree ttl = TREE_TYPE (marginal_memb_type); + tree ttr = TREE_TYPE (rhstype); - /* Don't let (0, 0) be null pointer constant. */ - if (!first_p && integer_zerop (TREE_VALUE (list))) - return non_lvalue (TREE_VALUE (list)); - return TREE_VALUE (list); - } - - rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE); + /* Const and volatile mean something different for function + types, so the usual warnings are not appropriate. */ + if (TREE_CODE (ttr) == FUNCTION_TYPE + && TREE_CODE (ttl) == FUNCTION_TYPE) + { + /* Because const and volatile on functions are + restrictions that say the function will not do + certain things, it is okay to use a const or volatile + function where an ordinary one is wanted, but not + vice-versa. */ + if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) + warn_for_assignment ("%s makes qualified function pointer from unqualified", + errtype, funname, parmnum); + } + else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) + warn_for_assignment ("%s discards qualifiers from pointer target type", + errtype, funname, + parmnum); + } - if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) - { - /* The left-hand operand of a comma expression is like an expression - statement: with -Wextra or -Wunused, we should warn if it doesn't have - any side-effects, unless it was explicitly cast to (void). */ - if (warn_unused_value - && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR - && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list))))) - warning ("left-hand operand of comma expression has no effect"); + if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl)) + pedwarn ("ISO C prohibits argument conversion to union type"); - /* When pedantic, a compound expression can be neither an lvalue - nor an integer constant expression. */ - if (! pedantic) - return rest; + return build1 (NOP_EXPR, type, rhs); + } } - /* With -Wunused, we should also warn if the left-hand operand does have - side-effects, but computes a value which is not used. For example, in - `foo() + bar(), baz()' the result of the `+' operator is not used, - so we should issue a warning. */ - else if (warn_unused_value) - warn_if_unused_value (TREE_VALUE (list)); - - return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest); -} - -/* Build an expression representing a cast to type TYPE of expression EXPR. */ - -tree -build_c_cast (tree type, tree expr) -{ - tree value = expr; - - if (type == error_mark_node || expr == error_mark_node) - return error_mark_node; - - /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing - only in qualifications. But when constructing cast expressions, - the protocols do matter and must be kept around. */ - if (!c_dialect_objc () || !objc_is_id (type)) - type = TYPE_MAIN_VARIANT (type); - - if (TREE_CODE (type) == ARRAY_TYPE) + /* Conversions among pointers */ + else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE) + && (coder == codel)) { - error ("cast specifies array type"); - return error_mark_node; - } + tree ttl = TREE_TYPE (type); + tree ttr = TREE_TYPE (rhstype); + bool is_opaque_pointer; - if (TREE_CODE (type) == FUNCTION_TYPE) - { - error ("cast specifies function type"); - return error_mark_node; - } + /* Opaque pointers are treated like void pointers. */ + is_opaque_pointer = ((*targetm.vector_opaque_p) (type) + || (*targetm.vector_opaque_p) (rhstype)) + && TREE_CODE (ttl) == VECTOR_TYPE + && TREE_CODE (ttr) == VECTOR_TYPE; - if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value))) + /* Any non-function converts to a [const][volatile] void * + and vice versa; otherwise, targets must be the same. + Meanwhile, the lhs target must have all the qualifiers of the rhs. */ + if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) + || comp_target_types (type, rhstype, 0) + || is_opaque_pointer + || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl)) + == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr)))) + { + if (pedantic + && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE) + || + (VOID_TYPE_P (ttr) + /* Check TREE_CODE to catch cases like (void *) (char *) 0 + which are not ANSI null ptr constants. */ + && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR) + && TREE_CODE (ttl) == FUNCTION_TYPE))) + warn_for_assignment ("ISO C forbids %s between function pointer and `void *'", + errtype, funname, parmnum); + /* Const and volatile mean something different for function types, + so the usual warnings are not appropriate. */ + else if (TREE_CODE (ttr) != FUNCTION_TYPE + && TREE_CODE (ttl) != FUNCTION_TYPE) + { + if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) + warn_for_assignment ("%s discards qualifiers from pointer target type", + errtype, funname, parmnum); + /* If this is not a case of ignoring a mismatch in signedness, + no warning. */ + else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) + || comp_target_types (type, rhstype, 0)) + ; + /* If there is a mismatch, do warn. */ + else if (pedantic) + warn_for_assignment ("pointer targets in %s differ in signedness", + errtype, funname, parmnum); + } + else if (TREE_CODE (ttl) == FUNCTION_TYPE + && TREE_CODE (ttr) == FUNCTION_TYPE) + { + /* Because const and volatile on functions are restrictions + that say the function will not do certain things, + it is okay to use a const or volatile function + where an ordinary one is wanted, but not vice-versa. */ + if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) + warn_for_assignment ("%s makes qualified function pointer from unqualified", + errtype, funname, parmnum); + } + } + else + warn_for_assignment ("%s from incompatible pointer type", + errtype, funname, parmnum); + return convert (type, rhs); + } + else if (codel == POINTER_TYPE && coder == INTEGER_TYPE) { - if (pedantic) + /* An explicit constant 0 can convert to a pointer, + or one that results from arithmetic, even including + a cast to integer type. */ + if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs)) + && + ! (TREE_CODE (rhs) == NOP_EXPR + && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE + && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST + && integer_zerop (TREE_OPERAND (rhs, 0)))) { - if (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE) - pedwarn ("ISO C forbids casting nonscalar to the same type"); + warn_for_assignment ("%s makes pointer from integer without a cast", + errtype, funname, parmnum); + return convert (type, rhs); } + return null_pointer_node; } - else if (TREE_CODE (type) == UNION_TYPE) + else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) { - tree field; - value = default_function_array_conversion (value); - - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), - TYPE_MAIN_VARIANT (TREE_TYPE (value)), COMPARE_STRICT)) - break; + warn_for_assignment ("%s makes integer from pointer without a cast", + errtype, funname, parmnum); + return convert (type, rhs); + } + else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE) + return convert (type, rhs); - if (field) + if (!errtype) + { + if (funname) { - tree t; + tree selector = objc_message_selector (); - if (pedantic) - pedwarn ("ISO C forbids casts to union type"); - t = digest_init (type, - build_constructor (type, - build_tree_list (field, value)), - 0); - TREE_CONSTANT (t) = TREE_CONSTANT (value); - return t; + if (selector && parmnum > 2) + error ("incompatible type for argument %d of `%s'", + parmnum - 2, IDENTIFIER_POINTER (selector)); + else + error ("incompatible type for argument %d of `%s'", + parmnum, IDENTIFIER_POINTER (funname)); } - error ("cast to union type from type not present in union"); - return error_mark_node; + else + error ("incompatible type for argument %d of indirect function call", + parmnum); } else - { - tree otype, ovalue; + error ("incompatible types in %s", errtype); - /* If casting to void, avoid the error that would come - from default_conversion in the case of a non-lvalue array. */ - if (type == void_type_node) - return build1 (CONVERT_EXPR, type, value); + return error_mark_node; +} - /* Convert functions and arrays to pointers, - but don't convert any other types. */ - value = default_function_array_conversion (value); - otype = TREE_TYPE (value); +/* Convert VALUE for assignment into inlined parameter PARM. */ - /* Optionally warn about potentially worrisome casts. */ +tree +c_convert_parm_for_inlining (tree parm, tree value, tree fn) +{ + tree ret, type; - if (warn_cast_qual - && TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (otype) == POINTER_TYPE) - { - tree in_type = type; - tree in_otype = otype; - int added = 0; - int discarded = 0; + /* If FN was prototyped, the value has been converted already + in convert_arguments. */ + if (! value || TYPE_ARG_TYPES (TREE_TYPE (fn))) + return value; - /* Check that the qualifiers on IN_TYPE are a superset of - the qualifiers of IN_OTYPE. The outermost level of - POINTER_TYPE nodes is uninteresting and we stop as soon - as we hit a non-POINTER_TYPE node on either type. */ - do - { - in_otype = TREE_TYPE (in_otype); - in_type = TREE_TYPE (in_type); + type = TREE_TYPE (parm); + ret = convert_for_assignment (type, value, + (char *) 0 /* arg passing */, fn, + DECL_NAME (fn), 0); + if (PROMOTE_PROTOTYPES + && INTEGRAL_TYPE_P (type) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + ret = default_conversion (ret); + return ret; +} - /* GNU C allows cv-qualified function types. 'const' - means the function is very pure, 'volatile' means it - can't return. We need to warn when such qualifiers - are added, not when they're taken away. */ - if (TREE_CODE (in_otype) == FUNCTION_TYPE - && TREE_CODE (in_type) == FUNCTION_TYPE) - added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype)); - else - discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type)); - } - while (TREE_CODE (in_type) == POINTER_TYPE - && TREE_CODE (in_otype) == POINTER_TYPE); +/* Print a warning using MSGID. + It gets OPNAME as its one parameter. + if OPNAME is null and ARGNUM is 0, it is replaced by "passing arg of `FUNCTION'". + Otherwise if OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'". + FUNCTION and ARGNUM are handled specially if we are building an + Objective-C selector. */ - if (added) - warning ("cast adds new qualifiers to function type"); +static void +warn_for_assignment (const char *msgid, const char *opname, tree function, + int argnum) +{ + if (opname == 0) + { + tree selector = objc_message_selector (); + char * new_opname; - if (discarded) - /* There are qualifiers present in IN_OTYPE that are not - present in IN_TYPE. */ - warning ("cast discards qualifiers from pointer target type"); + if (selector && argnum > 2) + { + function = selector; + argnum -= 2; } - - /* Warn about possible alignment problems. */ - if (STRICT_ALIGNMENT && warn_cast_align - && TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (otype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE - && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE - /* Don't warn about opaque types, where the actual alignment - restriction is unknown. */ - && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE - || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) - && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) - && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype))) - warning ("cast increases required alignment of target type"); - - if (TREE_CODE (type) == INTEGER_TYPE - && TREE_CODE (otype) == POINTER_TYPE - && TYPE_PRECISION (type) != TYPE_PRECISION (otype) - && !TREE_CONSTANT (value)) - warning ("cast from pointer to integer of different size"); - - if (warn_bad_function_cast - && TREE_CODE (value) == CALL_EXPR - && TREE_CODE (type) != TREE_CODE (otype)) - warning ("cast does not match function type"); - - if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (otype) == INTEGER_TYPE - && TYPE_PRECISION (type) != TYPE_PRECISION (otype) - /* Don't warn about converting any constant. */ - && !TREE_CONSTANT (value)) - warning ("cast to pointer from integer of different size"); - - if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (otype) == POINTER_TYPE - && TREE_CODE (expr) == ADDR_EXPR - && DECL_P (TREE_OPERAND (expr, 0)) - && flag_strict_aliasing && warn_strict_aliasing - && !VOID_TYPE_P (TREE_TYPE (type))) + if (argnum == 0) { - /* Casting the address of a decl to non void pointer. Warn - if the cast breaks type based aliasing. */ - if (!COMPLETE_TYPE_P (TREE_TYPE (type))) - warning ("type-punning to incomplete type might break strict-aliasing rules"); - else if (!alias_sets_conflict_p - (get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))), - get_alias_set (TREE_TYPE (type)))) - warning ("dereferencing type-punned pointer will break strict-aliasing rules"); + if (function) + { + /* Function name is known; supply it. */ + const char *const argstring = _("passing arg of `%s'"); + new_opname = (char *) alloca (IDENTIFIER_LENGTH (function) + + strlen (argstring) + 1 + + 1); + sprintf (new_opname, argstring, + IDENTIFIER_POINTER (function)); + } + else + { + /* Function name unknown (call through ptr). */ + const char *const argnofun = _("passing arg of pointer to function"); + new_opname = (char *) alloca (strlen (argnofun) + 1 + 1); + sprintf (new_opname, argnofun); + } } - - ovalue = value; - /* Replace a nonvolatile const static variable with its value. */ - if (optimize && TREE_CODE (value) == VAR_DECL) - value = decl_constant_value (value); - value = convert (type, value); - - /* Ignore any integer overflow caused by the cast. */ - if (TREE_CODE (value) == INTEGER_CST) + else if (function) { - TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); - TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); + /* Function name is known; supply it. */ + const char *const argstring = _("passing arg %d of `%s'"); + new_opname = (char *) alloca (IDENTIFIER_LENGTH (function) + + strlen (argstring) + 1 + 25 + /*%d*/ + 1); + sprintf (new_opname, argstring, argnum, + IDENTIFIER_POINTER (function)); + } + else + { + /* Function name unknown (call through ptr); just give arg number. */ + const char *const argnofun = _("passing arg %d of pointer to function"); + new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1); + sprintf (new_opname, argnofun, argnum); } + opname = new_opname; } - - /* Pedantically, don't let (void *) (FOO *) 0 be a null pointer constant. */ - if (pedantic && TREE_CODE (value) == INTEGER_CST - && TREE_CODE (expr) == INTEGER_CST - && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE) - value = non_lvalue (value); - - /* If pedantic, don't let a cast be an lvalue. */ - if (value == expr && pedantic) - value = non_lvalue (value); - - return value; + pedwarn (msgid, opname); } + +/* If VALUE is a compound expr all of whose expressions are constant, then + return its value. Otherwise, return error_mark_node. -/* Interpret a cast of expression EXPR to type TYPE. */ -tree -c_cast_expr (tree type, tree expr) -{ - int saved_wsp = warn_strict_prototypes; - - /* This avoids warnings about unprototyped casts on - integers. E.g. "#define SIG_DFL (void(*)())0". */ - if (TREE_CODE (expr) == INTEGER_CST) - warn_strict_prototypes = 0; - type = groktypename (type); - warn_strict_prototypes = saved_wsp; + This is for handling COMPOUND_EXPRs as initializer elements + which is allowed with a warning when -pedantic is specified. */ - return build_c_cast (type, expr); +static tree +valid_compound_expr_initializer (tree value, tree endtype) +{ + if (TREE_CODE (value) == COMPOUND_EXPR) + { + if (valid_compound_expr_initializer (TREE_OPERAND (value, 0), endtype) + == error_mark_node) + return error_mark_node; + return valid_compound_expr_initializer (TREE_OPERAND (value, 1), + endtype); + } + else if (! TREE_CONSTANT (value) + && ! initializer_constant_valid_p (value, endtype)) + return error_mark_node; + else + return value; } - -/* Build an assignment expression of lvalue LHS from value RHS. - MODIFYCODE is the code for a binary operator that we use - to combine the old value of LHS with RHS to get the new value. - Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. */ +/* Perform appropriate conversions on the initial value of a variable, + store it in the declaration DECL, + and print any error messages that are appropriate. + If the init is invalid, store an ERROR_MARK. */ -tree -build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) +void +store_init_value (tree decl, tree init) { - tree result; - tree newrhs; - tree lhstype = TREE_TYPE (lhs); - tree olhstype = lhstype; + tree value, type; - /* Types that aren't fully specified cannot be used in assignments. */ - lhs = require_complete_type (lhs); + /* If variable's type was invalidly declared, just ignore it. */ - /* Avoid duplicate error messages from operands that had errors. */ - if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) - return error_mark_node; + type = TREE_TYPE (decl); + if (TREE_CODE (type) == ERROR_MARK) + return; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + /* Digest the specified initializer into an expression. */ - newrhs = rhs; + value = digest_init (type, init, TREE_STATIC (decl)); - /* Handle control structure constructs used as "lvalues". */ + /* Store the expression if valid; else report error. */ - switch (TREE_CODE (lhs)) - { - /* Handle (a, b) used as an "lvalue". */ - case COMPOUND_EXPR: - pedantic_lvalue_warning (COMPOUND_EXPR); - newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs); - if (TREE_CODE (newrhs) == ERROR_MARK) - return error_mark_node; - return build (COMPOUND_EXPR, lhstype, - TREE_OPERAND (lhs, 0), newrhs); + if (warn_traditional && !in_system_header + && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && ! TREE_STATIC (decl)) + warning ("traditional C rejects automatic aggregate initialization"); - /* Handle (a ? b : c) used as an "lvalue". */ - case COND_EXPR: - pedantic_lvalue_warning (COND_EXPR); - rhs = save_expr (rhs); - { - /* Produce (a ? (b = rhs) : (c = rhs)) - except that the RHS goes through a save-expr - so the code to compute it is only emitted once. */ - tree cond - = build_conditional_expr (TREE_OPERAND (lhs, 0), - build_modify_expr (TREE_OPERAND (lhs, 1), - modifycode, rhs), - build_modify_expr (TREE_OPERAND (lhs, 2), - modifycode, rhs)); - if (TREE_CODE (cond) == ERROR_MARK) - return cond; - /* Make sure the code to compute the rhs comes out - before the split. */ - return build (COMPOUND_EXPR, TREE_TYPE (lhs), - /* But cast it to void to avoid an "unused" error. */ - convert (void_type_node, rhs), cond); - } - default: - break; - } + DECL_INITIAL (decl) = value; - /* If a binary op has been requested, combine the old LHS value with the RHS - producing the value we should actually store into the LHS. */ + /* ANSI wants warnings about out-of-range constant initializers. */ + STRIP_TYPE_NOPS (value); + constant_expression_warning (value); - if (modifycode != NOP_EXPR) + /* Check if we need to set array size from compound literal size. */ + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_DOMAIN (type) == 0 + && value != error_mark_node) { - lhs = stabilize_reference (lhs); - newrhs = build_binary_op (modifycode, lhs, rhs, 1); + tree inside_init = init; + + if (TREE_CODE (init) == NON_LVALUE_EXPR) + inside_init = TREE_OPERAND (init, 0); + inside_init = fold (inside_init); + + if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) + { + tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init); + + if (TYPE_DOMAIN (TREE_TYPE (decl))) + { + /* For int foo[] = (int [3]){1}; we need to set array size + now since later on array initializer will be just the + brace enclosed list of the compound literal. */ + TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (decl)); + layout_type (type); + layout_decl (decl, 0); + } + } } +} + +/* Methods for storing and printing names for error messages. */ - /* Handle a cast used as an "lvalue". - We have already performed any binary operator using the value as cast. - Now convert the result to the cast type of the lhs, - and then true type of the lhs and store it there; - then convert result back to the cast type to be the value - of the assignment. */ +/* Implement a spelling stack that allows components of a name to be pushed + and popped. Each element on the stack is this structure. */ - switch (TREE_CODE (lhs)) +struct spelling +{ + int kind; + union { - case NOP_EXPR: - case CONVERT_EXPR: - case FLOAT_EXPR: - case FIX_TRUNC_EXPR: - case FIX_FLOOR_EXPR: - case FIX_ROUND_EXPR: - case FIX_CEIL_EXPR: - newrhs = default_function_array_conversion (newrhs); - { - tree inner_lhs = TREE_OPERAND (lhs, 0); - tree result; - result = build_modify_expr (inner_lhs, NOP_EXPR, - convert (TREE_TYPE (inner_lhs), - convert (lhstype, newrhs))); - if (TREE_CODE (result) == ERROR_MARK) - return result; - pedantic_lvalue_warning (CONVERT_EXPR); - return convert (TREE_TYPE (lhs), result); - } + int i; + const char *s; + } u; +}; - default: - break; - } +#define SPELLING_STRING 1 +#define SPELLING_MEMBER 2 +#define SPELLING_BOUNDS 3 - /* Now we have handled acceptable kinds of LHS that are not truly lvalues. - Reject anything strange now. */ +static struct spelling *spelling; /* Next stack element (unused). */ +static struct spelling *spelling_base; /* Spelling stack base. */ +static int spelling_size; /* Size of the spelling stack. */ - if (!lvalue_or_else (lhs, "invalid lvalue in assignment")) - return error_mark_node; +/* Macros to save and restore the spelling stack around push_... functions. + Alternative to SAVE_SPELLING_STACK. */ - /* Warn about storing in something that is `const'. */ +#define SPELLING_DEPTH() (spelling - spelling_base) +#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH)) - if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype) - || ((TREE_CODE (lhstype) == RECORD_TYPE - || TREE_CODE (lhstype) == UNION_TYPE) - && C_TYPE_FIELDS_READONLY (lhstype))) - readonly_warning (lhs, "assignment"); +/* Push an element on the spelling stack with type KIND and assign VALUE + to MEMBER. */ - /* If storing into a structure or union member, - it has probably been given type `int'. - Compute the type that would go with - the actual amount of storage the member occupies. */ +#define PUSH_SPELLING(KIND, VALUE, MEMBER) \ +{ \ + int depth = SPELLING_DEPTH (); \ + \ + if (depth >= spelling_size) \ + { \ + spelling_size += 10; \ + if (spelling_base == 0) \ + spelling_base \ + = (struct spelling *) xmalloc (spelling_size * sizeof (struct spelling)); \ + else \ + spelling_base \ + = (struct spelling *) xrealloc (spelling_base, \ + spelling_size * sizeof (struct spelling)); \ + RESTORE_SPELLING_DEPTH (depth); \ + } \ + \ + spelling->kind = (KIND); \ + spelling->MEMBER = (VALUE); \ + spelling++; \ +} - if (TREE_CODE (lhs) == COMPONENT_REF - && (TREE_CODE (lhstype) == INTEGER_TYPE - || TREE_CODE (lhstype) == BOOLEAN_TYPE - || TREE_CODE (lhstype) == REAL_TYPE - || TREE_CODE (lhstype) == ENUMERAL_TYPE)) - lhstype = TREE_TYPE (get_unwidened (lhs, 0)); +/* Push STRING on the stack. Printed literally. */ - /* If storing in a field that is in actuality a short or narrower than one, - we must store in the field in its actual type. */ +static void +push_string (const char *string) +{ + PUSH_SPELLING (SPELLING_STRING, string, u.s); +} - if (lhstype != TREE_TYPE (lhs)) - { - lhs = copy_node (lhs); - TREE_TYPE (lhs) = lhstype; - } +/* Push a member name on the stack. Printed as '.' STRING. */ - /* Convert new value to destination type. */ +static void +push_member_name (tree decl) +{ + const char *const string + = DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : ""; + PUSH_SPELLING (SPELLING_MEMBER, string, u.s); +} - newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"), - NULL_TREE, NULL_TREE, 0); - if (TREE_CODE (newrhs) == ERROR_MARK) - return error_mark_node; +/* Push an array bounds on the stack. Printed as [BOUNDS]. */ - /* Scan operands */ +static void +push_array_bounds (int bounds) +{ + PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i); +} - result = build (MODIFY_EXPR, lhstype, lhs, newrhs); - TREE_SIDE_EFFECTS (result) = 1; +/* Compute the maximum size in bytes of the printed spelling. */ - /* If we got the LHS in a different type for storing in, - convert the result back to the nominal type of LHS - so that the value we return always has the same type - as the LHS argument. */ +static int +spelling_length (void) +{ + int size = 0; + struct spelling *p; - if (olhstype == TREE_TYPE (result)) - return result; - return convert_for_assignment (olhstype, result, _("assignment"), - NULL_TREE, NULL_TREE, 0); + for (p = spelling_base; p < spelling; p++) + { + if (p->kind == SPELLING_BOUNDS) + size += 25; + else + size += strlen (p->u.s) + 1; + } + + return size; } - -/* Convert value RHS to type TYPE as preparation for an assignment - to an lvalue of type TYPE. - The real work of conversion is done by `convert'. - The purpose of this function is to generate error messages - for assignments that are not allowed in C. - ERRTYPE is a string to use in error messages: - "assignment", "return", etc. If it is null, this is parameter passing - for a function call (and different error messages are output). - FUNNAME is the name of the function being called, - as an IDENTIFIER_NODE, or null. - PARMNUM is the number of the argument, for printing in error messages. */ +/* Print the spelling to BUFFER and return it. */ -static tree -convert_for_assignment (tree type, tree rhs, const char *errtype, - tree fundecl, tree funname, int parmnum) +static char * +print_spelling (char *buffer) { - enum tree_code codel = TREE_CODE (type); - tree rhstype; - enum tree_code coder; + char *d = buffer; + struct spelling *p; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + for (p = spelling_base; p < spelling; p++) + if (p->kind == SPELLING_BOUNDS) + { + sprintf (d, "[%d]", p->u.i); + d += strlen (d); + } + else + { + const char *s; + if (p->kind == SPELLING_MEMBER) + *d++ = '.'; + for (s = p->u.s; (*d = *s++); d++) + ; + } + *d++ = '\0'; + return buffer; +} - if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE) - rhs = default_conversion (rhs); - else if (optimize && TREE_CODE (rhs) == VAR_DECL) - rhs = decl_constant_value_for_broken_optimization (rhs); +/* Issue an error message for a bad initializer component. + MSGID identifies the message. + The component name is taken from the spelling stack. */ - rhstype = TREE_TYPE (rhs); - coder = TREE_CODE (rhstype); +void +error_init (const char *msgid) +{ + char *ofwhat; - if (coder == ERROR_MARK) - return error_mark_node; + error ("%s", _(msgid)); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); + if (*ofwhat) + error ("(near initialization for `%s')", ofwhat); +} - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) - { - overflow_warning (rhs); - /* Check for Objective-C protocols. This will automatically - issue a warning if there are protocol violations. No need to - use the return value. */ - if (c_dialect_objc ()) - objc_comptypes (type, rhstype, 0); - return rhs; - } +/* Issue a pedantic warning for a bad initializer component. + MSGID identifies the message. + The component name is taken from the spelling stack. */ - if (coder == VOID_TYPE) - { - error ("void value not ignored as it ought to be"); - return error_mark_node; - } - /* A type converts to a reference to it. - This code doesn't fully support references, it's just for the - special case of va_start and va_copy. */ - if (codel == REFERENCE_TYPE - && comptypes (TREE_TYPE (type), TREE_TYPE (rhs), COMPARE_STRICT) == 1) - { - if (!lvalue_p (rhs)) - { - error ("cannot pass rvalue to reference parameter"); - return error_mark_node; - } - if (!c_mark_addressable (rhs)) - return error_mark_node; - rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs); +void +pedwarn_init (const char *msgid) +{ + char *ofwhat; - /* We already know that these two types are compatible, but they - may not be exactly identical. In fact, `TREE_TYPE (type)' is - likely to be __builtin_va_list and `TREE_TYPE (rhs)' is - likely to be va_list, a typedef to __builtin_va_list, which - is different enough that it will cause problems later. */ - if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type)) - rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs); + pedwarn ("%s", _(msgid)); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); + if (*ofwhat) + pedwarn ("(near initialization for `%s')", ofwhat); +} - rhs = build1 (NOP_EXPR, type, rhs); - return rhs; - } - /* Some types can interconvert without explicit casts. */ - else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE - && ((*targetm.vector_opaque_p) (type) - || (*targetm.vector_opaque_p) (rhstype))) - return convert (type, rhs); - /* Arithmetic types all interconvert, and enum is treated like int. */ - else if ((codel == INTEGER_TYPE || codel == REAL_TYPE - || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE - || codel == BOOLEAN_TYPE) - && (coder == INTEGER_TYPE || coder == REAL_TYPE - || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE - || coder == BOOLEAN_TYPE)) - return convert_and_check (type, rhs); +/* Issue a warning for a bad initializer component. + MSGID identifies the message. + The component name is taken from the spelling stack. */ - /* Conversion to a transparent union from its member types. - This applies only to function arguments. */ - else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && ! errtype) - { - tree memb_types; - tree marginal_memb_type = 0; +static void +warning_init (const char *msgid) +{ + char *ofwhat; - for (memb_types = TYPE_FIELDS (type); memb_types; - memb_types = TREE_CHAIN (memb_types)) - { - tree memb_type = TREE_TYPE (memb_types); + warning ("%s", _(msgid)); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); + if (*ofwhat) + warning ("(near initialization for `%s')", ofwhat); +} + +/* Digest the parser output INIT as an initializer for type TYPE. + Return a C expression of type TYPE to represent the initial value. - if (comptypes (TYPE_MAIN_VARIANT (memb_type), - TYPE_MAIN_VARIANT (rhstype), COMPARE_STRICT)) - break; + REQUIRE_CONSTANT requests an error if non-constant initializers or + elements are seen. */ - if (TREE_CODE (memb_type) != POINTER_TYPE) - continue; +static tree +digest_init (tree type, tree init, int require_constant) +{ + enum tree_code code = TREE_CODE (type); + tree inside_init = init; - if (coder == POINTER_TYPE) - { - tree ttl = TREE_TYPE (memb_type); - tree ttr = TREE_TYPE (rhstype); + if (type == error_mark_node + || init == error_mark_node + || TREE_TYPE (init) == error_mark_node) + return error_mark_node; - /* Any non-function converts to a [const][volatile] void * - and vice versa; otherwise, targets must be the same. - Meanwhile, the lhs target must have all the qualifiers of - the rhs. */ - if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || comp_target_types (memb_type, rhstype, 0)) - { - /* If this type won't generate any warnings, use it. */ - if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr) - || ((TREE_CODE (ttr) == FUNCTION_TYPE - && TREE_CODE (ttl) == FUNCTION_TYPE) - ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) - == TYPE_QUALS (ttr)) - : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) - == TYPE_QUALS (ttl)))) - break; + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Do not use STRIP_NOPS here. We do not want an enumerator + whose value is 0 to count as a null pointer constant. */ + if (TREE_CODE (init) == NON_LVALUE_EXPR) + inside_init = TREE_OPERAND (init, 0); - /* Keep looking for a better type, but remember this one. */ - if (! marginal_memb_type) - marginal_memb_type = memb_type; - } - } + inside_init = fold (inside_init); - /* Can convert integer zero to any pointer type. */ - if (integer_zerop (rhs) - || (TREE_CODE (rhs) == NOP_EXPR - && integer_zerop (TREE_OPERAND (rhs, 0)))) - { - rhs = null_pointer_node; - break; - } - } + /* Initialization of an array of chars from a string constant + optionally enclosed in braces. */ - if (memb_types || marginal_memb_type) + if (code == ARRAY_TYPE) + { + tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + if ((typ1 == char_type_node + || typ1 == signed_char_type_node + || typ1 == unsigned_char_type_node + || typ1 == unsigned_wchar_type_node + || typ1 == signed_wchar_type_node) + && ((inside_init && TREE_CODE (inside_init) == STRING_CST))) { - if (! memb_types) - { - /* We have only a marginally acceptable member type; - it needs a warning. */ - tree ttl = TREE_TYPE (marginal_memb_type); - tree ttr = TREE_TYPE (rhstype); + if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), + TYPE_MAIN_VARIANT (type), COMPARE_STRICT)) + return inside_init; - /* Const and volatile mean something different for function - types, so the usual warnings are not appropriate. */ - if (TREE_CODE (ttr) == FUNCTION_TYPE - && TREE_CODE (ttl) == FUNCTION_TYPE) - { - /* Because const and volatile on functions are - restrictions that say the function will not do - certain things, it is okay to use a const or volatile - function where an ordinary one is wanted, but not - vice-versa. */ - if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) - warn_for_assignment ("%s makes qualified function pointer from unqualified", - errtype, funname, parmnum); - } - else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) - warn_for_assignment ("%s discards qualifiers from pointer target type", - errtype, funname, - parmnum); + if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) + != char_type_node) + && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node)) + { + error_init ("char-array initialized from wide string"); + return error_mark_node; + } + if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) + == char_type_node) + && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)) + { + error_init ("int-array initialized from non-wide string"); + return error_mark_node; } - if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl)) - pedwarn ("ISO C prohibits argument conversion to union type"); + TREE_TYPE (inside_init) = type; + if (TYPE_DOMAIN (type) != 0 + && TYPE_SIZE (type) != 0 + && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST + /* Subtract 1 (or sizeof (wchar_t)) + because it's ok to ignore the terminating null char + that is counted in the length of the constant. */ + && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), + TREE_STRING_LENGTH (inside_init) + - ((TYPE_PRECISION (typ1) + != TYPE_PRECISION (char_type_node)) + ? (TYPE_PRECISION (wchar_type_node) + / BITS_PER_UNIT) + : 1))) + pedwarn_init ("initializer-string for array of chars is too long"); - return build1 (NOP_EXPR, type, rhs); + return inside_init; } } - /* Conversions among pointers */ - else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE) - && (coder == codel)) - { - tree ttl = TREE_TYPE (type); - tree ttr = TREE_TYPE (rhstype); - bool is_opaque_pointer; + /* Build a VECTOR_CST from a *constant* vector constructor. If the + vector constructor is not constant (e.g. {1,2,3,foo()}) then punt + below and handle as a constructor. */ + if (code == VECTOR_TYPE + && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT) + && TREE_CONSTANT (inside_init)) + { + if (TREE_CODE (inside_init) == VECTOR_CST + && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), + TYPE_MAIN_VARIANT (type), + COMPARE_STRICT)) + return inside_init; + else + return build_vector (type, CONSTRUCTOR_ELTS (inside_init)); + } - /* Opaque pointers are treated like void pointers. */ - is_opaque_pointer = ((*targetm.vector_opaque_p) (type) - || (*targetm.vector_opaque_p) (rhstype)) - && TREE_CODE (ttl) == VECTOR_TYPE - && TREE_CODE (ttr) == VECTOR_TYPE; + /* Any type can be initialized + from an expression of the same type, optionally with braces. */ - /* Any non-function converts to a [const][volatile] void * - and vice versa; otherwise, targets must be the same. - Meanwhile, the lhs target must have all the qualifiers of the rhs. */ - if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || comp_target_types (type, rhstype, 0) - || is_opaque_pointer - || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl)) - == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr)))) + if (inside_init && TREE_TYPE (inside_init) != 0 + && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), + TYPE_MAIN_VARIANT (type), COMPARE_STRICT) + || (code == ARRAY_TYPE + && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)) + || (code == VECTOR_TYPE + && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)) + || (code == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE) + && comptypes (TREE_TYPE (TREE_TYPE (inside_init)), + TREE_TYPE (type), COMPARE_STRICT)))) + { + if (code == POINTER_TYPE) + inside_init = default_function_array_conversion (inside_init); + + if (require_constant && !flag_isoc99 + && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) { - if (pedantic - && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE) - || - (VOID_TYPE_P (ttr) - /* Check TREE_CODE to catch cases like (void *) (char *) 0 - which are not ANSI null ptr constants. */ - && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR) - && TREE_CODE (ttl) == FUNCTION_TYPE))) - warn_for_assignment ("ISO C forbids %s between function pointer and `void *'", - errtype, funname, parmnum); - /* Const and volatile mean something different for function types, - so the usual warnings are not appropriate. */ - else if (TREE_CODE (ttr) != FUNCTION_TYPE - && TREE_CODE (ttl) != FUNCTION_TYPE) - { - if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) - warn_for_assignment ("%s discards qualifiers from pointer target type", - errtype, funname, parmnum); - /* If this is not a case of ignoring a mismatch in signedness, - no warning. */ - else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || comp_target_types (type, rhstype, 0)) - ; - /* If there is a mismatch, do warn. */ - else if (pedantic) - warn_for_assignment ("pointer targets in %s differ in signedness", - errtype, funname, parmnum); - } - else if (TREE_CODE (ttl) == FUNCTION_TYPE - && TREE_CODE (ttr) == FUNCTION_TYPE) - { - /* Because const and volatile on functions are restrictions - that say the function will not do certain things, - it is okay to use a const or volatile function - where an ordinary one is wanted, but not vice-versa. */ - if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) - warn_for_assignment ("%s makes qualified function pointer from unqualified", - errtype, funname, parmnum); - } + /* As an extension, allow initializing objects with static storage + duration with compound literals (which are then treated just as + the brace enclosed list they contain). */ + tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init); + inside_init = DECL_INITIAL (decl); } - else - warn_for_assignment ("%s from incompatible pointer type", - errtype, funname, parmnum); - return convert (type, rhs); - } - else if (codel == POINTER_TYPE && coder == INTEGER_TYPE) - { - /* An explicit constant 0 can convert to a pointer, - or one that results from arithmetic, even including - a cast to integer type. */ - if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs)) - && - ! (TREE_CODE (rhs) == NOP_EXPR - && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE - && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST - && integer_zerop (TREE_OPERAND (rhs, 0)))) + + if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST + && TREE_CODE (inside_init) != CONSTRUCTOR) { - warn_for_assignment ("%s makes pointer from integer without a cast", - errtype, funname, parmnum); - return convert (type, rhs); + error_init ("array initialized from non-constant array expression"); + return error_mark_node; } - return null_pointer_node; - } - else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) - { - warn_for_assignment ("%s makes integer from pointer without a cast", - errtype, funname, parmnum); - return convert (type, rhs); - } - else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE) - return convert (type, rhs); - if (!errtype) - { - if (funname) - { - tree selector = objc_message_selector (); + if (optimize && TREE_CODE (inside_init) == VAR_DECL) + inside_init = decl_constant_value_for_broken_optimization (inside_init); - if (selector && parmnum > 2) - error ("incompatible type for argument %d of `%s'", - parmnum - 2, IDENTIFIER_POINTER (selector)); + /* Compound expressions can only occur here if -pedantic or + -pedantic-errors is specified. In the later case, we always want + an error. In the former case, we simply want a warning. */ + if (require_constant && pedantic + && TREE_CODE (inside_init) == COMPOUND_EXPR) + { + inside_init + = valid_compound_expr_initializer (inside_init, + TREE_TYPE (inside_init)); + if (inside_init == error_mark_node) + error_init ("initializer element is not constant"); else - error ("incompatible type for argument %d of `%s'", - parmnum, IDENTIFIER_POINTER (funname)); + pedwarn_init ("initializer element is not constant"); + if (flag_pedantic_errors) + inside_init = error_mark_node; + } + else if (require_constant + && (!TREE_CONSTANT (inside_init) + /* This test catches things like `7 / 0' which + result in an expression for which TREE_CONSTANT + is true, but which is not actually something + that is a legal constant. We really should not + be using this function, because it is a part of + the back-end. Instead, the expression should + already have been turned into ERROR_MARK_NODE. */ + || !initializer_constant_valid_p (inside_init, + TREE_TYPE (inside_init)))) + { + error_init ("initializer element is not constant"); + inside_init = error_mark_node; } - else - error ("incompatible type for argument %d of indirect function call", - parmnum); - } - else - error ("incompatible types in %s", errtype); - - return error_mark_node; -} - -/* Convert VALUE for assignment into inlined parameter PARM. */ - -tree -c_convert_parm_for_inlining (tree parm, tree value, tree fn) -{ - tree ret, type; - - /* If FN was prototyped, the value has been converted already - in convert_arguments. */ - if (! value || TYPE_ARG_TYPES (TREE_TYPE (fn))) - return value; - type = TREE_TYPE (parm); - ret = convert_for_assignment (type, value, - (char *) 0 /* arg passing */, fn, - DECL_NAME (fn), 0); - if (PROMOTE_PROTOTYPES - && INTEGRAL_TYPE_P (type) - && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) - ret = default_conversion (ret); - return ret; -} + return inside_init; + } -/* Print a warning using MSGID. - It gets OPNAME as its one parameter. - if OPNAME is null and ARGNUM is 0, it is replaced by "passing arg of `FUNCTION'". - Otherwise if OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'". - FUNCTION and ARGNUM are handled specially if we are building an - Objective-C selector. */ + /* Handle scalar types, including conversions. */ -static void -warn_for_assignment (const char *msgid, const char *opname, tree function, - int argnum) -{ - if (opname == 0) + if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE + || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE) { - tree selector = objc_message_selector (); - char * new_opname; + /* Note that convert_for_assignment calls default_conversion + for arrays and functions. We must not call it in the + case where inside_init is a null pointer constant. */ + inside_init + = convert_for_assignment (type, init, _("initialization"), + NULL_TREE, NULL_TREE, 0); - if (selector && argnum > 2) - { - function = selector; - argnum -= 2; - } - if (argnum == 0) - { - if (function) - { - /* Function name is known; supply it. */ - const char *const argstring = _("passing arg of `%s'"); - new_opname = (char *) alloca (IDENTIFIER_LENGTH (function) - + strlen (argstring) + 1 - + 1); - sprintf (new_opname, argstring, - IDENTIFIER_POINTER (function)); - } - else - { - /* Function name unknown (call through ptr). */ - const char *const argnofun = _("passing arg of pointer to function"); - new_opname = (char *) alloca (strlen (argnofun) + 1 + 1); - sprintf (new_opname, argnofun); - } - } - else if (function) + if (require_constant && ! TREE_CONSTANT (inside_init)) { - /* Function name is known; supply it. */ - const char *const argstring = _("passing arg %d of `%s'"); - new_opname = (char *) alloca (IDENTIFIER_LENGTH (function) - + strlen (argstring) + 1 + 25 - /*%d*/ + 1); - sprintf (new_opname, argstring, argnum, - IDENTIFIER_POINTER (function)); + error_init ("initializer element is not constant"); + inside_init = error_mark_node; } - else + else if (require_constant + && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0) { - /* Function name unknown (call through ptr); just give arg number. */ - const char *const argnofun = _("passing arg %d of pointer to function"); - new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1); - sprintf (new_opname, argnofun, argnum); + error_init ("initializer element is not computable at load time"); + inside_init = error_mark_node; } - opname = new_opname; + + return inside_init; } - pedwarn (msgid, opname); -} - -/* If VALUE is a compound expr all of whose expressions are constant, then - return its value. Otherwise, return error_mark_node. - This is for handling COMPOUND_EXPRs as initializer elements - which is allowed with a warning when -pedantic is specified. */ + /* Come here only for records and arrays. */ -static tree -valid_compound_expr_initializer (tree value, tree endtype) -{ - if (TREE_CODE (value) == COMPOUND_EXPR) + if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) { - if (valid_compound_expr_initializer (TREE_OPERAND (value, 0), endtype) - == error_mark_node) - return error_mark_node; - return valid_compound_expr_initializer (TREE_OPERAND (value, 1), - endtype); + error_init ("variable-sized object may not be initialized"); + return error_mark_node; } - else if (! TREE_CONSTANT (value) - && ! initializer_constant_valid_p (value, endtype)) - return error_mark_node; - else - return value; + + error_init ("invalid initializer"); + return error_mark_node; } -/* Perform appropriate conversions on the initial value of a variable, - store it in the declaration DECL, - and print any error messages that are appropriate. - If the init is invalid, store an ERROR_MARK. */ +/* Handle initializers that use braces. */ -void -store_init_value (tree decl, tree init) -{ - tree value, type; - - /* If variable's type was invalidly declared, just ignore it. */ +/* Type of object we are accumulating a constructor for. + This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE. */ +static tree constructor_type; - type = TREE_TYPE (decl); - if (TREE_CODE (type) == ERROR_MARK) - return; +/* For a RECORD_TYPE or UNION_TYPE, this is the chain of fields + left to fill. */ +static tree constructor_fields; - /* Digest the specified initializer into an expression. */ +/* For an ARRAY_TYPE, this is the specified index + at which to store the next element we get. */ +static tree constructor_index; - value = digest_init (type, init, TREE_STATIC (decl)); +/* For an ARRAY_TYPE, this is the maximum index. */ +static tree constructor_max_index; - /* Store the expression if valid; else report error. */ +/* For a RECORD_TYPE, this is the first field not yet written out. */ +static tree constructor_unfilled_fields; - if (warn_traditional && !in_system_header - && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && ! TREE_STATIC (decl)) - warning ("traditional C rejects automatic aggregate initialization"); +/* For an ARRAY_TYPE, this is the index of the first element + not yet written out. */ +static tree constructor_unfilled_index; - DECL_INITIAL (decl) = value; +/* In a RECORD_TYPE, the byte index of the next consecutive field. + This is so we can generate gaps between fields, when appropriate. */ +static tree constructor_bit_index; - /* ANSI wants warnings about out-of-range constant initializers. */ - STRIP_TYPE_NOPS (value); - constant_expression_warning (value); +/* If we are saving up the elements rather than allocating them, + this is the list of elements so far (in reverse order, + most recent first). */ +static tree constructor_elements; - /* Check if we need to set array size from compound literal size. */ - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) == 0 - && value != error_mark_node) - { - tree inside_init = init; +/* 1 if constructor should be incrementally stored into a constructor chain, + 0 if all the elements should be kept in AVL tree. */ +static int constructor_incremental; - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); - inside_init = fold (inside_init); +/* 1 if so far this constructor's elements are all compile-time constants. */ +static int constructor_constant; - if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) - { - tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init); +/* 1 if so far this constructor's elements are all valid address constants. */ +static int constructor_simple; - if (TYPE_DOMAIN (TREE_TYPE (decl))) - { - /* For int foo[] = (int [3]){1}; we need to set array size - now since later on array initializer will be just the - brace enclosed list of the compound literal. */ - TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (decl)); - layout_type (type); - layout_decl (decl, 0); - } - } - } -} - -/* Methods for storing and printing names for error messages. */ +/* 1 if this constructor is erroneous so far. */ +static int constructor_erroneous; -/* Implement a spelling stack that allows components of a name to be pushed - and popped. Each element on the stack is this structure. */ +/* Structure for managing pending initializer elements, organized as an + AVL tree. */ -struct spelling +struct init_node { - int kind; - union - { - int i; - const char *s; - } u; + struct init_node *left, *right; + struct init_node *parent; + int balance; + tree purpose; + tree value; }; -#define SPELLING_STRING 1 -#define SPELLING_MEMBER 2 -#define SPELLING_BOUNDS 3 +/* Tree of pending elements at this constructor level. + These are elements encountered out of order + which belong at places we haven't reached yet in actually + writing the output. + Will never hold tree nodes across GC runs. */ +static struct init_node *constructor_pending_elts; -static struct spelling *spelling; /* Next stack element (unused). */ -static struct spelling *spelling_base; /* Spelling stack base. */ -static int spelling_size; /* Size of the spelling stack. */ +/* The SPELLING_DEPTH of this constructor. */ +static int constructor_depth; -/* Macros to save and restore the spelling stack around push_... functions. - Alternative to SAVE_SPELLING_STACK. */ +/* 0 if implicitly pushing constructor levels is allowed. */ +int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */ -#define SPELLING_DEPTH() (spelling - spelling_base) -#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH)) +static int require_constant_value; +static int require_constant_elements; -/* Push an element on the spelling stack with type KIND and assign VALUE - to MEMBER. */ +/* DECL node for which an initializer is being read. + 0 means we are reading a constructor expression + such as (struct foo) {...}. */ +static tree constructor_decl; -#define PUSH_SPELLING(KIND, VALUE, MEMBER) \ -{ \ - int depth = SPELLING_DEPTH (); \ - \ - if (depth >= spelling_size) \ - { \ - spelling_size += 10; \ - if (spelling_base == 0) \ - spelling_base \ - = (struct spelling *) xmalloc (spelling_size * sizeof (struct spelling)); \ - else \ - spelling_base \ - = (struct spelling *) xrealloc (spelling_base, \ - spelling_size * sizeof (struct spelling)); \ - RESTORE_SPELLING_DEPTH (depth); \ - } \ - \ - spelling->kind = (KIND); \ - spelling->MEMBER = (VALUE); \ - spelling++; \ -} +/* start_init saves the ASMSPEC arg here for really_start_incremental_init. */ +static const char *constructor_asmspec; -/* Push STRING on the stack. Printed literally. */ +/* Nonzero if this is an initializer for a top-level decl. */ +static int constructor_top_level; -static void -push_string (const char *string) -{ - PUSH_SPELLING (SPELLING_STRING, string, u.s); -} +/* Nonzero if there were any member designators in this initializer. */ +static int constructor_designated; -/* Push a member name on the stack. Printed as '.' STRING. */ +/* Nesting depth of designator list. */ +static int designator_depth; -static void -push_member_name (tree decl) -{ - const char *const string - = DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : ""; - PUSH_SPELLING (SPELLING_MEMBER, string, u.s); -} +/* Nonzero if there were diagnosed errors in this designator list. */ +static int designator_errorneous; -/* Push an array bounds on the stack. Printed as [BOUNDS]. */ + +/* This stack has a level for each implicit or explicit level of + structuring in the initializer, including the outermost one. It + saves the values of most of the variables above. */ -static void -push_array_bounds (int bounds) +struct constructor_range_stack; + +struct constructor_stack { - PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i); -} + struct constructor_stack *next; + tree type; + tree fields; + tree index; + tree max_index; + tree unfilled_index; + tree unfilled_fields; + tree bit_index; + tree elements; + struct init_node *pending_elts; + int offset; + int depth; + /* If nonzero, this value should replace the entire + constructor at this level. */ + tree replacement_value; + struct constructor_range_stack *range_stack; + char constant; + char simple; + char implicit; + char erroneous; + char outer; + char incremental; + char designated; +}; -/* Compute the maximum size in bytes of the printed spelling. */ +struct constructor_stack *constructor_stack; -static int -spelling_length (void) -{ - int size = 0; - struct spelling *p; +/* This stack represents designators from some range designator up to + the last designator in the list. */ - for (p = spelling_base; p < spelling; p++) - { - if (p->kind == SPELLING_BOUNDS) - size += 25; - else - size += strlen (p->u.s) + 1; - } +struct constructor_range_stack +{ + struct constructor_range_stack *next, *prev; + struct constructor_stack *stack; + tree range_start; + tree index; + tree range_end; + tree fields; +}; - return size; -} +struct constructor_range_stack *constructor_range_stack; -/* Print the spelling to BUFFER and return it. */ +/* This stack records separate initializers that are nested. + Nested initializers can't happen in ANSI C, but GNU C allows them + in cases like { ... (struct foo) { ... } ... }. */ -static char * -print_spelling (char *buffer) +struct initializer_stack { - char *d = buffer; - struct spelling *p; + struct initializer_stack *next; + tree decl; + const char *asmspec; + struct constructor_stack *constructor_stack; + struct constructor_range_stack *constructor_range_stack; + tree elements; + struct spelling *spelling; + struct spelling *spelling_base; + int spelling_size; + char top_level; + char require_constant_value; + char require_constant_elements; +}; - for (p = spelling_base; p < spelling; p++) - if (p->kind == SPELLING_BOUNDS) - { - sprintf (d, "[%d]", p->u.i); - d += strlen (d); - } - else - { - const char *s; - if (p->kind == SPELLING_MEMBER) - *d++ = '.'; - for (s = p->u.s; (*d = *s++); d++) - ; - } - *d++ = '\0'; - return buffer; -} - -/* Issue an error message for a bad initializer component. - MSGID identifies the message. - The component name is taken from the spelling stack. */ +struct initializer_stack *initializer_stack; + +/* Prepare to parse and output the initializer for variable DECL. */ void -error_init (const char *msgid) +start_init (tree decl, tree asmspec_tree, int top_level) { - char *ofwhat; + const char *locus; + struct initializer_stack *p + = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack)); + const char *asmspec = 0; - error ("%s", _(msgid)); - ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) - error ("(near initialization for `%s')", ofwhat); -} + if (asmspec_tree) + asmspec = TREE_STRING_POINTER (asmspec_tree); -/* Issue a pedantic warning for a bad initializer component. - MSGID identifies the message. - The component name is taken from the spelling stack. */ + p->decl = constructor_decl; + p->asmspec = constructor_asmspec; + p->require_constant_value = require_constant_value; + p->require_constant_elements = require_constant_elements; + p->constructor_stack = constructor_stack; + p->constructor_range_stack = constructor_range_stack; + p->elements = constructor_elements; + p->spelling = spelling; + p->spelling_base = spelling_base; + p->spelling_size = spelling_size; + p->top_level = constructor_top_level; + p->next = initializer_stack; + initializer_stack = p; -void -pedwarn_init (const char *msgid) -{ - char *ofwhat; + constructor_decl = decl; + constructor_asmspec = asmspec; + constructor_designated = 0; + constructor_top_level = top_level; - pedwarn ("%s", _(msgid)); - ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) - pedwarn ("(near initialization for `%s')", ofwhat); -} + if (decl != 0) + { + require_constant_value = TREE_STATIC (decl); + require_constant_elements + = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99)) + /* For a scalar, you can always use any value to initialize, + even within braces. */ + && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE + || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE)); + locus = IDENTIFIER_POINTER (DECL_NAME (decl)); + } + else + { + require_constant_value = 0; + require_constant_elements = 0; + locus = "(anonymous)"; + } -/* Issue a warning for a bad initializer component. - MSGID identifies the message. - The component name is taken from the spelling stack. */ + constructor_stack = 0; + constructor_range_stack = 0; -static void -warning_init (const char *msgid) + missing_braces_mentioned = 0; + + spelling_base = 0; + spelling_size = 0; + RESTORE_SPELLING_DEPTH (0); + + if (locus) + push_string (locus); +} + +void +finish_init (void) { - char *ofwhat; + struct initializer_stack *p = initializer_stack; - warning ("%s", _(msgid)); - ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) - warning ("(near initialization for `%s')", ofwhat); + /* Free the whole constructor stack of this initializer. */ + while (constructor_stack) + { + struct constructor_stack *q = constructor_stack; + constructor_stack = q->next; + free (q); + } + + if (constructor_range_stack) + abort (); + + /* Pop back to the data of the outer initializer (if any). */ + constructor_decl = p->decl; + constructor_asmspec = p->asmspec; + require_constant_value = p->require_constant_value; + require_constant_elements = p->require_constant_elements; + constructor_stack = p->constructor_stack; + constructor_range_stack = p->constructor_range_stack; + constructor_elements = p->elements; + spelling = p->spelling; + spelling_base = p->spelling_base; + spelling_size = p->spelling_size; + constructor_top_level = p->top_level; + initializer_stack = p->next; + free (p); } -/* Digest the parser output INIT as an initializer for type TYPE. - Return a C expression of type TYPE to represent the initial value. +/* Call here when we see the initializer is surrounded by braces. + This is instead of a call to push_init_level; + it is matched by a call to pop_init_level. - REQUIRE_CONSTANT requests an error if non-constant initializers or - elements are seen. */ + TYPE is the type to initialize, for a constructor expression. + For an initializer for a decl, TYPE is zero. */ -static tree -digest_init (tree type, tree init, int require_constant) +void +really_start_incremental_init (tree type) { - enum tree_code code = TREE_CODE (type); - tree inside_init = init; + struct constructor_stack *p + = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack)); - if (type == error_mark_node - || init == error_mark_node - || TREE_TYPE (init) == error_mark_node) - return error_mark_node; + if (type == 0) + type = TREE_TYPE (constructor_decl); - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); + if ((*targetm.vector_opaque_p) (type)) + error ("opaque vector types cannot be initialized"); - inside_init = fold (inside_init); + p->type = constructor_type; + p->fields = constructor_fields; + p->index = constructor_index; + p->max_index = constructor_max_index; + p->unfilled_index = constructor_unfilled_index; + p->unfilled_fields = constructor_unfilled_fields; + p->bit_index = constructor_bit_index; + p->elements = constructor_elements; + p->constant = constructor_constant; + p->simple = constructor_simple; + p->erroneous = constructor_erroneous; + p->pending_elts = constructor_pending_elts; + p->depth = constructor_depth; + p->replacement_value = 0; + p->implicit = 0; + p->range_stack = 0; + p->outer = 0; + p->incremental = constructor_incremental; + p->designated = constructor_designated; + p->next = 0; + constructor_stack = p; - /* Initialization of an array of chars from a string constant - optionally enclosed in braces. */ + constructor_constant = 1; + constructor_simple = 1; + constructor_depth = SPELLING_DEPTH (); + constructor_elements = 0; + constructor_pending_elts = 0; + constructor_type = type; + constructor_incremental = 1; + constructor_designated = 0; + designator_depth = 0; + designator_errorneous = 0; - if (code == ARRAY_TYPE) + if (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) { - tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - if ((typ1 == char_type_node - || typ1 == signed_char_type_node - || typ1 == unsigned_char_type_node - || typ1 == unsigned_wchar_type_node - || typ1 == signed_wchar_type_node) - && ((inside_init && TREE_CODE (inside_init) == STRING_CST))) - { - if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), - TYPE_MAIN_VARIANT (type), COMPARE_STRICT)) - return inside_init; - - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) - != char_type_node) - && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node)) - { - error_init ("char-array initialized from wide string"); - return error_mark_node; - } - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) - == char_type_node) - && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)) - { - error_init ("int-array initialized from non-wide string"); - return error_mark_node; - } - - TREE_TYPE (inside_init) = type; - if (TYPE_DOMAIN (type) != 0 - && TYPE_SIZE (type) != 0 - && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - /* Subtract 1 (or sizeof (wchar_t)) - because it's ok to ignore the terminating null char - that is counted in the length of the constant. */ - && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), - TREE_STRING_LENGTH (inside_init) - - ((TYPE_PRECISION (typ1) - != TYPE_PRECISION (char_type_node)) - ? (TYPE_PRECISION (wchar_type_node) - / BITS_PER_UNIT) - : 1))) - pedwarn_init ("initializer-string for array of chars is too long"); + constructor_fields = TYPE_FIELDS (constructor_type); + /* Skip any nameless bit fields at the beginning. */ + while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) + && DECL_NAME (constructor_fields) == 0) + constructor_fields = TREE_CHAIN (constructor_fields); - return inside_init; - } + constructor_unfilled_fields = constructor_fields; + constructor_bit_index = bitsize_zero_node; } + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + if (TYPE_DOMAIN (constructor_type)) + { + constructor_max_index + = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); - /* Build a VECTOR_CST from a *constant* vector constructor. If the - vector constructor is not constant (e.g. {1,2,3,foo()}) then punt - below and handle as a constructor. */ - if (code == VECTOR_TYPE - && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT) - && TREE_CONSTANT (inside_init)) - { - if (TREE_CODE (inside_init) == VECTOR_CST - && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), - TYPE_MAIN_VARIANT (type), - COMPARE_STRICT)) - return inside_init; - else - return build_vector (type, CONSTRUCTOR_ELTS (inside_init)); - } - - /* Any type can be initialized - from an expression of the same type, optionally with braces. */ + /* Detect non-empty initializations of zero-length arrays. */ + if (constructor_max_index == NULL_TREE + && TYPE_SIZE (constructor_type)) + constructor_max_index = build_int_2 (-1, -1); - if (inside_init && TREE_TYPE (inside_init) != 0 - && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), - TYPE_MAIN_VARIANT (type), COMPARE_STRICT) - || (code == ARRAY_TYPE - && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)) - || (code == VECTOR_TYPE - && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)) - || (code == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE) - && comptypes (TREE_TYPE (TREE_TYPE (inside_init)), - TREE_TYPE (type), COMPARE_STRICT)))) - { - if (code == POINTER_TYPE) - inside_init = default_function_array_conversion (inside_init); + /* constructor_max_index needs to be an INTEGER_CST. Attempts + to initialize VLAs will cause a proper error; avoid tree + checking errors as well by setting a safe value. */ + if (constructor_max_index + && TREE_CODE (constructor_max_index) != INTEGER_CST) + constructor_max_index = build_int_2 (-1, -1); - if (require_constant && !flag_isoc99 - && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) - { - /* As an extension, allow initializing objects with static storage - duration with compound literals (which are then treated just as - the brace enclosed list they contain). */ - tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init); - inside_init = DECL_INITIAL (decl); + constructor_index + = convert (bitsizetype, + TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } + else + constructor_index = bitsize_zero_node; - if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST - && TREE_CODE (inside_init) != CONSTRUCTOR) - { - error_init ("array initialized from non-constant array expression"); - return error_mark_node; - } + constructor_unfilled_index = constructor_index; + } + else if (TREE_CODE (constructor_type) == VECTOR_TYPE) + { + /* Vectors are like simple fixed-size arrays. */ + constructor_max_index = + build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0); + constructor_index = convert (bitsizetype, bitsize_zero_node); + constructor_unfilled_index = constructor_index; + } + else + { + /* Handle the case of int x = {5}; */ + constructor_fields = constructor_type; + constructor_unfilled_fields = constructor_type; + } +} + +/* Push down into a subobject, for initialization. + If this is for an explicit set of braces, IMPLICIT is 0. + If it is because the next element belongs at a lower level, + IMPLICIT is 1 (or 2 if the push is because of designator list). */ - if (optimize && TREE_CODE (inside_init) == VAR_DECL) - inside_init = decl_constant_value_for_broken_optimization (inside_init); +void +push_init_level (int implicit) +{ + struct constructor_stack *p; + tree value = NULL_TREE; - /* Compound expressions can only occur here if -pedantic or - -pedantic-errors is specified. In the later case, we always want - an error. In the former case, we simply want a warning. */ - if (require_constant && pedantic - && TREE_CODE (inside_init) == COMPOUND_EXPR) - { - inside_init - = valid_compound_expr_initializer (inside_init, - TREE_TYPE (inside_init)); - if (inside_init == error_mark_node) - error_init ("initializer element is not constant"); - else - pedwarn_init ("initializer element is not constant"); - if (flag_pedantic_errors) - inside_init = error_mark_node; - } - else if (require_constant - && (!TREE_CONSTANT (inside_init) - /* This test catches things like `7 / 0' which - result in an expression for which TREE_CONSTANT - is true, but which is not actually something - that is a legal constant. We really should not - be using this function, because it is a part of - the back-end. Instead, the expression should - already have been turned into ERROR_MARK_NODE. */ - || !initializer_constant_valid_p (inside_init, - TREE_TYPE (inside_init)))) - { - error_init ("initializer element is not constant"); - inside_init = error_mark_node; - } + /* If we've exhausted any levels that didn't have braces, + pop them now. */ + while (constructor_stack->implicit) + { + if ((TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields == 0) + process_init_element (pop_init_level (1)); + else if (TREE_CODE (constructor_type) == ARRAY_TYPE + && constructor_max_index + && tree_int_cst_lt (constructor_max_index, constructor_index)) + process_init_element (pop_init_level (1)); + else + break; + } - return inside_init; + /* Unless this is an explicit brace, we need to preserve previous + content if any. */ + if (implicit) + { + if ((TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields) + value = find_init_member (constructor_fields); + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + value = find_init_member (constructor_index); } - /* Handle scalar types, including conversions. */ + p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack)); + p->type = constructor_type; + p->fields = constructor_fields; + p->index = constructor_index; + p->max_index = constructor_max_index; + p->unfilled_index = constructor_unfilled_index; + p->unfilled_fields = constructor_unfilled_fields; + p->bit_index = constructor_bit_index; + p->elements = constructor_elements; + p->constant = constructor_constant; + p->simple = constructor_simple; + p->erroneous = constructor_erroneous; + p->pending_elts = constructor_pending_elts; + p->depth = constructor_depth; + p->replacement_value = 0; + p->implicit = implicit; + p->outer = 0; + p->incremental = constructor_incremental; + p->designated = constructor_designated; + p->next = constructor_stack; + p->range_stack = 0; + constructor_stack = p; - if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE - || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE) + constructor_constant = 1; + constructor_simple = 1; + constructor_depth = SPELLING_DEPTH (); + constructor_elements = 0; + constructor_incremental = 1; + constructor_designated = 0; + constructor_pending_elts = 0; + if (!implicit) { - /* Note that convert_for_assignment calls default_conversion - for arrays and functions. We must not call it in the - case where inside_init is a null pointer constant. */ - inside_init - = convert_for_assignment (type, init, _("initialization"), - NULL_TREE, NULL_TREE, 0); + p->range_stack = constructor_range_stack; + constructor_range_stack = 0; + designator_depth = 0; + designator_errorneous = 0; + } - if (require_constant && ! TREE_CONSTANT (inside_init)) - { - error_init ("initializer element is not constant"); - inside_init = error_mark_node; - } - else if (require_constant - && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0) + /* Don't die if an entire brace-pair level is superfluous + in the containing level. */ + if (constructor_type == 0) + ; + else if (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + { + /* Don't die if there are extra init elts at the end. */ + if (constructor_fields == 0) + constructor_type = 0; + else { - error_init ("initializer element is not computable at load time"); - inside_init = error_mark_node; + constructor_type = TREE_TYPE (constructor_fields); + push_member_name (constructor_fields); + constructor_depth++; } - - return inside_init; + } + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + constructor_type = TREE_TYPE (constructor_type); + push_array_bounds (tree_low_cst (constructor_index, 0)); + constructor_depth++; } - /* Come here only for records and arrays. */ - - if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + if (constructor_type == 0) { - error_init ("variable-sized object may not be initialized"); - return error_mark_node; + error_init ("extra brace group at end of initializer"); + constructor_fields = 0; + constructor_unfilled_fields = 0; + return; } - error_init ("invalid initializer"); - return error_mark_node; -} - -/* Handle initializers that use braces. */ + if (value && TREE_CODE (value) == CONSTRUCTOR) + { + constructor_constant = TREE_CONSTANT (value); + constructor_simple = TREE_STATIC (value); + constructor_elements = CONSTRUCTOR_ELTS (value); + if (constructor_elements + && (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == ARRAY_TYPE)) + set_nonincremental_init (); + } -/* Type of object we are accumulating a constructor for. - This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE. */ -static tree constructor_type; + if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) + { + missing_braces_mentioned = 1; + warning_init ("missing braces around initializer"); + } -/* For a RECORD_TYPE or UNION_TYPE, this is the chain of fields - left to fill. */ -static tree constructor_fields; - -/* For an ARRAY_TYPE, this is the specified index - at which to store the next element we get. */ -static tree constructor_index; - -/* For an ARRAY_TYPE, this is the maximum index. */ -static tree constructor_max_index; + if (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + { + constructor_fields = TYPE_FIELDS (constructor_type); + /* Skip any nameless bit fields at the beginning. */ + while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) + && DECL_NAME (constructor_fields) == 0) + constructor_fields = TREE_CHAIN (constructor_fields); -/* For a RECORD_TYPE, this is the first field not yet written out. */ -static tree constructor_unfilled_fields; + constructor_unfilled_fields = constructor_fields; + constructor_bit_index = bitsize_zero_node; + } + else if (TREE_CODE (constructor_type) == VECTOR_TYPE) + { + /* Vectors are like simple fixed-size arrays. */ + constructor_max_index = + build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0); + constructor_index = convert (bitsizetype, integer_zero_node); + constructor_unfilled_index = constructor_index; + } + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + if (TYPE_DOMAIN (constructor_type)) + { + constructor_max_index + = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); -/* For an ARRAY_TYPE, this is the index of the first element - not yet written out. */ -static tree constructor_unfilled_index; + /* Detect non-empty initializations of zero-length arrays. */ + if (constructor_max_index == NULL_TREE + && TYPE_SIZE (constructor_type)) + constructor_max_index = build_int_2 (-1, -1); -/* In a RECORD_TYPE, the byte index of the next consecutive field. - This is so we can generate gaps between fields, when appropriate. */ -static tree constructor_bit_index; + /* constructor_max_index needs to be an INTEGER_CST. Attempts + to initialize VLAs will cause a proper error; avoid tree + checking errors as well by setting a safe value. */ + if (constructor_max_index + && TREE_CODE (constructor_max_index) != INTEGER_CST) + constructor_max_index = build_int_2 (-1, -1); -/* If we are saving up the elements rather than allocating them, - this is the list of elements so far (in reverse order, - most recent first). */ -static tree constructor_elements; + constructor_index + = convert (bitsizetype, + TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); + } + else + constructor_index = bitsize_zero_node; -/* 1 if constructor should be incrementally stored into a constructor chain, - 0 if all the elements should be kept in AVL tree. */ -static int constructor_incremental; + constructor_unfilled_index = constructor_index; + if (value && TREE_CODE (value) == STRING_CST) + { + /* We need to split the char/wchar array into individual + characters, so that we don't have to special case it + everywhere. */ + set_nonincremental_init_from_string (value); + } + } + else + { + warning_init ("braces around scalar initializer"); + constructor_fields = constructor_type; + constructor_unfilled_fields = constructor_type; + } +} -/* 1 if so far this constructor's elements are all compile-time constants. */ -static int constructor_constant; +/* At the end of an implicit or explicit brace level, + finish up that level of constructor. + If we were outputting the elements as they are read, return 0 + from inner levels (process_init_element ignores that), + but return error_mark_node from the outermost level + (that's what we want to put in DECL_INITIAL). + Otherwise, return a CONSTRUCTOR expression. */ -/* 1 if so far this constructor's elements are all valid address constants. */ -static int constructor_simple; +tree +pop_init_level (int implicit) +{ + struct constructor_stack *p; + tree constructor = 0; -/* 1 if this constructor is erroneous so far. */ -static int constructor_erroneous; + if (implicit == 0) + { + /* When we come to an explicit close brace, + pop any inner levels that didn't have explicit braces. */ + while (constructor_stack->implicit) + process_init_element (pop_init_level (1)); -/* Structure for managing pending initializer elements, organized as an - AVL tree. */ + if (constructor_range_stack) + abort (); + } -struct init_node -{ - struct init_node *left, *right; - struct init_node *parent; - int balance; - tree purpose; - tree value; -}; + p = constructor_stack; -/* Tree of pending elements at this constructor level. - These are elements encountered out of order - which belong at places we haven't reached yet in actually - writing the output. - Will never hold tree nodes across GC runs. */ -static struct init_node *constructor_pending_elts; + /* Error for initializing a flexible array member, or a zero-length + array member in an inappropriate context. */ + if (constructor_type && constructor_fields + && TREE_CODE (constructor_type) == ARRAY_TYPE + && TYPE_DOMAIN (constructor_type) + && ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type))) + { + /* Silently discard empty initializations. The parser will + already have pedwarned for empty brackets. */ + if (integer_zerop (constructor_unfilled_index)) + constructor_type = NULL_TREE; + else if (! TYPE_SIZE (constructor_type)) + { + if (constructor_depth > 2) + error_init ("initialization of flexible array member in a nested context"); + else if (pedantic) + pedwarn_init ("initialization of a flexible array member"); -/* The SPELLING_DEPTH of this constructor. */ -static int constructor_depth; + /* We have already issued an error message for the existence + of a flexible array member not at the end of the structure. + Discard the initializer so that we do not abort later. */ + if (TREE_CHAIN (constructor_fields) != NULL_TREE) + constructor_type = NULL_TREE; + } + else + /* Zero-length arrays are no longer special, so we should no longer + get here. */ + abort (); + } -/* 0 if implicitly pushing constructor levels is allowed. */ -int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */ + /* Warn when some struct elements are implicitly initialized to zero. */ + if (extra_warnings + && constructor_type + && TREE_CODE (constructor_type) == RECORD_TYPE + && constructor_unfilled_fields) + { + /* Do not warn for flexible array members or zero-length arrays. */ + while (constructor_unfilled_fields + && (! DECL_SIZE (constructor_unfilled_fields) + || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) + constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); -static int require_constant_value; -static int require_constant_elements; + /* Do not warn if this level of the initializer uses member + designators; it is likely to be deliberate. */ + if (constructor_unfilled_fields && !constructor_designated) + { + push_member_name (constructor_unfilled_fields); + warning_init ("missing initializer"); + RESTORE_SPELLING_DEPTH (constructor_depth); + } + } -/* DECL node for which an initializer is being read. - 0 means we are reading a constructor expression - such as (struct foo) {...}. */ -static tree constructor_decl; + /* Now output all pending elements. */ + constructor_incremental = 1; + output_pending_init_elements (1); -/* start_init saves the ASMSPEC arg here for really_start_incremental_init. */ -static const char *constructor_asmspec; + /* Pad out the end of the structure. */ + if (p->replacement_value) + /* If this closes a superfluous brace pair, + just pass out the element between them. */ + constructor = p->replacement_value; + else if (constructor_type == 0) + ; + else if (TREE_CODE (constructor_type) != RECORD_TYPE + && TREE_CODE (constructor_type) != UNION_TYPE + && TREE_CODE (constructor_type) != ARRAY_TYPE + && TREE_CODE (constructor_type) != VECTOR_TYPE) + { + /* A nonincremental scalar initializer--just return + the element, after verifying there is just one. */ + if (constructor_elements == 0) + { + if (!constructor_erroneous) + error_init ("empty scalar initializer"); + constructor = error_mark_node; + } + else if (TREE_CHAIN (constructor_elements) != 0) + { + error_init ("extra elements in scalar initializer"); + constructor = TREE_VALUE (constructor_elements); + } + else + constructor = TREE_VALUE (constructor_elements); + } + else + { + if (constructor_erroneous) + constructor = error_mark_node; + else + { + constructor = build_constructor (constructor_type, + nreverse (constructor_elements)); + if (constructor_constant) + TREE_CONSTANT (constructor) = 1; + if (constructor_constant && constructor_simple) + TREE_STATIC (constructor) = 1; + } + } -/* Nonzero if this is an initializer for a top-level decl. */ -static int constructor_top_level; + constructor_type = p->type; + constructor_fields = p->fields; + constructor_index = p->index; + constructor_max_index = p->max_index; + constructor_unfilled_index = p->unfilled_index; + constructor_unfilled_fields = p->unfilled_fields; + constructor_bit_index = p->bit_index; + constructor_elements = p->elements; + constructor_constant = p->constant; + constructor_simple = p->simple; + constructor_erroneous = p->erroneous; + constructor_incremental = p->incremental; + constructor_designated = p->designated; + constructor_pending_elts = p->pending_elts; + constructor_depth = p->depth; + if (!p->implicit) + constructor_range_stack = p->range_stack; + RESTORE_SPELLING_DEPTH (constructor_depth); -/* Nonzero if there were any member designators in this initializer. */ -static int constructor_designated; + constructor_stack = p->next; + free (p); -/* Nesting depth of designator list. */ -static int designator_depth; - -/* Nonzero if there were diagnosed errors in this designator list. */ -static int designator_errorneous; - - -/* This stack has a level for each implicit or explicit level of - structuring in the initializer, including the outermost one. It - saves the values of most of the variables above. */ - -struct constructor_range_stack; - -struct constructor_stack -{ - struct constructor_stack *next; - tree type; - tree fields; - tree index; - tree max_index; - tree unfilled_index; - tree unfilled_fields; - tree bit_index; - tree elements; - struct init_node *pending_elts; - int offset; - int depth; - /* If nonzero, this value should replace the entire - constructor at this level. */ - tree replacement_value; - struct constructor_range_stack *range_stack; - char constant; - char simple; - char implicit; - char erroneous; - char outer; - char incremental; - char designated; -}; - -struct constructor_stack *constructor_stack; - -/* This stack represents designators from some range designator up to - the last designator in the list. */ - -struct constructor_range_stack -{ - struct constructor_range_stack *next, *prev; - struct constructor_stack *stack; - tree range_start; - tree index; - tree range_end; - tree fields; -}; - -struct constructor_range_stack *constructor_range_stack; + if (constructor == 0) + { + if (constructor_stack == 0) + return error_mark_node; + return NULL_TREE; + } + return constructor; +} -/* This stack records separate initializers that are nested. - Nested initializers can't happen in ANSI C, but GNU C allows them - in cases like { ... (struct foo) { ... } ... }. */ +/* Common handling for both array range and field name designators. + ARRAY argument is nonzero for array ranges. Returns zero for success. */ -struct initializer_stack +static int +set_designator (int array) { - struct initializer_stack *next; - tree decl; - const char *asmspec; - struct constructor_stack *constructor_stack; - struct constructor_range_stack *constructor_range_stack; - tree elements; - struct spelling *spelling; - struct spelling *spelling_base; - int spelling_size; - char top_level; - char require_constant_value; - char require_constant_elements; -}; + tree subtype; + enum tree_code subcode; -struct initializer_stack *initializer_stack; - -/* Prepare to parse and output the initializer for variable DECL. */ + /* Don't die if an entire brace-pair level is superfluous + in the containing level. */ + if (constructor_type == 0) + return 1; -void -start_init (tree decl, tree asmspec_tree, int top_level) -{ - const char *locus; - struct initializer_stack *p - = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack)); - const char *asmspec = 0; + /* If there were errors in this designator list already, bail out silently. */ + if (designator_errorneous) + return 1; - if (asmspec_tree) - asmspec = TREE_STRING_POINTER (asmspec_tree); + if (!designator_depth) + { + if (constructor_range_stack) + abort (); - p->decl = constructor_decl; - p->asmspec = constructor_asmspec; - p->require_constant_value = require_constant_value; - p->require_constant_elements = require_constant_elements; - p->constructor_stack = constructor_stack; - p->constructor_range_stack = constructor_range_stack; - p->elements = constructor_elements; - p->spelling = spelling; - p->spelling_base = spelling_base; - p->spelling_size = spelling_size; - p->top_level = constructor_top_level; - p->next = initializer_stack; - initializer_stack = p; + /* Designator list starts at the level of closest explicit + braces. */ + while (constructor_stack->implicit) + process_init_element (pop_init_level (1)); + constructor_designated = 1; + return 0; + } - constructor_decl = decl; - constructor_asmspec = asmspec; - constructor_designated = 0; - constructor_top_level = top_level; + if (constructor_no_implicit) + { + error_init ("initialization designators may not nest"); + return 1; + } - if (decl != 0) + if (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) { - require_constant_value = TREE_STATIC (decl); - require_constant_elements - = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99)) - /* For a scalar, you can always use any value to initialize, - even within braces. */ - && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE - || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE - || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE)); - locus = IDENTIFIER_POINTER (DECL_NAME (decl)); + subtype = TREE_TYPE (constructor_fields); + if (subtype != error_mark_node) + subtype = TYPE_MAIN_VARIANT (subtype); } - else + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { - require_constant_value = 0; - require_constant_elements = 0; - locus = "(anonymous)"; + subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); } + else + abort (); - constructor_stack = 0; - constructor_range_stack = 0; - - missing_braces_mentioned = 0; - - spelling_base = 0; - spelling_size = 0; - RESTORE_SPELLING_DEPTH (0); + subcode = TREE_CODE (subtype); + if (array && subcode != ARRAY_TYPE) + { + error_init ("array index in non-array initializer"); + return 1; + } + else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE) + { + error_init ("field name not in record or union initializer"); + return 1; + } - if (locus) - push_string (locus); + constructor_designated = 1; + push_init_level (2); + return 0; } -void -finish_init (void) -{ - struct initializer_stack *p = initializer_stack; +/* If there are range designators in designator list, push a new designator + to constructor_range_stack. RANGE_END is end of such stack range or + NULL_TREE if there is no range designator at this level. */ - /* Free the whole constructor stack of this initializer. */ - while (constructor_stack) - { - struct constructor_stack *q = constructor_stack; - constructor_stack = q->next; - free (q); - } +static void +push_range_stack (tree range_end) +{ + struct constructor_range_stack *p; + p = (struct constructor_range_stack *) + ggc_alloc (sizeof (struct constructor_range_stack)); + p->prev = constructor_range_stack; + p->next = 0; + p->fields = constructor_fields; + p->range_start = constructor_index; + p->index = constructor_index; + p->stack = constructor_stack; + p->range_end = range_end; if (constructor_range_stack) - abort (); - - /* Pop back to the data of the outer initializer (if any). */ - constructor_decl = p->decl; - constructor_asmspec = p->asmspec; - require_constant_value = p->require_constant_value; - require_constant_elements = p->require_constant_elements; - constructor_stack = p->constructor_stack; - constructor_range_stack = p->constructor_range_stack; - constructor_elements = p->elements; - spelling = p->spelling; - spelling_base = p->spelling_base; - spelling_size = p->spelling_size; - constructor_top_level = p->top_level; - initializer_stack = p->next; - free (p); + constructor_range_stack->next = p; + constructor_range_stack = p; } - -/* Call here when we see the initializer is surrounded by braces. - This is instead of a call to push_init_level; - it is matched by a call to pop_init_level. - TYPE is the type to initialize, for a constructor expression. - For an initializer for a decl, TYPE is zero. */ +/* Within an array initializer, specify the next index to be initialized. + FIRST is that index. If LAST is nonzero, then initialize a range + of indices, running from FIRST through LAST. */ void -really_start_incremental_init (tree type) +set_init_index (tree first, tree last) { - struct constructor_stack *p - = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack)); + if (set_designator (1)) + return; - if (type == 0) - type = TREE_TYPE (constructor_decl); + designator_errorneous = 1; - if ((*targetm.vector_opaque_p) (type)) - error ("opaque vector types cannot be initialized"); + while ((TREE_CODE (first) == NOP_EXPR + || TREE_CODE (first) == CONVERT_EXPR + || TREE_CODE (first) == NON_LVALUE_EXPR) + && (TYPE_MODE (TREE_TYPE (first)) + == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0))))) + first = TREE_OPERAND (first, 0); - p->type = constructor_type; - p->fields = constructor_fields; - p->index = constructor_index; - p->max_index = constructor_max_index; - p->unfilled_index = constructor_unfilled_index; - p->unfilled_fields = constructor_unfilled_fields; - p->bit_index = constructor_bit_index; - p->elements = constructor_elements; - p->constant = constructor_constant; - p->simple = constructor_simple; - p->erroneous = constructor_erroneous; - p->pending_elts = constructor_pending_elts; - p->depth = constructor_depth; - p->replacement_value = 0; - p->implicit = 0; - p->range_stack = 0; - p->outer = 0; - p->incremental = constructor_incremental; - p->designated = constructor_designated; - p->next = 0; - constructor_stack = p; - - constructor_constant = 1; - constructor_simple = 1; - constructor_depth = SPELLING_DEPTH (); - constructor_elements = 0; - constructor_pending_elts = 0; - constructor_type = type; - constructor_incremental = 1; - constructor_designated = 0; - designator_depth = 0; - designator_errorneous = 0; + if (last) + while ((TREE_CODE (last) == NOP_EXPR + || TREE_CODE (last) == CONVERT_EXPR + || TREE_CODE (last) == NON_LVALUE_EXPR) + && (TYPE_MODE (TREE_TYPE (last)) + == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0))))) + last = TREE_OPERAND (last, 0); - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) + if (TREE_CODE (first) != INTEGER_CST) + error_init ("nonconstant array index in initializer"); + else if (last != 0 && TREE_CODE (last) != INTEGER_CST) + error_init ("nonconstant array index in initializer"); + else if (TREE_CODE (constructor_type) != ARRAY_TYPE) + error_init ("array index in non-array initializer"); + else if (constructor_max_index + && tree_int_cst_lt (constructor_max_index, first)) + error_init ("array index in initializer exceeds array bounds"); + else { - constructor_fields = TYPE_FIELDS (constructor_type); - /* Skip any nameless bit fields at the beginning. */ - while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) - && DECL_NAME (constructor_fields) == 0) - constructor_fields = TREE_CHAIN (constructor_fields); + constructor_index = convert (bitsizetype, first); - constructor_unfilled_fields = constructor_fields; - constructor_bit_index = bitsize_zero_node; - } - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - if (TYPE_DOMAIN (constructor_type)) + if (last) { - constructor_max_index - = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); - - /* Detect non-empty initializations of zero-length arrays. */ - if (constructor_max_index == NULL_TREE - && TYPE_SIZE (constructor_type)) - constructor_max_index = build_int_2 (-1, -1); - - /* constructor_max_index needs to be an INTEGER_CST. Attempts - to initialize VLAs will cause a proper error; avoid tree - checking errors as well by setting a safe value. */ - if (constructor_max_index - && TREE_CODE (constructor_max_index) != INTEGER_CST) - constructor_max_index = build_int_2 (-1, -1); - - constructor_index - = convert (bitsizetype, - TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); + if (tree_int_cst_equal (first, last)) + last = 0; + else if (tree_int_cst_lt (last, first)) + { + error_init ("empty index range in initializer"); + last = 0; + } + else + { + last = convert (bitsizetype, last); + if (constructor_max_index != 0 + && tree_int_cst_lt (constructor_max_index, last)) + { + error_init ("array index range in initializer exceeds array bounds"); + last = 0; + } + } } - else - constructor_index = bitsize_zero_node; - constructor_unfilled_index = constructor_index; - } - else if (TREE_CODE (constructor_type) == VECTOR_TYPE) - { - /* Vectors are like simple fixed-size arrays. */ - constructor_max_index = - build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0); - constructor_index = convert (bitsizetype, bitsize_zero_node); - constructor_unfilled_index = constructor_index; - } - else - { - /* Handle the case of int x = {5}; */ - constructor_fields = constructor_type; - constructor_unfilled_fields = constructor_type; + designator_depth++; + designator_errorneous = 0; + if (constructor_range_stack || last) + push_range_stack (last); } } - -/* Push down into a subobject, for initialization. - If this is for an explicit set of braces, IMPLICIT is 0. - If it is because the next element belongs at a lower level, - IMPLICIT is 1 (or 2 if the push is because of designator list). */ + +/* Within a struct initializer, specify the next field to be initialized. */ void -push_init_level (int implicit) +set_init_label (tree fieldname) { - struct constructor_stack *p; - tree value = NULL_TREE; + tree tail; - /* If we've exhausted any levels that didn't have braces, - pop them now. */ - while (constructor_stack->implicit) + if (set_designator (0)) + return; + + designator_errorneous = 1; + + if (TREE_CODE (constructor_type) != RECORD_TYPE + && TREE_CODE (constructor_type) != UNION_TYPE) { - if ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && constructor_fields == 0) - process_init_element (pop_init_level (1)); - else if (TREE_CODE (constructor_type) == ARRAY_TYPE - && constructor_max_index - && tree_int_cst_lt (constructor_max_index, constructor_index)) - process_init_element (pop_init_level (1)); - else - break; + error_init ("field name not in record or union initializer"); + return; } - /* Unless this is an explicit brace, we need to preserve previous - content if any. */ - if (implicit) + for (tail = TYPE_FIELDS (constructor_type); tail; + tail = TREE_CHAIN (tail)) { - if ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && constructor_fields) - value = find_init_member (constructor_fields); - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - value = find_init_member (constructor_index); + if (DECL_NAME (tail) == fieldname) + break; } - p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack)); - p->type = constructor_type; - p->fields = constructor_fields; - p->index = constructor_index; - p->max_index = constructor_max_index; - p->unfilled_index = constructor_unfilled_index; - p->unfilled_fields = constructor_unfilled_fields; - p->bit_index = constructor_bit_index; - p->elements = constructor_elements; - p->constant = constructor_constant; - p->simple = constructor_simple; - p->erroneous = constructor_erroneous; - p->pending_elts = constructor_pending_elts; - p->depth = constructor_depth; - p->replacement_value = 0; - p->implicit = implicit; - p->outer = 0; - p->incremental = constructor_incremental; - p->designated = constructor_designated; - p->next = constructor_stack; - p->range_stack = 0; - constructor_stack = p; - - constructor_constant = 1; - constructor_simple = 1; - constructor_depth = SPELLING_DEPTH (); - constructor_elements = 0; - constructor_incremental = 1; - constructor_designated = 0; - constructor_pending_elts = 0; - if (!implicit) + if (tail == 0) + error ("unknown field `%s' specified in initializer", + IDENTIFIER_POINTER (fieldname)); + else { - p->range_stack = constructor_range_stack; - constructor_range_stack = 0; - designator_depth = 0; + constructor_fields = tail; + designator_depth++; designator_errorneous = 0; + if (constructor_range_stack) + push_range_stack (NULL_TREE); } +} + +/* Add a new initializer to the tree of pending initializers. PURPOSE + identifies the initializer, either array index or field in a structure. + VALUE is the value of that index or field. */ - /* Don't die if an entire brace-pair level is superfluous - in the containing level. */ - if (constructor_type == 0) - ; - else if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) +static void +add_pending_init (tree purpose, tree value) +{ + struct init_node *p, **q, *r; + + q = &constructor_pending_elts; + p = 0; + + if (TREE_CODE (constructor_type) == ARRAY_TYPE) { - /* Don't die if there are extra init elts at the end. */ - if (constructor_fields == 0) - constructor_type = 0; - else + while (*q != 0) { - constructor_type = TREE_TYPE (constructor_fields); - push_member_name (constructor_fields); - constructor_depth++; + p = *q; + if (tree_int_cst_lt (purpose, p->purpose)) + q = &p->left; + else if (tree_int_cst_lt (p->purpose, purpose)) + q = &p->right; + else + { + if (TREE_SIDE_EFFECTS (p->value)) + warning_init ("initialized field with side-effects overwritten"); + p->value = value; + return; + } } } - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + else { - constructor_type = TREE_TYPE (constructor_type); - push_array_bounds (tree_low_cst (constructor_index, 0)); - constructor_depth++; - } + tree bitpos; - if (constructor_type == 0) - { - error_init ("extra brace group at end of initializer"); - constructor_fields = 0; - constructor_unfilled_fields = 0; - return; + bitpos = bit_position (purpose); + while (*q != NULL) + { + p = *q; + if (tree_int_cst_lt (bitpos, bit_position (p->purpose))) + q = &p->left; + else if (p->purpose != purpose) + q = &p->right; + else + { + if (TREE_SIDE_EFFECTS (p->value)) + warning_init ("initialized field with side-effects overwritten"); + p->value = value; + return; + } + } } - if (value && TREE_CODE (value) == CONSTRUCTOR) - { - constructor_constant = TREE_CONSTANT (value); - constructor_simple = TREE_STATIC (value); - constructor_elements = CONSTRUCTOR_ELTS (value); - if (constructor_elements - && (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == ARRAY_TYPE)) - set_nonincremental_init (); - } + r = (struct init_node *) ggc_alloc (sizeof (struct init_node)); + r->purpose = purpose; + r->value = value; - if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) - { - missing_braces_mentioned = 1; - warning_init ("missing braces around initializer"); - } + *q = r; + r->parent = p; + r->left = 0; + r->right = 0; + r->balance = 0; - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) + while (p) { - constructor_fields = TYPE_FIELDS (constructor_type); - /* Skip any nameless bit fields at the beginning. */ - while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) - && DECL_NAME (constructor_fields) == 0) - constructor_fields = TREE_CHAIN (constructor_fields); + struct init_node *s; - constructor_unfilled_fields = constructor_fields; - constructor_bit_index = bitsize_zero_node; - } - else if (TREE_CODE (constructor_type) == VECTOR_TYPE) - { - /* Vectors are like simple fixed-size arrays. */ - constructor_max_index = - build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0); - constructor_index = convert (bitsizetype, integer_zero_node); - constructor_unfilled_index = constructor_index; - } - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - if (TYPE_DOMAIN (constructor_type)) + if (r == p->left) { - constructor_max_index - = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); + if (p->balance == 0) + p->balance = -1; + else if (p->balance < 0) + { + if (r->balance < 0) + { + /* L rotation. */ + p->left = r->right; + if (p->left) + p->left->parent = p; + r->right = p; - /* Detect non-empty initializations of zero-length arrays. */ - if (constructor_max_index == NULL_TREE - && TYPE_SIZE (constructor_type)) - constructor_max_index = build_int_2 (-1, -1); + p->balance = 0; + r->balance = 0; - /* constructor_max_index needs to be an INTEGER_CST. Attempts - to initialize VLAs will cause a proper error; avoid tree - checking errors as well by setting a safe value. */ - if (constructor_max_index - && TREE_CODE (constructor_max_index) != INTEGER_CST) - constructor_max_index = build_int_2 (-1, -1); + s = p->parent; + p->parent = r; + r->parent = s; + if (s) + { + if (s->left == p) + s->left = r; + else + s->right = r; + } + else + constructor_pending_elts = r; + } + else + { + /* LR rotation. */ + struct init_node *t = r->right; - constructor_index - = convert (bitsizetype, - TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); + r->right = t->left; + if (r->right) + r->right->parent = r; + t->left = r; + + p->left = t->right; + if (p->left) + p->left->parent = p; + t->right = p; + + p->balance = t->balance < 0; + r->balance = -(t->balance > 0); + t->balance = 0; + + s = p->parent; + p->parent = t; + r->parent = t; + t->parent = s; + if (s) + { + if (s->left == p) + s->left = t; + else + s->right = t; + } + else + constructor_pending_elts = t; + } + break; + } + else + { + /* p->balance == +1; growth of left side balances the node. */ + p->balance = 0; + break; + } } - else - constructor_index = bitsize_zero_node; + else /* r == p->right */ + { + if (p->balance == 0) + /* Growth propagation from right side. */ + p->balance++; + else if (p->balance > 0) + { + if (r->balance > 0) + { + /* R rotation. */ + p->right = r->left; + if (p->right) + p->right->parent = p; + r->left = p; + + p->balance = 0; + r->balance = 0; + + s = p->parent; + p->parent = r; + r->parent = s; + if (s) + { + if (s->left == p) + s->left = r; + else + s->right = r; + } + else + constructor_pending_elts = r; + } + else /* r->balance == -1 */ + { + /* RL rotation */ + struct init_node *t = r->left; + + r->left = t->right; + if (r->left) + r->left->parent = r; + t->right = r; + + p->right = t->left; + if (p->right) + p->right->parent = p; + t->left = p; + + r->balance = (t->balance < 0); + p->balance = -(t->balance > 0); + t->balance = 0; + + s = p->parent; + p->parent = t; + r->parent = t; + t->parent = s; + if (s) + { + if (s->left == p) + s->left = t; + else + s->right = t; + } + else + constructor_pending_elts = t; + } + break; + } + else + { + /* p->balance == -1; growth of right side balances the node. */ + p->balance = 0; + break; + } + } + + r = p; + p = p->parent; + } +} + +/* Build AVL tree from a sorted chain. */ + +static void +set_nonincremental_init (void) +{ + tree chain; + + if (TREE_CODE (constructor_type) != RECORD_TYPE + && TREE_CODE (constructor_type) != ARRAY_TYPE) + return; + + for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain)) + add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain)); + constructor_elements = 0; + if (TREE_CODE (constructor_type) == RECORD_TYPE) + { + constructor_unfilled_fields = TYPE_FIELDS (constructor_type); + /* Skip any nameless bit fields at the beginning. */ + while (constructor_unfilled_fields != 0 + && DECL_C_BIT_FIELD (constructor_unfilled_fields) + && DECL_NAME (constructor_unfilled_fields) == 0) + constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); - constructor_unfilled_index = constructor_index; - if (value && TREE_CODE (value) == STRING_CST) - { - /* We need to split the char/wchar array into individual - characters, so that we don't have to special case it - everywhere. */ - set_nonincremental_init_from_string (value); - } } - else + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { - warning_init ("braces around scalar initializer"); - constructor_fields = constructor_type; - constructor_unfilled_fields = constructor_type; + if (TYPE_DOMAIN (constructor_type)) + constructor_unfilled_index + = convert (bitsizetype, + TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); + else + constructor_unfilled_index = bitsize_zero_node; } + constructor_incremental = 0; } -/* At the end of an implicit or explicit brace level, - finish up that level of constructor. - If we were outputting the elements as they are read, return 0 - from inner levels (process_init_element ignores that), - but return error_mark_node from the outermost level - (that's what we want to put in DECL_INITIAL). - Otherwise, return a CONSTRUCTOR expression. */ +/* Build AVL tree from a string constant. */ -tree -pop_init_level (int implicit) +static void +set_nonincremental_init_from_string (tree str) { - struct constructor_stack *p; - tree constructor = 0; + tree value, purpose, type; + HOST_WIDE_INT val[2]; + const char *p, *end; + int byte, wchar_bytes, charwidth, bitpos; - if (implicit == 0) - { - /* When we come to an explicit close brace, - pop any inner levels that didn't have explicit braces. */ - while (constructor_stack->implicit) - process_init_element (pop_init_level (1)); + if (TREE_CODE (constructor_type) != ARRAY_TYPE) + abort (); - if (constructor_range_stack) - abort (); - } + if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) + == TYPE_PRECISION (char_type_node)) + wchar_bytes = 1; + else if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) + == TYPE_PRECISION (wchar_type_node)) + wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; + else + abort (); - p = constructor_stack; + charwidth = TYPE_PRECISION (char_type_node); + type = TREE_TYPE (constructor_type); + p = TREE_STRING_POINTER (str); + end = p + TREE_STRING_LENGTH (str); - /* Error for initializing a flexible array member, or a zero-length - array member in an inappropriate context. */ - if (constructor_type && constructor_fields - && TREE_CODE (constructor_type) == ARRAY_TYPE - && TYPE_DOMAIN (constructor_type) - && ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type))) + for (purpose = bitsize_zero_node; + p < end && !tree_int_cst_lt (constructor_max_index, purpose); + purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node)) { - /* Silently discard empty initializations. The parser will - already have pedwarned for empty brackets. */ - if (integer_zerop (constructor_unfilled_index)) - constructor_type = NULL_TREE; - else if (! TYPE_SIZE (constructor_type)) + if (wchar_bytes == 1) { - if (constructor_depth > 2) - error_init ("initialization of flexible array member in a nested context"); - else if (pedantic) - pedwarn_init ("initialization of a flexible array member"); - - /* We have already issued an error message for the existence - of a flexible array member not at the end of the structure. - Discard the initializer so that we do not abort later. */ - if (TREE_CHAIN (constructor_fields) != NULL_TREE) - constructor_type = NULL_TREE; + val[1] = (unsigned char) *p++; + val[0] = 0; } else - /* Zero-length arrays are no longer special, so we should no longer - get here. */ - abort (); - } + { + val[0] = 0; + val[1] = 0; + for (byte = 0; byte < wchar_bytes; byte++) + { + if (BYTES_BIG_ENDIAN) + bitpos = (wchar_bytes - byte - 1) * charwidth; + else + bitpos = byte * charwidth; + val[bitpos < HOST_BITS_PER_WIDE_INT] + |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++)) + << (bitpos % HOST_BITS_PER_WIDE_INT); + } + } - /* Warn when some struct elements are implicitly initialized to zero. */ - if (extra_warnings - && constructor_type - && TREE_CODE (constructor_type) == RECORD_TYPE - && constructor_unfilled_fields) - { - /* Do not warn for flexible array members or zero-length arrays. */ - while (constructor_unfilled_fields - && (! DECL_SIZE (constructor_unfilled_fields) - || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) - constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); + if (!TREE_UNSIGNED (type)) + { + bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR; + if (bitpos < HOST_BITS_PER_WIDE_INT) + { + if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1))) + { + val[1] |= ((HOST_WIDE_INT) -1) << bitpos; + val[0] = -1; + } + } + else if (bitpos == HOST_BITS_PER_WIDE_INT) + { + if (val[1] < 0) + val[0] = -1; + } + else if (val[0] & (((HOST_WIDE_INT) 1) + << (bitpos - 1 - HOST_BITS_PER_WIDE_INT))) + val[0] |= ((HOST_WIDE_INT) -1) + << (bitpos - HOST_BITS_PER_WIDE_INT); + } - /* Do not warn if this level of the initializer uses member - designators; it is likely to be deliberate. */ - if (constructor_unfilled_fields && !constructor_designated) - { - push_member_name (constructor_unfilled_fields); - warning_init ("missing initializer"); - RESTORE_SPELLING_DEPTH (constructor_depth); - } + value = build_int_2 (val[1], val[0]); + TREE_TYPE (value) = type; + add_pending_init (purpose, value); } - /* Now output all pending elements. */ - constructor_incremental = 1; - output_pending_init_elements (1); + constructor_incremental = 0; +} - /* Pad out the end of the structure. */ - if (p->replacement_value) - /* If this closes a superfluous brace pair, - just pass out the element between them. */ - constructor = p->replacement_value; - else if (constructor_type == 0) - ; - else if (TREE_CODE (constructor_type) != RECORD_TYPE - && TREE_CODE (constructor_type) != UNION_TYPE - && TREE_CODE (constructor_type) != ARRAY_TYPE - && TREE_CODE (constructor_type) != VECTOR_TYPE) +/* Return value of FIELD in pending initializer or zero if the field was + not initialized yet. */ + +static tree +find_init_member (tree field) +{ + struct init_node *p; + + if (TREE_CODE (constructor_type) == ARRAY_TYPE) { - /* A nonincremental scalar initializer--just return - the element, after verifying there is just one. */ - if (constructor_elements == 0) - { - if (!constructor_erroneous) - error_init ("empty scalar initializer"); - constructor = error_mark_node; - } - else if (TREE_CHAIN (constructor_elements) != 0) + if (constructor_incremental + && tree_int_cst_lt (field, constructor_unfilled_index)) + set_nonincremental_init (); + + p = constructor_pending_elts; + while (p) { - error_init ("extra elements in scalar initializer"); - constructor = TREE_VALUE (constructor_elements); + if (tree_int_cst_lt (field, p->purpose)) + p = p->left; + else if (tree_int_cst_lt (p->purpose, field)) + p = p->right; + else + return p->value; } - else - constructor = TREE_VALUE (constructor_elements); } - else + else if (TREE_CODE (constructor_type) == RECORD_TYPE) { - if (constructor_erroneous) - constructor = error_mark_node; - else - { - constructor = build_constructor (constructor_type, - nreverse (constructor_elements)); - if (constructor_constant) - TREE_CONSTANT (constructor) = 1; - if (constructor_constant && constructor_simple) - TREE_STATIC (constructor) = 1; - } - } - - constructor_type = p->type; - constructor_fields = p->fields; - constructor_index = p->index; - constructor_max_index = p->max_index; - constructor_unfilled_index = p->unfilled_index; - constructor_unfilled_fields = p->unfilled_fields; - constructor_bit_index = p->bit_index; - constructor_elements = p->elements; - constructor_constant = p->constant; - constructor_simple = p->simple; - constructor_erroneous = p->erroneous; - constructor_incremental = p->incremental; - constructor_designated = p->designated; - constructor_pending_elts = p->pending_elts; - constructor_depth = p->depth; - if (!p->implicit) - constructor_range_stack = p->range_stack; - RESTORE_SPELLING_DEPTH (constructor_depth); + tree bitpos = bit_position (field); - constructor_stack = p->next; - free (p); + if (constructor_incremental + && (!constructor_unfilled_fields + || tree_int_cst_lt (bitpos, + bit_position (constructor_unfilled_fields)))) + set_nonincremental_init (); - if (constructor == 0) + p = constructor_pending_elts; + while (p) + { + if (field == p->purpose) + return p->value; + else if (tree_int_cst_lt (bitpos, bit_position (p->purpose))) + p = p->left; + else + p = p->right; + } + } + else if (TREE_CODE (constructor_type) == UNION_TYPE) { - if (constructor_stack == 0) - return error_mark_node; - return NULL_TREE; + if (constructor_elements + && TREE_PURPOSE (constructor_elements) == field) + return TREE_VALUE (constructor_elements); } - return constructor; + return 0; } -/* Common handling for both array range and field name designators. - ARRAY argument is nonzero for array ranges. Returns zero for success. */ - -static int -set_designator (int array) -{ - tree subtype; - enum tree_code subcode; - - /* Don't die if an entire brace-pair level is superfluous - in the containing level. */ - if (constructor_type == 0) - return 1; +/* "Output" the next constructor element. + At top level, really output it to assembler code now. + Otherwise, collect it in a list from which we will make a CONSTRUCTOR. + TYPE is the data type that the containing data type wants here. + FIELD is the field (a FIELD_DECL) or the index that this element fills. - /* If there were errors in this designator list already, bail out silently. */ - if (designator_errorneous) - return 1; + PENDING if non-nil means output pending elements that belong + right after this element. (PENDING is normally 1; + it is 0 while outputting pending elements, to avoid recursion.) */ - if (!designator_depth) +static void +output_init_element (tree value, tree type, tree field, int pending) +{ + if (type == error_mark_node) { - if (constructor_range_stack) - abort (); - - /* Designator list starts at the level of closest explicit - braces. */ - while (constructor_stack->implicit) - process_init_element (pop_init_level (1)); - constructor_designated = 1; - return 0; + constructor_erroneous = 1; + return; } + if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE + || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE + && !(TREE_CODE (value) == STRING_CST + && TREE_CODE (type) == ARRAY_TYPE + && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE) + && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)), + TYPE_MAIN_VARIANT (type), COMPARE_STRICT))) + value = default_conversion (value); - if (constructor_no_implicit) + if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR + && require_constant_value && !flag_isoc99 && pending) { - error_init ("initialization designators may not nest"); - return 1; + /* As an extension, allow initializing objects with static storage + duration with compound literals (which are then treated just as + the brace enclosed list they contain). */ + tree decl = COMPOUND_LITERAL_EXPR_DECL (value); + value = DECL_INITIAL (decl); } - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) + if (value == error_mark_node) + constructor_erroneous = 1; + else if (!TREE_CONSTANT (value)) + constructor_constant = 0; + else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0 + || ((TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + && DECL_C_BIT_FIELD (field) + && TREE_CODE (value) != INTEGER_CST)) + constructor_simple = 0; + + if (require_constant_value && ! TREE_CONSTANT (value)) { - subtype = TREE_TYPE (constructor_fields); - if (subtype != error_mark_node) - subtype = TYPE_MAIN_VARIANT (subtype); + error_init ("initializer element is not constant"); + value = error_mark_node; } - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + else if (require_constant_elements + && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0) + pedwarn ("initializer element is not computable at load time"); + + /* If this field is empty (and not at the end of structure), + don't do anything other than checking the initializer. */ + if (field + && (TREE_TYPE (field) == error_mark_node + || (COMPLETE_TYPE_P (TREE_TYPE (field)) + && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) + && (TREE_CODE (constructor_type) == ARRAY_TYPE + || TREE_CHAIN (field))))) + return; + + value = digest_init (type, value, require_constant_value); + if (value == error_mark_node) { - subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); + constructor_erroneous = 1; + return; } - else - abort (); - subcode = TREE_CODE (subtype); - if (array && subcode != ARRAY_TYPE) + /* If this element doesn't come next in sequence, + put it on constructor_pending_elts. */ + if (TREE_CODE (constructor_type) == ARRAY_TYPE + && (!constructor_incremental + || !tree_int_cst_equal (field, constructor_unfilled_index))) { - error_init ("array index in non-array initializer"); - return 1; + if (constructor_incremental + && tree_int_cst_lt (field, constructor_unfilled_index)) + set_nonincremental_init (); + + add_pending_init (field, value); + return; } - else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE) + else if (TREE_CODE (constructor_type) == RECORD_TYPE + && (!constructor_incremental + || field != constructor_unfilled_fields)) { - error_init ("field name not in record or union initializer"); - return 1; + /* We do this for records but not for unions. In a union, + no matter which field is specified, it can be initialized + right away since it starts at the beginning of the union. */ + if (constructor_incremental) + { + if (!constructor_unfilled_fields) + set_nonincremental_init (); + else + { + tree bitpos, unfillpos; + + bitpos = bit_position (field); + unfillpos = bit_position (constructor_unfilled_fields); + + if (tree_int_cst_lt (bitpos, unfillpos)) + set_nonincremental_init (); + } + } + + add_pending_init (field, value); + return; } + else if (TREE_CODE (constructor_type) == UNION_TYPE + && constructor_elements) + { + if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements))) + warning_init ("initialized field with side-effects overwritten"); - constructor_designated = 1; - push_init_level (2); - return 0; -} + /* We can have just one union field set. */ + constructor_elements = 0; + } -/* If there are range designators in designator list, push a new designator - to constructor_range_stack. RANGE_END is end of such stack range or - NULL_TREE if there is no range designator at this level. */ + /* Otherwise, output this element either to + constructor_elements or to the assembler file. */ -static void -push_range_stack (tree range_end) -{ - struct constructor_range_stack *p; + if (field && TREE_CODE (field) == INTEGER_CST) + field = copy_node (field); + constructor_elements + = tree_cons (field, value, constructor_elements); - p = (struct constructor_range_stack *) - ggc_alloc (sizeof (struct constructor_range_stack)); - p->prev = constructor_range_stack; - p->next = 0; - p->fields = constructor_fields; - p->range_start = constructor_index; - p->index = constructor_index; - p->stack = constructor_stack; - p->range_end = range_end; - if (constructor_range_stack) - constructor_range_stack->next = p; - constructor_range_stack = p; -} + /* Advance the variable that indicates sequential elements output. */ + if (TREE_CODE (constructor_type) == ARRAY_TYPE) + constructor_unfilled_index + = size_binop (PLUS_EXPR, constructor_unfilled_index, + bitsize_one_node); + else if (TREE_CODE (constructor_type) == RECORD_TYPE) + { + constructor_unfilled_fields + = TREE_CHAIN (constructor_unfilled_fields); -/* Within an array initializer, specify the next index to be initialized. - FIRST is that index. If LAST is nonzero, then initialize a range - of indices, running from FIRST through LAST. */ + /* Skip any nameless bit fields. */ + while (constructor_unfilled_fields != 0 + && DECL_C_BIT_FIELD (constructor_unfilled_fields) + && DECL_NAME (constructor_unfilled_fields) == 0) + constructor_unfilled_fields = + TREE_CHAIN (constructor_unfilled_fields); + } + else if (TREE_CODE (constructor_type) == UNION_TYPE) + constructor_unfilled_fields = 0; -void -set_init_index (tree first, tree last) -{ - if (set_designator (1)) - return; + /* Now output any pending elements which have become next. */ + if (pending) + output_pending_init_elements (0); +} - designator_errorneous = 1; +/* Output any pending elements which have become next. + As we output elements, constructor_unfilled_{fields,index} + advances, which may cause other elements to become next; + if so, they too are output. - while ((TREE_CODE (first) == NOP_EXPR - || TREE_CODE (first) == CONVERT_EXPR - || TREE_CODE (first) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (first)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0))))) - first = TREE_OPERAND (first, 0); + If ALL is 0, we return when there are + no more pending elements to output now. - if (last) - while ((TREE_CODE (last) == NOP_EXPR - || TREE_CODE (last) == CONVERT_EXPR - || TREE_CODE (last) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (last)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0))))) - last = TREE_OPERAND (last, 0); + If ALL is 1, we output space as necessary so that + we can output all the pending elements. */ - if (TREE_CODE (first) != INTEGER_CST) - error_init ("nonconstant array index in initializer"); - else if (last != 0 && TREE_CODE (last) != INTEGER_CST) - error_init ("nonconstant array index in initializer"); - else if (TREE_CODE (constructor_type) != ARRAY_TYPE) - error_init ("array index in non-array initializer"); - else if (constructor_max_index - && tree_int_cst_lt (constructor_max_index, first)) - error_init ("array index in initializer exceeds array bounds"); - else - { - constructor_index = convert (bitsizetype, first); +static void +output_pending_init_elements (int all) +{ + struct init_node *elt = constructor_pending_elts; + tree next; - if (last) + retry: + + /* Look thru the whole pending tree. + If we find an element that should be output now, + output it. Otherwise, set NEXT to the element + that comes first among those still pending. */ + + next = 0; + while (elt) + { + if (TREE_CODE (constructor_type) == ARRAY_TYPE) { - if (tree_int_cst_equal (first, last)) - last = 0; - else if (tree_int_cst_lt (last, first)) + if (tree_int_cst_equal (elt->purpose, + constructor_unfilled_index)) + output_init_element (elt->value, + TREE_TYPE (constructor_type), + constructor_unfilled_index, 0); + else if (tree_int_cst_lt (constructor_unfilled_index, + elt->purpose)) { - error_init ("empty index range in initializer"); - last = 0; + /* Advance to the next smaller node. */ + if (elt->left) + elt = elt->left; + else + { + /* We have reached the smallest node bigger than the + current unfilled index. Fill the space first. */ + next = elt->purpose; + break; + } } else { - last = convert (bitsizetype, last); - if (constructor_max_index != 0 - && tree_int_cst_lt (constructor_max_index, last)) + /* Advance to the next bigger node. */ + if (elt->right) + elt = elt->right; + else { - error_init ("array index range in initializer exceeds array bounds"); - last = 0; + /* We have reached the biggest node in a subtree. Find + the parent of it, which is the next bigger node. */ + while (elt->parent && elt->parent->right == elt) + elt = elt->parent; + elt = elt->parent; + if (elt && tree_int_cst_lt (constructor_unfilled_index, + elt->purpose)) + { + next = elt->purpose; + break; + } } } } + else if (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + { + tree ctor_unfilled_bitpos, elt_bitpos; - designator_depth++; - designator_errorneous = 0; - if (constructor_range_stack || last) - push_range_stack (last); - } -} - -/* Within a struct initializer, specify the next field to be initialized. */ + /* If the current record is complete we are done. */ + if (constructor_unfilled_fields == 0) + break; -void -set_init_label (tree fieldname) -{ - tree tail; + ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields); + elt_bitpos = bit_position (elt->purpose); + /* We can't compare fields here because there might be empty + fields in between. */ + if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) + { + constructor_unfilled_fields = elt->purpose; + output_init_element (elt->value, TREE_TYPE (elt->purpose), + elt->purpose, 0); + } + else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) + { + /* Advance to the next smaller node. */ + if (elt->left) + elt = elt->left; + else + { + /* We have reached the smallest node bigger than the + current unfilled field. Fill the space first. */ + next = elt->purpose; + break; + } + } + else + { + /* Advance to the next bigger node. */ + if (elt->right) + elt = elt->right; + else + { + /* We have reached the biggest node in a subtree. Find + the parent of it, which is the next bigger node. */ + while (elt->parent && elt->parent->right == elt) + elt = elt->parent; + elt = elt->parent; + if (elt + && (tree_int_cst_lt (ctor_unfilled_bitpos, + bit_position (elt->purpose)))) + { + next = elt->purpose; + break; + } + } + } + } + } - if (set_designator (0)) + /* Ordinarily return, but not if we want to output all + and there are elements left. */ + if (! (all && next != 0)) return; - designator_errorneous = 1; - - if (TREE_CODE (constructor_type) != RECORD_TYPE - && TREE_CODE (constructor_type) != UNION_TYPE) - { - error_init ("field name not in record or union initializer"); - return; - } - - for (tail = TYPE_FIELDS (constructor_type); tail; - tail = TREE_CHAIN (tail)) - { - if (DECL_NAME (tail) == fieldname) - break; - } + /* If it's not incremental, just skip over the gap, so that after + jumping to retry we will output the next successive element. */ + if (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + constructor_unfilled_fields = next; + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + constructor_unfilled_index = next; - if (tail == 0) - error ("unknown field `%s' specified in initializer", - IDENTIFIER_POINTER (fieldname)); - else - { - constructor_fields = tail; - designator_depth++; - designator_errorneous = 0; - if (constructor_range_stack) - push_range_stack (NULL_TREE); - } + /* ELT now points to the node in the pending tree with the next + initializer to output. */ + goto retry; } -/* Add a new initializer to the tree of pending initializers. PURPOSE - identifies the initializer, either array index or field in a structure. - VALUE is the value of that index or field. */ +/* Add one non-braced element to the current constructor level. + This adjusts the current position within the constructor's type. + This may also start or terminate implicit levels + to handle a partly-braced initializer. -static void -add_pending_init (tree purpose, tree value) + Once this has found the correct level for the new element, + it calls output_init_element. */ + +void +process_init_element (tree value) { - struct init_node *p, **q, *r; + tree orig_value = value; + int string_flag = value != 0 && TREE_CODE (value) == STRING_CST; - q = &constructor_pending_elts; - p = 0; + designator_depth = 0; + designator_errorneous = 0; - if (TREE_CODE (constructor_type) == ARRAY_TYPE) + /* Handle superfluous braces around string cst as in + char x[] = {"foo"}; */ + if (string_flag + && constructor_type + && TREE_CODE (constructor_type) == ARRAY_TYPE + && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE + && integer_zerop (constructor_unfilled_index)) { - while (*q != 0) - { - p = *q; - if (tree_int_cst_lt (purpose, p->purpose)) - q = &p->left; - else if (tree_int_cst_lt (p->purpose, purpose)) - q = &p->right; - else - { - if (TREE_SIDE_EFFECTS (p->value)) - warning_init ("initialized field with side-effects overwritten"); - p->value = value; - return; - } - } + if (constructor_stack->replacement_value) + error_init ("excess elements in char array initializer"); + constructor_stack->replacement_value = value; + return; } - else - { - tree bitpos; - bitpos = bit_position (purpose); - while (*q != NULL) - { - p = *q; - if (tree_int_cst_lt (bitpos, bit_position (p->purpose))) - q = &p->left; - else if (p->purpose != purpose) - q = &p->right; - else - { - if (TREE_SIDE_EFFECTS (p->value)) - warning_init ("initialized field with side-effects overwritten"); - p->value = value; - return; - } - } + if (constructor_stack->replacement_value != 0) + { + error_init ("excess elements in struct initializer"); + return; } - r = (struct init_node *) ggc_alloc (sizeof (struct init_node)); - r->purpose = purpose; - r->value = value; + /* Ignore elements of a brace group if it is entirely superfluous + and has already been diagnosed. */ + if (constructor_type == 0) + return; - *q = r; - r->parent = p; - r->left = 0; - r->right = 0; - r->balance = 0; + /* If we've exhausted any levels that didn't have braces, + pop them now. */ + while (constructor_stack->implicit) + { + if ((TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields == 0) + process_init_element (pop_init_level (1)); + else if (TREE_CODE (constructor_type) == ARRAY_TYPE + && (constructor_max_index == 0 + || tree_int_cst_lt (constructor_max_index, + constructor_index))) + process_init_element (pop_init_level (1)); + else + break; + } - while (p) + /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */ + if (constructor_range_stack) { - struct init_node *s; + /* If value is a compound literal and we'll be just using its + content, don't put it into a SAVE_EXPR. */ + if (TREE_CODE (value) != COMPOUND_LITERAL_EXPR + || !require_constant_value + || flag_isoc99) + value = save_expr (value); + } - if (r == p->left) + while (1) + { + if (TREE_CODE (constructor_type) == RECORD_TYPE) { - if (p->balance == 0) - p->balance = -1; - else if (p->balance < 0) - { - if (r->balance < 0) - { - /* L rotation. */ - p->left = r->right; - if (p->left) - p->left->parent = p; - r->right = p; - - p->balance = 0; - r->balance = 0; + tree fieldtype; + enum tree_code fieldcode; - s = p->parent; - p->parent = r; - r->parent = s; - if (s) - { - if (s->left == p) - s->left = r; - else - s->right = r; - } - else - constructor_pending_elts = r; - } - else - { - /* LR rotation. */ - struct init_node *t = r->right; + if (constructor_fields == 0) + { + pedwarn_init ("excess elements in struct initializer"); + break; + } - r->right = t->left; - if (r->right) - r->right->parent = r; - t->left = r; + fieldtype = TREE_TYPE (constructor_fields); + if (fieldtype != error_mark_node) + fieldtype = TYPE_MAIN_VARIANT (fieldtype); + fieldcode = TREE_CODE (fieldtype); - p->left = t->right; - if (p->left) - p->left->parent = p; - t->right = p; + /* Error for non-static initialization of a flexible array member. */ + if (fieldcode == ARRAY_TYPE + && !require_constant_value + && TYPE_SIZE (fieldtype) == NULL_TREE + && TREE_CHAIN (constructor_fields) == NULL_TREE) + { + error_init ("non-static initialization of a flexible array member"); + break; + } - p->balance = t->balance < 0; - r->balance = -(t->balance > 0); - t->balance = 0; + /* Accept a string constant to initialize a subarray. */ + if (value != 0 + && fieldcode == ARRAY_TYPE + && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE + && string_flag) + value = orig_value; + /* Otherwise, if we have come to a subaggregate, + and we don't have an element of its type, push into it. */ + else if (value != 0 && !constructor_no_implicit + && value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype + && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE + || fieldcode == UNION_TYPE)) + { + push_init_level (1); + continue; + } - s = p->parent; - p->parent = t; - r->parent = t; - t->parent = s; - if (s) - { - if (s->left == p) - s->left = t; - else - s->right = t; - } - else - constructor_pending_elts = t; - } - break; + if (value) + { + push_member_name (constructor_fields); + output_init_element (value, fieldtype, constructor_fields, 1); + RESTORE_SPELLING_DEPTH (constructor_depth); } else + /* Do the bookkeeping for an element that was + directly output as a constructor. */ { - /* p->balance == +1; growth of left side balances the node. */ - p->balance = 0; - break; + /* For a record, keep track of end position of last field. */ + if (DECL_SIZE (constructor_fields)) + constructor_bit_index + = size_binop (PLUS_EXPR, + bit_position (constructor_fields), + DECL_SIZE (constructor_fields)); + + /* If the current field was the first one not yet written out, + it isn't now, so update. */ + if (constructor_unfilled_fields == constructor_fields) + { + constructor_unfilled_fields = TREE_CHAIN (constructor_fields); + /* Skip any nameless bit fields. */ + while (constructor_unfilled_fields != 0 + && DECL_C_BIT_FIELD (constructor_unfilled_fields) + && DECL_NAME (constructor_unfilled_fields) == 0) + constructor_unfilled_fields = + TREE_CHAIN (constructor_unfilled_fields); + } } + + constructor_fields = TREE_CHAIN (constructor_fields); + /* Skip any nameless bit fields at the beginning. */ + while (constructor_fields != 0 + && DECL_C_BIT_FIELD (constructor_fields) + && DECL_NAME (constructor_fields) == 0) + constructor_fields = TREE_CHAIN (constructor_fields); } - else /* r == p->right */ + else if (TREE_CODE (constructor_type) == UNION_TYPE) { - if (p->balance == 0) - /* Growth propagation from right side. */ - p->balance++; - else if (p->balance > 0) - { - if (r->balance > 0) - { - /* R rotation. */ - p->right = r->left; - if (p->right) - p->right->parent = p; - r->left = p; - - p->balance = 0; - r->balance = 0; + tree fieldtype; + enum tree_code fieldcode; - s = p->parent; - p->parent = r; - r->parent = s; - if (s) - { - if (s->left == p) - s->left = r; - else - s->right = r; - } - else - constructor_pending_elts = r; - } - else /* r->balance == -1 */ - { - /* RL rotation */ - struct init_node *t = r->left; + if (constructor_fields == 0) + { + pedwarn_init ("excess elements in union initializer"); + break; + } - r->left = t->right; - if (r->left) - r->left->parent = r; - t->right = r; + fieldtype = TREE_TYPE (constructor_fields); + if (fieldtype != error_mark_node) + fieldtype = TYPE_MAIN_VARIANT (fieldtype); + fieldcode = TREE_CODE (fieldtype); - p->right = t->left; - if (p->right) - p->right->parent = p; - t->left = p; + /* Warn that traditional C rejects initialization of unions. + We skip the warning if the value is zero. This is done + under the assumption that the zero initializer in user + code appears conditioned on e.g. __STDC__ to avoid + "missing initializer" warnings and relies on default + initialization to zero in the traditional C case. + We also skip the warning if the initializer is designated, + again on the assumption that this must be conditional on + __STDC__ anyway (and we've already complained about the + member-designator already). */ + if (warn_traditional && !in_system_header && !constructor_designated + && !(value && (integer_zerop (value) || real_zerop (value)))) + warning ("traditional C rejects initialization of unions"); - r->balance = (t->balance < 0); - p->balance = -(t->balance > 0); - t->balance = 0; + /* Accept a string constant to initialize a subarray. */ + if (value != 0 + && fieldcode == ARRAY_TYPE + && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE + && string_flag) + value = orig_value; + /* Otherwise, if we have come to a subaggregate, + and we don't have an element of its type, push into it. */ + else if (value != 0 && !constructor_no_implicit + && value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype + && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE + || fieldcode == UNION_TYPE)) + { + push_init_level (1); + continue; + } - s = p->parent; - p->parent = t; - r->parent = t; - t->parent = s; - if (s) - { - if (s->left == p) - s->left = t; - else - s->right = t; - } - else - constructor_pending_elts = t; - } - break; + if (value) + { + push_member_name (constructor_fields); + output_init_element (value, fieldtype, constructor_fields, 1); + RESTORE_SPELLING_DEPTH (constructor_depth); } else + /* Do the bookkeeping for an element that was + directly output as a constructor. */ { - /* p->balance == -1; growth of right side balances the node. */ - p->balance = 0; - break; + constructor_bit_index = DECL_SIZE (constructor_fields); + constructor_unfilled_fields = TREE_CHAIN (constructor_fields); } - } - - r = p; - p = p->parent; - } -} -/* Build AVL tree from a sorted chain. */ + constructor_fields = 0; + } + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); + enum tree_code eltcode = TREE_CODE (elttype); -static void -set_nonincremental_init (void) -{ - tree chain; + /* Accept a string constant to initialize a subarray. */ + if (value != 0 + && eltcode == ARRAY_TYPE + && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE + && string_flag) + value = orig_value; + /* Otherwise, if we have come to a subaggregate, + and we don't have an element of its type, push into it. */ + else if (value != 0 && !constructor_no_implicit + && value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype + && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE + || eltcode == UNION_TYPE)) + { + push_init_level (1); + continue; + } - if (TREE_CODE (constructor_type) != RECORD_TYPE - && TREE_CODE (constructor_type) != ARRAY_TYPE) - return; + if (constructor_max_index != 0 + && (tree_int_cst_lt (constructor_max_index, constructor_index) + || integer_all_onesp (constructor_max_index))) + { + pedwarn_init ("excess elements in array initializer"); + break; + } - for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain)) - add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain)); - constructor_elements = 0; - if (TREE_CODE (constructor_type) == RECORD_TYPE) - { - constructor_unfilled_fields = TYPE_FIELDS (constructor_type); - /* Skip any nameless bit fields at the beginning. */ - while (constructor_unfilled_fields != 0 - && DECL_C_BIT_FIELD (constructor_unfilled_fields) - && DECL_NAME (constructor_unfilled_fields) == 0) - constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); + /* Now output the actual element. */ + if (value) + { + push_array_bounds (tree_low_cst (constructor_index, 0)); + output_init_element (value, elttype, constructor_index, 1); + RESTORE_SPELLING_DEPTH (constructor_depth); + } - } - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - if (TYPE_DOMAIN (constructor_type)) - constructor_unfilled_index - = convert (bitsizetype, - TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); - else - constructor_unfilled_index = bitsize_zero_node; - } - constructor_incremental = 0; -} + constructor_index + = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); -/* Build AVL tree from a string constant. */ + if (! value) + /* If we are doing the bookkeeping for an element that was + directly output as a constructor, we must update + constructor_unfilled_index. */ + constructor_unfilled_index = constructor_index; + } + else if (TREE_CODE (constructor_type) == VECTOR_TYPE) + { + tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); -static void -set_nonincremental_init_from_string (tree str) -{ - tree value, purpose, type; - HOST_WIDE_INT val[2]; - const char *p, *end; - int byte, wchar_bytes, charwidth, bitpos; + /* Do a basic check of initializer size. Note that vectors + always have a fixed size derived from their type. */ + if (tree_int_cst_lt (constructor_max_index, constructor_index)) + { + pedwarn_init ("excess elements in vector initializer"); + break; + } - if (TREE_CODE (constructor_type) != ARRAY_TYPE) - abort (); + /* Now output the actual element. */ + if (value) + output_init_element (value, elttype, constructor_index, 1); - if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) - == TYPE_PRECISION (char_type_node)) - wchar_bytes = 1; - else if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) - == TYPE_PRECISION (wchar_type_node)) - wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; - else - abort (); + constructor_index + = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); - charwidth = TYPE_PRECISION (char_type_node); - type = TREE_TYPE (constructor_type); - p = TREE_STRING_POINTER (str); - end = p + TREE_STRING_LENGTH (str); + if (! value) + /* If we are doing the bookkeeping for an element that was + directly output as a constructor, we must update + constructor_unfilled_index. */ + constructor_unfilled_index = constructor_index; + } - for (purpose = bitsize_zero_node; - p < end && !tree_int_cst_lt (constructor_max_index, purpose); - purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node)) - { - if (wchar_bytes == 1) + /* Handle the sole element allowed in a braced initializer + for a scalar variable. */ + else if (constructor_fields == 0) { - val[1] = (unsigned char) *p++; - val[0] = 0; + pedwarn_init ("excess elements in scalar initializer"); + break; } else { - val[0] = 0; - val[1] = 0; - for (byte = 0; byte < wchar_bytes; byte++) - { - if (BYTES_BIG_ENDIAN) - bitpos = (wchar_bytes - byte - 1) * charwidth; - else - bitpos = byte * charwidth; - val[bitpos < HOST_BITS_PER_WIDE_INT] - |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++)) - << (bitpos % HOST_BITS_PER_WIDE_INT); - } + if (value) + output_init_element (value, constructor_type, NULL_TREE, 1); + constructor_fields = 0; } - if (!TREE_UNSIGNED (type)) + /* Handle range initializers either at this level or anywhere higher + in the designator stack. */ + if (constructor_range_stack) { - bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR; - if (bitpos < HOST_BITS_PER_WIDE_INT) + struct constructor_range_stack *p, *range_stack; + int finish = 0; + + range_stack = constructor_range_stack; + constructor_range_stack = 0; + while (constructor_stack != range_stack->stack) { - if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1))) - { - val[1] |= ((HOST_WIDE_INT) -1) << bitpos; - val[0] = -1; - } + if (!constructor_stack->implicit) + abort (); + process_init_element (pop_init_level (1)); } - else if (bitpos == HOST_BITS_PER_WIDE_INT) + for (p = range_stack; + !p->range_end || tree_int_cst_equal (p->index, p->range_end); + p = p->prev) { - if (val[1] < 0) - val[0] = -1; + if (!constructor_stack->implicit) + abort (); + process_init_element (pop_init_level (1)); } - else if (val[0] & (((HOST_WIDE_INT) 1) - << (bitpos - 1 - HOST_BITS_PER_WIDE_INT))) - val[0] |= ((HOST_WIDE_INT) -1) - << (bitpos - HOST_BITS_PER_WIDE_INT); + + p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node); + if (tree_int_cst_equal (p->index, p->range_end) && !p->prev) + finish = 1; + + while (1) + { + constructor_index = p->index; + constructor_fields = p->fields; + if (finish && p->range_end && p->index == p->range_start) + { + finish = 0; + p->prev = 0; + } + p = p->next; + if (!p) + break; + push_init_level (2); + p->stack = constructor_stack; + if (p->range_end && tree_int_cst_equal (p->index, p->range_end)) + p->index = p->range_start; + } + + if (!finish) + constructor_range_stack = range_stack; + continue; } - value = build_int_2 (val[1], val[0]); - TREE_TYPE (value) = type; - add_pending_init (purpose, value); + break; } - constructor_incremental = 0; + constructor_range_stack = 0; +} + +/* Build a simple asm-statement, from one string literal. */ +tree +simple_asm_stmt (tree expr) +{ + STRIP_NOPS (expr); + + if (TREE_CODE (expr) == ADDR_EXPR) + expr = TREE_OPERAND (expr, 0); + + if (TREE_CODE (expr) == STRING_CST) + { + tree stmt; + + /* Simple asm statements are treated as volatile. */ + stmt = add_stmt (build_stmt (ASM_STMT, ridpointers[(int) RID_VOLATILE], + expr, NULL_TREE, NULL_TREE, NULL_TREE)); + ASM_INPUT_P (stmt) = 1; + return stmt; + } + + error ("argument of `asm' is not a constant string"); + return NULL_TREE; } -/* Return value of FIELD in pending initializer or zero if the field was - not initialized yet. */ +/* Build an asm-statement, whose components are a CV_QUALIFIER, a + STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */ -static tree -find_init_member (tree field) +tree +build_asm_stmt (tree cv_qualifier, tree string, tree outputs, tree inputs, + tree clobbers) { - struct init_node *p; + tree tail; - if (TREE_CODE (constructor_type) == ARRAY_TYPE) + if (TREE_CODE (string) != STRING_CST) { - if (constructor_incremental - && tree_int_cst_lt (field, constructor_unfilled_index)) - set_nonincremental_init (); + error ("asm template is not a string constant"); + return NULL_TREE; + } - p = constructor_pending_elts; - while (p) - { - if (tree_int_cst_lt (field, p->purpose)) - p = p->left; - else if (tree_int_cst_lt (p->purpose, field)) - p = p->right; - else - return p->value; - } + if (cv_qualifier != NULL_TREE + && cv_qualifier != ridpointers[(int) RID_VOLATILE]) + { + warning ("%s qualifier ignored on asm", + IDENTIFIER_POINTER (cv_qualifier)); + cv_qualifier = NULL_TREE; } - else if (TREE_CODE (constructor_type) == RECORD_TYPE) + + /* We can remove output conversions that change the type, + but not the mode. */ + for (tail = outputs; tail; tail = TREE_CHAIN (tail)) { - tree bitpos = bit_position (field); + tree output = TREE_VALUE (tail); - if (constructor_incremental - && (!constructor_unfilled_fields - || tree_int_cst_lt (bitpos, - bit_position (constructor_unfilled_fields)))) - set_nonincremental_init (); + STRIP_NOPS (output); + TREE_VALUE (tail) = output; - p = constructor_pending_elts; - while (p) - { - if (field == p->purpose) - return p->value; - else if (tree_int_cst_lt (bitpos, bit_position (p->purpose))) - p = p->left; - else - p = p->right; - } + /* Allow conversions as LHS here. build_modify_expr as called below + will do the right thing with them. */ + while (TREE_CODE (output) == NOP_EXPR + || TREE_CODE (output) == CONVERT_EXPR + || TREE_CODE (output) == FLOAT_EXPR + || TREE_CODE (output) == FIX_TRUNC_EXPR + || TREE_CODE (output) == FIX_FLOOR_EXPR + || TREE_CODE (output) == FIX_ROUND_EXPR + || TREE_CODE (output) == FIX_CEIL_EXPR) + output = TREE_OPERAND (output, 0); + + lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement"); } - else if (TREE_CODE (constructor_type) == UNION_TYPE) + + /* Remove output conversions that change the type but not the mode. */ + for (tail = outputs; tail; tail = TREE_CHAIN (tail)) { - if (constructor_elements - && TREE_PURPOSE (constructor_elements) == field) - return TREE_VALUE (constructor_elements); + tree output = TREE_VALUE (tail); + STRIP_NOPS (output); + TREE_VALUE (tail) = output; } - return 0; + + /* Perform default conversions on array and function inputs. + Don't do this for other types as it would screw up operands + expected to be in memory. */ + for (tail = inputs; tail; tail = TREE_CHAIN (tail)) + TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail)); + + return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string, + outputs, inputs, clobbers)); } -/* "Output" the next constructor element. - At top level, really output it to assembler code now. - Otherwise, collect it in a list from which we will make a CONSTRUCTOR. - TYPE is the data type that the containing data type wants here. - FIELD is the field (a FIELD_DECL) or the index that this element fills. +/* Expand an ASM statement with operands, handling output operands + that are not variables or INDIRECT_REFS by transforming such + cases into cases that expand_asm_operands can handle. - PENDING if non-nil means output pending elements that belong - right after this element. (PENDING is normally 1; - it is 0 while outputting pending elements, to avoid recursion.) */ + Arguments are same as for expand_asm_operands. */ -static void -output_init_element (tree value, tree type, tree field, int pending) +void +c_expand_asm_operands (tree string, tree outputs, tree inputs, + tree clobbers, int vol, const char *filename, + int line) { - if (type == error_mark_node) - { - constructor_erroneous = 1; - return; - } - if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE - || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE - && !(TREE_CODE (value) == STRING_CST - && TREE_CODE (type) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE) - && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)), - TYPE_MAIN_VARIANT (type), COMPARE_STRICT))) - value = default_conversion (value); + int noutputs = list_length (outputs); + int i; + /* o[I] is the place that output number I should be written. */ + tree *o = (tree *) alloca (noutputs * sizeof (tree)); + tree tail; - if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR - && require_constant_value && !flag_isoc99 && pending) + /* Record the contents of OUTPUTS before it is modified. */ + for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) { - /* As an extension, allow initializing objects with static storage - duration with compound literals (which are then treated just as - the brace enclosed list they contain). */ - tree decl = COMPOUND_LITERAL_EXPR_DECL (value); - value = DECL_INITIAL (decl); + o[i] = TREE_VALUE (tail); + if (o[i] == error_mark_node) + return; } - if (value == error_mark_node) - constructor_erroneous = 1; - else if (!TREE_CONSTANT (value)) - constructor_constant = 0; - else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0 - || ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && DECL_C_BIT_FIELD (field) - && TREE_CODE (value) != INTEGER_CST)) - constructor_simple = 0; + /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of + OUTPUTS some trees for where the values were actually stored. */ + expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line); - if (require_constant_value && ! TREE_CONSTANT (value)) + /* Copy all the intermediate outputs into the specified outputs. */ + for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) { - error_init ("initializer element is not constant"); - value = error_mark_node; + if (o[i] != TREE_VALUE (tail)) + { + expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)), + NULL_RTX, VOIDmode, EXPAND_NORMAL); + free_temp_slots (); + + /* Restore the original value so that it's correct the next + time we expand this function. */ + TREE_VALUE (tail) = o[i]; + } + /* Detect modification of read-only values. + (Otherwise done by build_modify_expr.) */ + else + { + tree type = TREE_TYPE (o[i]); + if (TREE_READONLY (o[i]) + || TYPE_READONLY (type) + || ((TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE) + && C_TYPE_FIELDS_READONLY (type))) + readonly_warning (o[i], "modification by `asm'"); + } } - else if (require_constant_elements - && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0) - pedwarn ("initializer element is not computable at load time"); - /* If this field is empty (and not at the end of structure), - don't do anything other than checking the initializer. */ - if (field - && (TREE_TYPE (field) == error_mark_node - || (COMPLETE_TYPE_P (TREE_TYPE (field)) - && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) - && (TREE_CODE (constructor_type) == ARRAY_TYPE - || TREE_CHAIN (field))))) - return; + /* Those MODIFY_EXPRs could do autoincrements. */ + emit_queue (); +} + +/* Expand a C `return' statement. + RETVAL is the expression for what to return, + or a null pointer for `return;' with no value. */ - value = digest_init (type, value, require_constant_value); - if (value == error_mark_node) +tree +c_expand_return (tree retval) +{ + tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); + + if (TREE_THIS_VOLATILE (current_function_decl)) + warning ("function declared `noreturn' has a `return' statement"); + + if (!retval) { - constructor_erroneous = 1; - return; + current_function_returns_null = 1; + if ((warn_return_type || flag_isoc99) + && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE) + pedwarn_c99 ("`return' with no value, in function returning non-void"); } - - /* If this element doesn't come next in sequence, - put it on constructor_pending_elts. */ - if (TREE_CODE (constructor_type) == ARRAY_TYPE - && (!constructor_incremental - || !tree_int_cst_equal (field, constructor_unfilled_index))) + else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) { - if (constructor_incremental - && tree_int_cst_lt (field, constructor_unfilled_index)) - set_nonincremental_init (); - - add_pending_init (field, value); - return; + current_function_returns_null = 1; + if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) + pedwarn ("`return' with a value, in function returning void"); } - else if (TREE_CODE (constructor_type) == RECORD_TYPE - && (!constructor_incremental - || field != constructor_unfilled_fields)) + else { - /* We do this for records but not for unions. In a union, - no matter which field is specified, it can be initialized - right away since it starts at the beginning of the union. */ - if (constructor_incremental) + tree t = convert_for_assignment (valtype, retval, _("return"), + NULL_TREE, NULL_TREE, 0); + tree res = DECL_RESULT (current_function_decl); + tree inner; + + current_function_returns_value = 1; + if (t == error_mark_node) + return NULL_TREE; + + inner = t = convert (TREE_TYPE (res), t); + + /* Strip any conversions, additions, and subtractions, and see if + we are returning the address of a local variable. Warn if so. */ + while (1) { - if (!constructor_unfilled_fields) - set_nonincremental_init (); - else + switch (TREE_CODE (inner)) { - tree bitpos, unfillpos; + case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR: + case PLUS_EXPR: + inner = TREE_OPERAND (inner, 0); + continue; + + case MINUS_EXPR: + /* If the second operand of the MINUS_EXPR has a pointer + type (or is converted from it), this may be valid, so + don't give a warning. */ + { + tree op1 = TREE_OPERAND (inner, 1); - bitpos = bit_position (field); - unfillpos = bit_position (constructor_unfilled_fields); + while (! POINTER_TYPE_P (TREE_TYPE (op1)) + && (TREE_CODE (op1) == NOP_EXPR + || TREE_CODE (op1) == NON_LVALUE_EXPR + || TREE_CODE (op1) == CONVERT_EXPR)) + op1 = TREE_OPERAND (op1, 0); - if (tree_int_cst_lt (bitpos, unfillpos)) - set_nonincremental_init (); - } - } + if (POINTER_TYPE_P (TREE_TYPE (op1))) + break; - add_pending_init (field, value); - return; - } - else if (TREE_CODE (constructor_type) == UNION_TYPE - && constructor_elements) - { - if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements))) - warning_init ("initialized field with side-effects overwritten"); + inner = TREE_OPERAND (inner, 0); + continue; + } - /* We can have just one union field set. */ - constructor_elements = 0; - } + case ADDR_EXPR: + inner = TREE_OPERAND (inner, 0); - /* Otherwise, output this element either to - constructor_elements or to the assembler file. */ + while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r') + inner = TREE_OPERAND (inner, 0); - if (field && TREE_CODE (field) == INTEGER_CST) - field = copy_node (field); - constructor_elements - = tree_cons (field, value, constructor_elements); + if (TREE_CODE (inner) == VAR_DECL + && ! DECL_EXTERNAL (inner) + && ! TREE_STATIC (inner) + && DECL_CONTEXT (inner) == current_function_decl) + warning ("function returns address of local variable"); + break; - /* Advance the variable that indicates sequential elements output. */ - if (TREE_CODE (constructor_type) == ARRAY_TYPE) - constructor_unfilled_index - = size_binop (PLUS_EXPR, constructor_unfilled_index, - bitsize_one_node); - else if (TREE_CODE (constructor_type) == RECORD_TYPE) - { - constructor_unfilled_fields - = TREE_CHAIN (constructor_unfilled_fields); + default: + break; + } - /* Skip any nameless bit fields. */ - while (constructor_unfilled_fields != 0 - && DECL_C_BIT_FIELD (constructor_unfilled_fields) - && DECL_NAME (constructor_unfilled_fields) == 0) - constructor_unfilled_fields = - TREE_CHAIN (constructor_unfilled_fields); + break; + } + + retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t); } - else if (TREE_CODE (constructor_type) == UNION_TYPE) - constructor_unfilled_fields = 0; - /* Now output any pending elements which have become next. */ - if (pending) - output_pending_init_elements (0); + return add_stmt (build_return_stmt (retval)); } + +struct c_switch { + /* The SWITCH_STMT being built. */ + tree switch_stmt; + /* A splay-tree mapping the low element of a case range to the high + element, or NULL_TREE if there is no high element. Used to + determine whether or not a new case label duplicates an old case + label. We need a tree, rather than simply a hash table, because + of the GNU case range extension. */ + splay_tree cases; + /* The next node on the stack. */ + struct c_switch *next; +}; -/* Output any pending elements which have become next. - As we output elements, constructor_unfilled_{fields,index} - advances, which may cause other elements to become next; - if so, they too are output. +/* A stack of the currently active switch statements. The innermost + switch statement is on the top of the stack. There is no need to + mark the stack for garbage collection because it is only active + during the processing of the body of a function, and we never + collect at that point. */ - If ALL is 0, we return when there are - no more pending elements to output now. +static struct c_switch *switch_stack; - If ALL is 1, we output space as necessary so that - we can output all the pending elements. */ +/* Start a C switch statement, testing expression EXP. Return the new + SWITCH_STMT. */ -static void -output_pending_init_elements (int all) +tree +c_start_case (tree exp) { - struct init_node *elt = constructor_pending_elts; - tree next; - - retry: - - /* Look thru the whole pending tree. - If we find an element that should be output now, - output it. Otherwise, set NEXT to the element - that comes first among those still pending. */ + enum tree_code code; + tree type, orig_type = error_mark_node; + struct c_switch *cs; - next = 0; - while (elt) + if (exp != error_mark_node) { - if (TREE_CODE (constructor_type) == ARRAY_TYPE) + code = TREE_CODE (TREE_TYPE (exp)); + orig_type = TREE_TYPE (exp); + + if (! INTEGRAL_TYPE_P (orig_type) + && code != ERROR_MARK) { - if (tree_int_cst_equal (elt->purpose, - constructor_unfilled_index)) - output_init_element (elt->value, - TREE_TYPE (constructor_type), - constructor_unfilled_index, 0); - else if (tree_int_cst_lt (constructor_unfilled_index, - elt->purpose)) - { - /* Advance to the next smaller node. */ - if (elt->left) - elt = elt->left; - else - { - /* We have reached the smallest node bigger than the - current unfilled index. Fill the space first. */ - next = elt->purpose; - break; - } - } - else - { - /* Advance to the next bigger node. */ - if (elt->right) - elt = elt->right; - else - { - /* We have reached the biggest node in a subtree. Find - the parent of it, which is the next bigger node. */ - while (elt->parent && elt->parent->right == elt) - elt = elt->parent; - elt = elt->parent; - if (elt && tree_int_cst_lt (constructor_unfilled_index, - elt->purpose)) - { - next = elt->purpose; - break; - } - } - } + error ("switch quantity not an integer"); + exp = integer_zero_node; } - else if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) + else { - tree ctor_unfilled_bitpos, elt_bitpos; + type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); - /* If the current record is complete we are done. */ - if (constructor_unfilled_fields == 0) - break; + if (warn_traditional && !in_system_header + && (type == long_integer_type_node + || type == long_unsigned_type_node)) + warning ("`long' switch expression not converted to `int' in ISO C"); - ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields); - elt_bitpos = bit_position (elt->purpose); - /* We can't compare fields here because there might be empty - fields in between. */ - if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) - { - constructor_unfilled_fields = elt->purpose; - output_init_element (elt->value, TREE_TYPE (elt->purpose), - elt->purpose, 0); - } - else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) - { - /* Advance to the next smaller node. */ - if (elt->left) - elt = elt->left; - else - { - /* We have reached the smallest node bigger than the - current unfilled field. Fill the space first. */ - next = elt->purpose; - break; - } - } - else - { - /* Advance to the next bigger node. */ - if (elt->right) - elt = elt->right; - else - { - /* We have reached the biggest node in a subtree. Find - the parent of it, which is the next bigger node. */ - while (elt->parent && elt->parent->right == elt) - elt = elt->parent; - elt = elt->parent; - if (elt - && (tree_int_cst_lt (ctor_unfilled_bitpos, - bit_position (elt->purpose)))) - { - next = elt->purpose; - break; - } - } - } + exp = default_conversion (exp); + type = TREE_TYPE (exp); + } + } + + /* Add this new SWITCH_STMT to the stack. */ + cs = (struct c_switch *) xmalloc (sizeof (*cs)); + cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type); + cs->cases = splay_tree_new (case_compare, NULL, NULL); + cs->next = switch_stack; + switch_stack = cs; + + return add_stmt (switch_stack->switch_stmt); +} + +/* Process a case label. */ + +tree +do_case (tree low_value, tree high_value) +{ + tree label = NULL_TREE; + + if (switch_stack) + { + bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE); + + label = c_add_case_label (switch_stack->cases, + SWITCH_COND (switch_stack->switch_stmt), + low_value, high_value); + if (label == error_mark_node) + label = NULL_TREE; + else if (switch_was_empty_p) + { + /* Attach the first case label to the SWITCH_BODY. */ + SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt); + TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE; } } + else if (low_value) + error ("case label not within a switch statement"); + else + error ("`default' label not within a switch statement"); - /* Ordinarily return, but not if we want to output all - and there are elements left. */ - if (! (all && next != 0)) - return; + return label; +} - /* If it's not incremental, just skip over the gap, so that after - jumping to retry we will output the next successive element. */ - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - constructor_unfilled_fields = next; - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - constructor_unfilled_index = next; +/* Finish the switch statement. */ - /* ELT now points to the node in the pending tree with the next - initializer to output. */ - goto retry; +void +c_finish_case (void) +{ + struct c_switch *cs = switch_stack; + + /* Rechain the next statements to the SWITCH_STMT. */ + last_tree = cs->switch_stmt; + + /* Pop the stack. */ + switch_stack = switch_stack->next; + splay_tree_delete (cs->cases); + free (cs); } - -/* Add one non-braced element to the current constructor level. - This adjusts the current position within the constructor's type. - This may also start or terminate implicit levels - to handle a partly-braced initializer. - Once this has found the correct level for the new element, - it calls output_init_element. */ +/* Build a binary-operation expression without default conversions. + CODE is the kind of expression to build. + This function differs from `build' in several ways: + the data type of the result is computed and recorded in it, + warnings are generated if arg data types are invalid, + special handling for addition and subtraction of pointers is known, + and some optimization is done (operations on narrow ints + are done in the narrower type when that gives the same result). + Constant folding is also done before the result is returned. -void -process_init_element (tree value) + Note that the operands will never have enumeral types, or function + or array types, because either they will have the default conversions + performed or they have both just been converted to some other type in which + the arithmetic is to be done. */ + +tree +build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, + int convert_p) { - tree orig_value = value; - int string_flag = value != 0 && TREE_CODE (value) == STRING_CST; + tree type0, type1; + enum tree_code code0, code1; + tree op0, op1; - designator_depth = 0; - designator_errorneous = 0; + /* Expression code to give to the expression when it is built. + Normally this is CODE, which is what the caller asked for, + but in some special cases we change it. */ + enum tree_code resultcode = code; - /* Handle superfluous braces around string cst as in - char x[] = {"foo"}; */ - if (string_flag - && constructor_type - && TREE_CODE (constructor_type) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE - && integer_zerop (constructor_unfilled_index)) + /* Data type in which the computation is to be performed. + In the simplest cases this is the common type of the arguments. */ + tree result_type = NULL; + + /* Nonzero means operands have already been type-converted + in whatever way is necessary. + Zero means they need to be converted to RESULT_TYPE. */ + int converted = 0; + + /* Nonzero means create the expression with this type, rather than + RESULT_TYPE. */ + tree build_type = 0; + + /* Nonzero means after finally constructing the expression + convert it to this type. */ + tree final_type = 0; + + /* Nonzero if this is an operation like MIN or MAX which can + safely be computed in short if both args are promoted shorts. + Also implies COMMON. + -1 indicates a bitwise operation; this makes a difference + in the exact conditions for when it is safe to do the operation + in a narrower mode. */ + int shorten = 0; + + /* Nonzero if this is a comparison operation; + if both args are promoted shorts, compare the original shorts. + Also implies COMMON. */ + int short_compare = 0; + + /* Nonzero if this is a right-shift operation, which can be computed on the + original short and then promoted if the operand is a promoted short. */ + int short_shift = 0; + + /* Nonzero means set RESULT_TYPE to the common type of the args. */ + int common = 0; + + if (convert_p) { - if (constructor_stack->replacement_value) - error_init ("excess elements in char array initializer"); - constructor_stack->replacement_value = value; - return; + op0 = default_conversion (orig_op0); + op1 = default_conversion (orig_op1); } - - if (constructor_stack->replacement_value != 0) + else { - error_init ("excess elements in struct initializer"); - return; + op0 = orig_op0; + op1 = orig_op1; } - /* Ignore elements of a brace group if it is entirely superfluous - and has already been diagnosed. */ - if (constructor_type == 0) - return; + type0 = TREE_TYPE (op0); + type1 = TREE_TYPE (op1); - /* If we've exhausted any levels that didn't have braces, - pop them now. */ - while (constructor_stack->implicit) + /* The expression codes of the data types of the arguments tell us + whether the arguments are integers, floating, pointers, etc. */ + code0 = TREE_CODE (type0); + code1 = TREE_CODE (type1); + + /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ + STRIP_TYPE_NOPS (op0); + STRIP_TYPE_NOPS (op1); + + /* If an error was already reported for one of the arguments, + avoid reporting another error. */ + + if (code0 == ERROR_MARK || code1 == ERROR_MARK) + return error_mark_node; + + switch (code) { - if ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && constructor_fields == 0) - process_init_element (pop_init_level (1)); - else if (TREE_CODE (constructor_type) == ARRAY_TYPE - && (constructor_max_index == 0 - || tree_int_cst_lt (constructor_max_index, - constructor_index))) - process_init_element (pop_init_level (1)); + case PLUS_EXPR: + /* Handle the pointer + int case. */ + if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) + return pointer_int_sum (PLUS_EXPR, op0, op1); + else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE) + return pointer_int_sum (PLUS_EXPR, op1, op0); else - break; - } + common = 1; + break; - /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */ - if (constructor_range_stack) - { - /* If value is a compound literal and we'll be just using its - content, don't put it into a SAVE_EXPR. */ - if (TREE_CODE (value) != COMPOUND_LITERAL_EXPR - || !require_constant_value - || flag_isoc99) - value = save_expr (value); - } + case MINUS_EXPR: + /* Subtraction of two similar pointers. + We must subtract them as integers, then divide by object size. */ + if (code0 == POINTER_TYPE && code1 == POINTER_TYPE + && comp_target_types (type0, type1, 1)) + return pointer_diff (op0, op1); + /* Handle pointer minus int. Just like pointer plus int. */ + else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) + return pointer_int_sum (MINUS_EXPR, op0, op1); + else + common = 1; + break; - while (1) - { - if (TREE_CODE (constructor_type) == RECORD_TYPE) + case MULT_EXPR: + common = 1; + break; + + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + /* Floating point division by zero is a legitimate way to obtain + infinities and NaNs. */ + if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1)) + warning ("division by zero"); + + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { - tree fieldtype; - enum tree_code fieldcode; + if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)) + resultcode = RDIV_EXPR; + else + /* Although it would be tempting to shorten always here, that + loses on some targets, since the modulo instruction is + undefined if the quotient can't be represented in the + computation mode. We shorten only if unsigned or if + dividing by something we know != -1. */ + shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0)) + || (TREE_CODE (op1) == INTEGER_CST + && ! integer_all_onesp (op1))); + common = 1; + } + break; - if (constructor_fields == 0) - { - pedwarn_init ("excess elements in struct initializer"); - break; - } + case BIT_AND_EXPR: + case BIT_ANDTC_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + shorten = -1; + else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + common = 1; + break; + + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1)) + warning ("division by zero"); - fieldtype = TREE_TYPE (constructor_fields); - if (fieldtype != error_mark_node) - fieldtype = TYPE_MAIN_VARIANT (fieldtype); - fieldcode = TREE_CODE (fieldtype); + if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + { + /* Although it would be tempting to shorten always here, that loses + on some targets, since the modulo instruction is undefined if the + quotient can't be represented in the computation mode. We shorten + only if unsigned or if dividing by something we know != -1. */ + shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0)) + || (TREE_CODE (op1) == INTEGER_CST + && ! integer_all_onesp (op1))); + common = 1; + } + break; - /* Error for non-static initialization of a flexible array member. */ - if (fieldcode == ARRAY_TYPE - && !require_constant_value - && TYPE_SIZE (fieldtype) == NULL_TREE - && TREE_CHAIN (constructor_fields) == NULL_TREE) - { - error_init ("non-static initialization of a flexible array member"); - break; - } + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + case TRUTH_AND_EXPR: + case TRUTH_OR_EXPR: + case TRUTH_XOR_EXPR: + if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE + || code0 == REAL_TYPE || code0 == COMPLEX_TYPE) + && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE + || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) + { + /* Result of these operations is always an int, + but that does not mean the operands should be + converted to ints! */ + result_type = integer_type_node; + op0 = c_common_truthvalue_conversion (op0); + op1 = c_common_truthvalue_conversion (op1); + converted = 1; + } + break; - /* Accept a string constant to initialize a subarray. */ - if (value != 0 - && fieldcode == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE - && string_flag) - value = orig_value; - /* Otherwise, if we have come to a subaggregate, - and we don't have an element of its type, push into it. */ - else if (value != 0 && !constructor_no_implicit - && value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype - && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE)) - { - push_init_level (1); - continue; - } + /* Shift operations: result has same type as first operand; + always convert second operand to int. + Also set SHORT_SHIFT if shifting rightward. */ - if (value) - { - push_member_name (constructor_fields); - output_init_element (value, fieldtype, constructor_fields, 1); - RESTORE_SPELLING_DEPTH (constructor_depth); - } - else - /* Do the bookkeeping for an element that was - directly output as a constructor. */ + case RSHIFT_EXPR: + if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + { + if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { - /* For a record, keep track of end position of last field. */ - if (DECL_SIZE (constructor_fields)) - constructor_bit_index - = size_binop (PLUS_EXPR, - bit_position (constructor_fields), - DECL_SIZE (constructor_fields)); - - /* If the current field was the first one not yet written out, - it isn't now, so update. */ - if (constructor_unfilled_fields == constructor_fields) + if (tree_int_cst_sgn (op1) < 0) + warning ("right shift count is negative"); + else { - constructor_unfilled_fields = TREE_CHAIN (constructor_fields); - /* Skip any nameless bit fields. */ - while (constructor_unfilled_fields != 0 - && DECL_C_BIT_FIELD (constructor_unfilled_fields) - && DECL_NAME (constructor_unfilled_fields) == 0) - constructor_unfilled_fields = - TREE_CHAIN (constructor_unfilled_fields); + if (! integer_zerop (op1)) + short_shift = 1; + + if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + warning ("right shift count >= width of type"); } } - constructor_fields = TREE_CHAIN (constructor_fields); - /* Skip any nameless bit fields at the beginning. */ - while (constructor_fields != 0 - && DECL_C_BIT_FIELD (constructor_fields) - && DECL_NAME (constructor_fields) == 0) - constructor_fields = TREE_CHAIN (constructor_fields); + /* Use the type of the value to be shifted. */ + result_type = type0; + /* Convert the shift-count to an integer, regardless of size + of value being shifted. */ + if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) + op1 = convert (integer_type_node, op1); + /* Avoid converting op1 to result_type later. */ + converted = 1; } - else if (TREE_CODE (constructor_type) == UNION_TYPE) - { - tree fieldtype; - enum tree_code fieldcode; - - if (constructor_fields == 0) - { - pedwarn_init ("excess elements in union initializer"); - break; - } - - fieldtype = TREE_TYPE (constructor_fields); - if (fieldtype != error_mark_node) - fieldtype = TYPE_MAIN_VARIANT (fieldtype); - fieldcode = TREE_CODE (fieldtype); - - /* Warn that traditional C rejects initialization of unions. - We skip the warning if the value is zero. This is done - under the assumption that the zero initializer in user - code appears conditioned on e.g. __STDC__ to avoid - "missing initializer" warnings and relies on default - initialization to zero in the traditional C case. - We also skip the warning if the initializer is designated, - again on the assumption that this must be conditional on - __STDC__ anyway (and we've already complained about the - member-designator already). */ - if (warn_traditional && !in_system_header && !constructor_designated - && !(value && (integer_zerop (value) || real_zerop (value)))) - warning ("traditional C rejects initialization of unions"); + break; - /* Accept a string constant to initialize a subarray. */ - if (value != 0 - && fieldcode == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE - && string_flag) - value = orig_value; - /* Otherwise, if we have come to a subaggregate, - and we don't have an element of its type, push into it. */ - else if (value != 0 && !constructor_no_implicit - && value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype - && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE)) + case LSHIFT_EXPR: + if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + { + if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { - push_init_level (1); - continue; - } + if (tree_int_cst_sgn (op1) < 0) + warning ("left shift count is negative"); - if (value) - { - push_member_name (constructor_fields); - output_init_element (value, fieldtype, constructor_fields, 1); - RESTORE_SPELLING_DEPTH (constructor_depth); - } - else - /* Do the bookkeeping for an element that was - directly output as a constructor. */ - { - constructor_bit_index = DECL_SIZE (constructor_fields); - constructor_unfilled_fields = TREE_CHAIN (constructor_fields); + else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + warning ("left shift count >= width of type"); } - constructor_fields = 0; + /* Use the type of the value to be shifted. */ + result_type = type0; + /* Convert the shift-count to an integer, regardless of size + of value being shifted. */ + if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) + op1 = convert (integer_type_node, op1); + /* Avoid converting op1 to result_type later. */ + converted = 1; } - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); - enum tree_code eltcode = TREE_CODE (elttype); + break; - /* Accept a string constant to initialize a subarray. */ - if (value != 0 - && eltcode == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE - && string_flag) - value = orig_value; - /* Otherwise, if we have come to a subaggregate, - and we don't have an element of its type, push into it. */ - else if (value != 0 && !constructor_no_implicit - && value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype - && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE - || eltcode == UNION_TYPE)) + case RROTATE_EXPR: + case LROTATE_EXPR: + if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + { + if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { - push_init_level (1); - continue; + if (tree_int_cst_sgn (op1) < 0) + warning ("shift count is negative"); + else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + warning ("shift count >= width of type"); } - if (constructor_max_index != 0 - && (tree_int_cst_lt (constructor_max_index, constructor_index) - || integer_all_onesp (constructor_max_index))) - { - pedwarn_init ("excess elements in array initializer"); - break; - } + /* Use the type of the value to be shifted. */ + result_type = type0; + /* Convert the shift-count to an integer, regardless of size + of value being shifted. */ + if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) + op1 = convert (integer_type_node, op1); + /* Avoid converting op1 to result_type later. */ + converted = 1; + } + break; - /* Now output the actual element. */ - if (value) + case EQ_EXPR: + case NE_EXPR: + if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE)) + warning ("comparing floating point with == or != is unsafe"); + /* Result of comparison is always int, + but don't convert the args to int! */ + build_type = integer_type_node; + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + || code0 == COMPLEX_TYPE + || code0 == VECTOR_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == COMPLEX_TYPE + || code1 == VECTOR_TYPE)) + short_compare = 1; + else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) + { + tree tt0 = TREE_TYPE (type0); + tree tt1 = TREE_TYPE (type1); + /* Anything compares with void *. void * compares with anything. + Otherwise, the targets must be compatible + and both must be object or both incomplete. */ + if (comp_target_types (type0, type1, 1)) + result_type = common_type (type0, type1); + else if (VOID_TYPE_P (tt0)) { - push_array_bounds (tree_low_cst (constructor_index, 0)); - output_init_element (value, elttype, constructor_index, 1); - RESTORE_SPELLING_DEPTH (constructor_depth); + /* op0 != orig_op0 detects the case of something + whose value is 0 but which isn't a valid null ptr const. */ + if (pedantic && (!integer_zerop (op0) || op0 != orig_op0) + && TREE_CODE (tt1) == FUNCTION_TYPE) + pedwarn ("ISO C forbids comparison of `void *' with function pointer"); } - - constructor_index - = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); - - if (! value) - /* If we are doing the bookkeeping for an element that was - directly output as a constructor, we must update - constructor_unfilled_index. */ - constructor_unfilled_index = constructor_index; - } - else if (TREE_CODE (constructor_type) == VECTOR_TYPE) - { - tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); - - /* Do a basic check of initializer size. Note that vectors - always have a fixed size derived from their type. */ - if (tree_int_cst_lt (constructor_max_index, constructor_index)) + else if (VOID_TYPE_P (tt1)) { - pedwarn_init ("excess elements in vector initializer"); - break; + if (pedantic && (!integer_zerop (op1) || op1 != orig_op1) + && TREE_CODE (tt0) == FUNCTION_TYPE) + pedwarn ("ISO C forbids comparison of `void *' with function pointer"); } + else + pedwarn ("comparison of distinct pointer types lacks a cast"); - /* Now output the actual element. */ - if (value) - output_init_element (value, elttype, constructor_index, 1); - - constructor_index - = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); - - if (! value) - /* If we are doing the bookkeeping for an element that was - directly output as a constructor, we must update - constructor_unfilled_index. */ - constructor_unfilled_index = constructor_index; + if (result_type == NULL_TREE) + result_type = ptr_type_node; } - - /* Handle the sole element allowed in a braced initializer - for a scalar variable. */ - else if (constructor_fields == 0) + else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST + && integer_zerop (op1)) + result_type = type0; + else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST + && integer_zerop (op0)) + result_type = type1; + else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { - pedwarn_init ("excess elements in scalar initializer"); - break; + result_type = type0; + pedwarn ("comparison between pointer and integer"); } - else + else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { - if (value) - output_init_element (value, constructor_type, NULL_TREE, 1); - constructor_fields = 0; + result_type = type1; + pedwarn ("comparison between pointer and integer"); } + break; - /* Handle range initializers either at this level or anywhere higher - in the designator stack. */ - if (constructor_range_stack) + case MAX_EXPR: + case MIN_EXPR: + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + shorten = 1; + else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { - struct constructor_range_stack *p, *range_stack; - int finish = 0; - - range_stack = constructor_range_stack; - constructor_range_stack = 0; - while (constructor_stack != range_stack->stack) - { - if (!constructor_stack->implicit) - abort (); - process_init_element (pop_init_level (1)); - } - for (p = range_stack; - !p->range_end || tree_int_cst_equal (p->index, p->range_end); - p = p->prev) + if (comp_target_types (type0, type1, 1)) { - if (!constructor_stack->implicit) - abort (); - process_init_element (pop_init_level (1)); + result_type = common_type (type0, type1); + if (pedantic + && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) + pedwarn ("ISO C forbids ordered comparisons of pointers to functions"); } - - p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node); - if (tree_int_cst_equal (p->index, p->range_end) && !p->prev) - finish = 1; - - while (1) + else { - constructor_index = p->index; - constructor_fields = p->fields; - if (finish && p->range_end && p->index == p->range_start) - { - finish = 0; - p->prev = 0; - } - p = p->next; - if (!p) - break; - push_init_level (2); - p->stack = constructor_stack; - if (p->range_end && tree_int_cst_equal (p->index, p->range_end)) - p->index = p->range_start; + result_type = ptr_type_node; + pedwarn ("comparison of distinct pointer types lacks a cast"); } - - if (!finish) - constructor_range_stack = range_stack; - continue; } - break; - } - - constructor_range_stack = 0; -} - -/* Build a simple asm-statement, from one string literal. */ -tree -simple_asm_stmt (tree expr) -{ - STRIP_NOPS (expr); - - if (TREE_CODE (expr) == ADDR_EXPR) - expr = TREE_OPERAND (expr, 0); - - if (TREE_CODE (expr) == STRING_CST) - { - tree stmt; - - /* Simple asm statements are treated as volatile. */ - stmt = add_stmt (build_stmt (ASM_STMT, ridpointers[(int) RID_VOLATILE], - expr, NULL_TREE, NULL_TREE, NULL_TREE)); - ASM_INPUT_P (stmt) = 1; - return stmt; - } - - error ("argument of `asm' is not a constant string"); - return NULL_TREE; -} - -/* Build an asm-statement, whose components are a CV_QUALIFIER, a - STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */ - -tree -build_asm_stmt (tree cv_qualifier, tree string, tree outputs, tree inputs, - tree clobbers) -{ - tree tail; - - if (TREE_CODE (string) != STRING_CST) - { - error ("asm template is not a string constant"); - return NULL_TREE; - } - - if (cv_qualifier != NULL_TREE - && cv_qualifier != ridpointers[(int) RID_VOLATILE]) - { - warning ("%s qualifier ignored on asm", - IDENTIFIER_POINTER (cv_qualifier)); - cv_qualifier = NULL_TREE; - } - - /* We can remove output conversions that change the type, - but not the mode. */ - for (tail = outputs; tail; tail = TREE_CHAIN (tail)) - { - tree output = TREE_VALUE (tail); - - STRIP_NOPS (output); - TREE_VALUE (tail) = output; - - /* Allow conversions as LHS here. build_modify_expr as called below - will do the right thing with them. */ - while (TREE_CODE (output) == NOP_EXPR - || TREE_CODE (output) == CONVERT_EXPR - || TREE_CODE (output) == FLOAT_EXPR - || TREE_CODE (output) == FIX_TRUNC_EXPR - || TREE_CODE (output) == FIX_FLOOR_EXPR - || TREE_CODE (output) == FIX_ROUND_EXPR - || TREE_CODE (output) == FIX_CEIL_EXPR) - output = TREE_OPERAND (output, 0); - - lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement"); - } - - /* Remove output conversions that change the type but not the mode. */ - for (tail = outputs; tail; tail = TREE_CHAIN (tail)) - { - tree output = TREE_VALUE (tail); - STRIP_NOPS (output); - TREE_VALUE (tail) = output; - } - - /* Perform default conversions on array and function inputs. - Don't do this for other types as it would screw up operands - expected to be in memory. */ - for (tail = inputs; tail; tail = TREE_CHAIN (tail)) - TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail)); - return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string, - outputs, inputs, clobbers)); -} - -/* Expand an ASM statement with operands, handling output operands - that are not variables or INDIRECT_REFS by transforming such - cases into cases that expand_asm_operands can handle. - - Arguments are same as for expand_asm_operands. */ + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + build_type = integer_type_node; + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + short_compare = 1; + else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) + { + if (comp_target_types (type0, type1, 1)) + { + result_type = common_type (type0, type1); + if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) + != !COMPLETE_TYPE_P (TREE_TYPE (type1))) + pedwarn ("comparison of complete and incomplete pointers"); + else if (pedantic + && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) + pedwarn ("ISO C forbids ordered comparisons of pointers to functions"); + } + else + { + result_type = ptr_type_node; + pedwarn ("comparison of distinct pointer types lacks a cast"); + } + } + else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST + && integer_zerop (op1)) + { + result_type = type0; + if (pedantic || extra_warnings) + pedwarn ("ordered comparison of pointer with integer zero"); + } + else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST + && integer_zerop (op0)) + { + result_type = type1; + if (pedantic) + pedwarn ("ordered comparison of pointer with integer zero"); + } + else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) + { + result_type = type0; + pedwarn ("comparison between pointer and integer"); + } + else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) + { + result_type = type1; + pedwarn ("comparison between pointer and integer"); + } + break; -void -c_expand_asm_operands (tree string, tree outputs, tree inputs, - tree clobbers, int vol, const char *filename, - int line) -{ - int noutputs = list_length (outputs); - int i; - /* o[I] is the place that output number I should be written. */ - tree *o = (tree *) alloca (noutputs * sizeof (tree)); - tree tail; + case UNORDERED_EXPR: + case ORDERED_EXPR: + case UNLT_EXPR: + case UNLE_EXPR: + case UNGT_EXPR: + case UNGE_EXPR: + case UNEQ_EXPR: + build_type = integer_type_node; + if (code0 != REAL_TYPE || code1 != REAL_TYPE) + { + error ("unordered comparison on non-floating point argument"); + return error_mark_node; + } + common = 1; + break; - /* Record the contents of OUTPUTS before it is modified. */ - for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) - { - o[i] = TREE_VALUE (tail); - if (o[i] == error_mark_node) - return; + default: + break; } - /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of - OUTPUTS some trees for where the values were actually stored. */ - expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line); - - /* Copy all the intermediate outputs into the specified outputs. */ - for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE + || code0 == VECTOR_TYPE) + && + (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE + || code1 == VECTOR_TYPE)) { - if (o[i] != TREE_VALUE (tail)) - { - expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)), - NULL_RTX, VOIDmode, EXPAND_NORMAL); - free_temp_slots (); + int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE); - /* Restore the original value so that it's correct the next - time we expand this function. */ - TREE_VALUE (tail) = o[i]; - } - /* Detect modification of read-only values. - (Otherwise done by build_modify_expr.) */ - else - { - tree type = TREE_TYPE (o[i]); - if (TREE_READONLY (o[i]) - || TYPE_READONLY (type) - || ((TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE) - && C_TYPE_FIELDS_READONLY (type))) - readonly_warning (o[i], "modification by `asm'"); - } - } + if (shorten || common || short_compare) + result_type = common_type (type0, type1); - /* Those MODIFY_EXPRs could do autoincrements. */ - emit_queue (); -} - -/* Expand a C `return' statement. - RETVAL is the expression for what to return, - or a null pointer for `return;' with no value. */ + /* For certain operations (which identify themselves by shorten != 0) + if both args were extended from the same smaller type, + do the arithmetic in that type and then extend. -tree -c_expand_return (tree retval) -{ - tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); + shorten !=0 and !=1 indicates a bitwise operation. + For them, this optimization is safe only if + both args are zero-extended or both are sign-extended. + Otherwise, we might change the result. + Eg, (short)-1 | (unsigned short)-1 is (int)-1 + but calculated in (unsigned short) it would be (unsigned short)-1. */ - if (TREE_THIS_VOLATILE (current_function_decl)) - warning ("function declared `noreturn' has a `return' statement"); + if (shorten && none_complex) + { + int unsigned0, unsigned1; + tree arg0 = get_narrower (op0, &unsigned0); + tree arg1 = get_narrower (op1, &unsigned1); + /* UNS is 1 if the operation to be done is an unsigned one. */ + int uns = TREE_UNSIGNED (result_type); + tree type; - if (!retval) - { - current_function_returns_null = 1; - if ((warn_return_type || flag_isoc99) - && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE) - pedwarn_c99 ("`return' with no value, in function returning non-void"); - } - else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) - { - current_function_returns_null = 1; - if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) - pedwarn ("`return' with a value, in function returning void"); - } - else - { - tree t = convert_for_assignment (valtype, retval, _("return"), - NULL_TREE, NULL_TREE, 0); - tree res = DECL_RESULT (current_function_decl); - tree inner; + final_type = result_type; - current_function_returns_value = 1; - if (t == error_mark_node) - return NULL_TREE; + /* Handle the case that OP0 (or OP1) does not *contain* a conversion + but it *requires* conversion to FINAL_TYPE. */ - inner = t = convert (TREE_TYPE (res), t); + if ((TYPE_PRECISION (TREE_TYPE (op0)) + == TYPE_PRECISION (TREE_TYPE (arg0))) + && TREE_TYPE (op0) != final_type) + unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0)); + if ((TYPE_PRECISION (TREE_TYPE (op1)) + == TYPE_PRECISION (TREE_TYPE (arg1))) + && TREE_TYPE (op1) != final_type) + unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1)); - /* Strip any conversions, additions, and subtractions, and see if - we are returning the address of a local variable. Warn if so. */ - while (1) - { - switch (TREE_CODE (inner)) - { - case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR: - case PLUS_EXPR: - inner = TREE_OPERAND (inner, 0); - continue; + /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */ - case MINUS_EXPR: - /* If the second operand of the MINUS_EXPR has a pointer - type (or is converted from it), this may be valid, so - don't give a warning. */ - { - tree op1 = TREE_OPERAND (inner, 1); + /* For bitwise operations, signedness of nominal type + does not matter. Consider only how operands were extended. */ + if (shorten == -1) + uns = unsigned0; - while (! POINTER_TYPE_P (TREE_TYPE (op1)) - && (TREE_CODE (op1) == NOP_EXPR - || TREE_CODE (op1) == NON_LVALUE_EXPR - || TREE_CODE (op1) == CONVERT_EXPR)) - op1 = TREE_OPERAND (op1, 0); + /* Note that in all three cases below we refrain from optimizing + an unsigned operation on sign-extended args. + That would not be valid. */ - if (POINTER_TYPE_P (TREE_TYPE (op1))) - break; + /* Both args variable: if both extended in same way + from same width, do it in that width. + Do it unsigned if args were zero-extended. */ + if ((TYPE_PRECISION (TREE_TYPE (arg0)) + < TYPE_PRECISION (result_type)) + && (TYPE_PRECISION (TREE_TYPE (arg1)) + == TYPE_PRECISION (TREE_TYPE (arg0))) + && unsigned0 == unsigned1 + && (unsigned0 || !uns)) + result_type + = c_common_signed_or_unsigned_type + (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); + else if (TREE_CODE (arg0) == INTEGER_CST + && (unsigned1 || !uns) + && (TYPE_PRECISION (TREE_TYPE (arg1)) + < TYPE_PRECISION (result_type)) + && (type + = c_common_signed_or_unsigned_type (unsigned1, + TREE_TYPE (arg1)), + int_fits_type_p (arg0, type))) + result_type = type; + else if (TREE_CODE (arg1) == INTEGER_CST + && (unsigned0 || !uns) + && (TYPE_PRECISION (TREE_TYPE (arg0)) + < TYPE_PRECISION (result_type)) + && (type + = c_common_signed_or_unsigned_type (unsigned0, + TREE_TYPE (arg0)), + int_fits_type_p (arg1, type))) + result_type = type; + } - inner = TREE_OPERAND (inner, 0); - continue; - } + /* Shifts can be shortened if shifting right. */ - case ADDR_EXPR: - inner = TREE_OPERAND (inner, 0); + if (short_shift) + { + int unsigned_arg; + tree arg0 = get_narrower (op0, &unsigned_arg); - while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r') - inner = TREE_OPERAND (inner, 0); + final_type = result_type; - if (TREE_CODE (inner) == VAR_DECL - && ! DECL_EXTERNAL (inner) - && ! TREE_STATIC (inner) - && DECL_CONTEXT (inner) == current_function_decl) - warning ("function returns address of local variable"); - break; + if (arg0 == op0 && final_type == TREE_TYPE (op0)) + unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0)); - default: - break; + if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type) + /* We can shorten only if the shift count is less than the + number of bits in the smaller type size. */ + && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0 + /* We cannot drop an unsigned shift after sign-extension. */ + && (!TREE_UNSIGNED (final_type) || unsigned_arg)) + { + /* Do an unsigned shift if the operand was zero-extended. */ + result_type + = c_common_signed_or_unsigned_type (unsigned_arg, + TREE_TYPE (arg0)); + /* Convert value-to-be-shifted to that type. */ + if (TREE_TYPE (op0) != result_type) + op0 = convert (result_type, op0); + converted = 1; } - - break; } - retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t); - } + /* Comparison operations are shortened too but differently. + They identify themselves by setting short_compare = 1. */ - return add_stmt (build_return_stmt (retval)); -} - -struct c_switch { - /* The SWITCH_STMT being built. */ - tree switch_stmt; - /* A splay-tree mapping the low element of a case range to the high - element, or NULL_TREE if there is no high element. Used to - determine whether or not a new case label duplicates an old case - label. We need a tree, rather than simply a hash table, because - of the GNU case range extension. */ - splay_tree cases; - /* The next node on the stack. */ - struct c_switch *next; -}; + if (short_compare) + { + /* Don't write &op0, etc., because that would prevent op0 + from being kept in a register. + Instead, make copies of the our local variables and + pass the copies by reference, then copy them back afterward. */ + tree xop0 = op0, xop1 = op1, xresult_type = result_type; + enum tree_code xresultcode = resultcode; + tree val + = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); -/* A stack of the currently active switch statements. The innermost - switch statement is on the top of the stack. There is no need to - mark the stack for garbage collection because it is only active - during the processing of the body of a function, and we never - collect at that point. */ + if (val != 0) + return val; -static struct c_switch *switch_stack; + op0 = xop0, op1 = xop1; + converted = 1; + resultcode = xresultcode; -/* Start a C switch statement, testing expression EXP. Return the new - SWITCH_STMT. */ + if (warn_sign_compare && skip_evaluation == 0) + { + int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0)); + int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1)); + int unsignedp0, unsignedp1; + tree primop0 = get_narrower (op0, &unsignedp0); + tree primop1 = get_narrower (op1, &unsignedp1); -tree -c_start_case (tree exp) -{ - enum tree_code code; - tree type, orig_type = error_mark_node; - struct c_switch *cs; + xop0 = orig_op0; + xop1 = orig_op1; + STRIP_TYPE_NOPS (xop0); + STRIP_TYPE_NOPS (xop1); - if (exp != error_mark_node) - { - code = TREE_CODE (TREE_TYPE (exp)); - orig_type = TREE_TYPE (exp); + /* Give warnings for comparisons between signed and unsigned + quantities that may fail. - if (! INTEGRAL_TYPE_P (orig_type) - && code != ERROR_MARK) - { - error ("switch quantity not an integer"); - exp = integer_zero_node; - } - else - { - type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); + Do the checking based on the original operand trees, so that + casts will be considered, but default promotions won't be. - if (warn_traditional && !in_system_header - && (type == long_integer_type_node - || type == long_unsigned_type_node)) - warning ("`long' switch expression not converted to `int' in ISO C"); + Do not warn if the comparison is being done in a signed type, + since the signed type will only be chosen if it can represent + all the values of the unsigned type. */ + if (! TREE_UNSIGNED (result_type)) + /* OK */; + /* Do not warn if both operands are the same signedness. */ + else if (op0_signed == op1_signed) + /* OK */; + else + { + tree sop, uop; - exp = default_conversion (exp); - type = TREE_TYPE (exp); - } - } + if (op0_signed) + sop = xop0, uop = xop1; + else + sop = xop1, uop = xop0; - /* Add this new SWITCH_STMT to the stack. */ - cs = (struct c_switch *) xmalloc (sizeof (*cs)); - cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type); - cs->cases = splay_tree_new (case_compare, NULL, NULL); - cs->next = switch_stack; - switch_stack = cs; + /* Do not warn if the signed quantity is an + unsuffixed integer literal (or some static + constant expression involving such literals or a + conditional expression involving such literals) + and it is non-negative. */ + if (c_tree_expr_nonnegative_p (sop)) + /* OK */; + /* Do not warn if the comparison is an equality operation, + the unsigned quantity is an integral constant, and it + would fit in the result if the result were signed. */ + else if (TREE_CODE (uop) == INTEGER_CST + && (resultcode == EQ_EXPR || resultcode == NE_EXPR) + && int_fits_type_p + (uop, c_common_signed_type (result_type))) + /* OK */; + /* Do not warn if the unsigned quantity is an enumeration + constant and its maximum value would fit in the result + if the result were signed. */ + else if (TREE_CODE (uop) == INTEGER_CST + && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE + && int_fits_type_p + (TYPE_MAX_VALUE (TREE_TYPE(uop)), + c_common_signed_type (result_type))) + /* OK */; + else + warning ("comparison between signed and unsigned"); + } - return add_stmt (switch_stack->switch_stmt); -} + /* Warn if two unsigned values are being compared in a size + larger than their original size, and one (and only one) is the + result of a `~' operator. This comparison will always fail. -/* Process a case label. */ + Also warn if one operand is a constant, and the constant + does not have all bits set that are set in the ~ operand + when it is extended. */ -tree -do_case (tree low_value, tree high_value) -{ - tree label = NULL_TREE; + if ((TREE_CODE (primop0) == BIT_NOT_EXPR) + != (TREE_CODE (primop1) == BIT_NOT_EXPR)) + { + if (TREE_CODE (primop0) == BIT_NOT_EXPR) + primop0 = get_narrower (TREE_OPERAND (primop0, 0), + &unsignedp0); + else + primop1 = get_narrower (TREE_OPERAND (primop1, 0), + &unsignedp1); - if (switch_stack) - { - bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE); + if (host_integerp (primop0, 0) || host_integerp (primop1, 0)) + { + tree primop; + HOST_WIDE_INT constant, mask; + int unsignedp, bits; - label = c_add_case_label (switch_stack->cases, - SWITCH_COND (switch_stack->switch_stmt), - low_value, high_value); - if (label == error_mark_node) - label = NULL_TREE; - else if (switch_was_empty_p) - { - /* Attach the first case label to the SWITCH_BODY. */ - SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt); - TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE; + if (host_integerp (primop0, 0)) + { + primop = primop1; + unsignedp = unsignedp1; + constant = tree_low_cst (primop0, 0); + } + else + { + primop = primop0; + unsignedp = unsignedp0; + constant = tree_low_cst (primop1, 0); + } + + bits = TYPE_PRECISION (TREE_TYPE (primop)); + if (bits < TYPE_PRECISION (result_type) + && bits < HOST_BITS_PER_WIDE_INT && unsignedp) + { + mask = (~ (HOST_WIDE_INT) 0) << bits; + if ((mask & constant) != mask) + warning ("comparison of promoted ~unsigned with constant"); + } + } + else if (unsignedp0 && unsignedp1 + && (TYPE_PRECISION (TREE_TYPE (primop0)) + < TYPE_PRECISION (result_type)) + && (TYPE_PRECISION (TREE_TYPE (primop1)) + < TYPE_PRECISION (result_type))) + warning ("comparison of promoted ~unsigned with unsigned"); + } + } } } - else if (low_value) - error ("case label not within a switch statement"); - else - error ("`default' label not within a switch statement"); - return label; -} + /* At this point, RESULT_TYPE must be nonzero to avoid an error message. + If CONVERTED is zero, both args will be converted to type RESULT_TYPE. + Then the expression will be built. + It will be given type FINAL_TYPE if that is nonzero; + otherwise, it will be given type RESULT_TYPE. */ -/* Finish the switch statement. */ + if (!result_type) + { + binary_op_error (code); + return error_mark_node; + } -void -c_finish_case (void) -{ - struct c_switch *cs = switch_stack; + if (! converted) + { + if (TREE_TYPE (op0) != result_type) + op0 = convert (result_type, op0); + if (TREE_TYPE (op1) != result_type) + op1 = convert (result_type, op1); + } - /* Rechain the next statements to the SWITCH_STMT. */ - last_tree = cs->switch_stmt; + if (build_type == NULL_TREE) + build_type = result_type; - /* Pop the stack. */ - switch_stack = switch_stack->next; - splay_tree_delete (cs->cases); - free (cs); + { + tree result = build (resultcode, build_type, op0, op1); + tree folded; + + /* Treat expressions in initializers specially as they can't trap. */ + folded = initializer_stack ? fold_initializer (result) + : fold (result); + if (folded == result) + TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1); + if (final_type != 0) + return convert (final_type, folded); + return folded; + } } + diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 95a68bcbeee..32c145effe1 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1228,14 +1228,31 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) if (TREE_CODE (arg1) == REAL_CST) { + enum machine_mode mode; REAL_VALUE_TYPE d1; REAL_VALUE_TYPE d2; REAL_VALUE_TYPE value; - tree t; + tree t, type; d1 = TREE_REAL_CST (arg1); d2 = TREE_REAL_CST (arg2); + type = TREE_TYPE (arg1); + mode = TYPE_MODE (type); + + /* Don't perform operation if we honor signaling NaNs and + either operand is a NaN. */ + if (HONOR_SNANS (mode) + && (REAL_VALUE_ISNAN (d1) || REAL_VALUE_ISNAN (d2))) + return NULL_TREE; + + /* Don't perform operation if it would raise a division + by zero exception. */ + if (code == RDIV_EXPR + && REAL_VALUES_EQUAL (d2, dconst0) + && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) + return NULL_TREE; + /* If either operand is a NaN, just return it. Otherwise, set up for floating-point trap; we return an overflow. */ if (REAL_VALUE_ISNAN (d1)) @@ -1245,9 +1262,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) REAL_ARITHMETIC (value, code, d1, d2); - t = build_real (TREE_TYPE (arg1), - real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)), - value)); + t = build_real (type, real_value_truncate (mode, value)); TREE_OVERFLOW (t) = (force_fit_type (t, 0) @@ -7886,6 +7901,31 @@ fold (tree expr) } /* switch (code) */ } +/* Perform constant folding and related simplification of intializer + expression EXPR. This behaves identically to "fold" but ignores + potential run-time traps and exceptions that fold must preserve. */ + +tree +fold_initializer (tree expr) +{ + int saved_signaling_nans = flag_signaling_nans; + int saved_trapping_math = flag_trapping_math; + int saved_trapv = flag_trapv; + tree result; + + flag_signaling_nans = 0; + flag_trapping_math = 0; + flag_trapv = 0; + + result = fold (expr); + + flag_signaling_nans = saved_signaling_nans; + flag_trapping_math = saved_trapping_math; + flag_trapv = saved_trapv; + + return result; +} + /* Determine if first argument is a multiple of second argument. Return 0 if it is not, or we cannot easily determined it to be. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 3b857673c72..8568529ef87 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -929,9 +929,13 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, f0 = real_value_truncate (mode, f0); f1 = real_value_truncate (mode, f1); + if (HONOR_SNANS (mode) + && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1))) + return 0; + if (code == DIV - && !MODE_HAS_INFINITIES (mode) - && REAL_VALUES_EQUAL (f1, dconst0)) + && REAL_VALUES_EQUAL (f1, dconst0) + && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) return 0; REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1); diff --git a/gcc/tree.h b/gcc/tree.h index 04ad1d020d1..b627a98c51c 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2715,6 +2715,7 @@ extern void using_eh_for_cleanups (void); subexpressions are not changed. */ extern tree fold (tree); +extern tree fold_initializer (tree); extern tree fold_single_bit_test (enum tree_code, tree, tree, tree); extern int force_fit_type (tree, int);