diff options
author | obrien <obrien@FreeBSD.org> | 2002-05-09 20:02:13 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2002-05-09 20:02:13 +0000 |
commit | c8f5fc7032940ad6633f932ac40cade82ec4d0cc (patch) | |
tree | 29a0f0a6c79a69ecc64f612947a0fe5904311713 /contrib/gcc/c-typeck.c | |
parent | c9ab9ae440a8066b2c2b85b157b1fdadcf09916a (diff) | |
download | FreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.zip FreeBSD-src-c8f5fc7032940ad6633f932ac40cade82ec4d0cc.tar.gz |
Gcc 3.1.0 pre-release from the FSF anoncvs repo on 9-May-2002 15:57:15 EDT.
Diffstat (limited to 'contrib/gcc/c-typeck.c')
-rw-r--r-- | contrib/gcc/c-typeck.c | 230 |
1 files changed, 108 insertions, 122 deletions
diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c index 37f6a87..b21cac0 100644 --- a/contrib/gcc/c-typeck.c +++ b/contrib/gcc/c-typeck.c @@ -58,7 +58,6 @@ static tree decl_constant_value_for_broken_optimization PARAMS ((tree)); static tree default_function_array_conversion PARAMS ((tree)); static tree lookup_field PARAMS ((tree, tree)); static tree convert_arguments PARAMS ((tree, tree, tree, tree)); -static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree)); static tree pointer_diff PARAMS ((tree, tree)); static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int)); static void pedantic_lvalue_warning PARAMS ((enum tree_code)); @@ -149,6 +148,11 @@ incomplete_type_error (value, type) case ARRAY_TYPE: if (TYPE_DOMAIN (type)) { + if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL) + { + error ("invalid use of flexible array member"); + return; + } type = TREE_TYPE (type); goto retry; } @@ -1547,6 +1551,9 @@ build_function_call (function, params) return error_mark_node; } + if (fundecl && TREE_THIS_VOLATILE (fundecl)) + current_function_returns_abnormally = 1; + /* fntype now gets the type of function pointed to. */ fntype = TREE_TYPE (fntype); @@ -2052,29 +2059,6 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) case BIT_XOR_EXPR: if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) shorten = -1; - /* If one operand is a constant, and the other is a short type - that has been converted to an int, - really do the work in the short type and then convert the - result to int. If we are lucky, the constant will be 0 or 1 - in the short type, making the entire operation go away. */ - if (TREE_CODE (op0) == INTEGER_CST - && TREE_CODE (op1) == NOP_EXPR - && TYPE_PRECISION (type1) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0))) - && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op1, 0)))) - { - final_type = result_type; - op1 = TREE_OPERAND (op1, 0); - result_type = TREE_TYPE (op1); - } - if (TREE_CODE (op1) == INTEGER_CST - && TREE_CODE (op0) == NOP_EXPR - && TYPE_PRECISION (type0) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0))) - && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0)))) - { - final_type = result_type; - op0 = TREE_OPERAND (op0, 0); - result_type = TREE_TYPE (op0); - } break; case TRUNC_MOD_EXPR: @@ -2652,95 +2636,6 @@ build_binary_op (code, orig_op0, orig_op1, convert_p) } } -/* Return a tree for the sum or difference (RESULTCODE says which) - of pointer PTROP and integer INTOP. */ - -static tree -pointer_int_sum (resultcode, ptrop, intop) - enum tree_code resultcode; - tree ptrop, intop; -{ - tree size_exp; - - tree result; - tree folded; - - /* The result is a pointer of the same type that is being added. */ - - tree result_type = TREE_TYPE (ptrop); - - if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE) - { - if (pedantic || warn_pointer_arith) - pedwarn ("pointer of type `void *' used in arithmetic"); - size_exp = integer_one_node; - } - else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE) - { - if (pedantic || warn_pointer_arith) - pedwarn ("pointer to a function used in arithmetic"); - size_exp = integer_one_node; - } - else - size_exp = c_size_in_bytes (TREE_TYPE (result_type)); - - /* If what we are about to multiply by the size of the elements - contains a constant term, apply distributive law - and multiply that constant term separately. - This helps produce common subexpressions. */ - - if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR) - && ! TREE_CONSTANT (intop) - && TREE_CONSTANT (TREE_OPERAND (intop, 1)) - && TREE_CONSTANT (size_exp) - /* If the constant comes from pointer subtraction, - skip this optimization--it would cause an error. */ - && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE - /* If the constant is unsigned, and smaller than the pointer size, - then we must skip this optimization. This is because it could cause - an overflow error if the constant is negative but INTOP is not. */ - && (! TREE_UNSIGNED (TREE_TYPE (intop)) - || (TYPE_PRECISION (TREE_TYPE (intop)) - == TYPE_PRECISION (TREE_TYPE (ptrop))))) - { - enum tree_code subcode = resultcode; - tree int_type = TREE_TYPE (intop); - if (TREE_CODE (intop) == MINUS_EXPR) - subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR); - /* Convert both subexpression types to the type of intop, - because weird cases involving pointer arithmetic - can result in a sum or difference with different type args. */ - ptrop = build_binary_op (subcode, ptrop, - convert (int_type, TREE_OPERAND (intop, 1)), 1); - intop = convert (int_type, TREE_OPERAND (intop, 0)); - } - - /* Convert the integer argument to a type the same size as sizetype - so the multiply won't overflow spuriously. */ - - if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype) - || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype)) - intop = convert (type_for_size (TYPE_PRECISION (sizetype), - TREE_UNSIGNED (sizetype)), intop); - - /* Replace the integer argument with a suitable product by the object size. - Do this multiplication as signed, then convert to the appropriate - pointer type (actually unsigned integral). */ - - intop = convert (result_type, - build_binary_op (MULT_EXPR, intop, - convert (TREE_TYPE (intop), size_exp), 1)); - - /* Create the sum or difference. */ - - result = build (resultcode, result_type, ptrop, intop); - - folded = fold (result); - if (folded == result) - TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop); - return folded; -} - /* Return a tree for the difference of pointers OP0 and OP1. The resulting tree has type int. */ @@ -3819,7 +3714,8 @@ build_c_cast (type, expr) { tree in_type = type; tree in_otype = otype; - int warn = 0; + int added = 0; + int discarded = 0; /* Check that the qualifiers on IN_TYPE are a superset of the qualifiers of IN_OTYPE. The outermost level of @@ -3829,12 +3725,24 @@ build_c_cast (type, expr) { in_otype = TREE_TYPE (in_otype); in_type = TREE_TYPE (in_type); - warn |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type)); + + /* 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 (warn) + if (added) + warning ("cast adds new qualifiers to function type"); + + if (discarded) /* There are qualifiers present in IN_OTYPE that are not present in IN_TYPE. */ warning ("cast discards qualifiers from pointer target type"); @@ -4372,6 +4280,30 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum) return error_mark_node; } +/* Convert VALUE for assignment into inlined parameter PARM. */ + +tree +c_convert_parm_for_inlining (parm, value, fn) + tree parm, value, 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; +} + /* Print a warning using MSGID. It gets OPNAME as its one parameter. If OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'". @@ -4809,6 +4741,8 @@ digest_init (type, init, require_constant, constructor_constant) TYPE_MAIN_VARIANT (type)) || (code == ARRAY_TYPE && comptypes (TREE_TYPE (inside_init), type)) + || (code == VECTOR_TYPE + && comptypes (TREE_TYPE (inside_init), type)) || (code == POINTER_TYPE && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE) @@ -5320,6 +5254,14 @@ really_start_incremental_init (type) 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, integer_zero_node); + constructor_unfilled_index = constructor_index; + } else { /* Handle the case of int x = {5}; */ @@ -5466,6 +5408,14 @@ push_init_level (implicit) 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)) @@ -5602,7 +5552,8 @@ pop_init_level (implicit) ; else if (TREE_CODE (constructor_type) != RECORD_TYPE && TREE_CODE (constructor_type) != UNION_TYPE - && TREE_CODE (constructor_type) != ARRAY_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. */ @@ -6648,6 +6599,16 @@ process_init_element (value) fieldtype = TYPE_MAIN_VARIANT (fieldtype); fieldcode = TREE_CODE (fieldtype); + /* 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; + } + /* Accept a string constant to initialize a subarray. */ if (value != 0 && fieldcode == ARRAY_TYPE @@ -6811,6 +6772,31 @@ process_init_element (value) 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)) + { + pedwarn_init ("excess elements in vector initializer"); + break; + } + + /* 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; + } /* Handle the sole element allowed in a braced initializer for a scalar variable. */ @@ -7071,6 +7057,7 @@ c_expand_return (retval) tree res = DECL_RESULT (current_function_decl); tree inner; + current_function_returns_value = 1; if (t == error_mark_node) return NULL_TREE; @@ -7128,7 +7115,6 @@ c_expand_return (retval) } retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t); - current_function_returns_value = 1; } return add_stmt (build_return_stmt (retval)); @@ -7163,15 +7149,15 @@ c_start_case (exp) tree exp; { enum tree_code code; - tree type; + tree type, orig_type = error_mark_node; struct c_switch *cs; if (exp != error_mark_node) { code = TREE_CODE (TREE_TYPE (exp)); - type = TREE_TYPE (exp); + orig_type = TREE_TYPE (exp); - if (! INTEGRAL_TYPE_P (type) + if (! INTEGRAL_TYPE_P (orig_type) && code != ERROR_MARK) { error ("switch quantity not an integer"); @@ -7193,7 +7179,7 @@ c_start_case (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, NULL_TREE); + 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; |