Commit 7e8176d7 by Richard Henderson Committed by Richard Henderson

c-typeck.c (initializer_constant_valid_p): Move ...

        * c-typeck.c (initializer_constant_valid_p): Move ...
        * c-common.c (initializer_constant_valid_p): ... here.  Use
        FOO_TYPE_P instead of tests against TREE_CODE.  Allow subtraction
        of label addresses.
        * c-common.h (initializer_constant_valid_p): Declare.
        * c-tree.h (initializer_constant_valid_p): Remove.

From-SVN: r28349
parent 96a0a146
1999-07-30 Richard Henderson <rth@cygnus.com>
* c-typeck.c (initializer_constant_valid_p): Move ...
* c-common.c (initializer_constant_valid_p): ... here. Use
FOO_TYPE_P instead of tests against TREE_CODE. Allow subtraction
of label addresses.
* c-common.h (initializer_constant_valid_p): Declare.
* c-tree.h (initializer_constant_valid_p): Remove.
Fri Jul 30 16:33:42 1999 Mathias Froehlich <frohlich@na.uni-tuebingen.de>
* config/i386/sol2-c1.asm: Align the stack.
......
......@@ -3767,3 +3767,159 @@ build_va_arg (expr, type)
{
return build1 (VA_ARG_EXPR, type, expr);
}
/* 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 (POINTER_TYPE_P (TREE_TYPE (value))
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
/* Allow conversions between real types. */
if (FLOAT_TYPE_P (TREE_TYPE (value))
&& FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
/* Allow length-preserving conversions between integer types. */
if (INTEGRAL_TYPE_P (TREE_TYPE (value))
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
&& (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 (INTEGRAL_TYPE_P (TREE_TYPE (value))
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
{
tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
if (inner == null_pointer_node)
return null_pointer_node;
break;
}
/* Allow (int) &foo provided int is as wide as a pointer. */
if (INTEGRAL_TYPE_P (TREE_TYPE (value))
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
&& (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 (POINTER_TYPE_P (TREE_TYPE (value))
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
{
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);
break;
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 terms relocation. */
if (valid0 == null_pointer_node)
return valid1;
if (valid1 == null_pointer_node)
return valid0;
}
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)
return null_pointer_node;
}
/* Support differences between labels. */
if (INTEGRAL_TYPE_P (endtype))
{
tree op0, op1;
op0 = TREE_OPERAND (value, 0);
op1 = TREE_OPERAND (value, 1);
STRIP_NOPS (op0);
STRIP_NOPS (op1);
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 null_pointer_node;
}
break;
default:
break;
}
return 0;
}
......@@ -190,3 +190,5 @@ extern tree builtin_function PROTO((const char *, tree, enum built_in_function
extern void c_common_nodes_and_builtins PROTO((int, int, int));
extern tree build_va_arg PROTO((tree, tree));
extern tree initializer_constant_valid_p PROTO((tree, tree));
......@@ -282,7 +282,6 @@ extern tree build_compound_expr PROTO((tree));
extern tree build_c_cast PROTO((tree, tree));
extern tree build_modify_expr PROTO((tree, enum tree_code,
tree));
extern tree initializer_constant_valid_p PROTO((tree, tree));
extern void store_init_value PROTO((tree, tree));
extern void error_init PROTO((const char *));
extern void pedwarn_init PROTO((const char *));
......
......@@ -4246,145 +4246,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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment