mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 03:00:25 +08:00
varasm.c (narrowing_initializer_constant_valid_p): New static function.
./: * varasm.c (narrowing_initializer_constant_valid_p): New static function. (initializer_constant_valid_p): Call it. testsuite/: * g++.dg/init/const7.C: New test. From-SVN: r140025
This commit is contained in:
parent
5419331358
commit
84320b0be2
@ -1,3 +1,9 @@
|
||||
2008-09-04 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* varasm.c (narrowing_initializer_constant_valid_p): New
|
||||
static function.
|
||||
(initializer_constant_valid_p): Call it.
|
||||
|
||||
2008-09-04 Jeff Law <law@redhat.com>
|
||||
|
||||
* fold-const.c (native_encode_real): Fix computation of WORDS.
|
||||
|
@ -1,3 +1,7 @@
|
||||
2008-09-04 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* g++.dg/init/const7.C: New test.
|
||||
|
||||
2008-09-04 Adam Nemet <anemet@caviumnetworks.com>
|
||||
|
||||
* gcc.target/mips/seq-1.c: New test.
|
||||
|
13
gcc/testsuite/g++.dg/init/const7.C
Normal file
13
gcc/testsuite/g++.dg/init/const7.C
Normal file
@ -0,0 +1,13 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fdump-tree-gimple" }
|
||||
|
||||
struct s { int x, y; };
|
||||
short offsets[1] = {
|
||||
((char*) &(((struct s*)16)->y) - (char *)16),
|
||||
};
|
||||
|
||||
// This ensures that we get a dump whether or not the bug is present.
|
||||
void fn() { }
|
||||
|
||||
// { dg-final { scan-tree-dump-not "initialization" "gimple" } }
|
||||
// { dg-final { cleanup-tree-dump "gimple" } }
|
135
gcc/varasm.c
135
gcc/varasm.c
@ -4063,6 +4063,73 @@ constructor_static_from_elts_p (const_tree ctor)
|
||||
&& !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
|
||||
}
|
||||
|
||||
/* A subroutine of initializer_constant_valid_p. VALUE is either a
|
||||
MINUS_EXPR or a POINTER_PLUS_EXPR, and ENDTYPE is a narrowing
|
||||
conversion to something smaller than a pointer. This returns
|
||||
null_pointer_node if the resulting value is an absolute constant
|
||||
which can be used to initialize a static variable. Otherwise it
|
||||
returns NULL. */
|
||||
|
||||
static tree
|
||||
narrowing_initializer_constant_valid_p (tree value, tree 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 (CONVERT_EXPR_P (op0)
|
||||
|| 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;
|
||||
}
|
||||
|
||||
while (CONVERT_EXPR_P (op1)
|
||||
|| 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 = initializer_constant_valid_p (op0, endtype);
|
||||
op1 = initializer_constant_valid_p (op1, endtype);
|
||||
|
||||
/* Both initializers must be known. */
|
||||
if (op0 && op1)
|
||||
{
|
||||
if (op0 == op1)
|
||||
return null_pointer_node;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
@ -4076,6 +4143,8 @@ constructor_static_from_elts_p (const_tree ctor)
|
||||
tree
|
||||
initializer_constant_valid_p (tree value, tree endtype)
|
||||
{
|
||||
tree ret;
|
||||
|
||||
switch (TREE_CODE (value))
|
||||
{
|
||||
case CONSTRUCTOR:
|
||||
@ -4216,6 +4285,14 @@ initializer_constant_valid_p (tree value, tree endtype)
|
||||
if (valid1 == null_pointer_node)
|
||||
return valid0;
|
||||
}
|
||||
|
||||
/* Support narrowing pointer differences. */
|
||||
if (TREE_CODE (value) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
ret = narrowing_initializer_constant_valid_p (value, endtype);
|
||||
if (ret != NULL_TREE)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case MINUS_EXPR:
|
||||
@ -4244,62 +4321,10 @@ initializer_constant_valid_p (tree value, tree endtype)
|
||||
}
|
||||
|
||||
/* Support narrowing differences. */
|
||||
if (INTEGRAL_TYPE_P (endtype))
|
||||
{
|
||||
tree op0, op1;
|
||||
ret = narrowing_initializer_constant_valid_p (value, endtype);
|
||||
if (ret != NULL_TREE)
|
||||
return ret;
|
||||
|
||||
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 (CONVERT_EXPR_P (op0)
|
||||
|| 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;
|
||||
}
|
||||
|
||||
while (CONVERT_EXPR_P (op1)
|
||||
|| 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 = initializer_constant_valid_p (op0, endtype);
|
||||
op1 = initializer_constant_valid_p (op1, endtype);
|
||||
|
||||
/* Both initializers must be known. */
|
||||
if (op0 && op1)
|
||||
{
|
||||
if (op0 == op1)
|
||||
return null_pointer_node;
|
||||
|
||||
/* 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;
|
||||
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user