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 *,
return decl_constant_value (decl);
}
+
+/* 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);
+ int not_lvalue = 0;
+
+ /* 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)))
+ {
+ 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));
+
+ if (code == FUNCTION_TYPE)
+ {
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
+ if (code == ARRAY_TYPE)
+ {
+ tree adr;
+ tree restype = TREE_TYPE (type);
+ tree ptrtype;
+ int constp = 0;
+ int volatilep = 0;
+ int lvalue_array_p;
+
+ if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
+ {
+ constp = TREE_READONLY (exp);
+ volatilep = TREE_THIS_VOLATILE (exp);
+ }
+
+ if (TYPE_QUALS (type) || constp || volatilep)
+ restype
+ = c_build_qualified_type (restype,
+ TYPE_QUALS (type)
+ | (constp * TYPE_QUAL_CONST)
+ | (volatilep * TYPE_QUAL_VOLATILE));
+
+ if (TREE_CODE (exp) == INDIRECT_REF)
+ return convert (TYPE_POINTER_TO (restype),
+ TREE_OPERAND (exp, 0));
+
+ if (TREE_CODE (exp) == COMPOUND_EXPR)
+ {
+ tree op1 = default_conversion (TREE_OPERAND (exp, 1));
+ return build (COMPOUND_EXPR, TREE_TYPE (op1),
+ TREE_OPERAND (exp, 0), op1);
+ }
+
+ lvalue_array_p = !not_lvalue && lvalue_p (exp);
+ if (!flag_isoc99 && !lvalue_array_p
+ && !(TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
+ {
+ /* 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);
+
+ if (TREE_CODE (exp) == VAR_DECL)
+ {
+ /* ??? This is not really quite correct
+ in that the type of the operand of ADDR_EXPR
+ 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)
+ return error_mark_node;
+ TREE_CONSTANT (adr) = staticp (exp);
+ TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
+ return adr;
+ }
+ /* This way is better for a COMPONENT_REF since it can
+ simplify the offset for a component. */
+ adr = build_unary_op (ADDR_EXPR, exp, 1);
+ return convert (ptrtype, adr);
+ }
+ return exp;
+}
+
/* Perform default promotions for C data used in expressions.
Arrays and functions are converted to pointers;
enumeral types or short or char, to int.
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);
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)
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);
- }
- if (code == ARRAY_TYPE)
- {
- tree adr;
- tree restype = TREE_TYPE (type);
- tree ptrtype;
- int constp = 0;
- int volatilep = 0;
-
- if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
- {
- constp = TREE_READONLY (exp);
- volatilep = TREE_THIS_VOLATILE (exp);
- }
-
- if (TYPE_QUALS (type) || constp || volatilep)
- restype
- = c_build_qualified_type (restype,
- TYPE_QUALS (type)
- | (constp * TYPE_QUAL_CONST)
- | (volatilep * TYPE_QUAL_VOLATILE));
-
- if (TREE_CODE (exp) == INDIRECT_REF)
- return convert (TYPE_POINTER_TO (restype),
- TREE_OPERAND (exp, 0));
-
- if (TREE_CODE (exp) == COMPOUND_EXPR)
- {
- tree op1 = default_conversion (TREE_OPERAND (exp, 1));
- return build (COMPOUND_EXPR, TREE_TYPE (op1),
- TREE_OPERAND (exp, 0), op1);
- }
-
- if (! lvalue_p (exp)
- && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
- {
- error ("invalid use of non-lvalue array");
- return error_mark_node;
- }
-
- ptrtype = build_pointer_type (restype);
-
- if (TREE_CODE (exp) == VAR_DECL)
- {
- /* ??? This is not really quite correct
- in that the type of the operand of ADDR_EXPR
- 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)
- return error_mark_node;
- TREE_CONSTANT (adr) = staticp (exp);
- TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
- return adr;
- }
- /* This way is better for a COMPONENT_REF since it can
- simplify the offset for a component. */
- adr = build_unary_op (ADDR_EXPR, exp, 1);
- return convert (ptrtype, adr);
- }
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. */
+/* 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);
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_READONLY (datum) || TREE_READONLY (field))
- TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
- TREE_THIS_VOLATILE (ref) = 1;
-
return ref;
}
else if (code != ERROR_MARK)
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);
tree type1 = TREE_TYPE (would_have_been);
if (TREE_CODE (type) == ENUMERAL_TYPE
- && type == TREE_TYPE (val))
+ && (TYPE_MAIN_VARIANT (type)
+ == TYPE_MAIN_VARIANT (TREE_TYPE (val))))
/* No warning if function asks for enum
and the actual arg is that enum type. */
;
enum tree_code code1 = ERROR_MARK;
enum tree_code code2 = ERROR_MARK;
- if (class1 == 'e' || class1 == '1'
- || class1 == '2' || class1 == '<')
+ if (IS_EXPR_CODE_CLASS (class1))
code1 = C_EXP_ORIGINAL_CODE (arg1);
- if (class2 == 'e' || class2 == '1'
- || class2 == '2' || class2 == '<')
+ if (IS_EXPR_CODE_CLASS (class2))
code2 = C_EXP_ORIGINAL_CODE (arg2);
/* Check for cases such as x+y<<z which users are likely
/* Record the code that was specified in the source,
for the sake of warnings about confusing nesting. */
- if (class == 'e' || class == '1'
- || class == '2' || class == '<')
+ if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE (result, code);
else
{
\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;
/* 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;
if (typecode != POINTER_TYPE
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
{
- error ("wrong type argument to %s",
- code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
- ? "increment" : "decrement");
+ if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+ error ("wrong type argument to increment");
+ else
+ error ("wrong type argument to decrement");
+
return error_mark_node;
}
/* 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)))
- error ("%s of pointer to unknown structure",
- code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
- ? "increment" : "decrement");
+ {
+ 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))
- pedwarn ("wrong type argument to %s",
- code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
- ? "increment" : "decrement");
+ {
+ 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
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)
/* 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;
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;
{
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))
{
/* 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;
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)),
/* 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. */
}
}
- /* Pedantically, don't ley (void *) (FOO *) 0 be a null pointer constant. */
+ /* 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)
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;
&& 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);
+ if (code == POINTER_TYPE)
+ inside_init = default_function_array_conversion (inside_init);
else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
&& TREE_CODE (inside_init) != CONSTRUCTOR)
{
/* Nonzero if this is an initializer for a top-level decl. */
static int constructor_top_level;
+/* Nonzero if there were any member designators in this initializer. */
+static int constructor_designated;
+
/* Nesting depth of designator list. */
static int designator_depth;
char erroneous;
char outer;
char incremental;
+ char designated;
};
struct constructor_stack *constructor_stack;
constructor_decl = decl;
constructor_asmspec = asmspec;
constructor_subconstants_deferred = 0;
+ constructor_designated = 0;
constructor_top_level = top_level;
if (decl != 0)
p->range_stack = 0;
p->outer = 0;
p->incremental = constructor_incremental;
+ p->designated = constructor_designated;
p->next = 0;
constructor_stack = p;
constructor_pending_elts = 0;
constructor_type = type;
constructor_incremental = 1;
+ constructor_designated = 0;
designator_depth = 0;
designator_errorneous = 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_depth = SPELLING_DEPTH ();
constructor_elements = 0;
constructor_incremental = 1;
+ constructor_designated = 0;
constructor_pending_elts = 0;
if (!implicit)
{
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 if (pedantic)
pedwarn_init ("initialization of a flexible array member");
- /* We have already issued an error message for the existance
+ /* 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)
|| integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
- if (constructor_unfilled_fields)
+ /* 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");
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)
braces. */
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
+ constructor_designated = 1;
return 0;
}
return 1;
}
+ constructor_designated = 1;
push_init_level (2);
return 0;
}
}
\f
/* Add a new initializer to the tree of pending initializers. PURPOSE
- indentifies the initializer, either array index or field in a structure.
+ identifies the initializer, either array index or field in a structure.
VALUE is the value of that index or field. */
static void
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. */
- if (warn_traditional && !in_system_header
+ 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");
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));