/* 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 "coretypes.h"
+#include "tm.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 undeclared_variable_notice;
static tree qualify_type PARAMS ((tree, tree));
-static int comp_target_types PARAMS ((tree, tree));
+static int comp_target_types PARAMS ((tree, tree, int));
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;
}
case RECORD_TYPE:
- if (maybe_objc_comptypes (t1, t2, 0) == 1)
+ if (flag_objc && objc_comptypes (t1, t2, 0) == 1)
val = 1;
break;
+ case VECTOR_TYPE:
+ /* The target might allow certain vector types to be compatible. */
+ val = (*targetm.vector_opaque_p) (t1)
+ || (*targetm.vector_opaque_p) (t2);
+ break;
+
default:
break;
}
}
/* Return 1 if TTL and TTR are pointers to types that are equivalent,
- ignoring their qualifiers. */
+ ignoring their qualifiers. REFLEXIVE is only used by ObjC - set it
+ to 1 or 0 depending if the check of the pointer types is meant to
+ be reflexive or not (typically, assignments are not reflexive,
+ while comparisons are reflexive).
+*/
static int
-comp_target_types (ttl, ttr)
+comp_target_types (ttl, ttr, reflexive)
tree ttl, ttr;
+ int reflexive;
{
int val;
- /* Give maybe_objc_comptypes a crack at letting these types through. */
- if ((val = maybe_objc_comptypes (ttl, ttr, 1)) >= 0)
+ /* Give objc_comptypes a crack at letting these types through. */
+ if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0)
return val;
val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
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)),
}
}
\f
-/* Compute the value of the `sizeof' operator. */
-
-tree
-c_sizeof (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree size;
-
- if (code == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("sizeof applied to a function type");
- size = size_one_node;
- }
- else if (code == VOID_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("sizeof applied to a void type");
- size = size_one_node;
- }
- else if (code == ERROR_MARK)
- size = size_one_node;
- else if (!COMPLETE_TYPE_P (type))
- {
- error ("sizeof applied to an incomplete type");
- size = size_zero_node;
- }
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- return fold (build1 (NOP_EXPR, c_size_type_node, size));
-}
-
-tree
-c_sizeof_nowarn (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree size;
-
- if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
- size = size_one_node;
- else if (!COMPLETE_TYPE_P (type))
- size = size_zero_node;
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- return fold (build1 (NOP_EXPR, c_size_type_node, size));
-}
-
/* Compute the size to increment a pointer by. */
tree
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.
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);
-
- /* 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 (TREE_CODE (exp) == NON_LVALUE_EXPR)
+ not_lvalue = 1;
+ exp = TREE_OPERAND (exp, 0);
}
- if (flag_traditional && !flag_allow_single_precision
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
+ /* 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 == 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;
-
- if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
- || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
- anon = lookup_field (TREE_TYPE (field), component, &junk);
+ tree anon = lookup_field (field, component);
- 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;
}
if (TREE_CODE (type) == POINTER_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
- && !flag_volatile
&& (TREE_TYPE (TREE_OPERAND (pointer, 0))
== TREE_TYPE (type)))
return TREE_OPERAND (pointer, 0);
to change it via some other pointer. */
TREE_READONLY (ref) = TYPE_READONLY (t);
TREE_SIDE_EFFECTS (ref)
- = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) || flag_volatile;
+ = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
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;
}
if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
pedwarn ("ISO C forbids subscripting `register' array");
else if (! flag_isoc99 && ! lvalue_p (foo))
- pedwarn ("ISO C89 forbids subscripting non-lvalue array");
+ pedwarn ("ISO C90 forbids subscripting non-lvalue array");
}
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
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)
if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node;
- assemble_external (ref);
+ if (!skip_evaluation)
+ assemble_external (ref);
TREE_USED (ref) = 1;
if (TREE_CODE (ref) == CONST_DECL)
{
tree fntype, fundecl = 0;
tree coerced_params;
- tree name = NULL_TREE, assembler_name = NULL_TREE, result;
+ tree name = NULL_TREE, result;
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (function);
if (TREE_CODE (function) == FUNCTION_DECL)
{
name = DECL_NAME (function);
- assembler_name = DECL_ASSEMBLER_NAME (function);
/* Differs from default_conversion by not setting TREE_ADDRESSABLE
(because calling an inline function does not mean the function
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);
coerced_params
= convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl);
- /* Check for errors in format strings. */
+ /* Check that the arguments to the function are valid. */
- if (warn_format)
- check_function_format (NULL, TYPE_ATTRIBUTES (fntype), coerced_params);
+ check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
/* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c
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 (TREE_CODE (result) == ERROR_MARK)
+ return error_mark_node;
+
+ 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
{
/* Subtraction of two similar pointers.
We must subtract them as integers, then divide by object size. */
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
- && comp_target_types (type0, type1))
+ && comp_target_types (type0, type1, 1))
return pointer_diff (op0, op1);
/* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
warning ("division by zero");
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
{
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
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);
- }
+ else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+ common = 1;
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;
but don't convert the args to int! */
build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE
+ || code0 == VECTOR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE
+ || code1 == VECTOR_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
/* Anything compares with void *. void * compares with anything.
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
- if (comp_target_types (type0, type1))
+ if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else if (VOID_TYPE_P (tt0))
{
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;
shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
- if (comp_target_types (type0, type1))
+ if (comp_target_types (type0, type1, 1))
{
result_type = common_type (type0, type1);
if (pedantic
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
- if (comp_target_types (type0, type1))
+ if (comp_target_types (type0, type1, 1))
{
result_type = common_type (type0, type1);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
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;
break;
}
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+ || code0 == VECTOR_TYPE)
&&
- (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+ (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+ || code1 == VECTOR_TYPE))
{
int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
&& 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);
constant expression involving such literals or a
conditional expression involving such literals)
and it is non-negative. */
- if (tree_expr_nonnegative_p (sop))
+ if (c_tree_expr_nonnegative_p (sop))
/* OK */;
/* Do not warn if the comparison is an equality operation,
the unsigned quantity is an integral constant, and it
would fit in the result if the result were signed. */
else if (TREE_CODE (uop) == INTEGER_CST
&& (resultcode == EQ_EXPR || resultcode == NE_EXPR)
- && int_fits_type_p (uop, 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;
+/* Return true if `t' is known to be non-negative. */
- /* 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)
+int
+c_tree_expr_nonnegative_p (t)
+ tree t;
+{
+ if (TREE_CODE (t) == STMT_EXPR)
{
- 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);
+ t = COMPOUND_BODY (STMT_EXPR_STMT (t));
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
- return folded;
+ /* Find the last statement in the chain, ignoring the final
+ * scope statement */
+ while (TREE_CHAIN (t) != NULL_TREE
+ && TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT)
+ t = TREE_CHAIN (t);
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ }
+ return tree_expr_nonnegative_p (t);
}
/* Return a tree for the difference of pointers OP0 and OP1.
\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:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
- || typecode == COMPLEX_TYPE))
+ || typecode == COMPLEX_TYPE
+ || typecode == VECTOR_TYPE))
{
error ("wrong type argument to unary minus");
return error_mark_node;
break;
case BIT_NOT_EXPR:
- if (typecode == COMPLEX_TYPE)
+ if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE)
+ {
+ if (!noconvert)
+ arg = default_conversion (arg);
+ }
+ else if (typecode == COMPLEX_TYPE)
{
code = CONJ_EXPR;
if (pedantic)
if (!noconvert)
arg = default_conversion (arg);
}
- else if (typecode != INTEGER_TYPE)
+ else
{
error ("wrong type argument to bit-complement");
return error_mark_node;
}
- else if (!noconvert)
- arg = default_conversion (arg);
break;
case ABS_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;
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
}
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
/* Do not warn if the signed quantity is an unsuffixed
integer literal (or some static constant expression
involving such literals) and it is non-negative. */
- else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
- || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
+ else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1))
+ || (unsigned_op1 && c_tree_expr_nonnegative_p (op2)))
/* OK */;
else
warning ("signed and unsigned type in conditional expression");
}
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
- if (comp_target_types (type1, type2))
+ if (comp_target_types (type1, type2, 1))
result_type = common_type (type1, type2);
else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
&& TREE_CODE (orig_op1) != NOP_EXPR)
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. */
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
/* The left-hand operand of a comma expression is like an expression
- statement: with -W or -Wunused, we should warn if it doesn't have
+ statement: with -Wextra or -Wunused, we should warn if it doesn't have
any side-effects, unless it was explicitly cast to (void). */
if ((extra_warnings || warn_unused_value)
&& ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
- type = TYPE_MAIN_VARIANT (type);
+
+ /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
+ only in <protocol> qualifications. But when constructing cast expressions,
+ the protocols do matter and must be kept around. */
+ if (!flag_objc || !objc_is_id (type))
+ type = TYPE_MAIN_VARIANT (type);
#if 0
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
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)),
if (field)
{
- const char *name;
tree t;
if (pedantic)
pedwarn ("ISO C forbids casts to union type");
- if (TYPE_NAME (type) != 0)
- {
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- name = IDENTIFIER_POINTER (TYPE_NAME (type));
- else
- name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
- }
- 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");
&& !TREE_CONSTANT (value))
warning ("cast to pointer from integer of different size");
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == POINTER_TYPE
+ && TREE_CODE (expr) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (expr, 0))
+ && flag_strict_aliasing && warn_strict_aliasing
+ && !VOID_TYPE_P (TREE_TYPE (type)))
+ {
+ /* Casting the address of a decl to non void pointer. Warn
+ if the cast breaks type based aliasing. */
+ if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
+ warning ("type-punning to incomplete type might break strict-aliasing rules");
+ else if (!alias_sets_conflict_p
+ (get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))),
+ get_alias_set (TREE_TYPE (type))))
+ warning ("dereferencing type-punned pointer will break strict-aliasing rules");
+ }
+
ovalue = value;
+ /* Replace a nonvolatile const static variable with its value. */
+ if (optimize && TREE_CODE (value) == VAR_DECL)
+ value = decl_constant_value (value);
value = convert (type, value);
/* Ignore any integer overflow caused by the cast. */
}
}
- /* 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;
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
overflow_warning (rhs);
- /* Check for Objective-C protocols. This will issue a warning if
- there are protocol violations. No need to use the return value. */
- maybe_objc_comptypes (type, rhstype, 0);
+ /* Check for Objective-C protocols. This will automatically
+ issue a warning if there are protocol violations. No need to
+ use the return value. */
+ if (flag_objc)
+ objc_comptypes (type, rhstype, 0);
return rhs;
}
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);
rhs = build1 (NOP_EXPR, type, rhs);
return rhs;
}
+ /* Some types can interconvert without explicit casts. */
+ else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
+ && ((*targetm.vector_opaque_p) (type)
+ || (*targetm.vector_opaque_p) (rhstype)))
+ return convert (type, rhs);
/* Arithmetic types all interconvert, and enum is treated like int. */
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|| codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
|| codel == BOOLEAN_TYPE)
- && (coder == INTEGER_TYPE || coder == REAL_TYPE
+ && (coder == INTEGER_TYPE || coder == REAL_TYPE
|| coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
|| coder == BOOLEAN_TYPE))
return convert_and_check (type, rhs);
Meanwhile, the lhs target must have all the qualifiers of
the rhs. */
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
- || comp_target_types (memb_type, rhstype))
+ || comp_target_types (memb_type, rhstype, 0))
{
/* If this type won't generate any warnings, use it. */
if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
/* 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);
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
- || comp_target_types (type, rhstype)
- || (unsigned_type (TYPE_MAIN_VARIANT (ttl))
- == unsigned_type (TYPE_MAIN_VARIANT (ttr))))
+ || comp_target_types (type, rhstype, 0)
+ || (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)
/* If this is not a case of ignoring a mismatch in signedness,
no warning. */
else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
- || comp_target_types (type, rhstype))
+ || comp_target_types (type, rhstype, 0))
;
/* If there is a mismatch, do warn. */
else if (pedantic)
{
if (funname)
{
- tree selector = maybe_building_objc_message_expr ();
+ tree selector = objc_message_selector ();
if (selector && parmnum > 2)
error ("incompatible type for argument %d of `%s'",
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'".
+ if OPNAME is null and ARGNUM is 0, it is replaced by "passing arg of `FUNCTION'".
+ Otherwise if OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'".
FUNCTION and ARGNUM are handled specially if we are building an
Objective-C selector. */
{
if (opname == 0)
{
- tree selector = maybe_building_objc_message_expr ();
+ tree selector = objc_message_selector ();
char * new_opname;
if (selector && argnum > 2)
function = selector;
argnum -= 2;
}
- if (function)
+ if (argnum == 0)
+ {
+ if (function)
+ {
+ /* Function name is known; supply it. */
+ const char *const argstring = _("passing arg of `%s'");
+ new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
+ + strlen (argstring) + 1
+ + 1);
+ sprintf (new_opname, argstring,
+ IDENTIFIER_POINTER (function));
+ }
+ else
+ {
+ /* Function name unknown (call through ptr). */
+ const char *const argnofun = _("passing arg of pointer to function");
+ new_opname = (char *) alloca (strlen (argnofun) + 1 + 1);
+ sprintf (new_opname, argnofun);
+ }
+ }
+ else if (function)
{
/* Function name is known; supply it. */
const char *const argstring = _("passing arg %d of `%s'");
}
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. */
#define SPELLING_DEPTH() (spelling - spelling_base)
#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH))
-/* Save and restore the spelling stack around arbitrary C code. */
-
-#define SAVE_SPELLING_DEPTH(code) \
-{ \
- int __depth = SPELLING_DEPTH (); \
- code; \
- RESTORE_SPELLING_DEPTH (__depth); \
-}
-
/* Push an element on the spelling stack with type KIND and assign VALUE
to MEMBER. */
{
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;
}
/* 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)
if (type == 0)
type = TREE_TYPE (constructor_decl);
+ if ((*targetm.vector_opaque_p) (type))
+ error ("opaque vector types cannot be initialized");
+
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
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;
&& TYPE_SIZE (constructor_type))
constructor_max_index = build_int_2 (-1, -1);
+ /* constructor_max_index needs to be an INTEGER_CST. Attempts
+ to initialize VLAs will cause a proper error; avoid tree
+ checking errors as well by setting a safe value. */
+ if (constructor_max_index
+ && TREE_CODE (constructor_max_index) != INTEGER_CST)
+ constructor_max_index = build_int_2 (-1, -1);
+
constructor_index
= convert (bitsizetype,
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
constructor_unfilled_index = constructor_index;
}
+ else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
+ {
+ /* Vectors are like simple fixed-size arrays. */
+ constructor_max_index =
+ build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0);
+ constructor_index = convert (bitsizetype, bitsize_zero_node);
+ constructor_unfilled_index = constructor_index;
+ }
else
{
/* Handle the case of int x = {5}; */
&& constructor_fields == 0)
process_init_element (pop_init_level (1));
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && constructor_max_index
&& tree_int_cst_lt (constructor_max_index, constructor_index))
process_init_element (pop_init_level (1));
else
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)
{
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 a proper error; avoid tree
+ checking errors as well by setting a safe value. */
+ if (constructor_max_index
+ && TREE_CODE (constructor_max_index) != INTEGER_CST)
+ constructor_max_index = build_int_2 (-1, -1);
+
constructor_index
= convert (bitsizetype,
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
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)
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. */
|| 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");
;
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. */
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)
}
/* Common handling for both array range and field name designators.
- ARRAY argument is non-zero for array ranges. Returns zero for success. */
+ ARRAY argument is nonzero for array ranges. Returns zero for success. */
static int
set_designator (array)
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
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
bit_position (constructor_fields),
DECL_SIZE (constructor_fields));
- constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
- /* Skip any nameless bit fields. */
- while (constructor_unfilled_fields != 0
- && DECL_C_BIT_FIELD (constructor_unfilled_fields)
- && DECL_NAME (constructor_unfilled_fields) == 0)
- constructor_unfilled_fields =
- TREE_CHAIN (constructor_unfilled_fields);
+ /* If the current field was the first one not yet written out,
+ it isn't now, so update. */
+ if (constructor_unfilled_fields == constructor_fields)
+ {
+ constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+ /* Skip any nameless bit fields. */
+ while (constructor_unfilled_fields != 0
+ && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+ && DECL_NAME (constructor_unfilled_fields) == 0)
+ constructor_unfilled_fields =
+ TREE_CHAIN (constructor_unfilled_fields);
+ }
}
constructor_fields = TREE_CHAIN (constructor_fields);
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");
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));
+ /* Simple asm statements are treated as volatile. */
+ stmt = add_stmt (build_stmt (ASM_STMT, ridpointers[(int) RID_VOLATILE],
+ expr, NULL_TREE, NULL_TREE, NULL_TREE));
ASM_INPUT_P (stmt) = 1;
return stmt;
}
{
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));
/* Record the contents of OUTPUTS before it is modified. */
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- o[i] = TREE_VALUE (tail);
+ {
+ o[i] = TREE_VALUE (tail);
+ if (o[i] == error_mark_node)
+ return;
+ }
/* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
OUTPUTS some trees for where the values were actually stored. */
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;
if (switch_stack)
{
+ bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE);
+
label = c_add_case_label (switch_stack->cases,
SWITCH_COND (switch_stack->switch_stmt),
low_value, high_value);
if (label == error_mark_node)
label = NULL_TREE;
+ else if (switch_was_empty_p)
+ {
+ /* Attach the first case label to the SWITCH_BODY. */
+ SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt);
+ TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE;
+ }
}
else if (low_value)
error ("case label not within a switch statement");
{
struct c_switch *cs = switch_stack;
- RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt));
+ /* Rechain the next statements to the SWITCH_STMT. */
+ last_tree = cs->switch_stmt;
/* Pop the stack. */
switch_stack = switch_stack->next;