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));
static int spelling_length PARAMS ((void));
static char *print_spelling PARAMS ((char *));
static void warning_init PARAMS ((const char *));
-static tree digest_init PARAMS ((tree, tree, int, int));
+static tree digest_init PARAMS ((tree, tree, int));
static void output_init_element PARAMS ((tree, tree, tree, int));
static void output_pending_init_elements PARAMS ((int));
static int set_designator PARAMS ((int));
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;
}
{
type = type_for_size (MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)),
- ((flag_traditional
- || (TYPE_PRECISION (type)
- >= TYPE_PRECISION (integer_type_node)))
+ ((TYPE_PRECISION (type)
+ >= TYPE_PRECISION (integer_type_node))
&& TREE_UNSIGNED (type)));
return convert (type, exp);
c_promoting_integer_type_p, otherwise leave it alone. */
&& 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
TYPE_PRECISION (integer_type_node)))
- return convert (flag_traditional && TREE_UNSIGNED (type)
- ? unsigned_type_node : integer_type_node,
- exp);
+ return convert (integer_type_node, exp);
if (c_promoting_integer_type_p (type))
{
- /* Traditionally, unsignedness is preserved in default promotions.
- Also preserve unsignedness if not really getting any wider. */
+ /* Preserve unsignedness if not really getting any wider. */
if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
return convert (unsigned_type_node, exp);
return convert (integer_type_node, exp);
}
- if (flag_traditional && !flag_allow_single_precision
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
-
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
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);
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:
}
}
- /* Use the type of the value to be shifted.
- This is what most traditional C compilers do. */
+ /* Use the type of the value to be shifted. */
result_type = type0;
- /* Unless traditional, convert the shift-count to an integer,
- regardless of size of value being shifted. */
- if (! flag_traditional)
- {
- 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;
- }
+ /* 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;
warning ("left shift count >= width of type");
}
- /* Use the type of the value to be shifted.
- This is what most traditional C compilers do. */
+ /* Use the type of the value to be shifted. */
result_type = type0;
- /* Unless traditional, convert the shift-count to an integer,
- regardless of size of value being shifted. */
- if (! flag_traditional)
- {
- 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;
- }
+ /* 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;
warning ("shift count >= width of type");
}
- /* Use the type of the value to be shifted.
- This is what most traditional C compilers do. */
+ /* Use the type of the value to be shifted. */
result_type = type0;
- /* Unless traditional, convert the shift-count to an integer,
- regardless of size of value being shifted. */
- if (! flag_traditional)
- {
- 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;
- }
+ /* 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;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
break;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
break;
}
}
\f
-/* 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. */
else
name = "";
t = digest_init (type, build (CONSTRUCTOR, type, NULL_TREE,
- build_tree_list (field, value)),
- 0, 0);
+ build_tree_list (field, value)), 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
return t;
}
{
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
{
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");
/* Digest the specified initializer into an expression. */
- value = digest_init (type, init, TREE_STATIC (decl),
- TREE_STATIC (decl) || (pedantic && !flag_isoc99));
+ value = digest_init (type, init, TREE_STATIC (decl));
/* Store the expression if valid; else report error. */
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
- The arguments REQUIRE_CONSTANT and CONSTRUCTOR_CONSTANT request errors
- if non-constant initializers or elements are seen. CONSTRUCTOR_CONSTANT
- applies only to elements of constructors. */
+ REQUIRE_CONSTANT requests an error if non-constant initializers or
+ elements are seen. */
static tree
-digest_init (type, init, require_constant, constructor_constant)
+digest_init (type, init, require_constant)
tree type, init;
- int require_constant, constructor_constant;
+ int require_constant;
{
enum tree_code code = TREE_CODE (type);
tree inside_init = init;
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)
return error_mark_node;
}
- /* Traditionally, you can write struct foo x = 0;
- and it initializes the first element of x to 0. */
- if (flag_traditional)
- {
- tree top = 0, prev = 0, otype = type;
- while (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE
- || TREE_CODE (type) == UNION_TYPE)
- {
- tree temp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
- if (prev == 0)
- top = temp;
- else
- TREE_OPERAND (prev, 1) = build_tree_list (NULL_TREE, temp);
- prev = temp;
- if (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- else if (TYPE_FIELDS (type))
- type = TREE_TYPE (TYPE_FIELDS (type));
- else
- {
- error_init ("invalid initializer");
- return error_mark_node;
- }
- }
-
- if (otype != type)
- {
- TREE_OPERAND (prev, 1)
- = build_tree_list (NULL_TREE,
- digest_init (type, init, require_constant,
- constructor_constant));
- return top;
- }
- else
- return error_mark_node;
- }
error_init ("invalid initializer");
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_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))
;
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. */
|| TREE_CHAIN (field)))))
return;
- value = digest_init (type, value, require_constant_value,
- require_constant_elements);
+ value = digest_init (type, value, require_constant_value);
if (value == error_mark_node)
{
constructor_erroneous = 1;
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. */
tree res = DECL_RESULT (current_function_decl);
tree inner;
+ current_function_returns_value = 1;
if (t == error_mark_node)
return NULL_TREE;
}
retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
- current_function_returns_value = 1;
}
return add_stmt (build_return_stmt (retval));
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");
/* 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;