/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "rtl.h"
#include "tree.h"
#include "c-tree.h"
#include "tm_p.h"
#include "flags.h"
#include "output.h"
-#include "rtl.h"
#include "expr.h"
#include "toplev.h"
#include "intl.h"
static int function_types_compatible_p PARAMS ((tree, tree));
static int type_lists_compatible_p PARAMS ((tree, tree));
static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
-static tree lookup_field PARAMS ((tree, tree, 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));
+static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int));
static void pedantic_lvalue_warning PARAMS ((enum tree_code));
static tree internal_build_compound_expr PARAMS ((tree, int));
static tree convert_for_assignment PARAMS ((tree, tree, const char *,
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));
{
tree type = TREE_TYPE (value);
- if (TREE_CODE (value) == ERROR_MARK)
+ if (value == error_mark_node || type == error_mark_node)
return error_mark_node;
/* First, detect a valid value with a complete type. */
if (COMPLETE_TYPE_P (type))
return value;
- incomplete_type_error (value, type);
+ c_incomplete_type_error (value, type);
return error_mark_node;
}
and TYPE is the type that was invalid. */
void
-incomplete_type_error (value, type)
+c_incomplete_type_error (value, type)
tree value;
tree 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;
}
}
}
+/* Given a type, apply default promotions wrt unnamed function
+ arguments and return the new type. */
+
+tree
+c_type_promotes_to (type)
+ tree type;
+{
+ if (TYPE_MAIN_VARIANT (type) == float_type_node)
+ return double_type_node;
+
+ if (c_promoting_integer_type_p (type))
+ {
+ /* Preserve unsignedness if not really getting any wider. */
+ if (TREE_UNSIGNED (type)
+ && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+ return unsigned_type_node;
+ return integer_type_node;
+ }
+
+ return type;
+}
+
/* Return a variant of TYPE which has all the type qualifiers of LIKE
as well as those of TYPE. */
/* Treat an enum type as the unsigned integer type of the same width. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
+ t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
+ t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
signedness. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
+ t1 = c_common_type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
+ t2 = c_common_type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
if (t1 == t2)
return 1;
So match anything that self-promotes. */
if (TREE_VALUE (args1) == 0)
{
- if (simple_type_promotes_to (TREE_VALUE (args2)) != NULL_TREE)
+ if (c_type_promotes_to (TREE_VALUE (args2)) != TREE_VALUE (args2))
return 0;
}
else if (TREE_VALUE (args2) == 0)
{
- if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE)
+ if (c_type_promotes_to (TREE_VALUE (args1)) != TREE_VALUE (args1))
return 0;
}
else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
return decl_constant_value (decl);
}
-/* Perform default promotions for C data used in expressions.
- Arrays and functions are converted to pointers;
- enumeral types or short or char, to int.
- In addition, manifest constants symbols are replaced by their values. */
-tree
-default_conversion (exp)
+/* Perform the default conversion of arrays and functions to pointers.
+ Return the result of converting EXP. For any other expression, just
+ return EXP. */
+
+static tree
+default_function_array_conversion (exp)
tree exp;
{
tree orig_exp;
tree type = TREE_TYPE (exp);
enum tree_code code = TREE_CODE (type);
-
- /* Constants can be used directly unless they're not loadable. */
- if (TREE_CODE (exp) == CONST_DECL)
- exp = DECL_INITIAL (exp);
-
- /* Replace a nonvolatile const static variable with its value unless
- it is an array, in which case we must be sure that taking the
- address of the array produces consistent results. */
- else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
- {
- exp = decl_constant_value_for_broken_optimization (exp);
- type = TREE_TYPE (exp);
- }
+ int not_lvalue = 0;
/* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as
an lvalue.
while (TREE_CODE (exp) == NON_LVALUE_EXPR
|| (TREE_CODE (exp) == NOP_EXPR
&& TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
- exp = TREE_OPERAND (exp, 0);
+ {
+ if (TREE_CODE (exp) == NON_LVALUE_EXPR)
+ not_lvalue = 1;
+ exp = TREE_OPERAND (exp, 0);
+ }
/* Preserve the original expression code. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp))))
C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
- /* Normally convert enums to int,
- but convert wide enums to something wider. */
- if (code == ENUMERAL_TYPE)
- {
- type = type_for_size (MAX (TYPE_PRECISION (type),
- TYPE_PRECISION (integer_type_node)),
- ((flag_traditional
- || (TYPE_PRECISION (type)
- >= TYPE_PRECISION (integer_type_node)))
- && TREE_UNSIGNED (type)));
-
- return convert (type, exp);
- }
-
- if (TREE_CODE (exp) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
- /* If it's thinner than an int, promote it like a
- 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);
-
- if (c_promoting_integer_type_p (type))
- {
- /* Traditionally, unsignedness is preserved in default promotions.
- Also preserve unsignedness if not really getting any wider. */
- if (TREE_UNSIGNED (type)
- && (flag_traditional
- || 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 (code == FUNCTION_TYPE)
{
return build_unary_op (ADDR_EXPR, exp, 0);
tree ptrtype;
int constp = 0;
int volatilep = 0;
+ int lvalue_array_p;
if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
{
TREE_OPERAND (exp, 0), op1);
}
- if (! lvalue_p (exp)
- && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
+ lvalue_array_p = !not_lvalue && lvalue_p (exp);
+ if (!flag_isoc99 && !lvalue_array_p)
{
- error ("invalid use of non-lvalue array");
- return error_mark_node;
+ /* Before C99, non-lvalue arrays do not decay to pointers.
+ Normally, using such an array would be invalid; but it can
+ be used correctly inside sizeof or as a statement expression.
+ Thus, do not give an error here; an error will result later. */
+ return exp;
}
ptrtype = build_pointer_type (restype);
is not the target type of the type of the ADDR_EXPR itself.
Question is, can this lossage be avoided? */
adr = build1 (ADDR_EXPR, ptrtype, exp);
- if (mark_addressable (exp) == 0)
+ if (!c_mark_addressable (exp))
return error_mark_node;
TREE_CONSTANT (adr) = staticp (exp);
TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
}
return exp;
}
-\f
-/* Look up component name in the structure type definition.
- If this component name is found indirectly within an anonymous union,
- store in *INDIRECT the component which directly contains
- that anonymous union. Otherwise, set *INDIRECT to 0. */
+/* Perform default promotions for C data used in expressions.
+ Arrays and functions are converted to pointers;
+ enumeral types or short or char, to int.
+ In addition, manifest constants symbols are replaced by their values. */
+
+tree
+default_conversion (exp)
+ tree exp;
+{
+ tree orig_exp;
+ tree type = TREE_TYPE (exp);
+ enum tree_code code = TREE_CODE (type);
+
+ if (code == FUNCTION_TYPE || code == ARRAY_TYPE)
+ return default_function_array_conversion (exp);
+
+ /* Constants can be used directly unless they're not loadable. */
+ if (TREE_CODE (exp) == CONST_DECL)
+ exp = DECL_INITIAL (exp);
+
+ /* Replace a nonvolatile const static variable with its value unless
+ it is an array, in which case we must be sure that taking the
+ address of the array produces consistent results. */
+ else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
+ {
+ exp = decl_constant_value_for_broken_optimization (exp);
+ type = TREE_TYPE (exp);
+ }
+
+ /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as
+ an lvalue.
+
+ Do not use STRIP_NOPS here! It will remove conversions from pointer
+ to integer and cause infinite recursion. */
+ orig_exp = exp;
+ while (TREE_CODE (exp) == NON_LVALUE_EXPR
+ || (TREE_CODE (exp) == NOP_EXPR
+ && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
+ exp = TREE_OPERAND (exp, 0);
+
+ /* Preserve the original expression code. */
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp))))
+ C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
+
+ /* Normally convert enums to int,
+ but convert wide enums to something wider. */
+ if (code == ENUMERAL_TYPE)
+ {
+ type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+ TYPE_PRECISION (integer_type_node)),
+ ((TYPE_PRECISION (type)
+ >= TYPE_PRECISION (integer_type_node))
+ && TREE_UNSIGNED (type)));
+
+ return convert (type, exp);
+ }
+
+ if (TREE_CODE (exp) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
+ /* If it's thinner than an int, promote it like a
+ 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 (integer_type_node, exp);
+
+ if (c_promoting_integer_type_p (type))
+ {
+ /* Preserve unsignedness if not really getting any wider. */
+ if (TREE_UNSIGNED (type)
+ && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+ return convert (unsigned_type_node, exp);
+
+ return convert (integer_type_node, exp);
+ }
+
+ if (code == VOID_TYPE)
+ {
+ error ("void value not ignored as it ought to be");
+ return error_mark_node;
+ }
+ return exp;
+}
+\f
+/* Look up COMPONENT in a structure or union DECL.
+
+ If the component name is not found, returns NULL_TREE. Otherwise,
+ the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
+ stepping down the chain to the component, which is in the last
+ TREE_VALUE of the list. Normally the list is of length one, but if
+ the component is embedded within (nested) anonymous structures or
+ unions, the list steps down the chain to the component. */
static tree
-lookup_field (type, component, indirect)
- tree type, component;
- tree *indirect;
+lookup_field (decl, component)
+ tree decl, component;
{
+ tree type = TREE_TYPE (decl);
tree field;
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
/* Step through all anon unions in linear fashion. */
while (DECL_NAME (field_array[bot]) == NULL_TREE)
{
- tree anon = 0, junk;
-
field = field_array[bot++];
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
- anon = lookup_field (TREE_TYPE (field), component, &junk);
-
- if (anon != NULL_TREE)
{
- *indirect = field;
- return anon;
- }
+ tree anon = lookup_field (field, component);
+
+ if (anon)
+ return tree_cons (NULL_TREE, field, anon);
+ }
}
/* Entire record is only anon unions. */
if (DECL_NAME (field_array[bot]) == component)
field = field_array[bot];
else if (DECL_NAME (field) != component)
- field = 0;
+ return NULL_TREE;
}
else
{
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
- if (DECL_NAME (field) == NULL_TREE)
+ if (DECL_NAME (field) == NULL_TREE
+ && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
{
- tree junk;
- tree anon = 0;
+ tree anon = lookup_field (field, component);
- if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
- || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
- anon = lookup_field (TREE_TYPE (field), component, &junk);
-
- if (anon != NULL_TREE)
- {
- *indirect = field;
- return anon;
- }
+ if (anon)
+ return tree_cons (NULL_TREE, field, anon);
}
if (DECL_NAME (field) == component)
break;
}
+
+ if (field == NULL_TREE)
+ return NULL_TREE;
}
- *indirect = NULL_TREE;
- return field;
+ return tree_cons (NULL_TREE, field, NULL_TREE);
}
/* Make an expression to refer to the COMPONENT field of
tree field = NULL;
tree ref;
- /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it
- unless we are not to support things not strictly ANSI. */
+ /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
+ If pedantic ensure that the arguments are not lvalues; otherwise,
+ if the component is an array, it would wrongly decay to a pointer in
+ C89 mode.
+ We cannot do this with a COND_EXPR, because in a conditional expression
+ the default promotions are applied to both sides, and this would yield
+ the wrong type of the result; for example, if the components have
+ type "char". */
switch (TREE_CODE (datum))
{
case COMPOUND_EXPR:
{
tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
return build (COMPOUND_EXPR, TREE_TYPE (value),
- TREE_OPERAND (datum, 0), value);
+ TREE_OPERAND (datum, 0), pedantic_non_lvalue (value));
}
- case COND_EXPR:
- return build_conditional_expr
- (TREE_OPERAND (datum, 0),
- build_component_ref (TREE_OPERAND (datum, 1), component),
- build_component_ref (TREE_OPERAND (datum, 2), component));
-
default:
break;
}
if (code == RECORD_TYPE || code == UNION_TYPE)
{
- tree indirect = 0;
-
if (!COMPLETE_TYPE_P (type))
{
- incomplete_type_error (NULL_TREE, type);
+ c_incomplete_type_error (NULL_TREE, type);
return error_mark_node;
}
- field = lookup_field (type, component, &indirect);
+ field = lookup_field (datum, component);
if (!field)
{
IDENTIFIER_POINTER (component));
return error_mark_node;
}
- if (TREE_TYPE (field) == error_mark_node)
- return error_mark_node;
- /* If FIELD was found buried within an anonymous union,
- make one COMPONENT_REF to get that anonymous union,
- then fall thru to make a second COMPONENT_REF to get FIELD. */
- if (indirect != 0)
+ /* Chain the COMPONENT_REFs if necessary down to the FIELD.
+ This might be better solved in future the way the C++ front
+ end does it - by giving the anonymous entities each a
+ separate name and type, and then have build_component_ref
+ recursively call itself. We can't do that here. */
+ for (; field; field = TREE_CHAIN (field))
{
- ref = build (COMPONENT_REF, TREE_TYPE (indirect), datum, indirect);
- if (TREE_READONLY (datum) || TREE_READONLY (indirect))
+ tree subdatum = TREE_VALUE (field);
+
+ if (TREE_TYPE (subdatum) == error_mark_node)
+ return error_mark_node;
+
+ ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum);
+ if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (indirect))
+ if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
TREE_THIS_VOLATILE (ref) = 1;
- datum = ref;
- }
- ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
+ if (TREE_DEPRECATED (subdatum))
+ warn_deprecated_use (subdatum);
- if (TREE_READONLY (datum) || TREE_READONLY (field))
- TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
- TREE_THIS_VOLATILE (ref) = 1;
+ datum = ref;
+ }
return ref;
}
|| (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
{
- if (mark_addressable (array) == 0)
+ if (!c_mark_addressable (array))
return error_mark_node;
}
/* An array that is indexed by a constant value which is not within
&& TYPE_VALUES (TREE_TYPE (array))
&& ! int_fits_type_p (index, TYPE_VALUES (TREE_TYPE (array))))
{
- if (mark_addressable (array) == 0)
+ if (!c_mark_addressable (array))
return error_mark_node;
}
tree decl = lookup_name (id);
tree objc_ivar = lookup_objc_ivar (id);
+ if (decl && TREE_DEPRECATED (decl))
+ warn_deprecated_use (decl);
+
if (!decl || decl == error_mark_node || C_DECL_ANTICIPATED (decl))
{
if (objc_ivar)
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);
if (TREE_CODE (val) == NON_LVALUE_EXPR)
val = TREE_OPERAND (val, 0);
- if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE)
- val = default_conversion (val);
+ val = default_function_array_conversion (val);
val = require_complete_type (val);
enum tree_code code1 = ERROR_MARK;
enum tree_code code2 = ERROR_MARK;
+ if (TREE_CODE (result) == ERROR_MARK)
+ return error_mark_node;
+
if (IS_EXPR_CODE_CLASS (class1))
code1 = C_EXP_ORIGINAL_CODE (arg1);
if (IS_EXPR_CODE_CLASS (class2))
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:
but that does not mean the operands should be
converted to ints! */
result_type = integer_type_node;
- op0 = truthvalue_conversion (op0);
- op1 = truthvalue_conversion (op1);
+ op0 = c_common_truthvalue_conversion (op0);
+ op1 = c_common_truthvalue_conversion (op1);
converted = 1;
}
break;
}
}
- /* 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;
&& unsigned0 == unsigned1
&& (unsigned0 || !uns))
result_type
- = signed_or_unsigned_type (unsigned0,
- common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+ = 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 = signed_or_unsigned_type (unsigned1,
- TREE_TYPE (arg1)),
+ && (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 = signed_or_unsigned_type (unsigned0,
- TREE_TYPE (arg0)),
+ && (type
+ = c_common_signed_or_unsigned_type (unsigned0,
+ TREE_TYPE (arg0)),
int_fits_type_p (arg1, type)))
result_type = type;
}
{
/* Do an unsigned shift if the operand was zero-extended. */
result_type
- = signed_or_unsigned_type (unsigned_arg, TREE_TYPE (arg0));
+ = 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);
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, signed_type (result_type)))
+ && 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)),
- signed_type (result_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");
}
}
\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. */
\f
/* Construct and perhaps optimize a tree representation
for a unary operation. CODE, a tree_code, specifies the operation
- and XARG is the operand. NOCONVERT nonzero suppresses
- the default promotions (such as from short to int). */
+ 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. */
tree
-build_unary_op (code, xarg, noconvert)
+build_unary_op (code, xarg, flag)
enum tree_code code;
tree xarg;
- int noconvert;
+ 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;
if (typecode == ERROR_MARK)
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
+ arg = non_lvalue (arg);
break;
case NEGATE_EXPR:
error ("wrong type argument to unary exclamation mark");
return error_mark_node;
}
- arg = truthvalue_conversion (arg);
+ arg = c_common_truthvalue_conversion (arg);
return invert_truthvalue (arg);
case NOP_EXPR:
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
- val = unary_complex_lvalue (code, arg);
+ val = unary_complex_lvalue (code, arg, 0);
if (val != 0)
return val;
readonly_warning (arg,
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
- ? _("increment") : _("decrement")));
+ ? "increment" : "decrement"));
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
val = boolean_increment (code, arg);
}
case ADDR_EXPR:
- /* Note that this operation never does default_conversion
- regardless of NOCONVERT. */
+ /* Note that this operation never does default_conversion. */
/* Let &* cancel out to simplify resulting code. */
if (TREE_CODE (arg) == INDIRECT_REF)
/* For &x[y], return x+y */
if (TREE_CODE (arg) == ARRAY_REF)
{
- if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
+ 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);
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
- val = unary_complex_lvalue (code, arg);
+ val = unary_complex_lvalue (code, arg, flag);
if (val != 0)
return val;
}
#endif
- /* Allow the address of a constructor if all the elements
- are constant. */
- if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg))
- ;
/* Anything not already handled and not a true memory reference
- is an error. */
- else if (typecode != FUNCTION_TYPE
+ 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;
argtype = build_pointer_type (argtype);
- if (mark_addressable (arg) == 0)
+ if (!c_mark_addressable (arg))
return error_mark_node;
{
{
tree field = TREE_OPERAND (arg, 1);
- addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
+ addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
if (DECL_C_BIT_FIELD (field))
{
case COMPONENT_REF:
return lvalue_p (TREE_OPERAND (ref, 0));
+ case COMPOUND_LITERAL_EXPR:
case STRING_CST:
return 1;
/* 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.
+ 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. */
static tree
-unary_complex_lvalue (code, arg)
+unary_complex_lvalue (code, arg, flag)
enum tree_code code;
tree arg;
+ int flag;
{
/* Handle (a, b) used as an "lvalue". */
if (TREE_CODE (arg) == COMPOUND_EXPR)
/* 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)
+ if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
pedantic_lvalue_warning (COMPOUND_EXPR);
return build (COMPOUND_EXPR, TREE_TYPE (real_result),
/* Handle (a ? b : c) used as an "lvalue". */
if (TREE_CODE (arg) == COND_EXPR)
{
- pedantic_lvalue_warning (COND_EXPR);
- if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE)
+ if (!flag)
+ pedantic_lvalue_warning (COND_EXPR);
+ if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
pedantic_lvalue_warning (COMPOUND_EXPR);
return (build_conditional_expr
(TREE_OPERAND (arg, 0),
- build_unary_op (code, TREE_OPERAND (arg, 1), 0),
- build_unary_op (code, TREE_OPERAND (arg, 2), 0)));
+ build_unary_op (code, TREE_OPERAND (arg, 1), flag),
+ build_unary_op (code, TREE_OPERAND (arg, 2), flag)));
}
return 0;
\f
/* Mark EXP saying that we need to be able to take the
address of it; it should not be allocated in a register.
- Value is 1 if successful. */
+ Returns true if successful. */
-int
-mark_addressable (exp)
+bool
+c_mark_addressable (exp)
tree exp;
{
tree x = exp;
+
while (1)
switch (TREE_CODE (x))
{
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
{
- error ("cannot take address of bitfield `%s'",
+ error ("cannot take address of bit-field `%s'",
IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
- return 0;
+ return false;
}
/* ... fall through ... */
x = TREE_OPERAND (x, 0);
break;
+ case COMPOUND_LITERAL_EXPR:
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
- return 1;
+ return true;
case VAR_DECL:
case CONST_DECL:
{
error ("global register variable `%s' used in nested function",
IDENTIFIER_POINTER (DECL_NAME (x)));
- return 0;
+ return false;
}
pedwarn ("register variable `%s' used in nested function",
IDENTIFIER_POINTER (DECL_NAME (x)));
{
error ("address of global register variable `%s' requested",
IDENTIFIER_POINTER (DECL_NAME (x)));
- return 0;
+ return false;
}
/* If we are making this addressable due to its having
else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x)))
{
error ("cannot put object with volatile field into register");
- return 0;
+ return false;
}
pedwarn ("address of register variable `%s' requested",
#endif
default:
- return 1;
+ return true;
}
}
\f
tree result_type = NULL;
tree orig_op1 = op1, orig_op2 = op2;
- ifexp = truthvalue_conversion (default_conversion (ifexp));
+ ifexp = c_common_truthvalue_conversion (default_conversion (ifexp));
#if 0 /* Produces wrong result if within sizeof. */
/* Don't promote the operands separately if they promote
if (TREE_CHAIN (list) == 0)
{
- /* Convert arrays to pointers when there really is a comma operator. */
- if (!first_p && TREE_CODE (TREE_TYPE (TREE_VALUE (list))) == ARRAY_TYPE)
- TREE_VALUE (list) = default_conversion (TREE_VALUE (list));
+ /* 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 0 /* If something inside inhibited lvalueness, we should not override. */
/* Consider (x, y+0), which is not an lvalue since y+0 is not. */
else if (TREE_CODE (type) == UNION_TYPE)
{
tree field;
- if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE)
- value = default_conversion (value);
+ value = default_function_array_conversion (value);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
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;
}
/* Convert functions and arrays to pointers,
but don't convert any other types. */
- if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE)
- value = default_conversion (value);
+ value = default_function_array_conversion (value);
otype = TREE_TYPE (value);
/* Optionally warn about potentially worrisome casts. */
{
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");
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
- if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE)
- newrhs = default_conversion (newrhs);
+ newrhs = default_function_array_conversion (newrhs);
{
tree inner_lhs = TREE_OPERAND (lhs, 0);
tree result;
if (codel == REFERENCE_TYPE
&& comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
{
- if (mark_addressable (rhs) == 0)
+ 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);
/* Conversions among pointers */
else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
- && (coder == POINTER_TYPE || coder == REFERENCE_TYPE))
+ && (coder == codel))
{
tree ttl = TREE_TYPE (type);
tree ttr = TREE_TYPE (rhstype);
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)
- || (unsigned_type (TYPE_MAIN_VARIANT (ttl))
- == unsigned_type (TYPE_MAIN_VARIANT (ttr))))
+ || (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)
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'".
}
else
{
- /* Function name unknown (call through ptr); just give arg number.*/
+ /* 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);
/* 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. */
/* ANSI wants warnings about out-of-range constant initializers. */
STRIP_TYPE_NOPS (value);
constant_expression_warning (value);
+
+ /* 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;
+
+ 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);
+ }
+ }
+ }
}
\f
/* Methods for storing and printing names for error messages. */
{
char *ofwhat;
- error ("%s", msgid);
+ error ("%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
error ("(near initialization for `%s')", ofwhat);
{
char *ofwhat;
- pedwarn ("%s", msgid);
+ pedwarn ("%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
pedwarn ("(near initialization for `%s')", ofwhat);
{
char *ofwhat;
- warning ("%s", msgid);
+ 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.
- 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;
if (type == error_mark_node
|| init == error_mark_node
- || TREE_TYPE (init) == error_mark_node)
+ || TREE_TYPE (init) == error_mark_node)
return error_mark_node;
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
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)
&& comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
TREE_TYPE (type)))))
{
- if (code == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE))
- inside_init = default_conversion (inside_init);
- else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
- && TREE_CODE (inside_init) != CONSTRUCTOR)
+ if (code == POINTER_TYPE)
+ inside_init = default_function_array_conversion (inside_init);
+
+ 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);
+ }
+
+ 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;
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;
}
&& 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 an 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)));
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))
&& 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 an 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)));
int implicit;
{
struct constructor_stack *p;
- HOST_WIDE_INT size = 0;
tree constructor = 0;
if (implicit == 0)
p = constructor_stack;
- if (constructor_type != 0)
- size = int_size_in_bytes (constructor_type);
-
/* Error for initializing a flexible array member, or a zero-length
array member in an inappropriate context. */
if (constructor_type && constructor_fields
else
/* Zero-length arrays are no longer special, so we should no longer
get here. */
- abort();
+ abort ();
}
/* Warn when some struct elements are implicitly initialized to zero. */
;
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. */
TYPE_MAIN_VARIANT (type))))
value = default_conversion (value);
+ if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
+ && require_constant_value && !flag_isoc99 && pending)
+ {
+ /* 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 (value == error_mark_node)
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
|| TREE_CHAIN (field)))))
return;
+ value = digest_init (type, value, require_constant_value);
if (value == error_mark_node)
{
constructor_erroneous = 1;
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init ();
- add_pending_init (field,
- digest_init (type, value, require_constant_value,
- require_constant_elements));
+ add_pending_init (field, value);
return;
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
}
}
- add_pending_init (field,
- digest_init (type, value, require_constant_value,
- require_constant_elements));
+ add_pending_init (field, value);
return;
}
else if (TREE_CODE (constructor_type) == UNION_TYPE
if (field && TREE_CODE (field) == INTEGER_CST)
field = copy_node (field);
constructor_elements
- = tree_cons (field, digest_init (type, value,
- require_constant_value,
- require_constant_elements),
- constructor_elements);
+ = tree_cons (field, value, constructor_elements);
/* Advance the variable that indicates sequential elements output. */
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
/* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */
if (constructor_range_stack)
- value = save_expr (value);
+ {
+ /* 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);
+ }
while (1)
{
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
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 stmt;
- if (TREE_CHAIN (expr))
- expr = combine_strings (expr);
stmt = add_stmt (build_stmt (ASM_STMT, NULL_TREE, expr,
NULL_TREE, NULL_TREE,
NULL_TREE));
{
tree tail;
- if (TREE_CHAIN (string))
- string = combine_strings (string);
if (TREE_CODE (string) != STRING_CST)
{
error ("asm template is not a string constant");
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))
- if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
- TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
+ TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail));
return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
outputs, inputs, clobbers));
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");
}
else
{
- tree index;
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
if (warn_traditional && !in_system_header
exp = default_conversion (exp);
type = TREE_TYPE (exp);
- index = get_unwidened (exp, NULL_TREE);
- /* We can't strip a conversion from a signed type to an
- unsigned, because if we did, int_fits_type_p would do the
- wrong thing when checking case values for being in range,
- and it's too hard to do the right thing. */
- if (TREE_UNSIGNED (TREE_TYPE (exp))
- == TREE_UNSIGNED (TREE_TYPE (index)))
- exp = index;
}
}
/* 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;