mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-16 10:50:42 +08:00
c-typeck.c (build_unary_op): Don't expand ADDR_EXPR of a COMPONENT_REF to pointer arithmetic.
* c-typeck.c (build_unary_op): Don't expand ADDR_EXPR of a COMPONENT_REF to pointer arithmetic. * varasm.c (initializer_constant_valid_p): Allow "&(*c).f", for constant "c" as a valid constant initializer. Allow narrowing of differences against the same base object, for any base object. From-SVN: r86794
This commit is contained in:
parent
1c340cb66c
commit
5cc200fcf0
@ -1,3 +1,11 @@
|
||||
2004-08-30 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* c-typeck.c (build_unary_op): Don't expand ADDR_EXPR of a
|
||||
COMPONENT_REF to pointer arithmetic.
|
||||
* varasm.c (initializer_constant_valid_p): Allow "&(*c).f", for
|
||||
constant "c" as a valid constant initializer. Allow narrowing of
|
||||
differences against the same base object, for any base object.
|
||||
|
||||
2004-08-30 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* expr.c (expand_expr_addr_expr): New.
|
||||
|
@ -2514,44 +2514,24 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
||||
TREE_READONLY (arg),
|
||||
TREE_THIS_VOLATILE (arg));
|
||||
|
||||
argtype = build_pointer_type (argtype);
|
||||
|
||||
if (!c_mark_addressable (arg))
|
||||
return error_mark_node;
|
||||
|
||||
{
|
||||
tree addr;
|
||||
if (TREE_CODE (arg) == COMPONENT_REF
|
||||
&& DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
|
||||
{
|
||||
error ("attempt to take address of bit-field structure member `%D'",
|
||||
TREE_OPERAND (arg, 1));
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (TREE_CODE (arg) == COMPONENT_REF)
|
||||
{
|
||||
tree field = TREE_OPERAND (arg, 1);
|
||||
argtype = build_pointer_type (argtype);
|
||||
val = build1 (ADDR_EXPR, argtype, arg);
|
||||
|
||||
addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
|
||||
if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
|
||||
TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
|
||||
|
||||
if (DECL_C_BIT_FIELD (field))
|
||||
{
|
||||
error ("attempt to take address of bit-field structure member `%s'",
|
||||
IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
addr = fold (build2 (PLUS_EXPR, argtype,
|
||||
convert (argtype, addr),
|
||||
convert (argtype, byte_position (field))));
|
||||
|
||||
/* If the folded PLUS_EXPR is not a constant address, wrap
|
||||
it in an ADDR_EXPR. */
|
||||
if (!TREE_CONSTANT (addr))
|
||||
addr = build1 (ADDR_EXPR, argtype, arg);
|
||||
}
|
||||
else
|
||||
addr = build1 (ADDR_EXPR, argtype, arg);
|
||||
|
||||
if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
|
||||
TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1;
|
||||
|
||||
return addr;
|
||||
}
|
||||
return val;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
42
gcc/varasm.c
42
gcc/varasm.c
@ -3463,7 +3463,14 @@ initializer_constant_valid_p (tree value, tree endtype)
|
||||
|
||||
case ADDR_EXPR:
|
||||
case FDESC_EXPR:
|
||||
return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
|
||||
value = staticp (TREE_OPERAND (value, 0));
|
||||
/* "&(*a).f" is like unto pointer arithmetic. If "a" turns out to
|
||||
be a constant, this is old-skool offsetof-like nonsense. */
|
||||
if (value
|
||||
&& TREE_CODE (value) == INDIRECT_REF
|
||||
&& TREE_CONSTANT (TREE_OPERAND (value, 0)))
|
||||
return null_pointer_node;
|
||||
return value;
|
||||
|
||||
case VIEW_CONVERT_EXPR:
|
||||
case NON_LVALUE_EXPR:
|
||||
@ -3565,16 +3572,17 @@ initializer_constant_valid_p (tree value, tree endtype)
|
||||
/* 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 &&
|
||||
TREE_STRING_POINTER (valid0) == TREE_STRING_POINTER (valid1))
|
||||
if (valid0 && TREE_CODE (valid0) == STRING_CST
|
||||
&& valid1 && TREE_CODE (valid1) == STRING_CST
|
||||
&& operand_equal_p (valid0, valid1, 1))
|
||||
return null_pointer_node;
|
||||
}
|
||||
|
||||
/* Support differences between labels. */
|
||||
/* Support narrowing differences. */
|
||||
if (INTEGRAL_TYPE_P (endtype))
|
||||
{
|
||||
tree op0, op1;
|
||||
|
||||
op0 = TREE_OPERAND (value, 0);
|
||||
op1 = TREE_OPERAND (value, 1);
|
||||
|
||||
@ -3609,11 +3617,25 @@ initializer_constant_valid_p (tree value, tree endtype)
|
||||
op1 = inner;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user