/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "expr.h"
#include "toplev.h"
#include "intl.h"
-#include "defaults.h"
#include "ggc.h"
+#include "target.h"
/* Nonzero if we've already printed a "missing braces around initializer"
message within this initializer. */
static tree digest_init PARAMS ((tree, tree, int, 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));
+static void push_range_stack PARAMS ((tree));
static void add_pending_init PARAMS ((tree, tree));
-static int pending_init_member PARAMS ((tree));
+static void set_nonincremental_init PARAMS ((void));
+static void set_nonincremental_init_from_string PARAMS ((tree));
+static tree find_init_member PARAMS ((tree));
\f
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) */
return t1;
/* Merge the attributes. */
- attributes = merge_machine_type_attributes (t1, t2);
+ attributes = (*target.merge_type_attributes) (t1, t2);
/* Treat an enum type as the unsigned integer type of the same width. */
/* If both args specify argument types, we must merge the two
lists, argument by argument. */
+ pushlevel (0);
+ declare_parm_level (1);
+
len = list_length (p1);
newargs = 0;
parm_done: ;
}
+ poplevel (0, 0, 0);
+
t1 = build_function_type (valtype, newargs);
/* ... falls through ... */
}
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
-#ifndef COMP_TYPE_ATTRIBUTES
-#define COMP_TYPE_ATTRIBUTES(t1,t2) 1
-#endif
-
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
- if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
+ if (! (attrval = (*target.comp_type_attributes) (t1, t2)))
return 0;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE)
return 0;
}
- else if (! (newval = comptypes (TREE_VALUE (args1), TREE_VALUE (args2))))
+ else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (args2)))))
{
/* Allow wait (union {union wait *u; int *i} *)
and wait (union wait *) to be compatible. */
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");
- return size_one_node;
+ size = size_one_node;
}
- if (code == VOID_TYPE)
+ else if (code == VOID_TYPE)
{
if (pedantic || warn_pointer_arith)
pedwarn ("sizeof applied to a void type");
- return size_one_node;
+ size = size_one_node;
}
-
- if (code == ERROR_MARK)
- return size_one_node;
-
- if (!COMPLETE_TYPE_P (type))
+ else if (code == ERROR_MARK)
+ size = size_one_node;
+ else if (!COMPLETE_TYPE_P (type))
{
error ("sizeof applied to an incomplete type");
- return size_zero_node;
+ size = size_zero_node;
}
-
- /* Convert in case a char is more than one unit. */
- return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
+ 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
tree type;
{
enum tree_code code = TREE_CODE (type);
+ tree size;
if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
- return size_one_node;
-
- if (!COMPLETE_TYPE_P (type))
- return size_zero_node;
-
- /* Convert in case a char is more than one unit. */
- return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
+ 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 type;
{
enum tree_code code = TREE_CODE (type);
+ tree t;
if (code == FUNCTION_TYPE)
- return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-
- if (code == VOID_TYPE || code == ERROR_MARK)
- return size_one_node;
-
- if (!COMPLETE_TYPE_P (type))
+ t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ else if (code == VOID_TYPE || code == ERROR_MARK)
+ t = size_one_node;
+ else if (code == ERROR_MARK)
+ t = size_one_node;
+ else if (!COMPLETE_TYPE_P (type))
{
error ("__alignof__ applied to an incomplete type");
- return size_zero_node;
+ t = size_zero_node;
}
+ else
+ t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
- return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
+ return fold (build1 (NOP_EXPR, c_size_type_node, t));
}
\f
/* Implement the __alignof keyword: Return the minimum required
c_alignof_expr (expr)
tree expr;
{
+ tree t;
+
if (TREE_CODE (expr) == VAR_DECL)
- return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
+ t = size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
- if (TREE_CODE (expr) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ else if (TREE_CODE (expr) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
{
error ("`__alignof' applied to a bit-field");
- return size_one_node;
+ t = size_one_node;
}
else if (TREE_CODE (expr) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
- return size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT);
+ t = size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT);
- if (TREE_CODE (expr) == INDIRECT_REF)
+ else if (TREE_CODE (expr) == INDIRECT_REF)
{
tree t = TREE_OPERAND (expr, 0);
tree best = t;
}
else
return c_alignof (TREE_TYPE (expr));
+
+ return fold (build1 (NOP_EXPR, c_size_type_node, t));
}
/* Return either DECL or its known constant value (if it has one). */
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. */
+ 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))
+ if (c_promoting_integer_type_p (type))
{
/* Traditionally, unsignedness is preserved in default promotions.
Also preserve unsignedness if not really getting any wider. */
return convert (integer_type_node, exp);
}
- if (code == BOOLEAN_TYPE)
- return convert (integer_type_node, exp);
-
if (flag_traditional && !flag_allow_single_precision
&& TYPE_MAIN_VARIANT (type) == float_type_node)
return convert (double_type_node, exp);
{
/* Optionally warn about conversions that
differ from the default conversions. */
- if (warn_conversion)
+ if (warn_conversion || warn_traditional)
{
int formal_prec = TYPE_PRECISION (type);
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1);
+ if (INTEGRAL_TYPE_P (type)
+ && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
+ warn_for_assignment ("%s as integer rather than complex due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == REAL_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1);
+ else if (TREE_CODE (type) == COMPLEX_TYPE
+ && INTEGRAL_TYPE_P (TREE_TYPE (val)))
+ warn_for_assignment ("%s as complex rather than integer due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1);
if (formal_prec == TYPE_PRECISION (float_type_node))
warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);
}
- /* Detect integer changing in width or signedness. */
- else if (INTEGRAL_TYPE_P (type)
+ /* Detect integer changing in width or signedness.
+ These warnings are only activated with
+ -Wconversion, not with -Wtraditional. */
+ else if (warn_conversion && INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
{
tree would_have_been = default_conversion (val);
fundecl, name, parmnum + 1);
if (PROMOTE_PROTOTYPES
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE
- || TREE_CODE (type) == BOOLEAN_TYPE)
+ && INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
}
{
if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
- result_type = qualify_type (type1, type2);
+ result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
+ TREE_TYPE (type2)));
}
else if (VOID_TYPE_P (TREE_TYPE (type2)))
{
if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
- result_type = qualify_type (type2, type1);
+ result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
+ TREE_TYPE (type1)));
}
else
{
else
{
op2 = null_pointer_node;
-#if 0 /* The spec seems to say this is permitted. */
- if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids conditional expr between 0 and function pointer");
-#endif
}
result_type = type1;
}
else
{
op1 = null_pointer_node;
-#if 0 /* The spec seems to say this is permitted. */
- if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids conditional expr between 0 and function pointer");
-#endif
}
result_type = type2;
}
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));
+
#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. */
return TREE_VALUE (list);
}
- if (TREE_CHAIN (list) != 0 && TREE_CHAIN (TREE_CHAIN (list)) == 0)
- {
- /* Convert arrays to pointers when there really is a comma operator. */
- if (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (list)))) == ARRAY_TYPE)
- TREE_VALUE (TREE_CHAIN (list))
- = default_conversion (TREE_VALUE (TREE_CHAIN (list)));
- }
-
rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
return error_mark_node;
}
- if (type == TREE_TYPE (value))
+ if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
{
if (pedantic)
{
return value;
}
+
+/* Interpret a cast of expression EXPR to type TYPE. */
+tree
+c_cast_expr (type, expr)
+ tree type, expr;
+{
+ int saved_wsp = warn_strict_prototypes;
+
+ /* This avoids warnings about unprototyped casts on
+ integers. E.g. "#define SIG_DFL (void(*)())0". */
+ if (TREE_CODE (expr) == INTEGER_CST)
+ warn_strict_prototypes = 0;
+ type = groktypename (type);
+ warn_strict_prototypes = saved_wsp;
+
+ return build_c_cast (type, expr);
+}
+
\f
/* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use
/* Digest the specified initializer into an expression. */
value = digest_init (type, init, TREE_STATIC (decl),
- TREE_STATIC (decl) || pedantic);
+ TREE_STATIC (decl) || (pedantic && !flag_isoc99));
/* Store the expression if valid; else report error. */
if (TREE_CODE (init) == NON_LVALUE_EXPR)
inside_init = TREE_OPERAND (init, 0);
+ inside_init = fold (inside_init);
+
/* Initialization of an array of chars from a string constant
optionally enclosed in braces. */
if (flag_pedantic_errors)
inside_init = error_mark_node;
}
- else if (require_constant && ! TREE_CONSTANT (inside_init))
+ else if (require_constant
+ && (!TREE_CONSTANT (inside_init)
+ /* This test catches things like `7 / 0' which
+ result in an expression for which TREE_CONSTANT
+ is true, but which is not actually something
+ that is a legal constant. We really should not
+ be using this function, because it is a part of
+ the back-end. Instead, the expression should
+ already have been turned into ERROR_MARK_NODE. */
+ || !initializer_constant_valid_p (inside_init,
+ TREE_TYPE (inside_init))))
{
error_init ("initializer element is not constant");
inside_init = error_mark_node;
}
- else if (require_constant
- && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
- {
- error_init ("initializer element is not computable at load time");
- inside_init = error_mark_node;
- }
return inside_init;
}
/* Handle scalar types, including conversions. */
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
- || code == ENUMERAL_TYPE || code == COMPLEX_TYPE)
+ || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE)
{
/* Note that convert_for_assignment calls default_conversion
for arrays and functions. We must not call it in the
at which to store the next element we get. */
static tree constructor_index;
-/* For an ARRAY_TYPE, this is the end index of the range
- to initialize with the next element, or NULL in the ordinary case
- where the element is used just once. */
-static tree constructor_range_end;
-
/* For an ARRAY_TYPE, this is the maximum index. */
static tree constructor_max_index;
most recent first). */
static tree constructor_elements;
+/* 1 if constructor should be incrementally stored into a constructor chain,
+ 0 if all the elements should be kept in AVL tree. */
+static int constructor_incremental;
+
/* 1 if so far this constructor's elements are all compile-time constants. */
static int constructor_constant;
static tree constructor_decl;
/* start_init saves the ASMSPEC arg here for really_start_incremental_init. */
-static char *constructor_asmspec;
+static const char *constructor_asmspec;
/* Nonzero if this is an initializer for a top-level decl. */
static int constructor_top_level;
+/* Nesting depth of designator list. */
+static int designator_depth;
+
+/* Nonzero if there were diagnosed errors in this designator list. */
+static int designator_errorneous;
+
\f
/* This stack has a level for each implicit or explicit level of
structuring in the initializer, including the outermost one. It
saves the values of most of the variables above. */
+struct constructor_range_stack;
+
struct constructor_stack
{
struct constructor_stack *next;
tree type;
tree fields;
tree index;
- tree range_end;
tree max_index;
tree unfilled_index;
tree unfilled_fields;
tree bit_index;
tree elements;
- int offset;
struct init_node *pending_elts;
+ int offset;
int depth;
/* If nonzero, this value should replace the entire
constructor at this level. */
tree replacement_value;
+ struct constructor_range_stack *range_stack;
char constant;
char simple;
char implicit;
char erroneous;
char outer;
+ char incremental;
};
struct constructor_stack *constructor_stack;
+/* This stack represents designators from some range designator up to
+ the last designator in the list. */
+
+struct constructor_range_stack
+{
+ struct constructor_range_stack *next, *prev;
+ struct constructor_stack *stack;
+ tree range_start;
+ tree index;
+ tree range_end;
+ tree fields;
+};
+
+struct constructor_range_stack *constructor_range_stack;
+
/* This stack records separate initializers that are nested.
Nested initializers can't happen in ANSI C, but GNU C allows them
in cases like { ... (struct foo) { ... } ... }. */
{
struct initializer_stack *next;
tree decl;
- char *asmspec;
+ const char *asmspec;
struct constructor_stack *constructor_stack;
+ struct constructor_range_stack *constructor_range_stack;
tree elements;
struct spelling *spelling;
struct spelling *spelling_base;
const char *locus;
struct initializer_stack *p
= (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
- char *asmspec = 0;
+ const char *asmspec = 0;
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
p->require_constant_value = require_constant_value;
p->require_constant_elements = require_constant_elements;
p->constructor_stack = constructor_stack;
+ p->constructor_range_stack = constructor_range_stack;
p->elements = constructor_elements;
p->spelling = spelling;
p->spelling_base = spelling_base;
{
require_constant_value = TREE_STATIC (decl);
require_constant_elements
- = ((TREE_STATIC (decl) || pedantic)
+ = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99))
/* For a scalar, you can always use any value to initialize,
even within braces. */
&& (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
}
constructor_stack = 0;
+ constructor_range_stack = 0;
missing_braces_mentioned = 0;
free (q);
}
+ if (constructor_range_stack)
+ abort ();
+
/* Pop back to the data of the outer initializer (if any). */
constructor_decl = p->decl;
constructor_asmspec = p->asmspec;
require_constant_value = p->require_constant_value;
require_constant_elements = p->require_constant_elements;
constructor_stack = p->constructor_stack;
+ constructor_range_stack = p->constructor_range_stack;
constructor_elements = p->elements;
spelling = p->spelling;
spelling_base = p->spelling_base;
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
- p->range_end = constructor_range_end;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
p->depth = constructor_depth;
p->replacement_value = 0;
p->implicit = 0;
+ p->range_stack = 0;
p->outer = 0;
+ p->incremental = constructor_incremental;
p->next = 0;
constructor_stack = p;
constructor_elements = 0;
constructor_pending_elts = 0;
constructor_type = type;
+ constructor_incremental = 1;
+ designator_depth = 0;
+ designator_errorneous = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
- constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
= TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+
+ /* Detect non-empty initializations of zero-length arrays. */
+ if (constructor_max_index == NULL_TREE)
+ constructor_max_index = build_int_2 (-1, -1);
+
constructor_index
= convert (bitsizetype,
TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
/* Push down into a subobject, for initialization.
If this is for an explicit set of braces, IMPLICIT is 0.
If it is because the next element belongs at a lower level,
- IMPLICIT is 1. */
+ IMPLICIT is 1 (or 2 if the push is because of designator list). */
void
push_init_level (implicit)
int implicit;
{
struct constructor_stack *p;
+ tree value = NULL_TREE;
/* If we've exhausted any levels that didn't have braces,
pop them now. */
break;
}
+ /* Unless this is an explicit brace, we need to preserve previous
+ content if any. */
+ if (implicit)
+ {
+ if ((TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ && constructor_fields)
+ value = find_init_member (constructor_fields);
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ value = find_init_member (constructor_index);
+ }
+
p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
- p->range_end = constructor_range_end;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
p->replacement_value = 0;
p->implicit = implicit;
p->outer = 0;
+ p->incremental = constructor_incremental;
p->next = constructor_stack;
+ p->range_stack = 0;
constructor_stack = p;
constructor_constant = 1;
constructor_simple = 1;
constructor_depth = SPELLING_DEPTH ();
constructor_elements = 0;
+ constructor_incremental = 1;
constructor_pending_elts = 0;
+ if (!implicit)
+ {
+ p->range_stack = constructor_range_stack;
+ constructor_range_stack = 0;
+ designator_depth = 0;
+ designator_errorneous = 0;
+ }
/* Don't die if an entire brace-pair level is superfluous
in the containing level. */
return;
}
- if (implicit && warn_missing_braces && !missing_braces_mentioned)
+ if (value && TREE_CODE (value) == CONSTRUCTOR)
+ {
+ constructor_constant = TREE_CONSTANT (value);
+ constructor_simple = TREE_STATIC (value);
+ constructor_elements = TREE_OPERAND (value, 1);
+ if (constructor_elements
+ && (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == ARRAY_TYPE))
+ set_nonincremental_init ();
+ }
+
+ if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
warning_init ("missing braces around initializer");
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
- constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
= TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
constructor_index
= convert (bitsizetype,
- TYPE_MIN_VALUE
- (TYPE_DOMAIN (constructor_type)));
+ TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+
+ /* ??? For GCC 3.1, remove special case initialization of
+ zero-length array members from pop_init_level and set
+ constructor_max_index such that we get the normal
+ "excess elements" warning. */
}
else
constructor_index = bitsize_zero_node;
constructor_unfilled_index = constructor_index;
+ if (value && TREE_CODE (value) == STRING_CST)
+ {
+ /* We need to split the char/wchar array into individual
+ characters, so that we don't have to special case it
+ everywhere. */
+ set_nonincremental_init_from_string (value);
+ }
}
else
{
pop any inner levels that didn't have explicit braces. */
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
+
+ if (constructor_range_stack)
+ abort ();
}
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
+ && TREE_CODE (constructor_type) == ARRAY_TYPE
+ && TYPE_DOMAIN (constructor_type)
+ && ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
+ {
+ /* Silently discard empty initializations. The parser will
+ already have pedwarned for empty brackets. */
+ if (integer_zerop (constructor_unfilled_index))
+ constructor_type = NULL_TREE;
+ else if (! TYPE_SIZE (constructor_type))
+ {
+ if (constructor_depth > 2)
+ error_init ("initialization of flexible array member in a nested context");
+ else if (pedantic)
+ pedwarn_init ("initialization of a flexible array member");
+
+ /* We have already issued an error message for the existance
+ 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)
+ constructor_type = NULL_TREE;
+ }
+ else
+ {
+ warning_init ("deprecated initialization of zero-length array");
+
+ /* We must be initializing the last member of a top-level struct. */
+ if (TREE_CHAIN (constructor_fields) != NULL_TREE)
+ {
+ error_init ("initialization of zero-length array before end of structure");
+ /* Discard the initializer so that we do not abort later. */
+ constructor_type = NULL_TREE;
+ }
+ else if (constructor_depth > 2)
+ error_init ("initialization of zero-length array inside a nested context");
+ }
+ }
+
/* Warn when some struct elements are implicitly initialized to zero. */
if (extra_warnings
&& constructor_type
&& TREE_CODE (constructor_type) == RECORD_TYPE
&& constructor_unfilled_fields)
{
- push_member_name (constructor_unfilled_fields);
- warning_init ("missing initializer");
- RESTORE_SPELLING_DEPTH (constructor_depth);
+ /* Do not warn for flexible array members or zero-length arrays. */
+ while (constructor_unfilled_fields
+ && (! DECL_SIZE (constructor_unfilled_fields)
+ || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
+ constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
+
+ if (constructor_unfilled_fields)
+ {
+ push_member_name (constructor_unfilled_fields);
+ warning_init ("missing initializer");
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+ }
}
/* Now output all pending elements. */
+ constructor_incremental = 1;
output_pending_init_elements (1);
-#if 0 /* c-parse.in warns about {}. */
- /* In ANSI, each brace level must have at least one element. */
- if (! implicit && pedantic
- && (TREE_CODE (constructor_type) == ARRAY_TYPE
- ? integer_zerop (constructor_unfilled_index)
- : constructor_unfilled_fields == TYPE_FIELDS (constructor_type)))
- pedwarn_init ("empty braces in initializer");
-#endif
-
/* Pad out the end of the structure. */
-
if (p->replacement_value)
/* If this closes a superfluous brace pair,
just pass out the element between them. */
the element, after verifying there is just one. */
if (constructor_elements == 0)
{
- error_init ("empty scalar initializer");
+ if (!constructor_erroneous)
+ error_init ("empty scalar initializer");
constructor = error_mark_node;
}
else if (TREE_CHAIN (constructor_elements) != 0)
constructor_type = p->type;
constructor_fields = p->fields;
constructor_index = p->index;
- constructor_range_end = p->range_end;
constructor_max_index = p->max_index;
constructor_unfilled_index = p->unfilled_index;
constructor_unfilled_fields = p->unfilled_fields;
constructor_constant = p->constant;
constructor_simple = p->simple;
constructor_erroneous = p->erroneous;
+ constructor_incremental = p->incremental;
constructor_pending_elts = p->pending_elts;
constructor_depth = p->depth;
+ if (!p->implicit)
+ constructor_range_stack = p->range_stack;
RESTORE_SPELLING_DEPTH (constructor_depth);
constructor_stack = p->next;
return constructor;
}
+/* Common handling for both array range and field name designators.
+ ARRAY argument is non-zero for array ranges. Returns zero for success. */
+
+static int
+set_designator (array)
+ int array;
+{
+ tree subtype;
+ enum tree_code subcode;
+
+ /* Don't die if an entire brace-pair level is superfluous
+ in the containing level. */
+ if (constructor_type == 0)
+ return 1;
+
+ /* If there were errors in this designator list already, bail out silently. */
+ if (designator_errorneous)
+ return 1;
+
+ if (!designator_depth)
+ {
+ if (constructor_range_stack)
+ abort ();
+
+ /* Designator list starts at the level of closest explicit
+ braces. */
+ while (constructor_stack->implicit)
+ process_init_element (pop_init_level (1));
+ return 0;
+ }
+
+ if (constructor_no_implicit)
+ {
+ error_init ("initialization designators may not nest");
+ return 1;
+ }
+
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ subtype = TREE_TYPE (constructor_fields);
+ if (subtype != error_mark_node)
+ subtype = TYPE_MAIN_VARIANT (subtype);
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+ }
+ else
+ abort ();
+
+ subcode = TREE_CODE (subtype);
+ if (array && subcode != ARRAY_TYPE)
+ {
+ error_init ("array index in non-array initializer");
+ return 1;
+ }
+ else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
+ {
+ error_init ("field name not in record or union initializer");
+ return 1;
+ }
+
+ push_init_level (2);
+ return 0;
+}
+
+/* If there are range designators in designator list, push a new designator
+ to constructor_range_stack. RANGE_END is end of such stack range or
+ NULL_TREE if there is no range designator at this level. */
+
+static void
+push_range_stack (range_end)
+ tree range_end;
+{
+ struct constructor_range_stack *p;
+
+ p = (struct constructor_range_stack *)
+ ggc_alloc (sizeof (struct constructor_range_stack));
+ p->prev = constructor_range_stack;
+ p->next = 0;
+ p->fields = constructor_fields;
+ p->range_start = constructor_index;
+ p->index = constructor_index;
+ p->stack = constructor_stack;
+ p->range_end = range_end;
+ if (constructor_range_stack)
+ constructor_range_stack->next = p;
+ constructor_range_stack = p;
+}
+
/* Within an array initializer, specify the next index to be initialized.
FIRST is that index. If LAST is nonzero, then initialize a range
of indices, running from FIRST through LAST. */
set_init_index (first, last)
tree first, last;
{
+ if (set_designator (1))
+ return;
+
+ designator_errorneous = 1;
+
while ((TREE_CODE (first) == NOP_EXPR
|| TREE_CODE (first) == CONVERT_EXPR
|| TREE_CODE (first) == NON_LVALUE_EXPR)
error_init ("nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
error_init ("nonconstant array index in initializer");
- else if (! constructor_unfilled_index)
+ else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
error_init ("array index in non-array initializer");
- else if (tree_int_cst_lt (first, constructor_unfilled_index))
- error_init ("duplicate array index in initializer");
+ else if (constructor_max_index
+ && tree_int_cst_lt (constructor_max_index, first))
+ error_init ("array index in initializer exceeds array bounds");
else
{
constructor_index = convert (bitsizetype, first);
- if (last != 0 && tree_int_cst_lt (last, first))
- error_init ("empty index range in initializer");
- else
- constructor_range_end = last ? convert (bitsizetype, last) : 0;
+ if (last)
+ {
+ if (tree_int_cst_equal (first, last))
+ last = 0;
+ else if (tree_int_cst_lt (last, first))
+ {
+ error_init ("empty index range in initializer");
+ last = 0;
+ }
+ else
+ {
+ last = convert (bitsizetype, last);
+ if (constructor_max_index != 0
+ && tree_int_cst_lt (constructor_max_index, last))
+ {
+ error_init ("array index range in initializer exceeds array bounds");
+ last = 0;
+ }
+ }
+ }
+
+ designator_depth++;
+ designator_errorneous = 0;
+ if (constructor_range_stack || last)
+ push_range_stack (last);
}
}
tree fieldname;
{
tree tail;
- int passed = 0;
- /* Don't die if an entire brace-pair level is superfluous
- in the containing level. */
- if (constructor_type == 0)
+ if (set_designator (0))
return;
+ designator_errorneous = 1;
+
+ if (TREE_CODE (constructor_type) != RECORD_TYPE
+ && TREE_CODE (constructor_type) != UNION_TYPE)
+ {
+ error_init ("field name not in record or union initializer");
+ return;
+ }
+
for (tail = TYPE_FIELDS (constructor_type); tail;
tail = TREE_CHAIN (tail))
{
- if (tail == constructor_unfilled_fields)
- passed = 1;
if (DECL_NAME (tail) == fieldname)
break;
}
if (tail == 0)
error ("unknown field `%s' specified in initializer",
IDENTIFIER_POINTER (fieldname));
- else if (!passed)
- error ("field `%s' already initialized",
- IDENTIFIER_POINTER (fieldname));
else
- constructor_fields = tail;
+ {
+ constructor_fields = tail;
+ designator_depth++;
+ designator_errorneous = 0;
+ if (constructor_range_stack)
+ push_range_stack (NULL_TREE);
+ }
}
\f
/* Add a new initializer to the tree of pending initializers. PURPOSE
p = *q;
if (tree_int_cst_lt (purpose, p->purpose))
q = &p->left;
- else if (p->purpose != purpose)
+ else if (tree_int_cst_lt (p->purpose, purpose))
q = &p->right;
else
- abort ();
+ {
+ if (TREE_SIDE_EFFECTS (p->value))
+ warning_init ("initialized field with side-effects overwritten");
+ p->value = value;
+ return;
+ }
}
}
else
{
+ tree bitpos;
+
+ bitpos = bit_position (purpose);
while (*q != NULL)
{
p = *q;
- if (tree_int_cst_lt (bit_position (purpose),
- bit_position (p->purpose)))
+ if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
q = &p->left;
else if (p->purpose != purpose)
q = &p->right;
else
- abort ();
+ {
+ if (TREE_SIDE_EFFECTS (p->value))
+ warning_init ("initialized field with side-effects overwritten");
+ p->value = value;
+ return;
+ }
}
}
}
}
-/* Return nonzero if FIELD is equal to the index of a pending initializer. */
+/* Build AVL tree from a sorted chain. */
-static int
-pending_init_member (field)
+static void
+set_nonincremental_init ()
+{
+ tree chain;
+
+ if (TREE_CODE (constructor_type) != RECORD_TYPE
+ && TREE_CODE (constructor_type) != ARRAY_TYPE)
+ return;
+
+ for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain))
+ add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain));
+ constructor_elements = 0;
+ if (TREE_CODE (constructor_type) == RECORD_TYPE)
+ {
+ constructor_unfilled_fields = TYPE_FIELDS (constructor_type);
+ /* Skip any nameless bit fields at the beginning. */
+ 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);
+
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ if (TYPE_DOMAIN (constructor_type))
+ constructor_unfilled_index
+ = convert (bitsizetype,
+ TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+ else
+ constructor_unfilled_index = bitsize_zero_node;
+ }
+ constructor_incremental = 0;
+}
+
+/* Build AVL tree from a string constant. */
+
+static void
+set_nonincremental_init_from_string (str)
+ tree str;
+{
+ tree value, purpose, type;
+ HOST_WIDE_INT val[2];
+ const char *p, *end;
+ int byte, wchar_bytes, charwidth, bitpos;
+
+ if (TREE_CODE (constructor_type) != ARRAY_TYPE)
+ abort ();
+
+ if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
+ == TYPE_PRECISION (char_type_node))
+ wchar_bytes = 1;
+ else if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
+ == TYPE_PRECISION (wchar_type_node))
+ wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+ else
+ abort ();
+
+ charwidth = TYPE_PRECISION (char_type_node);
+ type = TREE_TYPE (constructor_type);
+ p = TREE_STRING_POINTER (str);
+ end = p + TREE_STRING_LENGTH (str);
+
+ for (purpose = bitsize_zero_node;
+ p < end && !tree_int_cst_lt (constructor_max_index, purpose);
+ purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node))
+ {
+ if (wchar_bytes == 1)
+ {
+ val[1] = (unsigned char) *p++;
+ val[0] = 0;
+ }
+ else
+ {
+ val[0] = 0;
+ val[1] = 0;
+ for (byte = 0; byte < wchar_bytes; byte++)
+ {
+ if (BYTES_BIG_ENDIAN)
+ bitpos = (wchar_bytes - byte - 1) * charwidth;
+ else
+ bitpos = byte * charwidth;
+ val[bitpos < HOST_BITS_PER_WIDE_INT]
+ |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
+ << (bitpos % HOST_BITS_PER_WIDE_INT);
+ }
+ }
+
+ if (!TREE_UNSIGNED (type))
+ {
+ bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
+ if (bitpos < HOST_BITS_PER_WIDE_INT)
+ {
+ if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
+ {
+ val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
+ val[0] = -1;
+ }
+ }
+ else if (bitpos == HOST_BITS_PER_WIDE_INT)
+ {
+ if (val[1] < 0)
+ val[0] = -1;
+ }
+ else if (val[0] & (((HOST_WIDE_INT) 1)
+ << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
+ val[0] |= ((HOST_WIDE_INT) -1)
+ << (bitpos - HOST_BITS_PER_WIDE_INT);
+ }
+
+ value = build_int_2 (val[1], val[0]);
+ TREE_TYPE (value) = type;
+ add_pending_init (purpose, value);
+ }
+
+ constructor_incremental = 0;
+}
+
+/* Return value of FIELD in pending initializer or zero if the field was
+ not initialized yet. */
+
+static tree
+find_init_member (field)
tree field;
{
struct init_node *p;
- p = constructor_pending_elts;
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
+ if (constructor_incremental
+ && tree_int_cst_lt (field, constructor_unfilled_index))
+ set_nonincremental_init ();
+
+ p = constructor_pending_elts;
while (p)
{
- if (field == p->purpose)
- return 1;
- else if (tree_int_cst_lt (field, p->purpose))
+ if (tree_int_cst_lt (field, p->purpose))
p = p->left;
- else
+ else if (tree_int_cst_lt (p->purpose, field))
p = p->right;
+ else
+ return p->value;
}
}
- else
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
+ tree bitpos = bit_position (field);
+
+ if (constructor_incremental
+ && (!constructor_unfilled_fields
+ || tree_int_cst_lt (bitpos,
+ bit_position (constructor_unfilled_fields))))
+ set_nonincremental_init ();
+
+ p = constructor_pending_elts;
while (p)
{
if (field == p->purpose)
- return 1;
- else if (tree_int_cst_lt (bit_position (field),
- bit_position (p->purpose)))
+ return p->value;
+ else if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
p = p->left;
else
p = p->right;
}
}
-
+ else if (TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ if (constructor_elements
+ && TREE_PURPOSE (constructor_elements) == field)
+ return TREE_VALUE (constructor_elements);
+ }
return 0;
}
tree value, type, field;
int pending;
{
- int duplicate = 0;
-
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
|| (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
&& !(TREE_CODE (value) == STRING_CST
}
else if (require_constant_elements
&& initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
- {
- error_init ("initializer element is not computable at load time");
- value = error_mark_node;
- }
+ pedwarn ("initializer element is not computable at load time");
+
+ /* If this field is empty (and not at the end of structure),
+ don't do anything other than checking the initializer. */
+ if (field
+ && (TREE_TYPE (field) == error_mark_node
+ || (COMPLETE_TYPE_P (TREE_TYPE (field))
+ && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
+ && (TREE_CODE (constructor_type) == ARRAY_TYPE
+ || TREE_CHAIN (field)))))
+ return;
- /* If this element duplicates one on constructor_pending_elts,
- print a message and ignore it. Don't do this when we're
- processing elements taken off constructor_pending_elts,
- because we'd always get spurious errors. */
- if (pending)
+ if (value == error_mark_node)
{
- if (TREE_CODE (constructor_type) == RECORD_TYPE
- || TREE_CODE (constructor_type) == UNION_TYPE
- || TREE_CODE (constructor_type) == ARRAY_TYPE)
- {
- if (pending_init_member (field))
- {
- error_init ("duplicate initializer");
- duplicate = 1;
- }
- }
+ constructor_erroneous = 1;
+ return;
}
/* If this element doesn't come next in sequence,
put it on constructor_pending_elts. */
if (TREE_CODE (constructor_type) == ARRAY_TYPE
- && ! tree_int_cst_equal (field, constructor_unfilled_index))
+ && (!constructor_incremental
+ || !tree_int_cst_equal (field, constructor_unfilled_index)))
{
- if (! duplicate)
- add_pending_init (field,
- digest_init (type, value, require_constant_value,
- require_constant_elements));
+ if (constructor_incremental
+ && 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));
+ return;
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
- && field != constructor_unfilled_fields)
+ && (!constructor_incremental
+ || field != constructor_unfilled_fields))
{
/* We do this for records but not for unions. In a union,
no matter which field is specified, it can be initialized
right away since it starts at the beginning of the union. */
- if (!duplicate)
- add_pending_init (field,
- digest_init (type, value, require_constant_value,
- require_constant_elements));
+ if (constructor_incremental)
+ {
+ if (!constructor_unfilled_fields)
+ set_nonincremental_init ();
+ else
+ {
+ tree bitpos, unfillpos;
+
+ bitpos = bit_position (field);
+ unfillpos = bit_position (constructor_unfilled_fields);
+
+ if (tree_int_cst_lt (bitpos, unfillpos))
+ set_nonincremental_init ();
+ }
+ }
+
+ add_pending_init (field,
+ digest_init (type, value, require_constant_value,
+ require_constant_elements));
+ return;
}
- else
+ else if (TREE_CODE (constructor_type) == UNION_TYPE
+ && constructor_elements)
{
- /* Otherwise, output this element either to
- constructor_elements or to the assembler file. */
+ if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
+ warning_init ("initialized field with side-effects overwritten");
- if (!duplicate)
- {
- 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);
- }
+ /* We can have just one union field set. */
+ constructor_elements = 0;
+ }
- /* Advance the variable that indicates sequential elements output. */
- if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- constructor_unfilled_index
- = size_binop (PLUS_EXPR, constructor_unfilled_index,
- bitsize_one_node);
- else if (TREE_CODE (constructor_type) == RECORD_TYPE)
- {
- constructor_unfilled_fields
- = TREE_CHAIN (constructor_unfilled_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);
- }
- else if (TREE_CODE (constructor_type) == UNION_TYPE)
- constructor_unfilled_fields = 0;
+ /* Otherwise, output this element either to
+ constructor_elements or to the assembler file. */
- /* Now output any pending elements which have become next. */
- if (pending)
- output_pending_init_elements (0);
+ 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);
+
+ /* Advance the variable that indicates sequential elements output. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ constructor_unfilled_index
+ = size_binop (PLUS_EXPR, constructor_unfilled_index,
+ bitsize_one_node);
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE)
+ {
+ constructor_unfilled_fields
+ = TREE_CHAIN (constructor_unfilled_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);
}
+ else if (TREE_CODE (constructor_type) == UNION_TYPE)
+ constructor_unfilled_fields = 0;
+
+ /* Now output any pending elements which have become next. */
+ if (pending)
+ output_pending_init_elements (0);
}
/* Output any pending elements which have become next.
else if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
+ tree ctor_unfilled_bitpos, elt_bitpos;
+
/* If the current record is complete we are done. */
if (constructor_unfilled_fields == 0)
break;
- if (elt->purpose == constructor_unfilled_fields)
+
+ ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields);
+ elt_bitpos = bit_position (elt->purpose);
+ /* We can't compare fields here because there might be empty
+ fields in between. */
+ if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
{
- output_init_element (elt->value,
- TREE_TYPE (constructor_unfilled_fields),
- constructor_unfilled_fields,
- 0);
+ constructor_unfilled_fields = elt->purpose;
+ output_init_element (elt->value, TREE_TYPE (elt->purpose),
+ elt->purpose, 0);
}
- else if (tree_int_cst_lt (bit_position (constructor_unfilled_fields),
- bit_position (elt->purpose)))
+ else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
{
/* Advance to the next smaller node. */
if (elt->left)
elt = elt->parent;
elt = elt->parent;
if (elt
- && (tree_int_cst_lt
- (bit_position (constructor_unfilled_fields),
- bit_position (elt->purpose))))
+ && (tree_int_cst_lt (ctor_unfilled_bitpos,
+ bit_position (elt->purpose))))
{
next = elt->purpose;
break;
tree orig_value = value;
int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
+ designator_depth = 0;
+ designator_errorneous = 0;
+
/* Handle superfluous braces around string cst as in
char x[] = {"foo"}; */
if (string_flag
break;
}
+ /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */
+ if (constructor_range_stack)
+ value = save_expr (value);
+
while (1)
{
if (TREE_CODE (constructor_type) == RECORD_TYPE)
directly output as a constructor. */
{
/* For a record, keep track of end position of last field. */
- constructor_bit_index
- = size_binop (PLUS_EXPR,
- bit_position (constructor_fields),
- DECL_SIZE (constructor_fields));
+ if (DECL_SIZE (constructor_fields))
+ constructor_bit_index
+ = size_binop (PLUS_EXPR,
+ bit_position (constructor_fields),
+ DECL_SIZE (constructor_fields));
constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
/* Skip any nameless bit fields. */
&& DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
- break;
}
- if (TREE_CODE (constructor_type) == UNION_TYPE)
+ else if (TREE_CODE (constructor_type) == UNION_TYPE)
{
tree fieldtype;
enum tree_code fieldcode;
}
constructor_fields = 0;
- break;
}
- if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
enum tree_code eltcode = TREE_CODE (elttype);
break;
}
- /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */
- if (constructor_range_end)
+ /* Now output the actual element. */
+ if (value)
{
- if (constructor_max_index != 0
- && tree_int_cst_lt (constructor_max_index,
- constructor_range_end))
- {
- pedwarn_init ("excess elements in array initializer");
- constructor_range_end = constructor_max_index;
- }
-
- value = save_expr (value);
+ push_array_bounds (tree_low_cst (constructor_index, 0));
+ output_init_element (value, elttype, constructor_index, 1);
+ RESTORE_SPELLING_DEPTH (constructor_depth);
}
- /* Now output the actual element.
- Ordinarily, output once.
- If there is a range, repeat it till we advance past the range. */
- do
- {
- if (value)
- {
- push_array_bounds (tree_low_cst (constructor_index, 0));
- output_init_element (value, elttype, constructor_index, 1);
- RESTORE_SPELLING_DEPTH (constructor_depth);
- }
-
- 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;
- }
- while (! (constructor_range_end == 0
- || tree_int_cst_lt (constructor_range_end,
- constructor_index)));
+ constructor_index
+ = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
- break;
+ 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. */
- if (constructor_fields == 0)
+ else if (constructor_fields == 0)
{
pedwarn_init ("excess elements in scalar initializer");
break;
}
+ else
+ {
+ if (value)
+ output_init_element (value, constructor_type, NULL_TREE, 1);
+ constructor_fields = 0;
+ }
+
+ /* Handle range initializers either at this level or anywhere higher
+ in the designator stack. */
+ if (constructor_range_stack)
+ {
+ struct constructor_range_stack *p, *range_stack;
+ int finish = 0;
+
+ range_stack = constructor_range_stack;
+ constructor_range_stack = 0;
+ while (constructor_stack != range_stack->stack)
+ {
+ if (!constructor_stack->implicit)
+ abort ();
+ process_init_element (pop_init_level (1));
+ }
+ for (p = range_stack;
+ !p->range_end || tree_int_cst_equal (p->index, p->range_end);
+ p = p->prev)
+ {
+ if (!constructor_stack->implicit)
+ abort ();
+ process_init_element (pop_init_level (1));
+ }
+
+ p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
+ if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
+ finish = 1;
+
+ while (1)
+ {
+ constructor_index = p->index;
+ constructor_fields = p->fields;
+ if (finish && p->range_end && p->index == p->range_start)
+ {
+ finish = 0;
+ p->prev = 0;
+ }
+ p = p->next;
+ if (!p)
+ break;
+ push_init_level (2);
+ p->stack = constructor_stack;
+ if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
+ p->index = p->range_start;
+ }
+
+ if (!finish)
+ constructor_range_stack = range_stack;
+ continue;
+ }
- if (value)
- output_init_element (value, constructor_type, NULL_TREE, 1);
- constructor_fields = 0;
break;
}
+
+ constructor_range_stack = 0;
}
\f
-/* Expand an ASM statement with operands, handling output operands
- that are not variables or INDIRECT_REFS by transforming such
- cases into cases that expand_asm_operands can handle.
+/* Build a simple asm-statement, from one string literal. */
+tree
+simple_asm_stmt (expr)
+ tree expr;
+{
+ STRIP_NOPS (expr);
- Arguments are same as for expand_asm_operands. */
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ expr = TREE_OPERAND (expr, 0);
-void
-c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
- tree string, outputs, inputs, clobbers;
- int vol;
- const char *filename;
- int line;
+ if (TREE_CODE (expr) == STRING_CST)
+ {
+ 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));
+ ASM_INPUT_P (stmt) = 1;
+ return stmt;
+ }
+
+ error ("argument of `asm' is not a constant string");
+ return NULL_TREE;
+}
+
+/* Build an asm-statement, whose components are a CV_QUALIFIER, a
+ STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */
+
+tree
+build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers)
+ tree cv_qualifier;
+ tree string;
+ tree outputs;
+ tree inputs;
+ tree clobbers;
{
- int noutputs = list_length (outputs);
- register int i;
- /* o[I] is the place that output number I should be written. */
- register tree *o = (tree *) alloca (noutputs * sizeof (tree));
- register tree tail;
+ tree tail;
- if (TREE_CODE (string) == ADDR_EXPR)
- string = TREE_OPERAND (string, 0);
- if (last_tree && TREE_CODE (string) != STRING_CST)
+ if (TREE_CHAIN (string))
+ string = combine_strings (string);
+ if (TREE_CODE (string) != STRING_CST)
{
error ("asm template is not a string constant");
- return;
+ return NULL_TREE;
}
- /* Record the contents of OUTPUTS before it is modified. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+ if (cv_qualifier != NULL_TREE
+ && cv_qualifier != ridpointers[(int) RID_VOLATILE])
+ {
+ warning ("%s qualifier ignored on asm",
+ IDENTIFIER_POINTER (cv_qualifier));
+ cv_qualifier = NULL_TREE;
+ }
+
+ /* We can remove output conversions that change the type,
+ but not the mode. */
+ for (tail = outputs; tail; tail = TREE_CHAIN (tail))
{
tree output = TREE_VALUE (tail);
- /* We can remove conversions that just change the type, not the mode. */
STRIP_NOPS (output);
- o[i] = output;
+ TREE_VALUE (tail) = output;
/* Allow conversions as LHS here. build_modify_expr as called below
will do the right thing with them. */
|| TREE_CODE (output) == FIX_CEIL_EXPR)
output = TREE_OPERAND (output, 0);
- if (last_tree)
- lvalue_or_else (o[i], "invalid lvalue in asm statement");
+ lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement");
+ }
+
+ /* Remove output conversions that change the type but not the mode. */
+ for (tail = outputs; tail; tail = TREE_CHAIN (tail))
+ {
+ tree output = TREE_VALUE (tail);
+ STRIP_NOPS (output);
+ TREE_VALUE (tail) = output;
}
- /* Perform default conversions on array and function inputs. */
- /* Don't do this for other types--
- it would screw up operands expected to be in memory. */
- for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++)
+ /* Perform default conversions on array and function inputs.
+ 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));
- if (last_tree)
- {
- add_stmt (build_stmt (ASM_STMT,
- vol ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
- string, outputs, inputs, clobbers));
- return;
- }
+ return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
+ outputs, inputs, clobbers));
+}
+
+/* Expand an ASM statement with operands, handling output operands
+ that are not variables or INDIRECT_REFS by transforming such
+ cases into cases that expand_asm_operands can handle.
- /* Generate the ASM_OPERANDS insn;
- store into the TREE_VALUEs of OUTPUTS some trees for
- where the values were actually stored. */
+ Arguments are same as for expand_asm_operands. */
+
+void
+c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
+ tree string, outputs, inputs, clobbers;
+ int vol;
+ const char *filename;
+ int line;
+{
+ int noutputs = list_length (outputs);
+ register int i;
+ /* o[I] is the place that output number I should be written. */
+ register tree *o = (tree *) alloca (noutputs * sizeof (tree));
+ register tree tail;
+
+ /* 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);
+
+ /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
+ OUTPUTS some trees for where the values were actually stored. */
expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
/* Copy all the intermediate outputs into the specified outputs. */
RETVAL is the expression for what to return,
or a null pointer for `return;' with no value. */
-void
+tree
c_expand_return (retval)
tree retval;
{
tree inner;
if (t == error_mark_node)
- return;
+ return NULL_TREE;
inner = t = convert (TREE_TYPE (res), t);
current_function_returns_value = 1;
}
- add_stmt (build_return_stmt (retval));
+ return add_stmt (build_return_stmt (retval));
}
\f
struct c_switch {
code = TREE_CODE (TREE_TYPE (exp));
type = TREE_TYPE (exp);
- if (code != INTEGER_TYPE
- && code != ENUMERAL_TYPE
+ if (! INTEGRAL_TYPE_P (type)
&& code != ERROR_MARK)
{
error ("switch quantity not an integer");
/* Process a case label. */
-void
+tree
do_case (low_value, high_value)
tree low_value;
tree high_value;
{
+ tree label = NULL_TREE;
+
if (switch_stack)
- c_add_case_label (switch_stack->cases,
- SWITCH_COND (switch_stack->switch_stmt),
- low_value,
- high_value);
+ {
+ 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 (low_value)
error ("case label not within a switch statement");
else
error ("`default' label not within a switch statement");
+
+ return label;
}
/* Finish the switch statement. */