This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH RFC/RFA] refactor initializer_constant_valid_p, fixes label difference bug
- From: Paolo Bonzini <bonzini at gnu dot org>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 25 Apr 2008 12:10:14 +0200
- Subject: [PATCH RFC/RFA] refactor initializer_constant_valid_p, fixes label difference bug
initializer_constant_valid_p is a weird predicate because on one hand
its users only consider its result as boolean (NULL/not NULL), on the
other hand it returns a tree and performs some complicated tests on the
return value.
The reason it performs these tests is that some values that are valid
constant initializers may not be folded; so initializer_constant_valid_p
tries to do this folding itself by associating a tree with a "relocation
base" (e.g. "a" for "&a[5]").
My attempt to simplify this started from the observation that all of
these values *are* nowadays folded, which makes the computations in
initializer_constant_valid_p pointless. Actually this patch had quite
some ramifications, as I'll show.
Starting from the analysis of initializer_constant_valid_p, the only
interesting cases are PLUS_EXPR and MINUS_EXPR.
MINUS_EXPR catches two cases: one is &a[5] - &a[2], which is done by
returning "a" as the relocation base for both and then returning
null_pointer_node because the relocation bases cancel each other. The
other is &&label2 - &&label1, where the code for ADDR_EXPR returns the
label itself as the relocation base -- then initalizer_constant_valid_p
treats two LABEL_DECL relocation bases as if they always cancel each other.
In my patch, the first special case is removed because it is handled by
fold. I was worried that folding may not detect some patterns because
of associativity problems. However this does not happen because the
type system forces the presence of parentheses that help the folder to
do the right thing. For example, in this example
int a[5], b[5];
const int x = &a[5] + (&b[3] - &b[1]) - a;
this is the only valid parenthesization of the definition of x.
The second special case is handled by not recursing and matching
directly the ADDR_EXPR<LABEL_DECL> - ADDR_EXPR<LABEL_DECL> pattern.
Regarding PLUS_EXPR and POINTER_PLUS_EXPR, it would call itself
recursively on the operands and perform this three-state operation on
the results (called valid0 and valid1 here):
valid1 \ valid0 NULL_TREE null_pointer_node other
NULL_TREE NULL_TREE NULL_TREE NULL_TREE
null_pointer_node NULL_TREE null_pointer_node valid0
other NULL_TREE valid1 NULL_TREE
So, this patch introduces a new initializer_constant_absolute_p. This
actually fixes a bug. Before the patch, this function was diagnosed as
wrong...
int f()
{
struct s { int a[3]; };
static const void *x = (&&a - &&b) + 5;
static int y = (&&a - &&b) + 5;
return x;
a: abort ();
b: return y;
}
... while now it is compiled correctly (whatever it means). Again, fold
comes to the rescue and makes us able to deal with this too:
int f()
{
struct s { int a[3]; };
static const void *x = &&a + 5 - &&b;
static int y = &&a + 5 - &&b;
return x;
a: abort ();
b: return y;
}
On the other hand this highlighted a bug in final.c, which was not
prepared to handle MINUS expressions in targets whose assembler has no
parentheses. So this patch adds this capability.
Bootstrapped/regtested i686-pc-linux-gnu, including Ada. Ok? Or more
precisely, is it worth it? :-)
(By the way, the reason to do this cleanup is to tackle the other
extra-obscure predicate, staticp. It also returns a tree and its value
was only used by initializer_constant_valid_p).
Paolo
2008-04-25 Paolo Bonzini <bonzini@gnu.org>
* tree.h (categorize_ctor_elements): Fix documentation.
* expr.c (categorize_ctor_elements_1): Fix calls to
initializer_constant_valid_p.
(categorize_ctor_elements): Fix documentation.
* output.h (initializer_constant_valid_p): Fix documentation.
* final.c (output_addr_const_1): New, from...
(output_addr_const): ... this one. Call it from here.
* varasm.c (initializer_constant_absolute_p): New.
(initializer_constant_valid_p): Return bool. Simplify assuming
more powerful folding and correct POINTER_PLUS_EXPR semantics.
2008-04-25 Paolo Bonzini <bonzini@gnu.org>
* cp/typeck.c (build_ptrmemfunc1): Fix calls to
initializer_constant_valid_p.
Index: tree.h
===================================================================
--- tree.h (revision 134628)
+++ tree.h (working copy)
@@ -4411,7 +4411,7 @@ extern bool initializer_zerop (const_tre
is not the largest element in the union, then set *p_must_clear.
Return whether or not CTOR is a valid static constant initializer, the same
- as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */
+ as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR))". */
extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
bool *);
Index: final.c
===================================================================
--- final.c (revision 134628)
+++ final.c (working copy)
@@ -3363,18 +3363,70 @@ output_address (rtx x)
}
/* Print an integer constant expression in assembler syntax.
- Addition and subtraction are the only arithmetic
- that may appear in these expressions. */
+ Recursive workhorse, handling simplification of addition and
+ subtraction. */
-void
-output_addr_const (FILE *file, rtx x)
+static void
+output_addr_const_1 (FILE *file, rtx x, char op)
{
char buf[256];
+ HOST_WIDE_INT val;
restart:
switch (GET_CODE (x))
{
+ case PLUS:
+ /* Some assemblers need integer constants to appear last (eg masm). */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+ {
+ output_addr_const_1 (file, XEXP (x, 1), op);
+ output_addr_const_1 (file, XEXP (x, 0), op == '-' ? '-' : '+');
+ }
+ else
+ {
+ output_addr_const_1 (file, XEXP (x, 0), op);
+ output_addr_const_1 (file, XEXP (x, 1), op == '-' ? '-' : '+');
+ }
+ return;
+
+ case MINUS:
+ /* Avoid outputting things like x-x or x+5-x,
+ since some assemblers can't handle that. */
+ x = simplify_subtraction (x);
+ if (GET_CODE (x) != MINUS)
+ goto restart;
+
+ output_addr_const_1 (file, XEXP (x, 0), op);
+ output_addr_const_1 (file, XEXP (x, 1), op == '-' ? '+' : '-');
+ return;
+
+ case CONST_INT:
+ val = INTVAL (x);
+ if (op == '-')
+ op = '+', val = -val;
+ if (val >= 0 && op == '+')
+ putc ('+', file);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
+ return;
+
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
+ case SUBREG:
+ case TRUNCATE:
+ case CONST:
+ output_addr_const_1 (file, XEXP (x, 0), op);
+ return;
+
+ default:
+ break;
+ }
+
+ if (op)
+ putc (op, file);
+
+ switch (GET_CODE (x))
+ {
case PC:
putc ('.', file);
break;
@@ -3400,16 +3453,6 @@ output_addr_const (FILE *file, rtx x)
#endif
break;
- case CONST_INT:
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
- break;
-
- case CONST:
- /* This used to output parentheses around the expression,
- but that does not work on the 386 (either ATT or BSD assembler). */
- output_addr_const (file, XEXP (x, 0));
- break;
-
case CONST_DOUBLE:
if (GET_MODE (x) == VOIDmode)
{
@@ -3435,56 +3478,13 @@ output_addr_const (FILE *file, rtx x)
(unsigned HOST_WIDE_INT) CONST_FIXED_VALUE_LOW (x));
break;
- case PLUS:
- /* Some assemblers need integer constants to appear last (eg masm). */
- if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- {
- output_addr_const (file, XEXP (x, 1));
- if (INTVAL (XEXP (x, 0)) >= 0)
- fprintf (file, "+");
- output_addr_const (file, XEXP (x, 0));
- }
- else
- {
- output_addr_const (file, XEXP (x, 0));
- if (GET_CODE (XEXP (x, 1)) != CONST_INT
- || INTVAL (XEXP (x, 1)) >= 0)
- fprintf (file, "+");
- output_addr_const (file, XEXP (x, 1));
- }
- break;
-
- case MINUS:
- /* Avoid outputting things like x-x or x+5-x,
- since some assemblers can't handle that. */
- x = simplify_subtraction (x);
- if (GET_CODE (x) != MINUS)
- goto restart;
-
- output_addr_const (file, XEXP (x, 0));
- fprintf (file, "-");
- if ((GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0)
- || GET_CODE (XEXP (x, 1)) == PC
- || GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
- output_addr_const (file, XEXP (x, 1));
- else
- {
- fputs (targetm.asm_out.open_paren, file);
- output_addr_const (file, XEXP (x, 1));
- fputs (targetm.asm_out.close_paren, file);
- }
- break;
-
- case ZERO_EXTEND:
- case SIGN_EXTEND:
- case SUBREG:
- case TRUNCATE:
- output_addr_const (file, XEXP (x, 0));
- break;
-
default:
#ifdef OUTPUT_ADDR_CONST_EXTRA
+ if (op == '-')
+ fputs (targetm.asm_out.open_paren, file);
OUTPUT_ADDR_CONST_EXTRA (file, x, fail);
+ if (op == '-')
+ fputs (targetm.asm_out.close_paren, file);
break;
fail:
@@ -3492,6 +3492,17 @@ output_addr_const (FILE *file, rtx x)
output_operand_lossage ("invalid expression as operand");
}
}
+
+/* Print an integer constant expression in assembler syntax.
+ Addition and subtraction are the only arithmetic
+ that may appear in these expressions. */
+
+void
+output_addr_const (FILE *file, rtx x)
+{
+ output_addr_const_1 (file, x, 0);
+}
+
/* A poor man's fprintf, with the added features of %I, %R, %L, and %U.
%R prints the value of REGISTER_PREFIX.
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 134628)
+++ cp/typeck.c (working copy)
@@ -6396,10 +6396,8 @@ build_ptrmemfunc1 (tree type, tree delta
u = build_constructor (type, v);
TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta);
TREE_STATIC (u) = (TREE_CONSTANT (u)
- && (initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
- != NULL_TREE)
- && (initializer_constant_valid_p (delta, TREE_TYPE (delta))
- != NULL_TREE));
+ && initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
+ && initializer_constant_valid_p (delta, TREE_TYPE (delta)));
return u;
}
Index: expr.c
===================================================================
--- expr.c (revision 134628)
+++ expr.c (working copy)
@@ -4845,8 +4845,7 @@ categorize_ctor_elements_1 (const_tree c
elt_count += mult;
if (const_from_elts_p && const_p)
- const_p = initializer_constant_valid_p (value, TREE_TYPE (value))
- != NULL_TREE;
+ const_p = initializer_constant_valid_p (value, TREE_TYPE (value));
break;
}
}
@@ -4902,7 +4901,7 @@ categorize_ctor_elements_1 (const_tree c
is not the largest element in the union, then set *p_must_clear.
Return whether or not CTOR is a valid static constant initializer, the same
- as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0". */
+ as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR))". */
bool
categorize_ctor_elements (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
Index: varasm.c
===================================================================
--- varasm.c (revision 134628)
+++ varasm.c (working copy)
@@ -4001,17 +4001,59 @@ constructor_static_from_elts_p (const_tr
&& !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
}
-/* Return nonzero if VALUE is a valid constant-valued expression
+/* Return true if the value is absolute, i.e. it does not refer to the
+ address of a static variable. */
+
+static bool
+initializer_constant_absolute_p (tree value, tree endtype)
+{
+ switch (TREE_CODE (value))
+ {
+ case CONSTRUCTOR:
+ if (constructor_static_from_elts_p (value))
+ {
+ unsigned HOST_WIDE_INT idx;
+ tree elt;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
+ if (!initializer_constant_absolute_p (elt, TREE_TYPE (elt)))
+ return false;
+
+ return true;
+ }
+
+ return TREE_STATIC (value);
+
+ case MINUS_EXPR:
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ case VIEW_CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ /* These always produce absolute values, but we need to
+ ascertain their validity anyway. */
+ return initializer_constant_valid_p (value, endtype);
+
+ case INTEGER_CST:
+ case VECTOR_CST:
+ case REAL_CST:
+ case FIXED_CST:
+ case COMPLEX_CST:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Return true 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.
+ 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
+bool
initializer_constant_valid_p (tree value, tree endtype)
{
switch (TREE_CODE (value))
@@ -4021,24 +4063,15 @@ initializer_constant_valid_p (tree value
{
unsigned HOST_WIDE_INT idx;
tree elt;
- bool absolute = true;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
- {
- tree reloc;
- reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt));
- if (!reloc)
- return NULL_TREE;
- if (reloc != null_pointer_node)
- absolute = false;
- }
- /* For a non-absolute relocation, there is no single
- variable that can be "the variable that determines the
- relocation." */
- return absolute ? null_pointer_node : error_mark_node;
+ if (!initializer_constant_valid_p (elt, TREE_TYPE (elt)))
+ return false;
+
+ return true;
}
- return TREE_STATIC (value) ? null_pointer_node : NULL_TREE;
+ return TREE_STATIC (value);
case INTEGER_CST:
case VECTOR_CST:
@@ -4046,29 +4079,29 @@ initializer_constant_valid_p (tree value
case FIXED_CST:
case STRING_CST:
case COMPLEX_CST:
- return null_pointer_node;
+ return true;
case ADDR_EXPR:
case FDESC_EXPR:
value = staticp (TREE_OPERAND (value, 0));
- if (value)
- {
- /* "&(*a).f" is like unto pointer arithmetic. If "a" turns out to
- be a constant, this is old-skool offsetof-like nonsense. */
- if (TREE_CODE (value) == INDIRECT_REF
- && TREE_CONSTANT (TREE_OPERAND (value, 0)))
- return null_pointer_node;
- /* Taking the address of a nested function involves a trampoline. */
- if (TREE_CODE (value) == FUNCTION_DECL
- && decl_function_context (value)
- && !DECL_NO_STATIC_CHAIN (value))
- return NULL_TREE;
- /* "&{...}" requires a temporary to hold the constructed
- object. */
- if (TREE_CODE (value) == CONSTRUCTOR)
- return NULL_TREE;
- }
- return value;
+ if (!value)
+ return false;
+
+ /* "&(*a).f" is like unto pointer arithmetic. If "a" turns out to
+ be a constant, this is old-skool offsetof-like nonsense. */
+ if (TREE_CODE (value) == INDIRECT_REF
+ && TREE_CONSTANT (TREE_OPERAND (value, 0)))
+ return true;
+ /* Taking the address of a nested function involves a trampoline. */
+ if (TREE_CODE (value) == FUNCTION_DECL
+ && decl_function_context (value)
+ && !DECL_NO_STATIC_CHAIN (value))
+ return false;
+ /* "&{...}" requires a temporary to hold the constructed object. */
+ if (TREE_CODE (value) == CONSTRUCTOR)
+ return false;
+
+ return true;
case VIEW_CONVERT_EXPR:
case NON_LVALUE_EXPR:
@@ -4101,12 +4134,7 @@ initializer_constant_valid_p (tree value
/* Allow conversions between other integer types only if
explicit value. */
if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
- {
- tree inner = initializer_constant_valid_p (src, endtype);
- if (inner == null_pointer_node)
- return null_pointer_node;
- break;
- }
+ return initializer_constant_valid_p (src, endtype);
/* Allow (int) &foo provided int is as wide as a pointer. */
if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
@@ -4121,9 +4149,9 @@ initializer_constant_valid_p (tree value
{
if (TREE_CODE (src) == INTEGER_CST
&& TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type))
- return null_pointer_node;
+ return true;
if (integer_zerop (src))
- return null_pointer_node;
+ return true;
else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
return initializer_constant_valid_p (src, endtype);
}
@@ -4136,106 +4164,742@@ initializer_constant_valid_p (tree value
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
- if (! INTEGRAL_TYPE_P (endtype)
- || TYPE_PRECISION (endtype) >= POINTER_SIZE)
- {
- 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 term's relocation. */
- if (valid0 == null_pointer_node)
- return valid1;
- if (valid1 == null_pointer_node)
- return valid0;
- }
+ if (initializer_constant_absolute_p (TREE_OPERAND (value, 1), endtype)
+ && initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype))
+ return true;
+ if (initializer_constant_absolute_p (TREE_OPERAND (value, 0), endtype)
+ && initializer_constant_valid_p (TREE_OPERAND (value, 1), endtype))
+ return true;
break;
case MINUS_EXPR:
- if (! INTEGRAL_TYPE_P (endtype)
- || TYPE_PRECISION (endtype) >= POINTER_SIZE)
- {
- 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 && valid0 != 0)
- return null_pointer_node;
-
- /* Since GCC guarantees that string constants are unique in the
- generated code, a subtraction between two copies of the same
- constant string is absolute. */
- if (valid0 && TREE_CODE (valid0) == STRING_CST
- && valid1 && TREE_CODE (valid1) == STRING_CST
- && operand_equal_p (valid0, valid1, 1))
- return null_pointer_node;
- }
-
- /* Support narrowing differences. */
- if (INTEGRAL_TYPE_P (endtype))
- {
- tree op0, op1;
-
- op0 = TREE_OPERAND (value, 0);
- op1 = TREE_OPERAND (value, 1);
-
- /* Like STRIP_NOPS except allow the operand mode to widen.
- This works around a feature of fold that simplifies
- (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory
- that the narrower operation is cheaper. */
-
- while (TREE_CODE (op0) == NOP_EXPR
- || TREE_CODE (op0) == CONVERT_EXPR
- || TREE_CODE (op0) == NON_LVALUE_EXPR)
- {
- tree inner = TREE_OPERAND (op0, 0);
- if (inner == error_mark_node
- || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
- || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
- > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
- break;
- op0 = inner;
- }
+ {
+ tree op0, op1;
- while (TREE_CODE (op1) == NOP_EXPR
- || TREE_CODE (op1) == CONVERT_EXPR
- || TREE_CODE (op1) == NON_LVALUE_EXPR)
- {
- tree inner = TREE_OPERAND (op1, 0);
- if (inner == error_mark_node
- || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
- || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
- > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
- break;
- op1 = inner;
- }
+ op0 = TREE_OPERAND (value, 0);
+ op1 = TREE_OPERAND (value, 1);
+
+ /* Support narrowing differences. */
+ if (INTEGRAL_TYPE_P (endtype))
+ {
+ /* Like STRIP_NOPS except allow the operand mode to widen.
+ This works around a feature of fold that simplifies
+ (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory
+ that the narrower operation is cheaper. */
+
+ while (TREE_CODE (op0) == NOP_EXPR
+ || TREE_CODE (op0) == CONVERT_EXPR
+ || TREE_CODE (op0) == NON_LVALUE_EXPR)
+ {
+ tree inner = TREE_OPERAND (op0, 0);
+ if (inner == error_mark_node
+ || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
+ || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
+ > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+ break;
+ op0 = inner;
+ }
- op0 = initializer_constant_valid_p (op0, endtype);
- op1 = initializer_constant_valid_p (op1, endtype);
+ while (TREE_CODE (op1) == NOP_EXPR
+ || TREE_CODE (op1) == CONVERT_EXPR
+ || TREE_CODE (op1) == NON_LVALUE_EXPR)
+ {
+ tree inner = TREE_OPERAND (op1, 0);
+ if (inner == error_mark_node
+ || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
+ || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
+ > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+ break;
+ op1 = inner;
+ }
+ }
- /* Both initializers must be known. */
- if (op0 && op1)
- {
- if (op0 == op1)
- return null_pointer_node;
+ /* Support differences between labels. */
+ if (TREE_CODE (op0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
+ && TREE_CODE (op1) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL)
+ return true;
+
+ /* Assuming all folding has been done, things like
+ &a[1] - &a[0] won't survive until here. */
+ if (! INTEGRAL_TYPE_P (endtype)
+ || TYPE_PRECISION (endtype) >= POINTER_SIZE)
+ return (initializer_constant_valid_p (op0, endtype)
+ && initializer_constant_valid_p (op1, endtype));
- /* Support differences between labels. */
- if (TREE_CODE (op0) == LABEL_DECL
- && TREE_CODE (op1) == LABEL_DECL)
- return null_pointer_node;
-
- if (TREE_CODE (op0) == STRING_CST
- && TREE_CODE (op1) == STRING_CST
- && operand_equal_p (op0, op1, 1))
- return null_pointer_node;
- }
- }
- break;
+ break;
+ }
default:
break;
Index: output.h
===================================================================
--- output.h (revision 134628)
+++ output.h (working copy)
@@ -285,16 +285,10 @@ extern void output_object_blocks (void);
extern bool constructor_static_from_elts_p (const_tree);
-/* Return nonzero if VALUE is a valid constant-valued expression
+/* Return whether 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. */
-extern tree initializer_constant_valid_p (tree, tree);
+ element of a "constant" initializer. */
+extern bool initializer_constant_valid_p (tree, tree);
/* Output assembler code for constant EXP to FILE, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.