summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/c-typeck.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
committerobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
commitc9ab9ae440a8066b2c2b85b157b1fdadcf09916a (patch)
tree086d9d6c8fbd4fc8fe4495059332f66bc0f8d12b /contrib/gcc/c-typeck.c
parent2ecfd8bd04b63f335c1ec6295740a4bfd97a4fa6 (diff)
downloadFreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.zip
FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.tar.gz
Enlist the FreeBSD-CURRENT users as testers of what is to become Gcc 3.1.0.
These bits are taken from the FSF anoncvs repo on 1-Feb-2002 08:20 PST.
Diffstat (limited to 'contrib/gcc/c-typeck.c')
-rw-r--r--contrib/gcc/c-typeck.c3618
1 files changed, 1956 insertions, 1662 deletions
diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c
index a24cc38..37f6a87 100644
--- a/contrib/gcc/c-typeck.c
+++ b/contrib/gcc/c-typeck.c
@@ -1,23 +1,23 @@
/* 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.
+ Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* This file is part of the C front end.
@@ -31,49 +31,58 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "rtl.h"
#include "tree.h"
#include "c-tree.h"
+#include "tm_p.h"
#include "flags.h"
#include "output.h"
-#include "rtl.h"
#include "expr.h"
#include "toplev.h"
#include "intl.h"
+#include "ggc.h"
+#include "target.h"
/* Nonzero if we've already printed a "missing braces around initializer"
message within this initializer. */
static int missing_braces_mentioned;
-static tree qualify_type PROTO((tree, tree));
-static int comp_target_types PROTO((tree, tree));
-static int function_types_compatible_p PROTO((tree, tree));
-static int type_lists_compatible_p PROTO((tree, tree));
-static int self_promoting_type_p PROTO((tree));
-static tree decl_constant_value PROTO((tree));
-static tree lookup_field PROTO((tree, tree, tree *));
-static tree convert_arguments PROTO((tree, tree, tree, tree));
-static tree pointer_int_sum PROTO((enum tree_code, tree, tree));
-static tree pointer_diff PROTO((tree, tree));
-static tree unary_complex_lvalue PROTO((enum tree_code, tree));
-static void pedantic_lvalue_warning PROTO((enum tree_code));
-static tree internal_build_compound_expr PROTO((tree, int));
-static tree convert_for_assignment PROTO((tree, tree, const char *, tree,
- tree, int));
-static void warn_for_assignment PROTO((const char *, const char *,
- tree, int));
-static tree valid_compound_expr_initializer PROTO((tree, tree));
-static void push_string PROTO((const char *));
-static void push_member_name PROTO((tree));
-static void push_array_bounds PROTO((int));
-static int spelling_length PROTO((void));
-static char *print_spelling PROTO((char *));
-static void warning_init PROTO((const char *));
-static tree digest_init PROTO((tree, tree, int, int));
-static void check_init_type_bitfields PROTO((tree));
-static void output_init_element PROTO((tree, tree, tree, int));
-static void output_pending_init_elements PROTO((int));
-static void add_pending_init PROTO((tree, tree));
-static int pending_init_member PROTO((tree));
+/* 1 if we explained undeclared var errors. */
+static int undeclared_variable_notice;
+
+static tree qualify_type PARAMS ((tree, tree));
+static int comp_target_types PARAMS ((tree, tree));
+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 default_function_array_conversion PARAMS ((tree));
+static tree lookup_field PARAMS ((tree, tree));
+static tree convert_arguments PARAMS ((tree, tree, tree, tree));
+static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
+static tree pointer_diff PARAMS ((tree, tree));
+static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int));
+static void pedantic_lvalue_warning PARAMS ((enum tree_code));
+static tree internal_build_compound_expr PARAMS ((tree, int));
+static tree convert_for_assignment PARAMS ((tree, tree, const char *,
+ tree, tree, int));
+static void warn_for_assignment PARAMS ((const char *, const char *,
+ tree, int));
+static tree valid_compound_expr_initializer PARAMS ((tree, tree));
+static void push_string PARAMS ((const char *));
+static void push_member_name PARAMS ((tree));
+static void push_array_bounds PARAMS ((int));
+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 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 void set_nonincremental_init PARAMS ((void));
+static void set_nonincremental_init_from_string PARAMS ((tree));
+static tree find_init_member PARAMS ((tree));
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) */
@@ -84,12 +93,11 @@ require_complete_type (value)
{
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 (TYPE_SIZE (type) != 0
- && type != void_type_node)
+ if (COMPLETE_TYPE_P (type))
return value;
incomplete_type_error (value, type);
@@ -184,8 +192,8 @@ tree
common_type (t1, t2)
tree t1, t2;
{
- register enum tree_code code1;
- register enum tree_code code2;
+ enum tree_code code1;
+ enum tree_code code2;
tree attributes;
/* Save time if the two types are the same. */
@@ -199,7 +207,7 @@ common_type (t1, t2)
return t1;
/* Merge the attributes. */
- attributes = merge_machine_type_attributes (t1, t2);
+ attributes = (*targetm.merge_type_attributes) (t1, t2);
/* Treat an enum type as the unsigned integer type of the same width. */
@@ -347,6 +355,9 @@ common_type (t1, t2)
/* 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;
@@ -384,7 +395,7 @@ common_type (t1, t2)
{
TREE_VALUE (n) = TREE_VALUE (p2);
if (pedantic)
- pedwarn ("function types not truly compatible in ANSI C");
+ pedwarn ("function types not truly compatible in ISO C");
goto parm_done;
}
}
@@ -398,7 +409,7 @@ common_type (t1, t2)
{
TREE_VALUE (n) = TREE_VALUE (p1);
if (pedantic)
- pedwarn ("function types not truly compatible in ANSI C");
+ pedwarn ("function types not truly compatible in ISO C");
goto parm_done;
}
}
@@ -406,6 +417,8 @@ common_type (t1, t2)
parm_done: ;
}
+ poplevel (0, 0, 0);
+
t1 = build_function_type (valtype, newargs);
/* ... falls through ... */
}
@@ -424,8 +437,8 @@ int
comptypes (type1, type2)
tree type1, type2;
{
- register tree t1 = type1;
- register tree t2 = type2;
+ tree t1 = type1;
+ tree t2 = type2;
int attrval, val;
/* Suppress errors caused by previously reported errors. */
@@ -434,6 +447,16 @@ comptypes (type1, type2)
|| TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
return 1;
+ /* If either type is the internal version of sizetype, return the
+ language version. */
+ if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
+ && TYPE_DOMAIN (t1) != 0)
+ t1 = TYPE_DOMAIN (t1);
+
+ if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
+ && TYPE_DOMAIN (t2) != 0)
+ t2 = TYPE_DOMAIN (t2);
+
/* Treat an enum type as the integer type of the same width and
signedness. */
@@ -461,12 +484,8 @@ comptypes (type1, type2)
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 = (*targetm.comp_type_attributes) (t1, t2)))
return 0;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
@@ -487,6 +506,8 @@ comptypes (type1, type2)
{
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
+ bool d1_variable, d2_variable;
+ bool d1_zero, d2_zero;
val = 1;
/* Target types must match incl. qualifiers. */
@@ -495,22 +516,28 @@ comptypes (type1, type2)
return 0;
/* Sizes must match unless one is missing or variable. */
- if (d1 == 0 || d2 == 0 || d1 == d2
- || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
+ if (d1 == 0 || d2 == 0 || d1 == d2)
break;
- if (! ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2)))))
- val = 0;
+ d1_zero = ! TYPE_MAX_VALUE (d1);
+ d2_zero = ! TYPE_MAX_VALUE (d2);
+
+ d1_variable = (! d1_zero
+ && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
+ || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
+ d2_variable = (! d2_zero
+ && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
+ || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+
+ if (d1_variable || d2_variable)
+ break;
+ if (d1_zero && d2_zero)
+ break;
+ if (d1_zero || d2_zero
+ || ! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
+ || ! tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
+ val = 0;
+
break;
}
@@ -627,15 +654,16 @@ type_lists_compatible_p (args1, args2)
So match anything that self-promotes. */
if (TREE_VALUE (args1) == 0)
{
- if (! self_promoting_type_p (TREE_VALUE (args2)))
+ if (simple_type_promotes_to (TREE_VALUE (args2)) != NULL_TREE)
return 0;
}
else if (TREE_VALUE (args2) == 0)
{
- if (! self_promoting_type_p (TREE_VALUE (args1)))
+ 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. */
@@ -681,132 +709,7 @@ type_lists_compatible_p (args1, args2)
args2 = TREE_CHAIN (args2);
}
}
-
-/* Return 1 if PARMS specifies a fixed number of parameters
- and none of their types is affected by default promotions. */
-
-int
-self_promoting_args_p (parms)
- tree parms;
-{
- register tree t;
- for (t = parms; t; t = TREE_CHAIN (t))
- {
- register tree type = TREE_VALUE (t);
-
- if (TREE_CHAIN (t) == 0 && type != void_type_node)
- return 0;
-
- if (type == 0)
- return 0;
-
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
- return 0;
-
- if (C_PROMOTING_INTEGER_TYPE_P (type))
- return 0;
- }
- return 1;
-}
-
-/* Return 1 if TYPE is not affected by default promotions. */
-
-static int
-self_promoting_type_p (type)
- tree type;
-{
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
- return 0;
-
- if (C_PROMOTING_INTEGER_TYPE_P (type))
- return 0;
-
- return 1;
-}
-/* Return an unsigned type the same as TYPE in other respects. */
-
-tree
-unsigned_type (type)
- tree type;
-{
- tree type1 = TYPE_MAIN_VARIANT (type);
- if (type1 == signed_char_type_node || type1 == char_type_node)
- return unsigned_char_type_node;
- if (type1 == integer_type_node)
- return unsigned_type_node;
- if (type1 == short_integer_type_node)
- return short_unsigned_type_node;
- if (type1 == long_integer_type_node)
- return long_unsigned_type_node;
- if (type1 == long_long_integer_type_node)
- return long_long_unsigned_type_node;
- if (type1 == intDI_type_node)
- return unsigned_intDI_type_node;
- if (type1 == intSI_type_node)
- return unsigned_intSI_type_node;
- if (type1 == intHI_type_node)
- return unsigned_intHI_type_node;
- if (type1 == intQI_type_node)
- return unsigned_intQI_type_node;
-
- return signed_or_unsigned_type (1, type);
-}
-
-/* Return a signed type the same as TYPE in other respects. */
-
-tree
-signed_type (type)
- tree type;
-{
- tree type1 = TYPE_MAIN_VARIANT (type);
- if (type1 == unsigned_char_type_node || type1 == char_type_node)
- return signed_char_type_node;
- if (type1 == unsigned_type_node)
- return integer_type_node;
- if (type1 == short_unsigned_type_node)
- return short_integer_type_node;
- if (type1 == long_unsigned_type_node)
- return long_integer_type_node;
- if (type1 == long_long_unsigned_type_node)
- return long_long_integer_type_node;
- if (type1 == unsigned_intDI_type_node)
- return intDI_type_node;
- if (type1 == unsigned_intSI_type_node)
- return intSI_type_node;
- if (type1 == unsigned_intHI_type_node)
- return intHI_type_node;
- if (type1 == unsigned_intQI_type_node)
- return intQI_type_node;
-
- return signed_or_unsigned_type (0, type);
-}
-
-/* Return a type the same as TYPE except unsigned or
- signed according to UNSIGNEDP. */
-
-tree
-signed_or_unsigned_type (unsignedp, type)
- int unsignedp;
- tree type;
-{
- if ((! INTEGRAL_TYPE_P (type) && ! POINTER_TYPE_P (type))
- || TREE_UNSIGNED (type) == unsignedp)
- return type;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
- return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
- return unsignedp ? unsigned_type_node : integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
- return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
- return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
- return (unsignedp ? long_long_unsigned_type_node
- : long_long_integer_type_node);
- return type;
-}
-
/* Compute the value of the `sizeof' operator. */
tree
@@ -814,36 +717,38 @@ c_sizeof (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
- tree t;
+ tree size;
if (code == FUNCTION_TYPE)
{
if (pedantic || warn_pointer_arith)
pedwarn ("sizeof applied to a function type");
- return size_int (1);
+ 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_int (1);
+ size = size_one_node;
}
- if (code == ERROR_MARK)
- return size_int (1);
- if (TYPE_SIZE (type) == 0)
+ else if (code == ERROR_MARK)
+ size = size_one_node;
+ else if (!COMPLETE_TYPE_P (type))
{
error ("sizeof applied to an incomplete type");
- return size_int (0);
+ size = size_zero_node;
}
-
- /* Convert in case a char is more than one unit. */
- t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
- size_int (TYPE_PRECISION (char_type_node)));
- t = convert (sizetype, t);
- /* size_binop does not put the constant in range, so do it now. */
- if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0))
- TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1;
- return t;
+ 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
@@ -851,21 +756,23 @@ c_sizeof_nowarn (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
- tree t;
-
- if (code == FUNCTION_TYPE
- || code == VOID_TYPE
- || code == ERROR_MARK)
- return size_int (1);
- if (TYPE_SIZE (type) == 0)
- return size_int (0);
+ tree size;
- /* Convert in case a char is more than one unit. */
- t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
- size_int (TYPE_PRECISION (char_type_node)));
- t = convert (sizetype, t);
- force_fit_type (t, 0);
- return t;
+ 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. */
@@ -875,102 +782,33 @@ c_size_in_bytes (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
- tree t;
- if (code == FUNCTION_TYPE)
- return size_int (1);
- if (code == VOID_TYPE)
- return size_int (1);
- if (code == ERROR_MARK)
- return size_int (1);
- if (TYPE_SIZE (type) == 0)
+ if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
+ return size_one_node;
+
+ if (!COMPLETE_OR_VOID_TYPE_P (type))
{
error ("arithmetic on pointer to an incomplete type");
- return size_int (1);
+ return size_one_node;
}
/* Convert in case a char is more than one unit. */
- t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
- size_int (BITS_PER_UNIT));
- t = convert (sizetype, t);
- force_fit_type (t, 0);
- return t;
-}
-
-/* Implement the __alignof keyword: Return the minimum required
- alignment of TYPE, measured in bytes. */
-
-tree
-c_alignof (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
-
- if (code == FUNCTION_TYPE)
- return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-
- if (code == VOID_TYPE || code == ERROR_MARK)
- return size_int (1);
-
- return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
+ return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+ size_int (TYPE_PRECISION (char_type_node)
+ / BITS_PER_UNIT));
}
-/* Implement the __alignof keyword: Return the minimum required
- alignment of EXPR, measured in bytes. For VAR_DECL's and
- FIELD_DECL's return DECL_ALIGN (which can be set from an
- "aligned" __attribute__ specification). */
-
-tree
-c_alignof_expr (expr)
- tree expr;
-{
- if (TREE_CODE (expr) == VAR_DECL)
- return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
-
- if (TREE_CODE (expr) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
- {
- error ("`__alignof' applied to a bit-field");
- return size_int (1);
- }
- 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);
-
- if (TREE_CODE (expr) == INDIRECT_REF)
- {
- tree t = TREE_OPERAND (expr, 0);
- tree best = t;
- int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
-
- while (TREE_CODE (t) == NOP_EXPR
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
- {
- int thisalign;
-
- t = TREE_OPERAND (t, 0);
- thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
- if (thisalign > bestalign)
- best = t, bestalign = thisalign;
- }
- return c_alignof (TREE_TYPE (TREE_TYPE (best)));
- }
- else
- return c_alignof (TREE_TYPE (expr));
-}
-
/* Return either DECL or its known constant value (if it has one). */
-static tree
+tree
decl_constant_value (decl)
tree decl;
{
if (/* Don't change a variable array bound or initial value to a constant
in a place where a variable is invalid. */
current_function_decl != 0
- && ! pedantic
&& ! TREE_THIS_VOLATILE (decl)
- && TREE_READONLY (decl) && ! ITERATOR_P (decl)
+ && TREE_READONLY (decl)
&& DECL_INITIAL (decl) != 0
&& TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
/* This is invalid if initial value is not constant.
@@ -978,109 +816,76 @@ decl_constant_value (decl)
or a variable, then re-evaluating it could give different results. */
&& TREE_CONSTANT (DECL_INITIAL (decl))
/* Check for cases where this is sub-optimal, even though valid. */
- && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
- && DECL_MODE (decl) != BLKmode)
+ && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
return DECL_INITIAL (decl);
return 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. */
+/* Return either DECL or its known constant value (if it has one), but
+ return DECL if pedantic or DECL has mode BLKmode. This is for
+ bug-compatibility with the old behavior of decl_constant_value
+ (before GCC 3.0); every use of this function is a bug and it should
+ be removed before GCC 3.1. It is not appropriate to use pedantic
+ in a way that affects optimization, and BLKmode is probably not the
+ right test for avoiding misoptimizations either. */
-tree
-default_conversion (exp)
- tree exp;
+static tree
+decl_constant_value_for_broken_optimization (decl)
+ tree decl;
{
- register tree type = TREE_TYPE (exp);
- register enum tree_code code = TREE_CODE (type);
+ if (pedantic || DECL_MODE (decl) == BLKmode)
+ return decl;
+ else
+ return decl_constant_value (decl);
+}
- /* 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 (exp);
- type = TREE_TYPE (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);
+ 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
+ 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) == NON_LVALUE_EXPR)
+ not_lvalue = 1;
+ exp = TREE_OPERAND (exp, 0);
}
- if (TREE_CODE (exp) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)))
- {
- tree width = DECL_SIZE (TREE_OPERAND (exp, 1));
- HOST_WIDE_INT low = TREE_INT_CST_LOW (width);
-
- /* If it's thinner than an int, promote it like a
- C_PROMOTING_INTEGER_TYPE_P, otherwise leave it alone. */
+ /* 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 (low < TYPE_PRECISION (integer_type_node))
- {
- if (flag_traditional && TREE_UNSIGNED (type))
- return convert (unsigned_type_node, exp);
- else
- return convert (integer_type_node, exp);
- }
- }
-
- if (C_PROMOTING_INTEGER_TYPE_P (type))
- {
- /* Traditionally, unsignedness is preserved in default promotions.
- Also preserve unsignedness if not really getting any wider. */
- if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
- return convert (unsigned_type_node, exp);
- return convert (integer_type_node, exp);
- }
- if (flag_traditional && !flag_allow_single_precision
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
- if (code == VOID_TYPE)
- {
- error ("void value not ignored as it ought to be");
- return error_mark_node;
- }
if (code == FUNCTION_TYPE)
{
return build_unary_op (ADDR_EXPR, exp, 0);
}
if (code == ARRAY_TYPE)
{
- register tree adr;
+ tree adr;
tree restype = TREE_TYPE (type);
tree ptrtype;
int constp = 0;
int volatilep = 0;
+ int lvalue_array_p;
- if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r'
- || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
+ if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
{
constp = TREE_READONLY (exp);
volatilep = TREE_THIS_VOLATILE (exp);
@@ -1104,11 +909,14 @@ default_conversion (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);
@@ -1133,18 +941,113 @@ default_conversion (exp)
}
return exp;
}
-
-/* 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 = type_for_size (MAX (TYPE_PRECISION (type),
+ TYPE_PRECISION (integer_type_node)),
+ ((flag_traditional
+ || (TYPE_PRECISION (type)
+ >= TYPE_PRECISION (integer_type_node)))
+ && TREE_UNSIGNED (type)));
+
+ return convert (type, exp);
+ }
+
+ if (TREE_CODE (exp) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
+ /* If it's thinner than an int, promote it like a
+ c_promoting_integer_type_p, otherwise leave it alone. */
+ && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
+ TYPE_PRECISION (integer_type_node)))
+ return convert (flag_traditional && TREE_UNSIGNED (type)
+ ? unsigned_type_node : integer_type_node,
+ exp);
+
+ if (c_promoting_integer_type_p (type))
+ {
+ /* Traditionally, unsignedness is preserved in default promotions.
+ Also preserve unsignedness if not really getting any wider. */
+ if (TREE_UNSIGNED (type)
+ && (flag_traditional
+ || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+ return convert (unsigned_type_node, exp);
+
+ return convert (integer_type_node, exp);
+ }
+
+ if (flag_traditional && !flag_allow_single_precision
+ && TYPE_MAIN_VARIANT (type) == float_type_node)
+ return convert (double_type_node, exp);
+
+ if (code == VOID_TYPE)
+ {
+ error ("void value not ignored as it ought to be");
+ return error_mark_node;
+ }
+ return exp;
+}
+
+/* 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
@@ -1170,18 +1073,15 @@ lookup_field (type, component, indirect)
/* 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. */
@@ -1203,35 +1103,31 @@ lookup_field (type, component, indirect)
if (DECL_NAME (field_array[bot]) == component)
field = field_array[bot];
else if (DECL_NAME (field) != component)
- field = 0;
+ return NULL_TREE;
}
else
{
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
- if (DECL_NAME (field) == NULL_TREE)
+ if (DECL_NAME (field) == NULL_TREE
+ && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
{
- tree junk;
- tree anon = 0;
+ tree anon = lookup_field (field, component);
- if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
- || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
- anon = lookup_field (TREE_TYPE (field), component, &junk);
-
- if (anon != NULL_TREE)
- {
- *indirect = field;
- return anon;
- }
+ if (anon)
+ return tree_cons (NULL_TREE, field, anon);
}
if (DECL_NAME (field) == component)
break;
}
+
+ if (field == NULL_TREE)
+ return NULL_TREE;
}
- *indirect = NULL_TREE;
- return field;
+ return tree_cons (NULL_TREE, field, NULL_TREE);
}
/* Make an expression to refer to the COMPONENT field of
@@ -1241,27 +1137,27 @@ tree
build_component_ref (datum, component)
tree datum, component;
{
- register tree type = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (type);
- register tree field = NULL;
- register 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. */
+ tree type = TREE_TYPE (datum);
+ enum tree_code code = TREE_CODE (type);
+ tree field = NULL;
+ tree ref;
+
+ /* 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;
}
@@ -1270,46 +1166,45 @@ build_component_ref (datum, component)
if (code == RECORD_TYPE || code == UNION_TYPE)
{
- tree indirect = 0;
-
- if (TYPE_SIZE (type) == 0)
+ if (!COMPLETE_TYPE_P (type))
{
incomplete_type_error (NULL_TREE, type);
return error_mark_node;
}
- field = lookup_field (type, component, &indirect);
+ field = lookup_field (datum, component);
if (!field)
{
- error (code == RECORD_TYPE
- ? "structure has no member named `%s'"
- : "union has no member named `%s'",
+ error ("%s has no member named `%s'",
+ code == RECORD_TYPE ? "structure" : "union",
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;
}
@@ -1329,8 +1224,8 @@ build_indirect_ref (ptr, errorstring)
tree ptr;
const char *errorstring;
{
- register tree pointer = default_conversion (ptr);
- register tree type = TREE_TYPE (pointer);
+ tree pointer = default_conversion (ptr);
+ tree type = TREE_TYPE (pointer);
if (TREE_CODE (type) == POINTER_TYPE)
{
@@ -1342,15 +1237,14 @@ build_indirect_ref (ptr, errorstring)
else
{
tree t = TREE_TYPE (type);
- register tree ref = build1 (INDIRECT_REF,
- TYPE_MAIN_VARIANT (t), pointer);
+ tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer);
- if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE)
+ if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
{
error ("dereferencing pointer to incomplete type");
return error_mark_node;
}
- if (TREE_CODE (t) == VOID_TYPE && skip_evaluation == 0)
+ if (VOID_TYPE_P (t) && skip_evaluation == 0)
warning ("dereferencing `void *' pointer");
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
@@ -1425,7 +1319,7 @@ build_array_ref (array, index)
address arithmetic on its address.
Likewise an array of elements of variable size. */
if (TREE_CODE (index) != INTEGER_CST
- || (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0
+ || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
{
if (mark_addressable (array) == 0)
@@ -1443,21 +1337,15 @@ build_array_ref (array, index)
return error_mark_node;
}
- if (pedantic && !lvalue_p (array))
- {
- if (DECL_REGISTER (array))
- pedwarn ("ANSI C forbids subscripting `register' array");
- else
- pedwarn ("ANSI C forbids subscripting non-lvalue array");
- }
-
if (pedantic)
{
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
- pedwarn ("ANSI C forbids subscripting non-lvalue array");
+ pedwarn ("ISO C forbids subscripting `register' array");
+ else if (! flag_isoc99 && ! lvalue_p (foo))
+ pedwarn ("ISO C89 forbids subscripting non-lvalue array");
}
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
@@ -1520,6 +1408,99 @@ build_array_ref (array, index)
}
}
+/* Build an external reference to identifier ID. FUN indicates
+ whether this will be used for a function call. */
+tree
+build_external_ref (id, fun)
+ tree id;
+ int fun;
+{
+ tree ref;
+ 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)
+ ref = objc_ivar;
+ else if (fun)
+ {
+ if (!decl || decl == error_mark_node)
+ /* Ordinary implicit function declaration. */
+ ref = implicitly_declare (id);
+ else
+ {
+ /* Implicit declaration of built-in function. Don't
+ change the built-in declaration, but don't let this
+ go by silently, either. */
+ implicit_decl_warning (id);
+
+ /* only issue this warning once */
+ C_DECL_ANTICIPATED (decl) = 0;
+ ref = decl;
+ }
+ }
+ else
+ {
+ /* Reference to undeclared variable, including reference to
+ builtin outside of function-call context. */
+ if (current_function_decl == 0)
+ error ("`%s' undeclared here (not in a function)",
+ IDENTIFIER_POINTER (id));
+ else
+ {
+ if (IDENTIFIER_GLOBAL_VALUE (id) != error_mark_node
+ || IDENTIFIER_ERROR_LOCUS (id) != current_function_decl)
+ {
+ error ("`%s' undeclared (first use in this function)",
+ IDENTIFIER_POINTER (id));
+
+ if (! undeclared_variable_notice)
+ {
+ error ("(Each undeclared identifier is reported only once");
+ error ("for each function it appears in.)");
+ undeclared_variable_notice = 1;
+ }
+ }
+ IDENTIFIER_GLOBAL_VALUE (id) = error_mark_node;
+ IDENTIFIER_ERROR_LOCUS (id) = current_function_decl;
+ }
+ return error_mark_node;
+ }
+ }
+ else
+ {
+ /* Properly declared variable or function reference. */
+ if (!objc_ivar)
+ ref = decl;
+ else if (decl != objc_ivar && IDENTIFIER_LOCAL_VALUE (id))
+ {
+ warning ("local declaration of `%s' hides instance variable",
+ IDENTIFIER_POINTER (id));
+ ref = decl;
+ }
+ else
+ ref = objc_ivar;
+ }
+
+ if (TREE_TYPE (ref) == error_mark_node)
+ return error_mark_node;
+
+ assemble_external (ref);
+ TREE_USED (ref) = 1;
+
+ if (TREE_CODE (ref) == CONST_DECL)
+ {
+ ref = DECL_INITIAL (ref);
+ TREE_CONSTANT (ref) = 1;
+ }
+
+ return ref;
+}
+
/* Build a function call to function FUNCTION with parameters PARAMS.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
TREE_VALUE of each node is a parameter-expression.
@@ -1529,9 +1510,9 @@ tree
build_function_call (function, params)
tree function, params;
{
- register tree fntype, fundecl = 0;
- register tree coerced_params;
- tree name = NULL_TREE, assembler_name = NULL_TREE;
+ tree fntype, fundecl = 0;
+ tree coerced_params;
+ tree name = NULL_TREE, assembler_name = NULL_TREE, result;
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (function);
@@ -1577,8 +1558,8 @@ build_function_call (function, params)
/* Check for errors in format strings. */
- if (warn_format && (name || assembler_name))
- check_function_format (name, assembler_name, coerced_params);
+ if (warn_format)
+ check_function_format (NULL, 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
@@ -1587,28 +1568,21 @@ build_function_call (function, params)
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (function, 0)))
- switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0)))
- {
- case BUILT_IN_ABS:
- case BUILT_IN_LABS:
- case BUILT_IN_FABS:
- if (coerced_params == 0)
- return integer_zero_node;
- return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
- default:
- break;
- }
+ {
+ result = expand_tree_builtin (TREE_OPERAND (function, 0),
+ params, coerced_params);
+ if (result)
+ return result;
+ }
- {
- register tree result
- = build (CALL_EXPR, TREE_TYPE (fntype),
- function, coerced_params, NULL_TREE);
-
- TREE_SIDE_EFFECTS (result) = 1;
- if (TREE_TYPE (result) == void_type_node)
- return result;
- return require_complete_type (result);
- }
+ result = build (CALL_EXPR, TREE_TYPE (fntype),
+ function, coerced_params, NULL_TREE);
+ TREE_SIDE_EFFECTS (result) = 1;
+ result = fold (result);
+
+ if (VOID_TYPE_P (TREE_TYPE (result)))
+ return result;
+ return require_complete_type (result);
}
/* Convert the argument expressions in the list VALUES
@@ -1633,8 +1607,8 @@ static tree
convert_arguments (typelist, values, name, fundecl)
tree typelist, values, name, fundecl;
{
- register tree typetail, valtail;
- register tree result = NULL;
+ tree typetail, valtail;
+ tree result = NULL;
int parmnum;
/* Scan the given expressions and types, producing individual
@@ -1644,8 +1618,8 @@ convert_arguments (typelist, values, name, fundecl)
valtail;
valtail = TREE_CHAIN (valtail), parmnum++)
{
- register tree type = typetail ? TREE_VALUE (typetail) : 0;
- register tree val = TREE_VALUE (valtail);
+ tree type = typetail ? TREE_VALUE (typetail) : 0;
+ tree val = TREE_VALUE (valtail);
if (type == void_type_node)
{
@@ -1663,9 +1637,7 @@ convert_arguments (typelist, values, name, fundecl)
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);
@@ -1674,7 +1646,7 @@ convert_arguments (typelist, values, name, fundecl)
/* Formal parm type is specified by a function prototype. */
tree parmval;
- if (TYPE_SIZE (type) == 0)
+ if (!COMPLETE_TYPE_P (type))
{
error ("type of formal parameter %d is incomplete", parmnum + 1);
parmval = val;
@@ -1683,19 +1655,25 @@ convert_arguments (typelist, values, name, fundecl)
{
/* 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);
@@ -1710,15 +1688,18 @@ convert_arguments (typelist, values, name, fundecl)
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);
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. */
;
@@ -1767,12 +1748,10 @@ convert_arguments (typelist, values, name, fundecl)
(char *) 0, /* arg passing */
fundecl, name, parmnum + 1);
-#ifdef PROMOTE_PROTOTYPES
- if ((TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
+ if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
-#endif
}
result = tree_cons (NULL_TREE, parmval, result);
}
@@ -1820,11 +1799,12 @@ parser_build_binary_op (code, arg1, arg2)
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
@@ -1894,8 +1874,7 @@ parser_build_binary_op (code, arg1, arg2)
/* 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
{
@@ -1934,17 +1913,17 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
int convert_p;
{
tree type0, type1;
- register enum tree_code code0, code1;
+ enum tree_code code0, code1;
tree op0, op1;
/* Expression code to give to the expression when it is built.
Normally this is CODE, which is what the caller asked for,
but in some special cases we change it. */
- register enum tree_code resultcode = code;
+ enum tree_code resultcode = code;
/* Data type in which the computation is to be performed.
In the simplest cases this is the common type of the arguments. */
- register tree result_type = NULL;
+ tree result_type = NULL;
/* Nonzero means operands have already been type-converted
in whatever way is necessary.
@@ -2042,6 +2021,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
+ /* Floating point division by zero is a legitimate way to obtain
+ infinities and NaNs. */
+ if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
+ warning ("division by zero");
+
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == COMPLEX_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -2050,17 +2034,14 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
- {
- /* Although it would be tempting to shorten always here, that
- loses on some targets, since the modulo instruction is
- undefined if the quotient can't be represented in the
- computation mode. We shorten only if unsigned or if
- dividing by something we know != -1. */
- shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
- || (TREE_CODE (op1) == INTEGER_CST
- && (TREE_INT_CST_LOW (op1) != -1
- || TREE_INT_CST_HIGH (op1) != -1)));
- }
+ /* Although it would be tempting to shorten always here, that
+ loses on some targets, since the modulo instruction is
+ undefined if the quotient can't be represented in the
+ computation mode. We shorten only if unsigned or if
+ dividing by something we know != -1. */
+ shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
+ || (TREE_CODE (op1) == INTEGER_CST
+ && ! integer_all_onesp (op1)));
common = 1;
}
break;
@@ -2098,6 +2079,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
+ if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
+ warning ("division by zero");
+
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
/* Although it would be tempting to shorten always here, that loses
@@ -2106,8 +2090,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
only if unsigned or if dividing by something we know != -1. */
shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
|| (TREE_CODE (op1) == INTEGER_CST
- && (TREE_INT_CST_LOW (op1) != -1
- || TREE_INT_CST_HIGH (op1) != -1)));
+ && ! integer_all_onesp (op1)));
common = 1;
}
break;
@@ -2145,14 +2128,14 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
warning ("right shift count is negative");
else
{
- if (TREE_INT_CST_LOW (op1) | TREE_INT_CST_HIGH (op1))
+ if (! integer_zerop (op1))
short_shift = 1;
- if (TREE_INT_CST_HIGH (op1) != 0
- || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
- >= TYPE_PRECISION (type0)))
+
+ if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
warning ("right shift count >= width of type");
}
}
+
/* Use the type of the value to be shifted.
This is what most traditional C compilers do. */
result_type = type0;
@@ -2175,11 +2158,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("left shift count is negative");
- else if (TREE_INT_CST_HIGH (op1) != 0
- || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
- >= TYPE_PRECISION (type0)))
+
+ else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
warning ("left shift count >= width of type");
}
+
/* Use the type of the value to be shifted.
This is what most traditional C compilers do. */
result_type = type0;
@@ -2203,11 +2186,10 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("shift count is negative");
- else if (TREE_INT_CST_HIGH (op1) != 0
- || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
- >= TYPE_PRECISION (type0)))
+ else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
warning ("shift count >= width of type");
}
+
/* Use the type of the value to be shifted.
This is what most traditional C compilers do. */
result_type = type0;
@@ -2225,6 +2207,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
case EQ_EXPR:
case NE_EXPR:
+ if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE))
+ warning ("comparing floating point with == or != is unsafe");
/* Result of comparison is always int,
but don't convert the args to int! */
build_type = integer_type_node;
@@ -2235,26 +2219,26 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
- register tree tt0 = TREE_TYPE (type0);
- register tree tt1 = TREE_TYPE (type1);
+ tree tt0 = TREE_TYPE (type0);
+ tree tt1 = TREE_TYPE (type1);
/* 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))
result_type = common_type (type0, type1);
- else if (TYPE_MAIN_VARIANT (tt0) == void_type_node)
+ else if (VOID_TYPE_P (tt0))
{
/* op0 != orig_op0 detects the case of something
whose value is 0 but which isn't a valid null ptr const. */
if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
&& TREE_CODE (tt1) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
+ pedwarn ("ISO C forbids comparison of `void *' with function pointer");
}
- else if (TYPE_MAIN_VARIANT (tt1) == void_type_node)
+ else if (VOID_TYPE_P (tt1))
{
if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
&& TREE_CODE (tt0) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
+ pedwarn ("ISO C forbids comparison of `void *' with function pointer");
}
else
pedwarn ("comparison of distinct pointer types lacks a cast");
@@ -2294,7 +2278,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
result_type = common_type (type0, type1);
if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
+ pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
}
else
{
@@ -2317,12 +2301,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
if (comp_target_types (type0, type1))
{
result_type = common_type (type0, type1);
- if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
- != (TYPE_SIZE (TREE_TYPE (type1)) != 0))
+ if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
+ != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn ("comparison of complete and incomplete pointers");
else if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
+ pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
}
else
{
@@ -2357,7 +2341,23 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
pedwarn ("comparison between pointer and integer");
}
break;
-
+
+ case UNORDERED_EXPR:
+ case ORDERED_EXPR:
+ case UNLT_EXPR:
+ case UNLE_EXPR:
+ case UNGT_EXPR:
+ case UNGE_EXPR:
+ case UNEQ_EXPR:
+ build_type = integer_type_node;
+ if (code0 != REAL_TYPE || code1 != REAL_TYPE)
+ {
+ error ("unordered comparison on non-floating point argument");
+ return error_mark_node;
+ }
+ common = 1;
+ break;
+
default:
break;
}
@@ -2461,23 +2461,13 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
/* We can shorten only if the shift count is less than the
number of bits in the smaller type size. */
- && TREE_INT_CST_HIGH (op1) == 0
- && TYPE_PRECISION (TREE_TYPE (arg0)) > TREE_INT_CST_LOW (op1)
- /* If arg is sign-extended and then unsigned-shifted,
- we can simulate this with a signed shift in arg's type
- only if the extended result is at least twice as wide
- as the arg. Otherwise, the shift could use up all the
- ones made by sign-extension and bring in zeros.
- We can't optimize that case at all, but in most machines
- it never happens because available widths are 2**N. */
- && (!TREE_UNSIGNED (final_type)
- || unsigned_arg
- || 2 * TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (result_type)))
+ && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
+ /* We cannot drop an unsigned shift after sign-extension. */
+ && (!TREE_UNSIGNED (final_type) || unsigned_arg))
{
/* Do an unsigned shift if the operand was zero-extended. */
result_type
- = signed_or_unsigned_type (unsigned_arg,
- TREE_TYPE (arg0));
+ = 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);
@@ -2498,8 +2488,10 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
enum tree_code xresultcode = resultcode;
tree val
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
+
if (val != 0)
return val;
+
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
@@ -2509,50 +2501,63 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
{
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
-
int unsignedp0, unsignedp1;
tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1);
- /* Avoid spurious warnings for comparison with enumerators. */
-
xop0 = orig_op0;
xop1 = orig_op1;
STRIP_TYPE_NOPS (xop0);
STRIP_TYPE_NOPS (xop1);
/* Give warnings for comparisons between signed and unsigned
- quantities that may fail. */
- /* Do the checking based on the original operand trees, so that
- casts will be considered, but default promotions won't be. */
+ quantities that may fail.
- /* Do not warn if the comparison is being done in a signed type,
+ Do the checking based on the original operand trees, so that
+ casts will be considered, but default promotions won't be.
+
+ Do not warn if the comparison is being done in a signed type,
since the signed type will only be chosen if it can represent
all the values of the unsigned type. */
if (! TREE_UNSIGNED (result_type))
/* OK */;
- /* Do not warn if both operands are unsigned. */
+ /* Do not warn if both operands are the same signedness. */
else if (op0_signed == op1_signed)
/* OK */;
- /* 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 ((op0_signed && TREE_CODE (xop0) == INTEGER_CST
- && tree_int_cst_sgn (xop0) >= 0)
- || (op1_signed && TREE_CODE (xop1) == INTEGER_CST
- && tree_int_cst_sgn (xop1) >= 0))
- /* OK */;
- /* Do not warn if the comparison is an equality operation,
- the unsigned quantity is an integral constant and it does
- not use the most significant bit of result_type. */
- else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
- && ((op0_signed && TREE_CODE (xop1) == INTEGER_CST
- && int_fits_type_p (xop1, signed_type (result_type)))
- || (op1_signed && TREE_CODE (xop0) == INTEGER_CST
- && int_fits_type_p (xop0, signed_type (result_type)))))
- /* OK */;
else
- warning ("comparison between signed and unsigned");
+ {
+ tree sop, uop;
+
+ if (op0_signed)
+ sop = xop0, uop = xop1;
+ else
+ sop = xop1, uop = xop0;
+
+ /* Do not warn if the signed quantity is an
+ unsuffixed integer literal (or some static
+ constant expression involving such literals or a
+ conditional expression involving such literals)
+ and it is non-negative. */
+ if (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)))
+ /* 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)))
+ /* OK */;
+ else
+ warning ("comparison between signed and unsigned");
+ }
/* Warn if two unsigned values are being compared in a size
larger than their original size, and one (and only one) is the
@@ -2572,31 +2577,30 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
primop1 = get_narrower (TREE_OPERAND (primop1, 0),
&unsignedp1);
- if (TREE_CODE (primop0) == INTEGER_CST
- || TREE_CODE (primop1) == INTEGER_CST)
+ if (host_integerp (primop0, 0) || host_integerp (primop1, 0))
{
tree primop;
- long constant, mask;
+ HOST_WIDE_INT constant, mask;
int unsignedp, bits;
- if (TREE_CODE (primop0) == INTEGER_CST)
+ if (host_integerp (primop0, 0))
{
primop = primop1;
unsignedp = unsignedp1;
- constant = TREE_INT_CST_LOW (primop0);
+ constant = tree_low_cst (primop0, 0);
}
else
{
primop = primop0;
unsignedp = unsignedp0;
- constant = TREE_INT_CST_LOW (primop1);
+ constant = tree_low_cst (primop1, 0);
}
bits = TYPE_PRECISION (TREE_TYPE (primop));
if (bits < TYPE_PRECISION (result_type)
- && bits < HOST_BITS_PER_LONG && unsignedp)
+ && bits < HOST_BITS_PER_WIDE_INT && unsignedp)
{
- mask = (~0L) << bits;
+ mask = (~ (HOST_WIDE_INT) 0) << bits;
if ((mask & constant) != mask)
warning ("comparison of promoted ~unsigned with constant");
}
@@ -2636,8 +2640,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
build_type = result_type;
{
- register tree result = build (resultcode, build_type, op0, op1);
- register tree folded;
+ tree result = build (resultcode, build_type, op0, op1);
+ tree folded;
folded = fold (result);
if (folded == result)
@@ -2654,16 +2658,16 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
static tree
pointer_int_sum (resultcode, ptrop, intop)
enum tree_code resultcode;
- register tree ptrop, intop;
+ tree ptrop, intop;
{
tree size_exp;
- register tree result;
- register tree folded;
+ tree result;
+ tree folded;
/* The result is a pointer of the same type that is being added. */
- register tree result_type = TREE_TYPE (ptrop);
+ tree result_type = TREE_TYPE (ptrop);
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
@@ -2742,12 +2746,14 @@ pointer_int_sum (resultcode, ptrop, intop)
static tree
pointer_diff (op0, op1)
- register tree op0, op1;
+ tree op0, op1;
{
- register tree result, folded;
+ tree result, folded;
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (TREE_TYPE (op0));
+ tree con0, con1, lit0, lit1;
+ tree orig_op1 = op1;
if (pedantic || warn_pointer_arith)
{
@@ -2757,6 +2763,40 @@ pointer_diff (op0, op1)
pedwarn ("pointer to a function used in subtraction");
}
+ /* If the conversion to ptrdiff_type does anything like widening or
+ converting a partial to an integral mode, we get a convert_expression
+ that is in the way to do any simplifications.
+ (fold-const.c doesn't know that the extra bits won't be needed.
+ split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a
+ different mode in place.)
+ So first try to find a common term here 'by hand'; we want to cover
+ at least the cases that occur in legal static initializers. */
+ con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0;
+ con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1;
+
+ if (TREE_CODE (con0) == PLUS_EXPR)
+ {
+ lit0 = TREE_OPERAND (con0, 1);
+ con0 = TREE_OPERAND (con0, 0);
+ }
+ else
+ lit0 = integer_zero_node;
+
+ if (TREE_CODE (con1) == PLUS_EXPR)
+ {
+ lit1 = TREE_OPERAND (con1, 1);
+ con1 = TREE_OPERAND (con1, 0);
+ }
+ else
+ lit1 = integer_zero_node;
+
+ if (operand_equal_p (con0, con1, 0))
+ {
+ op0 = lit0;
+ op1 = lit1;
+ }
+
+
/* First do the subtraction as integers;
then drop through to build the divide operator.
Do not do default conversions on the minus operator
@@ -2765,7 +2805,7 @@ pointer_diff (op0, op1)
op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
convert (restype, op1), 0);
/* This generates an error if op1 is pointer to incomplete type. */
- if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
+ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
error ("arithmetic on pointer to an incomplete type");
/* This generates an error if op0 is pointer to incomplete type. */
@@ -2783,24 +2823,29 @@ pointer_diff (op0, op1)
/* 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. */
- register tree arg = xarg;
- register tree argtype = 0;
- register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
+ 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;
- if (typecode == ENUMERAL_TYPE)
+ if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
typecode = INTEGER_TYPE;
switch (code)
@@ -2834,6 +2879,8 @@ build_unary_op (code, xarg, noconvert)
if (typecode == COMPLEX_TYPE)
{
code = CONJ_EXPR;
+ if (pedantic)
+ pedwarn ("ISO C does not support `~' for complex conjugation");
if (!noconvert)
arg = default_conversion (arg);
}
@@ -2908,7 +2955,7 @@ build_unary_op (code, xarg, noconvert)
/* 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;
@@ -2918,6 +2965,9 @@ build_unary_op (code, xarg, noconvert)
{
tree real, imag;
+ if (pedantic)
+ pedwarn ("ISO C does not support `++' and `--' on complex types");
+
arg = stabilize_reference (arg);
real = build_unary_op (REALPART_EXPR, arg, 1);
imag = build_unary_op (IMAGPART_EXPR, arg, 1);
@@ -2930,14 +2980,16 @@ build_unary_op (code, xarg, noconvert)
if (typecode != POINTER_TYPE
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
{
- error (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
- ? "wrong type argument to increment"
- : "wrong type argument to 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;
}
{
- register tree inc;
+ tree inc;
tree result_type = TREE_TYPE (arg);
arg = get_unwidened (arg, 0);
@@ -2949,16 +3001,23 @@ build_unary_op (code, xarg, noconvert)
{
/* If pointer target is an undefined struct,
we just cannot know how to do the arithmetic. */
- if (TYPE_SIZE (TREE_TYPE (result_type)) == 0)
- error (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
- ? "increment of pointer to unknown structure"
- : "decrement of pointer to unknown structure");
+ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
+ {
+ 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 (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
- ? "wrong type argument to increment"
- : "wrong type argument to 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
@@ -2990,18 +3049,23 @@ build_unary_op (code, xarg, noconvert)
else
{
tree incremented, modify, value;
- arg = stabilize_reference (arg);
- if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
- value = arg;
+ if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+ value = boolean_increment (code, arg);
else
- value = save_expr (arg);
- incremented = build (((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? PLUS_EXPR : MINUS_EXPR),
- argtype, value, inc);
- TREE_SIDE_EFFECTS (incremented) = 1;
- modify = build_modify_expr (arg, NOP_EXPR, incremented);
- value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+ {
+ arg = stabilize_reference (arg);
+ if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+ value = arg;
+ else
+ value = save_expr (arg);
+ incremented = build (((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? PLUS_EXPR : MINUS_EXPR),
+ argtype, value, inc);
+ TREE_SIDE_EFFECTS (incremented) = 1;
+ modify = build_modify_expr (arg, NOP_EXPR, incremented);
+ value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+ }
TREE_USED (value) = 1;
return value;
}
@@ -3026,7 +3090,10 @@ build_unary_op (code, xarg, noconvert)
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"));
- val = build (code, TREE_TYPE (arg), arg, inc);
+ if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+ val = boolean_increment (code, arg);
+ else
+ val = build (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
val = convert (result_type, val);
if (TREE_CODE (val) != code)
@@ -3035,8 +3102,7 @@ build_unary_op (code, xarg, noconvert)
}
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)
@@ -3058,7 +3124,7 @@ build_unary_op (code, xarg, noconvert)
/* 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;
@@ -3077,37 +3143,31 @@ build_unary_op (code, xarg, noconvert)
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
if (pedantic)
- pedwarn ("ANSI C forbids the address of a cast expression");
+ pedwarn ("ISO C forbids the address of a cast expression");
return convert (build_pointer_type (TREE_TYPE (arg)),
build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0),
0));
}
#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;
/* Ordinary case; arg is a COMPONENT_REF or a decl. */
argtype = TREE_TYPE (arg);
+
/* If the lvalue is const or volatile, merge that into the type
to which the address will point. Note that you can't get a
restricted pointer by taking the address of something, so we
only have to deal with `const' and `volatile' here. */
- if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
- || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
- {
- if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
- argtype = c_build_type_variant (argtype,
- TREE_READONLY (arg),
- TREE_THIS_VOLATILE (arg));
- }
+ if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
+ && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
+ argtype = c_build_type_variant (argtype,
+ TREE_READONLY (arg),
+ TREE_THIS_VOLATILE (arg));
argtype = build_pointer_type (argtype);
@@ -3121,7 +3181,7 @@ build_unary_op (code, xarg, noconvert)
{
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))
{
@@ -3130,18 +3190,9 @@ build_unary_op (code, xarg, noconvert)
return error_mark_node;
}
- addr = convert (argtype, addr);
-
- if (! integer_zerop (DECL_FIELD_BITPOS (field)))
- {
- tree offset
- = size_binop (EASY_DIV_EXPR, DECL_FIELD_BITPOS (field),
- size_int (BITS_PER_UNIT));
- int flag = TREE_CONSTANT (addr);
- addr = fold (build (PLUS_EXPR, argtype,
- addr, convert (argtype, offset)));
- TREE_CONSTANT (addr) = flag;
- }
+ addr = fold (build (PLUS_EXPR, argtype,
+ convert (argtype, addr),
+ convert (argtype, byte_position (field))));
}
else
addr = build1 (code, argtype, arg);
@@ -3201,7 +3252,7 @@ int
lvalue_p (ref)
tree ref;
{
- register enum tree_code code = TREE_CODE (ref);
+ enum tree_code code = TREE_CODE (ref);
switch (code)
{
@@ -3210,6 +3261,7 @@ lvalue_p (ref)
case COMPONENT_REF:
return lvalue_p (TREE_OPERAND (ref, 0));
+ case COMPOUND_LITERAL_EXPR:
case STRING_CST:
return 1;
@@ -3240,21 +3292,26 @@ lvalue_or_else (ref, msgid)
const char *msgid;
{
int win = lvalue_p (ref);
+
if (! win)
- error (msgid);
+ error ("%s", msgid);
+
return win;
}
/* 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)
@@ -3263,7 +3320,7 @@ unary_complex_lvalue (code, arg)
/* 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),
@@ -3273,14 +3330,15 @@ unary_complex_lvalue (code, arg)
/* 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;
@@ -3294,11 +3352,18 @@ pedantic_lvalue_warning (code)
enum tree_code code;
{
if (pedantic)
- pedwarn (code == COND_EXPR
- ? "ANSI C forbids use of conditional expressions as lvalues"
- : code == COMPOUND_EXPR
- ? "ANSI C forbids use of compound expressions as lvalues"
- : "ANSI C forbids use of cast expressions as lvalues");
+ switch (code)
+ {
+ case COND_EXPR:
+ pedwarn ("ISO C forbids use of conditional expressions as lvalues");
+ break;
+ case COMPOUND_EXPR:
+ pedwarn ("ISO C forbids use of compound expressions as lvalues");
+ break;
+ default:
+ pedwarn ("ISO C forbids use of cast expressions as lvalues");
+ break;
+ }
}
/* Warn about storing in something that is `const'. */
@@ -3308,11 +3373,6 @@ readonly_warning (arg, msgid)
tree arg;
const char *msgid;
{
- /* Forbid assignments to iterators. */
- if (TREE_CODE (arg) == VAR_DECL && ITERATOR_P (arg))
- pedwarn ("%s of iterator `%s'", _(msgid),
- IDENTIFIER_POINTER (DECL_NAME (arg)));
-
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
@@ -3336,14 +3396,14 @@ int
mark_addressable (exp)
tree exp;
{
- register tree x = 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;
}
@@ -3357,6 +3417,7 @@ mark_addressable (exp)
x = TREE_OPERAND (x, 0);
break;
+ case COMPOUND_LITERAL_EXPR:
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
return 1;
@@ -3421,11 +3482,11 @@ tree
build_conditional_expr (ifexp, op1, op2)
tree ifexp, op1, op2;
{
- register tree type1;
- register tree type2;
- register enum tree_code code1;
- register enum tree_code code2;
- register tree result_type = NULL;
+ tree type1;
+ tree type2;
+ enum tree_code code1;
+ enum tree_code code2;
+ tree result_type = NULL;
tree orig_op1 = op1, orig_op2 = op2;
ifexp = truthvalue_conversion (default_conversion (ifexp));
@@ -3473,15 +3534,46 @@ build_conditional_expr (ifexp, op1, op2)
else
result_type = TYPE_MAIN_VARIANT (type1);
}
- else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE)
- && (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
+ else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE)
+ && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
+ || code2 == COMPLEX_TYPE))
{
result_type = common_type (type1, type2);
+
+ /* If -Wsign-compare, warn here if type1 and type2 have
+ different signedness. We'll promote the signed to unsigned
+ and later code won't know it used to be different.
+ Do this check on the original types, so that explicit casts
+ will be considered, but default promotions won't. */
+ if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare)
+ && !skip_evaluation)
+ {
+ int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1));
+ int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2));
+
+ if (unsigned_op1 ^ unsigned_op2)
+ {
+ /* Do not warn if the result type is signed, since the
+ signed type will only be chosen if it can represent
+ all the values of the unsigned type. */
+ if (! TREE_UNSIGNED (result_type))
+ /* OK */;
+ /* 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)))
+ /* OK */;
+ else
+ warning ("signed and unsigned type in conditional expression");
+ }
+ }
}
else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
{
if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
- pedwarn ("ANSI C forbids conditional expr with only one void side");
+ pedwarn ("ISO C forbids conditional expr with only one void side");
result_type = void_type_node;
}
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
@@ -3494,17 +3586,19 @@ build_conditional_expr (ifexp, op1, op2)
else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
&& TREE_CODE (orig_op2) != NOP_EXPR)
result_type = qualify_type (type1, type2);
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
+ else if (VOID_TYPE_P (TREE_TYPE (type1)))
{
if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids conditional expr between `void *' and function pointer");
- result_type = qualify_type (type1, type2);
+ pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
+ result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
+ TREE_TYPE (type2)));
}
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (type2)) == void_type_node)
+ else if (VOID_TYPE_P (TREE_TYPE (type2)))
{
if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids conditional expr between `void *' and function pointer");
- result_type = qualify_type (type2, type1);
+ pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
+ result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
+ TREE_TYPE (type1)));
}
else
{
@@ -3519,10 +3613,6 @@ build_conditional_expr (ifexp, op1, op2)
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;
}
@@ -3533,10 +3623,6 @@ build_conditional_expr (ifexp, op1, op2)
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;
}
@@ -3563,43 +3649,6 @@ build_conditional_expr (ifexp, op1, op2)
if (result_type != TREE_TYPE (op2))
op2 = convert_and_check (result_type, op2);
-#if 0
- if (code1 == RECORD_TYPE || code1 == UNION_TYPE)
- {
- result_type = TREE_TYPE (op1);
- if (TREE_CONSTANT (ifexp))
- return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
-
- if (TYPE_MODE (result_type) == BLKmode)
- {
- register tree tempvar
- = build_decl (VAR_DECL, NULL_TREE, result_type);
- register tree xop1 = build_modify_expr (tempvar, op1);
- register tree xop2 = build_modify_expr (tempvar, op2);
- register tree result = fold (build (COND_EXPR, result_type,
- ifexp, xop1, xop2));
-
- layout_decl (tempvar, TYPE_ALIGN (result_type));
- /* No way to handle variable-sized objects here.
- I fear that the entire handling of BLKmode conditional exprs
- needs to be redone. */
- if (TREE_CODE (DECL_SIZE (tempvar)) != INTEGER_CST)
- abort ();
- DECL_RTL (tempvar)
- = assign_stack_local (DECL_MODE (tempvar),
- (TREE_INT_CST_LOW (DECL_SIZE (tempvar))
- + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT,
- 0);
-
- TREE_SIDE_EFFECTS (result)
- = TREE_SIDE_EFFECTS (ifexp) | TREE_SIDE_EFFECTS (op1)
- | TREE_SIDE_EFFECTS (op2);
- return build (COMPOUND_EXPR, result_type, result, tempvar);
- }
- }
-#endif /* 0 */
-
if (TREE_CODE (ifexp) == INTEGER_CST)
return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
@@ -3621,10 +3670,16 @@ internal_build_compound_expr (list, first_p)
tree list;
int first_p;
{
- register tree rest;
+ tree rest;
if (TREE_CHAIN (list) == 0)
{
+ /* 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. */
@@ -3639,14 +3694,6 @@ internal_build_compound_expr (list, first_p)
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)))
@@ -3654,9 +3701,9 @@ internal_build_compound_expr (list, first_p)
/* 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
any side-effects, unless it was explicitly cast to (void). */
- if ((extra_warnings || warn_unused)
+ if ((extra_warnings || warn_unused_value)
&& ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
- && TREE_TYPE (TREE_VALUE (list)) == void_type_node))
+ && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list)))))
warning ("left-hand operand of comma expression has no effect");
/* When pedantic, a compound expression can be neither an lvalue
@@ -3669,7 +3716,7 @@ internal_build_compound_expr (list, first_p)
side-effects, but computes a value which is not used. For example, in
`foo() + bar(), baz()' the result of the `+' operator is not used,
so we should issue a warning. */
- else if (warn_unused)
+ else if (warn_unused_value)
warn_if_unused_value (TREE_VALUE (list));
return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);
@@ -3679,10 +3726,10 @@ internal_build_compound_expr (list, first_p)
tree
build_c_cast (type, expr)
- register tree type;
+ tree type;
tree expr;
{
- register tree value = expr;
+ tree value = expr;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
@@ -3706,21 +3753,19 @@ build_c_cast (type, expr)
return error_mark_node;
}
- if (type == TREE_TYPE (value))
+ if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
{
if (pedantic)
{
if (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
- pedwarn ("ANSI C forbids casting nonscalar to the same type");
+ pedwarn ("ISO C forbids casting nonscalar to the same type");
}
}
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)),
@@ -3733,7 +3778,7 @@ build_c_cast (type, expr)
tree t;
if (pedantic)
- pedwarn ("ANSI C forbids casts to union type");
+ pedwarn ("ISO C forbids casts to union type");
if (TYPE_NAME (type) != 0)
{
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
@@ -3763,9 +3808,7 @@ build_c_cast (type, expr)
/* 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. */
@@ -3774,19 +3817,27 @@ build_c_cast (type, expr)
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE)
{
- /* Go to the innermost object being pointed to. */
tree in_type = type;
tree in_otype = otype;
+ int warn = 0;
- while (TREE_CODE (in_type) == POINTER_TYPE)
- in_type = TREE_TYPE (in_type);
- while (TREE_CODE (in_otype) == POINTER_TYPE)
- in_otype = TREE_TYPE (in_otype);
-
- if (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type))
+ /* Check that the qualifiers on IN_TYPE are a superset of
+ the qualifiers of IN_OTYPE. The outermost level of
+ POINTER_TYPE nodes is uninteresting and we stop as soon
+ as we hit a non-POINTER_TYPE node on either type. */
+ do
+ {
+ in_otype = TREE_TYPE (in_otype);
+ in_type = TREE_TYPE (in_type);
+ warn |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+ }
+ while (TREE_CODE (in_type) == POINTER_TYPE
+ && TREE_CODE (in_otype) == POINTER_TYPE);
+
+ if (warn)
/* There are qualifiers present in IN_OTYPE that are not
present in IN_TYPE. */
- pedwarn ("cast discards qualifiers from pointer target type");
+ warning ("cast discards qualifiers from pointer target type");
}
/* Warn about possible alignment problems. */
@@ -3817,11 +3868,6 @@ build_c_cast (type, expr)
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == INTEGER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype)
-#if 0
- /* Don't warn about converting 0 to pointer,
- provided the 0 was explicit--not cast or made by folding. */
- && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value))
-#endif
/* Don't warn about converting any constant. */
&& !TREE_CONSTANT (value))
warning ("cast to pointer from integer of different size");
@@ -3837,7 +3883,7 @@ build_c_cast (type, expr)
}
}
- /* 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)
@@ -3849,6 +3895,24 @@ build_c_cast (type, expr)
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);
+}
+
/* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use
@@ -3860,7 +3924,7 @@ build_modify_expr (lhs, modifycode, rhs)
tree lhs, rhs;
enum tree_code modifycode;
{
- register tree result;
+ tree result;
tree newrhs;
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
@@ -3887,8 +3951,7 @@ build_modify_expr (lhs, modifycode, rhs)
/* Handle (a, b) used as an "lvalue". */
case COMPOUND_EXPR:
pedantic_lvalue_warning (COMPOUND_EXPR);
- newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
- modifycode, rhs);
+ newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs);
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype,
@@ -3945,9 +4008,7 @@ build_modify_expr (lhs, modifycode, rhs)
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;
@@ -3985,6 +4046,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_CODE (lhs) == COMPONENT_REF
&& (TREE_CODE (lhstype) == INTEGER_TYPE
+ || TREE_CODE (lhstype) == BOOLEAN_TYPE
|| TREE_CODE (lhstype) == REAL_TYPE
|| TREE_CODE (lhstype) == ENUMERAL_TYPE))
lhstype = TREE_TYPE (get_unwidened (lhs, 0));
@@ -4005,6 +4067,8 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
+ /* Scan operands */
+
result = build (MODIFY_EXPR, lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1;
@@ -4039,9 +4103,9 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
tree fundecl, funname;
int parmnum;
{
- register enum tree_code codel = TREE_CODE (type);
- register tree rhstype;
- register enum tree_code coder;
+ enum tree_code codel = TREE_CODE (type);
+ tree rhstype;
+ enum tree_code coder;
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
/* Do not use STRIP_NOPS here. We do not want an enumerator
@@ -4053,7 +4117,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
|| TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
rhs = default_conversion (rhs);
else if (optimize && TREE_CODE (rhs) == VAR_DECL)
- rhs = decl_constant_value (rhs);
+ rhs = decl_constant_value_for_broken_optimization (rhs);
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
@@ -4075,11 +4139,34 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
error ("void value not ignored as it ought to be");
return error_mark_node;
}
+ /* A type converts to a reference to it.
+ This code doesn't fully support references, it's just for the
+ special case of va_start and va_copy. */
+ if (codel == REFERENCE_TYPE
+ && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
+ {
+ if (mark_addressable (rhs) == 0)
+ return error_mark_node;
+ rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
+
+ /* We already know that these two types are compatible, but they
+ may not be exactly identical. In fact, `TREE_TYPE (type)' is
+ likely to be __builtin_va_list and `TREE_TYPE (rhs)' is
+ likely to be va_list, a typedef to __builtin_va_list, which
+ is different enough that it will cause problems later. */
+ if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
+ rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
+
+ rhs = build1 (NOP_EXPR, type, rhs);
+ return rhs;
+ }
/* Arithmetic types all interconvert, and enum is treated like int. */
- if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE
- || codel == COMPLEX_TYPE)
- && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE
- || coder == COMPLEX_TYPE))
+ else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
+ || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
+ || codel == BOOLEAN_TYPE)
+ && (coder == INTEGER_TYPE || coder == REAL_TYPE
+ || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
+ || coder == BOOLEAN_TYPE))
return convert_and_check (type, rhs);
/* Conversion to a transparent union from its member types.
@@ -4103,15 +4190,14 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
if (coder == POINTER_TYPE)
{
- register tree ttl = TREE_TYPE (memb_type);
- register tree ttr = TREE_TYPE (rhstype);
+ tree ttl = TREE_TYPE (memb_type);
+ tree ttr = TREE_TYPE (rhstype);
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of
the rhs. */
- if (TYPE_MAIN_VARIANT (ttl) == void_type_node
- || TYPE_MAIN_VARIANT (ttr) == void_type_node
+ if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| comp_target_types (memb_type, rhstype))
{
/* If this type won't generate any warnings, use it. */
@@ -4146,8 +4232,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
{
/* We have only a marginally acceptable member type;
it needs a warning. */
- register tree ttl = TREE_TYPE (marginal_memb_type);
- register tree ttr = TREE_TYPE (rhstype);
+ tree ttl = TREE_TYPE (marginal_memb_type);
+ tree ttr = TREE_TYPE (rhstype);
/* Const and volatile mean something different for function
types, so the usual warnings are not appropriate. */
@@ -4170,37 +4256,36 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
}
if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
- pedwarn ("ANSI C prohibits argument conversion to union type");
+ pedwarn ("ISO C prohibits argument conversion to union type");
return build1 (NOP_EXPR, type, rhs);
}
}
/* Conversions among pointers */
- else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
+ else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
+ && (coder == POINTER_TYPE || coder == REFERENCE_TYPE))
{
- register tree ttl = TREE_TYPE (type);
- register tree ttr = TREE_TYPE (rhstype);
+ tree ttl = TREE_TYPE (type);
+ tree ttr = TREE_TYPE (rhstype);
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
- if (TYPE_MAIN_VARIANT (ttl) == void_type_node
- || TYPE_MAIN_VARIANT (ttr) == void_type_node
+ 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))))
{
if (pedantic
- && ((TYPE_MAIN_VARIANT (ttl) == void_type_node
- && TREE_CODE (ttr) == FUNCTION_TYPE)
+ && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
||
- (TYPE_MAIN_VARIANT (ttr) == void_type_node
+ (VOID_TYPE_P (ttr)
/* Check TREE_CODE to catch cases like (void *) (char *) 0
which are not ANSI null ptr constants. */
&& (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
- warn_for_assignment ("ANSI forbids %s between function pointer and `void *'",
+ warn_for_assignment ("ISO C forbids %s between function pointer and `void *'",
errtype, funname, parmnum);
/* Const and volatile mean something different for function types,
so the usual warnings are not appropriate. */
@@ -4212,8 +4297,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
errtype, funname, parmnum);
/* If this is not a case of ignoring a mismatch in signedness,
no warning. */
- else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
- || TYPE_MAIN_VARIANT (ttr) == void_type_node
+ else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| comp_target_types (type, rhstype))
;
/* If there is a mismatch, do warn. */
@@ -4262,6 +4346,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
errtype, funname, parmnum);
return convert (type, rhs);
}
+ else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
+ return convert (type, rhs);
if (!errtype)
{
@@ -4312,7 +4398,7 @@ warn_for_assignment (msgid, opname, function, argnum)
if (function)
{
/* Function name is known; supply it. */
- const char *argstring = _("passing arg %d of `%s'");
+ const char *const argstring = _("passing arg %d of `%s'");
new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
+ strlen (argstring) + 1 + 25
/*%d*/ + 1);
@@ -4321,8 +4407,8 @@ warn_for_assignment (msgid, opname, function, argnum)
}
else
{
- /* Function name unknown (call through ptr); just give arg number.*/
- const char *argnofun = _("passing arg %d of pointer to function");
+ /* 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);
}
@@ -4331,145 +4417,6 @@ warn_for_assignment (msgid, opname, function, argnum)
pedwarn (msgid, opname);
}
-/* Return nonzero if VALUE is a valid constant-valued expression
- for use in initializing a static variable; one that can be an
- element of a "constant" initializer.
-
- Return null_pointer_node if the value is absolute;
- if it is relocatable, return the variable that determines the relocation.
- We assume that VALUE has been folded as much as possible;
- therefore, we do not need to check for such things as
- arithmetic-combinations of integers. */
-
-tree
-initializer_constant_valid_p (value, endtype)
- tree value;
- tree endtype;
-{
- switch (TREE_CODE (value))
- {
- case CONSTRUCTOR:
- if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
- || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
- && TREE_CONSTANT (value)
- && CONSTRUCTOR_ELTS (value))
- return
- initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
- endtype);
-
- return TREE_STATIC (value) ? null_pointer_node : 0;
-
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case COMPLEX_CST:
- return null_pointer_node;
-
- case ADDR_EXPR:
- return TREE_OPERAND (value, 0);
-
- case NON_LVALUE_EXPR:
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- case CONVERT_EXPR:
- case NOP_EXPR:
- /* Allow conversions between pointer types. */
- if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- /* Allow conversions between real types. */
- if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- /* Allow length-preserving conversions between integer types. */
- if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (value))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- /* Allow conversions between other integer types only if
- explicit value. */
- if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- {
- tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- if (inner == null_pointer_node)
- return null_pointer_node;
- return 0;
- }
-
- /* Allow (int) &foo provided int is as wide as a pointer. */
- if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (value))
- >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
-
- /* Likewise conversions from int to pointers, but also allow
- conversions from 0. */
- if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- {
- if (integer_zerop (TREE_OPERAND (value, 0)))
- return null_pointer_node;
- else if (TYPE_PRECISION (TREE_TYPE (value))
- <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- }
-
- /* Allow conversions to union types if the value inside is okay. */
- if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- return 0;
-
- case PLUS_EXPR:
- if (TREE_CODE (endtype) == INTEGER_TYPE
- && TYPE_PRECISION (endtype) < POINTER_SIZE)
- return 0;
- {
- tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- endtype);
- /* If either term is absolute, use the other terms relocation. */
- if (valid0 == null_pointer_node)
- return valid1;
- if (valid1 == null_pointer_node)
- return valid0;
- return 0;
- }
-
- case MINUS_EXPR:
- if (TREE_CODE (endtype) == INTEGER_TYPE
- && TYPE_PRECISION (endtype) < POINTER_SIZE)
- return 0;
- {
- tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- endtype);
- /* Win if second argument is absolute. */
- if (valid1 == null_pointer_node)
- return valid0;
- /* Win if both arguments have the same relocation.
- Then the value is absolute. */
- if (valid0 == valid1)
- return null_pointer_node;
- return 0;
- }
-
- default:
- return 0;
- }
-}
-
/* If VALUE is a compound expr all of whose expressions are constant, then
return its value. Otherwise, return error_mark_node.
@@ -4505,7 +4452,7 @@ void
store_init_value (decl, init)
tree decl, init;
{
- register tree value, type;
+ tree value, type;
/* If variable's type was invalidly declared, just ignore it. */
@@ -4516,7 +4463,7 @@ store_init_value (decl, init)
/* 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. */
@@ -4549,11 +4496,42 @@ store_init_value (decl, init)
}
#endif
+ if (warn_traditional && !in_system_header
+ && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && ! TREE_STATIC (decl))
+ warning ("traditional C rejects automatic aggregate initialization");
+
DECL_INITIAL (decl) = value;
/* 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);
+ }
+ }
+ }
}
/* Methods for storing and printing names for error messages. */
@@ -4583,7 +4561,7 @@ static int spelling_size; /* Size of the spelling stack. */
Alternative to SAVE_SPELLING_STACK. */
#define SPELLING_DEPTH() (spelling - spelling_base)
-#define RESTORE_SPELLING_DEPTH(depth) (spelling = spelling_base + depth)
+#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH))
/* Save and restore the spelling stack around arbitrary C code. */
@@ -4635,7 +4613,7 @@ push_member_name (decl)
tree decl;
{
- const char *string
+ const char *const string
= DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
}
@@ -4654,8 +4632,8 @@ push_array_bounds (bounds)
static int
spelling_length ()
{
- register int size = 0;
- register struct spelling *p;
+ int size = 0;
+ struct spelling *p;
for (p = spelling_base; p < spelling; p++)
{
@@ -4672,10 +4650,10 @@ spelling_length ()
static char *
print_spelling (buffer)
- register char *buffer;
+ char *buffer;
{
- register char *d = buffer;
- register struct spelling *p;
+ char *d = buffer;
+ struct spelling *p;
for (p = spelling_base; p < spelling; p++)
if (p->kind == SPELLING_BOUNDS)
@@ -4685,7 +4663,7 @@ print_spelling (buffer)
}
else
{
- register const char *s;
+ const char *s;
if (p->kind == SPELLING_MEMBER)
*d++ = '.';
for (s = p->u.s; (*d = *s++); d++)
@@ -4705,7 +4683,7 @@ error_init (msgid)
{
char *ofwhat;
- error (msgid);
+ error ("%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
error ("(near initialization for `%s')", ofwhat);
@@ -4721,7 +4699,7 @@ pedwarn_init (msgid)
{
char *ofwhat;
- pedwarn (msgid);
+ pedwarn ("%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
pedwarn ("(near initialization for `%s')", ofwhat);
@@ -4737,7 +4715,7 @@ warning_init (msgid)
{
char *ofwhat;
- warning (msgid);
+ warning ("%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
warning ("(near initialization for `%s')", ofwhat);
@@ -4758,8 +4736,10 @@ digest_init (type, init, require_constant, constructor_constant)
enum tree_code code = TREE_CODE (type);
tree inside_init = init;
- if (init == error_mark_node)
- return init;
+ if (type == error_mark_node
+ || 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. */
/* Do not use STRIP_NOPS here. We do not want an enumerator
@@ -4767,6 +4747,8 @@ digest_init (type, init, require_constant, constructor_constant)
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. */
@@ -4801,19 +4783,20 @@ digest_init (type, init, require_constant, constructor_constant)
TREE_TYPE (inside_init) = type;
if (TYPE_DOMAIN (type) != 0
- && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
- {
- register int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
- size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
+ && TYPE_SIZE (type) != 0
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
/* Subtract 1 (or sizeof (wchar_t))
because it's ok to ignore the terminating null char
that is counted in the length of the constant. */
- if (size < TREE_STRING_LENGTH (inside_init)
- - (TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)
- ? TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT
- : 1))
- pedwarn_init ("initializer-string for array of chars is too long");
- }
+ && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
+ TREE_STRING_LENGTH (inside_init)
+ - ((TYPE_PRECISION (typ1)
+ != TYPE_PRECISION (char_type_node))
+ ? (TYPE_PRECISION (wchar_type_node)
+ / BITS_PER_UNIT)
+ : 1)))
+ pedwarn_init ("initializer-string for array of chars is too long");
+
return inside_init;
}
}
@@ -4832,19 +4815,28 @@ digest_init (type, init, require_constant, constructor_constant)
&& 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;
}
if (optimize && TREE_CODE (inside_init) == VAR_DECL)
- inside_init = decl_constant_value (inside_init);
+ inside_init = decl_constant_value_for_broken_optimization (inside_init);
/* Compound expressions can only occur here if -pedantic or
-pedantic-errors is specified. In the later case, we always want
@@ -4862,17 +4854,21 @@ digest_init (type, init, require_constant, constructor_constant)
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;
}
@@ -4880,7 +4876,7 @@ digest_init (type, init, require_constant, constructor_constant)
/* 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
@@ -4906,7 +4902,7 @@ digest_init (type, init, require_constant, constructor_constant)
/* Come here only for records and arrays. */
- if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
error_init ("variable-sized object may not be initialized");
return error_mark_node;
@@ -4965,15 +4961,9 @@ static tree constructor_type;
static tree constructor_fields;
/* For an ARRAY_TYPE, this is the specified index
- at which to store the next element we get.
- This is a special INTEGER_CST node that we modify in place. */
+ 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;
@@ -4981,13 +4971,11 @@ static tree constructor_max_index;
static tree constructor_unfilled_fields;
/* For an ARRAY_TYPE, this is the index of the first element
- not yet written out.
- This is a special INTEGER_CST node that we modify in place. */
+ not yet written out. */
static tree constructor_unfilled_index;
/* In a RECORD_TYPE, the byte index of the next consecutive field.
- This is so we can generate gaps between fields, when appropriate.
- This is a special INTEGER_CST node that we modify in place. */
+ This is so we can generate gaps between fields, when appropriate. */
static tree constructor_bit_index;
/* If we are saving up the elements rather than allocating them,
@@ -4995,6 +4983,10 @@ static tree constructor_bit_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;
@@ -5022,7 +5014,8 @@ struct init_node
/* Tree of pending elements at this constructor level.
These are elements encountered out of order
which belong at places we haven't reached yet in actually
- writing the output. */
+ writing the output.
+ Will never hold tree nodes across GC runs. */
static struct init_node *constructor_pending_elts;
/* The SPELLING_DEPTH of this constructor. */
@@ -5034,54 +5027,77 @@ int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */
static int require_constant_value;
static int require_constant_elements;
-/* 1 if it is ok to output this constructor as we read it.
- 0 means must accumulate a CONSTRUCTOR expression. */
-static int constructor_incremental;
-
/* DECL node for which an initializer is being read.
0 means we are reading a constructor expression
such as (struct foo) {...}. */
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;
+/* Nonzero if there were any member designators in this initializer. */
+static int constructor_designated;
+
+/* Nesting depth of designator list. */
+static int designator_depth;
+
+/* Nonzero if there were diagnosed errors in this designator list. */
+static int designator_errorneous;
+
/* 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 incremental;
char erroneous;
char outer;
+ char incremental;
+ char designated;
};
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) { ... } ... }. */
@@ -5090,14 +5106,14 @@ struct initializer_stack
{
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;
int spelling_size;
char top_level;
- char incremental;
char require_constant_value;
char require_constant_elements;
char deferred;
@@ -5116,17 +5132,17 @@ start_init (decl, asmspec_tree, top_level)
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->decl = constructor_decl;
p->asmspec = constructor_asmspec;
- p->incremental = constructor_incremental;
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;
@@ -5137,16 +5153,16 @@ start_init (decl, asmspec_tree, top_level)
initializer_stack = p;
constructor_decl = decl;
- constructor_incremental = top_level;
constructor_asmspec = asmspec;
constructor_subconstants_deferred = 0;
+ constructor_designated = 0;
constructor_top_level = top_level;
if (decl != 0)
{
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
@@ -5154,7 +5170,6 @@ start_init (decl, asmspec_tree, top_level)
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
locus = IDENTIFIER_POINTER (DECL_NAME (decl));
- constructor_incremental |= TREE_STATIC (decl);
}
else
{
@@ -5164,6 +5179,7 @@ start_init (decl, asmspec_tree, top_level)
}
constructor_stack = 0;
+ constructor_range_stack = 0;
missing_braces_mentioned = 0;
@@ -5194,13 +5210,16 @@ finish_init ()
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;
- constructor_incremental = p->incremental;
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;
@@ -5228,15 +5247,9 @@ really_start_incremental_init (type)
if (type == 0)
type = TREE_TYPE (constructor_decl);
- /* Turn off constructor_incremental if type is a struct with bitfields.
- Do this before the first push, so that the corrected value
- is available in finish_init. */
- check_init_type_bitfields (type);
-
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;
@@ -5249,8 +5262,10 @@ really_start_incremental_init (type)
p->depth = constructor_depth;
p->replacement_value = 0;
p->implicit = 0;
- p->incremental = constructor_incremental;
+ p->range_stack = 0;
p->outer = 0;
+ p->incremental = constructor_incremental;
+ p->designated = constructor_designated;
p->next = 0;
constructor_stack = p;
@@ -5260,6 +5275,10 @@ really_start_incremental_init (type)
constructor_elements = 0;
constructor_pending_elts = 0;
constructor_type = type;
+ constructor_incremental = 1;
+ constructor_designated = 0;
+ designator_depth = 0;
+ designator_errorneous = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
@@ -5269,23 +5288,37 @@ really_start_incremental_init (type)
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
+
constructor_unfilled_fields = constructor_fields;
- constructor_bit_index = copy_node (integer_zero_node);
- TREE_TYPE (constructor_bit_index) = sbitsizetype;
+ constructor_bit_index = bitsize_zero_node;
}
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
+ && TYPE_SIZE (constructor_type))
+ constructor_max_index = build_int_2 (-1, -1);
+
+ /* constructor_max_index needs to be an INTEGER_CST. Attempts
+ to initialize VLAs will cause an proper error; avoid tree
+ checking errors as well by setting a safe value. */
+ if (constructor_max_index
+ && TREE_CODE (constructor_max_index) != INTEGER_CST)
+ constructor_max_index = build_int_2 (-1, -1);
+
constructor_index
- = copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+ = convert (bitsizetype,
+ TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
- constructor_index = copy_node (integer_zero_node);
- constructor_unfilled_index = copy_node (constructor_index);
+ constructor_index = bitsize_zero_node;
+
+ constructor_unfilled_index = constructor_index;
}
else
{
@@ -5293,37 +5326,19 @@ really_start_incremental_init (type)
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
-
- if (constructor_incremental)
- {
- int momentary = suspend_momentary ();
- push_obstacks_nochange ();
- if (TREE_PERMANENT (constructor_decl))
- end_temporary_allocation ();
- make_decl_rtl (constructor_decl, constructor_asmspec,
- constructor_top_level);
- assemble_variable (constructor_decl, constructor_top_level, 0, 1);
- pop_obstacks ();
- resume_momentary (momentary);
- }
-
- if (constructor_incremental)
- {
- defer_addressed_constants ();
- constructor_subconstants_deferred = 1;
- }
}
/* 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. */
@@ -5340,39 +5355,22 @@ push_init_level (implicit)
break;
}
- /* Structure elements may require alignment. Do this now if necessary
- for the subaggregate, and if it comes next in sequence. Don't do
- this for subaggregates that will go on the pending list. */
- if (constructor_incremental && constructor_type != 0
- && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields
- && constructor_fields == constructor_unfilled_fields)
+ /* Unless this is an explicit brace, we need to preserve previous
+ content if any. */
+ if (implicit)
{
- /* Advance to offset of this element. */
- if (! tree_int_cst_equal (constructor_bit_index,
- DECL_FIELD_BITPOS (constructor_fields)))
- {
- /* By using unsigned arithmetic, the result will be correct even
- in case of overflows, if BITS_PER_UNIT is a power of two. */
- unsigned next = (TREE_INT_CST_LOW
- (DECL_FIELD_BITPOS (constructor_fields))
- / (unsigned)BITS_PER_UNIT);
- unsigned here = (TREE_INT_CST_LOW (constructor_bit_index)
- / (unsigned)BITS_PER_UNIT);
-
- assemble_zeros ((next - here)
- * (unsigned)BITS_PER_UNIT
- / (unsigned)BITS_PER_UNIT);
- }
- /* Indicate that we have now filled the structure up to the current
- field. */
- constructor_unfilled_fields = constructor_fields;
+ 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;
@@ -5385,16 +5383,27 @@ push_init_level (implicit)
p->depth = constructor_depth;
p->replacement_value = 0;
p->implicit = implicit;
- p->incremental = constructor_incremental;
p->outer = 0;
+ p->incremental = constructor_incremental;
+ p->designated = constructor_designated;
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_designated = 0;
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. */
@@ -5411,18 +5420,13 @@ push_init_level (implicit)
constructor_type = TREE_TYPE (constructor_fields);
push_member_name (constructor_fields);
constructor_depth++;
- if (constructor_fields != constructor_unfilled_fields)
- constructor_incremental = 0;
}
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
constructor_type = TREE_TYPE (constructor_type);
- push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+ push_array_bounds (tree_low_cst (constructor_index, 0));
constructor_depth++;
- if (! tree_int_cst_equal (constructor_index, constructor_unfilled_index)
- || constructor_range_end != 0)
- constructor_incremental = 0;
}
if (constructor_type == 0)
@@ -5433,10 +5437,18 @@ push_init_level (implicit)
return;
}
- /* Turn off constructor_incremental if type is a struct with bitfields. */
- check_init_type_bitfields (constructor_type);
+ 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 && warn_missing_braces && !missing_braces_mentioned)
+ if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
warning_init ("missing braces around initializer");
@@ -5450,23 +5462,44 @@ push_init_level (implicit)
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
+
constructor_unfilled_fields = constructor_fields;
- constructor_bit_index = copy_node (integer_zero_node);
- TREE_TYPE (constructor_bit_index) = sbitsizetype;
+ constructor_bit_index = bitsize_zero_node;
}
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
+ && TYPE_SIZE (constructor_type))
+ constructor_max_index = build_int_2 (-1, -1);
+
+ /* constructor_max_index needs to be an INTEGER_CST. Attempts
+ to initialize VLAs will cause an proper error; avoid tree
+ checking errors as well by setting a safe value. */
+ if (constructor_max_index
+ && TREE_CODE (constructor_max_index) != INTEGER_CST)
+ constructor_max_index = build_int_2 (-1, -1);
+
constructor_index
- = copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+ = convert (bitsizetype,
+ TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
- constructor_index = copy_node (integer_zero_node);
- constructor_unfilled_index = copy_node (constructor_index);
+ 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
{
@@ -5476,45 +5509,6 @@ push_init_level (implicit)
}
}
-/* Don't read a struct incrementally if it has any bitfields,
- because the incremental reading code doesn't know how to
- handle bitfields yet. */
-
-static void
-check_init_type_bitfields (type)
- tree type;
-{
- if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree tail;
- for (tail = TYPE_FIELDS (type); tail;
- tail = TREE_CHAIN (tail))
- {
- if (DECL_C_BIT_FIELD (tail))
- {
- constructor_incremental = 0;
- break;
- }
-
- check_init_type_bitfields (TREE_TYPE (tail));
- }
- }
-
- else if (TREE_CODE (type) == UNION_TYPE)
- {
- tree tail = TYPE_FIELDS (type);
- if (tail && DECL_C_BIT_FIELD (tail))
- /* We also use the nonincremental algorithm for initiliazation
- of unions whose first member is a bitfield, becuase the
- incremental algorithm has no code for dealing with
- bitfields. */
- constructor_incremental = 0;
- }
-
- else if (TREE_CODE (type) == ARRAY_TYPE)
- check_init_type_bitfields (TREE_TYPE (type));
-}
-
/* At the end of an implicit or explicit brace level,
finish up that level of constructor.
If we were outputting the elements as they are read, return 0
@@ -5528,7 +5522,6 @@ pop_init_level (implicit)
int implicit;
{
struct constructor_stack *p;
- int size = 0;
tree constructor = 0;
if (implicit == 0)
@@ -5537,12 +5530,42 @@ pop_init_level (implicit)
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 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)
+ constructor_type = NULL_TREE;
+ }
+ else
+ /* Zero-length arrays are no longer special, so we should no longer
+ get here. */
+ abort ();
+ }
/* Warn when some struct elements are implicitly initialized to zero. */
if (extra_warnings
@@ -5550,85 +5573,43 @@ pop_init_level (implicit)
&& 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);
+
+ /* 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");
+ 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. */
- constructor = p->replacement_value;
- /* If this is the top level thing within the initializer,
- and it's for a variable, then since we already called
- assemble_variable, we must output the value now. */
- if (p->next == 0 && constructor_decl != 0
- && constructor_incremental)
- {
- constructor = digest_init (constructor_type, constructor,
- require_constant_value,
- require_constant_elements);
-
- /* If initializing an array of unknown size,
- determine the size now. */
- if (TREE_CODE (constructor_type) == ARRAY_TYPE
- && TYPE_DOMAIN (constructor_type) == 0)
- {
- int failure;
- int momentary_p;
-
- push_obstacks_nochange ();
- if (TREE_PERMANENT (constructor_type))
- end_temporary_allocation ();
-
- momentary_p = suspend_momentary ();
-
- /* We shouldn't have an incomplete array type within
- some other type. */
- if (constructor_stack->next)
- abort ();
-
- failure
- = complete_array_type (constructor_type,
- constructor, 0);
- if (failure)
- abort ();
-
- size = int_size_in_bytes (constructor_type);
- resume_momentary (momentary_p);
- pop_obstacks ();
- }
-
- output_constant (constructor, size);
- }
- }
+ /* If this closes a superfluous brace pair,
+ just pass out the element between them. */
+ constructor = p->replacement_value;
else if (constructor_type == 0)
;
else if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != UNION_TYPE
- && TREE_CODE (constructor_type) != ARRAY_TYPE
- && ! constructor_incremental)
+ && TREE_CODE (constructor_type) != ARRAY_TYPE)
{
/* A nonincremental scalar initializer--just return
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)
@@ -5639,86 +5620,24 @@ pop_init_level (implicit)
else
constructor = TREE_VALUE (constructor_elements);
}
- else if (! constructor_incremental)
+ else
{
if (constructor_erroneous)
constructor = error_mark_node;
else
{
- int momentary = suspend_momentary ();
-
constructor = build (CONSTRUCTOR, constructor_type, NULL_TREE,
nreverse (constructor_elements));
if (constructor_constant)
TREE_CONSTANT (constructor) = 1;
if (constructor_constant && constructor_simple)
TREE_STATIC (constructor) = 1;
-
- resume_momentary (momentary);
- }
- }
- else
- {
- tree filled;
- int momentary = suspend_momentary ();
-
- if (TREE_CODE (constructor_type) == RECORD_TYPE
- || TREE_CODE (constructor_type) == UNION_TYPE)
- {
- /* Find the offset of the end of that field. */
- filled = size_binop (CEIL_DIV_EXPR,
- constructor_bit_index,
- size_int (BITS_PER_UNIT));
- }
- else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- {
- /* If initializing an array of unknown size,
- determine the size now. */
- if (TREE_CODE (constructor_type) == ARRAY_TYPE
- && TYPE_DOMAIN (constructor_type) == 0)
- {
- tree maxindex
- = size_binop (MINUS_EXPR,
- constructor_unfilled_index,
- integer_one_node);
-
- push_obstacks_nochange ();
- if (TREE_PERMANENT (constructor_type))
- end_temporary_allocation ();
- maxindex = copy_node (maxindex);
- TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
- TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
-
- /* TYPE_MAX_VALUE is always one less than the number of elements
- in the array, because we start counting at zero. Therefore,
- warn only if the value is less than zero. */
- if (pedantic
- && (tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
- < 0))
- error_with_decl (constructor_decl,
- "zero or negative array size `%s'");
- layout_type (constructor_type);
- size = int_size_in_bytes (constructor_type);
- pop_obstacks ();
- }
-
- filled = size_binop (MULT_EXPR, constructor_unfilled_index,
- size_in_bytes (TREE_TYPE (constructor_type)));
}
- else
- filled = 0;
-
- if (filled != 0)
- assemble_zeros (size - TREE_INT_CST_LOW (filled));
-
- resume_momentary (momentary);
}
-
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;
@@ -5727,9 +5646,12 @@ pop_init_level (implicit)
constructor_constant = p->constant;
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;
- constructor_incremental = p->incremental;
+ if (!p->implicit)
+ constructor_range_stack = p->range_stack;
RESTORE_SPELLING_DEPTH (constructor_depth);
constructor_stack = p->next;
@@ -5744,6 +5666,99 @@ pop_init_level (implicit)
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));
+ constructor_designated = 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;
+ }
+
+ constructor_designated = 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. */
@@ -5752,41 +5767,64 @@ void
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)
&& (TYPE_MODE (TREE_TYPE (first))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0)))))
- (first) = TREE_OPERAND (first, 0);
+ first = TREE_OPERAND (first, 0);
+
if (last)
while ((TREE_CODE (last) == NOP_EXPR
|| TREE_CODE (last) == CONVERT_EXPR
|| TREE_CODE (last) == NON_LVALUE_EXPR)
&& (TYPE_MODE (TREE_TYPE (last))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0)))))
- (last) = TREE_OPERAND (last, 0);
+ last = TREE_OPERAND (last, 0);
if (TREE_CODE (first) != INTEGER_CST)
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
{
- TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (first);
- TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (first);
+ constructor_index = convert (bitsizetype, first);
- if (last != 0 && tree_int_cst_lt (last, first))
- error_init ("empty index range in initializer");
- else
+ if (last)
{
- if (pedantic)
- pedwarn ("ANSI C forbids specifying element to initialize");
- constructor_range_end = 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);
}
}
@@ -5797,18 +5835,22 @@ set_init_label (fieldname)
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;
}
@@ -5816,19 +5858,18 @@ set_init_label (fieldname)
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;
- if (pedantic)
- pedwarn ("ANSI C forbids specifying structure member to initialize");
+ designator_depth++;
+ designator_errorneous = 0;
+ if (constructor_range_stack)
+ push_range_stack (NULL_TREE);
}
}
/* 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
@@ -5847,28 +5888,40 @@ add_pending_init (purpose, value)
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 (DECL_FIELD_BITPOS (purpose),
- DECL_FIELD_BITPOS (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;
+ }
}
}
- r = (struct init_node *) oballoc (sizeof (struct init_node));
+ r = (struct init_node *) ggc_alloc (sizeof (struct init_node));
r->purpose = purpose;
r->value = value;
@@ -5890,7 +5943,7 @@ add_pending_init (purpose, value)
{
if (r->balance < 0)
{
- /* L rotation. */
+ /* L rotation. */
p->left = r->right;
if (p->left)
p->left->parent = p;
@@ -5914,7 +5967,7 @@ add_pending_init (purpose, value)
}
else
{
- /* LR rotation. */
+ /* LR rotation. */
struct init_node *t = r->right;
r->right = t->left;
@@ -5963,7 +6016,7 @@ add_pending_init (purpose, value)
{
if (r->balance > 0)
{
- /* R rotation. */
+ /* R rotation. */
p->right = r->left;
if (p->right)
p->right->parent = p;
@@ -6022,7 +6075,7 @@ add_pending_init (purpose, value)
}
else
{
- /* p->balance == -1; growth of right side balances the node. */
+ /* p->balance == -1; growth of right side balances the node. */
p->balance = 0;
break;
}
@@ -6033,41 +6086,178 @@ add_pending_init (purpose, value)
}
}
-/* 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 (DECL_FIELD_BITPOS (field),
- DECL_FIELD_BITPOS (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;
}
@@ -6086,8 +6276,6 @@ output_init_element (value, type, field, pending)
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
@@ -6097,6 +6285,16 @@ output_init_element (value, type, field, pending)
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))
@@ -6115,133 +6313,106 @@ output_init_element (value, type, field, pending)
}
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)
+ value = digest_init (type, value, require_constant_value,
+ require_constant_elements);
+ 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)
- /* The copy_node is needed in case field is actually
- constructor_index, which is modified in place. */
- add_pending_init (copy_node (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, value);
+ 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));
- }
- else
- {
- /* Otherwise, output this element either to
- constructor_elements or to the assembler file. */
-
- if (!duplicate)
+ if (constructor_incremental)
{
- if (! constructor_incremental)
- {
- 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);
- }
+ if (!constructor_unfilled_fields)
+ set_nonincremental_init ();
else
{
- /* Structure elements may require alignment.
- Do this, if necessary. */
- if (TREE_CODE (constructor_type) == RECORD_TYPE)
- {
- /* Advance to offset of this element. */
- if (! tree_int_cst_equal (constructor_bit_index,
- DECL_FIELD_BITPOS (field)))
- {
- /* By using unsigned arithmetic, the result will be
- correct even in case of overflows, if BITS_PER_UNIT
- is a power of two. */
- unsigned next = (TREE_INT_CST_LOW
- (DECL_FIELD_BITPOS (field))
- / (unsigned)BITS_PER_UNIT);
- unsigned here = (TREE_INT_CST_LOW
- (constructor_bit_index)
- / (unsigned)BITS_PER_UNIT);
-
- assemble_zeros ((next - here)
- * (unsigned)BITS_PER_UNIT
- / (unsigned)BITS_PER_UNIT);
- }
- }
- output_constant (digest_init (type, value,
- require_constant_value,
- require_constant_elements),
- int_size_in_bytes (type));
-
- /* For a record or union,
- keep track of end position of last field. */
- if (TREE_CODE (constructor_type) == RECORD_TYPE
- || TREE_CODE (constructor_type) == UNION_TYPE)
- {
- tree temp = size_binop (PLUS_EXPR, DECL_FIELD_BITPOS (field),
- DECL_SIZE (field));
- TREE_INT_CST_LOW (constructor_bit_index)
- = TREE_INT_CST_LOW (temp);
- TREE_INT_CST_HIGH (constructor_bit_index)
- = TREE_INT_CST_HIGH (temp);
- }
+ tree bitpos, unfillpos;
+
+ bitpos = bit_position (field);
+ unfillpos = bit_position (constructor_unfilled_fields);
+
+ if (tree_int_cst_lt (bitpos, unfillpos))
+ set_nonincremental_init ();
}
}
- /* Advance the variable that indicates sequential elements output. */
- if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- {
- tree tem = size_binop (PLUS_EXPR, constructor_unfilled_index,
- integer_one_node);
- TREE_INT_CST_LOW (constructor_unfilled_index)
- = TREE_INT_CST_LOW (tem);
- TREE_INT_CST_HIGH (constructor_unfilled_index)
- = TREE_INT_CST_HIGH (tem);
- }
- else if (TREE_CODE (constructor_type) == RECORD_TYPE)
- constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
- else if (TREE_CODE (constructor_type) == UNION_TYPE)
- constructor_unfilled_fields = 0;
+ add_pending_init (field, value);
+ return;
+ }
+ else if (TREE_CODE (constructor_type) == UNION_TYPE
+ && constructor_elements)
+ {
+ if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
+ warning_init ("initialized field with side-effects overwritten");
- /* Now output any pending elements which have become next. */
- if (pending)
- output_pending_init_elements (0);
+ /* We can have just one union field set. */
+ constructor_elements = 0;
}
+
+ /* Otherwise, output this element either to
+ constructor_elements or to the assembler file. */
+
+ if (field && TREE_CODE (field) == INTEGER_CST)
+ field = copy_node (field);
+ constructor_elements
+ = tree_cons (field, value, 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.
@@ -6317,18 +6488,23 @@ output_pending_init_elements (all)
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 (DECL_FIELD_BITPOS (constructor_unfilled_fields),
- DECL_FIELD_BITPOS (elt->purpose)))
+ else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
{
/* Advance to the next smaller node. */
if (elt->left)
@@ -6354,8 +6530,8 @@ output_pending_init_elements (all)
elt = elt->parent;
elt = elt->parent;
if (elt
- && tree_int_cst_lt (DECL_FIELD_BITPOS (constructor_unfilled_fields),
- DECL_FIELD_BITPOS (elt->purpose)))
+ && (tree_int_cst_lt (ctor_unfilled_bitpos,
+ bit_position (elt->purpose))))
{
next = elt->purpose;
break;
@@ -6370,80 +6546,13 @@ output_pending_init_elements (all)
if (! (all && next != 0))
return;
- /* Generate space up to the position of NEXT. */
- if (constructor_incremental)
- {
- tree filled;
- tree nextpos_tree = size_int (0);
-
- if (TREE_CODE (constructor_type) == RECORD_TYPE
- || TREE_CODE (constructor_type) == UNION_TYPE)
- {
- tree tail;
- /* Find the last field written out, if any. */
- for (tail = TYPE_FIELDS (constructor_type); tail;
- tail = TREE_CHAIN (tail))
- if (TREE_CHAIN (tail) == constructor_unfilled_fields)
- break;
-
- if (tail)
- /* Find the offset of the end of that field. */
- filled = size_binop (CEIL_DIV_EXPR,
- size_binop (PLUS_EXPR,
- DECL_FIELD_BITPOS (tail),
- DECL_SIZE (tail)),
- size_int (BITS_PER_UNIT));
- else
- filled = size_int (0);
-
- nextpos_tree = size_binop (CEIL_DIV_EXPR,
- DECL_FIELD_BITPOS (next),
- size_int (BITS_PER_UNIT));
-
- TREE_INT_CST_HIGH (constructor_bit_index)
- = TREE_INT_CST_HIGH (DECL_FIELD_BITPOS (next));
- TREE_INT_CST_LOW (constructor_bit_index)
- = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (next));
- constructor_unfilled_fields = next;
- }
- else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- {
- filled = size_binop (MULT_EXPR, constructor_unfilled_index,
- size_in_bytes (TREE_TYPE (constructor_type)));
- nextpos_tree
- = size_binop (MULT_EXPR, next,
- size_in_bytes (TREE_TYPE (constructor_type)));
- TREE_INT_CST_LOW (constructor_unfilled_index)
- = TREE_INT_CST_LOW (next);
- TREE_INT_CST_HIGH (constructor_unfilled_index)
- = TREE_INT_CST_HIGH (next);
- }
- else
- filled = 0;
-
- if (filled)
- {
- int nextpos = TREE_INT_CST_LOW (nextpos_tree);
-
- assemble_zeros (nextpos - TREE_INT_CST_LOW (filled));
- }
- }
- else
- {
- /* If it's not incremental, just skip over the gap,
- so that after jumping to retry we will output the next
- successive element. */
- if (TREE_CODE (constructor_type) == RECORD_TYPE
- || TREE_CODE (constructor_type) == UNION_TYPE)
- constructor_unfilled_fields = next;
- else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- {
- TREE_INT_CST_LOW (constructor_unfilled_index)
- = TREE_INT_CST_LOW (next);
- TREE_INT_CST_HIGH (constructor_unfilled_index)
- = TREE_INT_CST_HIGH (next);
- }
- }
+ /* If it's not incremental, just skip over the gap, so that after
+ jumping to retry we will output the next successive element. */
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ constructor_unfilled_fields = next;
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ constructor_unfilled_index = next;
/* ELT now points to the node in the pending tree with the next
initializer to output. */
@@ -6456,13 +6565,7 @@ output_pending_init_elements (all)
to handle a partly-braced initializer.
Once this has found the correct level for the new element,
- it calls output_init_element.
-
- Note: if we are incrementally outputting this constructor,
- this function may be called with a null argument
- representing a sub-constructor that was already incrementally output.
- When that happens, we output nothing, but we do the bookkeeping
- to skip past that element of the current constructor. */
+ it calls output_init_element. */
void
process_init_element (value)
@@ -6471,6 +6574,9 @@ process_init_element (value)
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
@@ -6479,6 +6585,8 @@ process_init_element (value)
&& TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
&& integer_zerop (constructor_unfilled_index))
{
+ if (constructor_stack->replacement_value)
+ error_init ("excess elements in char array initializer");
constructor_stack->replacement_value = value;
return;
}
@@ -6511,6 +6619,17 @@ process_init_element (value)
break;
}
+ /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */
+ if (constructor_range_stack)
+ {
+ /* 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)
{
if (TREE_CODE (constructor_type) == RECORD_TYPE)
@@ -6558,15 +6677,19 @@ process_init_element (value)
directly output as a constructor. */
{
/* For a record, keep track of end position of last field. */
- tree temp = size_binop (PLUS_EXPR,
- DECL_FIELD_BITPOS (constructor_fields),
- DECL_SIZE (constructor_fields));
- TREE_INT_CST_LOW (constructor_bit_index)
- = TREE_INT_CST_LOW (temp);
- TREE_INT_CST_HIGH (constructor_bit_index)
- = TREE_INT_CST_HIGH (temp);
+ 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. */
+ 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);
@@ -6575,9 +6698,8 @@ process_init_element (value)
&& 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;
@@ -6593,6 +6715,20 @@ process_init_element (value)
fieldtype = TYPE_MAIN_VARIANT (fieldtype);
fieldcode = TREE_CODE (fieldtype);
+ /* Warn that traditional C rejects initialization of unions.
+ We skip the warning if the value is zero. This is done
+ 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.
+ 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");
+
/* Accept a string constant to initialize a subarray. */
if (value != 0
&& fieldcode == ARRAY_TYPE
@@ -6621,18 +6757,13 @@ process_init_element (value)
/* Do the bookkeeping for an element that was
directly output as a constructor. */
{
- TREE_INT_CST_LOW (constructor_bit_index)
- = TREE_INT_CST_LOW (DECL_SIZE (constructor_fields));
- TREE_INT_CST_HIGH (constructor_bit_index)
- = TREE_INT_CST_HIGH (DECL_SIZE (constructor_fields));
-
+ constructor_bit_index = DECL_SIZE (constructor_fields);
constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
}
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);
@@ -6656,87 +6787,199 @@ process_init_element (value)
}
if (constructor_max_index != 0
- && tree_int_cst_lt (constructor_max_index, constructor_index))
+ && (tree_int_cst_lt (constructor_max_index, constructor_index)
+ || integer_all_onesp (constructor_max_index)))
{
pedwarn_init ("excess elements in array initializer");
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");
- TREE_INT_CST_HIGH (constructor_range_end)
- = TREE_INT_CST_HIGH (constructor_max_index);
- TREE_INT_CST_LOW (constructor_range_end)
- = TREE_INT_CST_LOW (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
- {
- tree tem;
-
- if (value)
- {
- push_array_bounds (TREE_INT_CST_LOW (constructor_index));
- output_init_element (value, elttype, constructor_index, 1);
- RESTORE_SPELLING_DEPTH (constructor_depth);
- }
-
- tem = size_binop (PLUS_EXPR, constructor_index,
- integer_one_node);
- TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (tem);
- TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (tem);
-
- if (!value)
- /* If we are doing the bookkeeping for an element that was
- directly output as a constructor,
- we must update constructor_unfilled_index. */
- {
- TREE_INT_CST_LOW (constructor_unfilled_index)
- = TREE_INT_CST_LOW (constructor_index);
- TREE_INT_CST_HIGH (constructor_unfilled_index)
- = TREE_INT_CST_HIGH (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;
}
- /* If the (lexically) previous elments are not now saved,
- we can discard the storage for them. */
- if (constructor_incremental && constructor_pending_elts == 0 && value != 0
- && constructor_stack == 0)
- clear_momentary ();
+ constructor_range_stack = 0;
}
+/* Build a simple asm-statement, from one string literal. */
+tree
+simple_asm_stmt (expr)
+ tree expr;
+{
+ STRIP_NOPS (expr);
+
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ 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;
+{
+ tree tail;
+
+ if (TREE_CHAIN (string))
+ string = combine_strings (string);
+ if (TREE_CODE (string) != STRING_CST)
+ {
+ error ("asm template is not a string constant");
+ return NULL_TREE;
+ }
+
+ 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);
+
+ STRIP_NOPS (output);
+ TREE_VALUE (tail) = output;
+
+ /* Allow conversions as LHS here. build_modify_expr as called below
+ will do the right thing with them. */
+ while (TREE_CODE (output) == NOP_EXPR
+ || TREE_CODE (output) == CONVERT_EXPR
+ || TREE_CODE (output) == FLOAT_EXPR
+ || TREE_CODE (output) == FIX_TRUNC_EXPR
+ || TREE_CODE (output) == FIX_FLOOR_EXPR
+ || TREE_CODE (output) == FIX_ROUND_EXPR
+ || TREE_CODE (output) == FIX_CEIL_EXPR)
+ output = TREE_OPERAND (output, 0);
+
+ 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 as it would screw up operands
+ expected to be in memory. */
+ for (tail = inputs; tail; tail = TREE_CHAIN (tail))
+ TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail));
+
+ 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.
@@ -6747,38 +6990,21 @@ void
c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
tree string, outputs, inputs, clobbers;
int vol;
- char *filename;
+ const char *filename;
int line;
{
int noutputs = list_length (outputs);
- register int i;
+ 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;
-
- if (TREE_CODE (string) == ADDR_EXPR)
- string = TREE_OPERAND (string, 0);
- if (TREE_CODE (string) != STRING_CST)
- {
- error ("asm template is not a string constant");
- return;
- }
+ tree *o = (tree *) alloca (noutputs * sizeof (tree));
+ 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);
- /* 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++)
- 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));
-
- /* Generate the ASM_OPERANDS insn;
- store into the TREE_VALUEs of OUTPUTS some trees for
- where the values were actually stored. */
+ /* 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. */
@@ -6789,6 +7015,10 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
NULL_RTX, VOIDmode, EXPAND_NORMAL);
free_temp_slots ();
+
+ /* Restore the original value so that it's correct the next
+ time we expand this function. */
+ TREE_VALUE (tail) = o[i];
}
/* Detect modification of read-only values.
(Otherwise done by build_modify_expr.) */
@@ -6812,7 +7042,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
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;
{
@@ -6824,16 +7054,15 @@ c_expand_return (retval)
if (!retval)
{
current_function_returns_null = 1;
- if (warn_return_type && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
- warning ("`return' with no value, in function returning non-void");
- expand_null_return ();
+ if ((warn_return_type || flag_isoc99)
+ && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
+ pedwarn_c99 ("`return' with no value, in function returning non-void");
}
else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("`return' with a value, in function returning void");
- expand_return (retval);
}
else
{
@@ -6843,7 +7072,7 @@ c_expand_return (retval)
tree inner;
if (t == error_mark_node)
- return;
+ return NULL_TREE;
inner = t = convert (TREE_TYPE (res), t);
@@ -6898,51 +7127,116 @@ c_expand_return (retval)
break;
}
- t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_return (t);
+ retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
current_function_returns_value = 1;
}
+
+ return add_stmt (build_return_stmt (retval));
}
-/* Start a C switch statement, testing expression EXP.
- Return EXP if it is valid, an error node otherwise. */
+struct c_switch {
+ /* The SWITCH_STMT being built. */
+ tree switch_stmt;
+ /* A splay-tree mapping the low element of a case range to the high
+ element, or NULL_TREE if there is no high element. Used to
+ determine whether or not a new case label duplicates an old case
+ label. We need a tree, rather than simply a hash table, because
+ of the GNU case range extension. */
+ splay_tree cases;
+ /* The next node on the stack. */
+ struct c_switch *next;
+};
+
+/* A stack of the currently active switch statements. The innermost
+ switch statement is on the top of the stack. There is no need to
+ mark the stack for garbage collection because it is only active
+ during the processing of the body of a function, and we never
+ collect at that point. */
+
+static struct c_switch *switch_stack;
+
+/* Start a C switch statement, testing expression EXP. Return the new
+ SWITCH_STMT. */
tree
-c_expand_start_case (exp)
+c_start_case (exp)
tree exp;
{
- register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
- tree type = TREE_TYPE (exp);
+ enum tree_code code;
+ tree type;
+ struct c_switch *cs;
- if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
+ if (exp != error_mark_node)
{
- error ("switch quantity not an integer");
- exp = error_mark_node;
+ code = TREE_CODE (TREE_TYPE (exp));
+ type = TREE_TYPE (exp);
+
+ if (! INTEGRAL_TYPE_P (type)
+ && code != ERROR_MARK)
+ {
+ error ("switch quantity not an integer");
+ exp = integer_zero_node;
+ }
+ else
+ {
+ type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+
+ if (warn_traditional && !in_system_header
+ && (type == long_integer_type_node
+ || type == long_unsigned_type_node))
+ warning ("`long' switch expression not converted to `int' in ISO C");
+
+ exp = default_conversion (exp);
+ type = TREE_TYPE (exp);
+ }
}
- else
- {
- tree index;
- type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
- if (warn_traditional
- && (type == long_integer_type_node
- || type == long_unsigned_type_node))
- pedwarn ("`long' switch expression not converted to `int' in ANSI C");
+ /* 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->cases = splay_tree_new (case_compare, NULL, NULL);
+ cs->next = switch_stack;
+ switch_stack = cs;
- 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;
+ return add_stmt (switch_stack->switch_stmt);
+}
+
+/* Process a case label. */
+
+tree
+do_case (low_value, high_value)
+ tree low_value;
+ tree high_value;
+{
+ tree label = NULL_TREE;
+
+ if (switch_stack)
+ {
+ 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");
- expand_start_case (1, exp, type, "switch statement");
+ return label;
+}
- return exp;
+/* Finish the switch statement. */
+
+void
+c_finish_case ()
+{
+ struct c_switch *cs = switch_stack;
+
+ RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt));
+
+ /* Pop the stack. */
+ switch_stack = switch_stack->next;
+ splay_tree_delete (cs->cases);
+ free (cs);
}
OpenPOWER on IntegriCloud