Commit 5cc200fc by Richard Henderson Committed by Richard Henderson

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
parent 1c340cb6
2004-08-30 Richard Henderson <rth@redhat.com> 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. * expr.c (expand_expr_addr_expr): New.
(expand_expr_real_1) <case ADDR_EXPR>: Use it. (expand_expr_real_1) <case ADDR_EXPR>: Use it.
......
...@@ -2514,44 +2514,24 @@ build_unary_op (enum tree_code code, tree xarg, int flag) ...@@ -2514,44 +2514,24 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
TREE_READONLY (arg), TREE_READONLY (arg),
TREE_THIS_VOLATILE (arg)); TREE_THIS_VOLATILE (arg));
argtype = build_pointer_type (argtype);
if (!c_mark_addressable (arg)) if (!c_mark_addressable (arg))
return error_mark_node; return error_mark_node;
{ if (TREE_CODE (arg) == COMPONENT_REF
tree addr; && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
{
if (TREE_CODE (arg) == COMPONENT_REF) error ("attempt to take address of bit-field structure member `%D'",
{ TREE_OPERAND (arg, 1));
tree field = TREE_OPERAND (arg, 1); return error_mark_node;
}
addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
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, argtype = build_pointer_type (argtype);
convert (argtype, addr), val = build1 (ADDR_EXPR, argtype, arg);
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) if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1; TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
return addr; return val;
}
default: default:
break; break;
......
...@@ -3463,7 +3463,14 @@ initializer_constant_valid_p (tree value, tree endtype) ...@@ -3463,7 +3463,14 @@ initializer_constant_valid_p (tree value, tree endtype)
case ADDR_EXPR: case ADDR_EXPR:
case FDESC_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 VIEW_CONVERT_EXPR:
case NON_LVALUE_EXPR: case NON_LVALUE_EXPR:
...@@ -3565,16 +3572,17 @@ initializer_constant_valid_p (tree value, tree endtype) ...@@ -3565,16 +3572,17 @@ initializer_constant_valid_p (tree value, tree endtype)
/* Since GCC guarantees that string constants are unique in the /* Since GCC guarantees that string constants are unique in the
generated code, a subtraction between two copies of the same generated code, a subtraction between two copies of the same
constant string is absolute. */ constant string is absolute. */
if (valid0 && TREE_CODE (valid0) == STRING_CST && if (valid0 && TREE_CODE (valid0) == STRING_CST
valid1 && TREE_CODE (valid1) == STRING_CST && && valid1 && TREE_CODE (valid1) == STRING_CST
TREE_STRING_POINTER (valid0) == TREE_STRING_POINTER (valid1)) && operand_equal_p (valid0, valid1, 1))
return null_pointer_node; return null_pointer_node;
} }
/* Support differences between labels. */ /* Support narrowing differences. */
if (INTEGRAL_TYPE_P (endtype)) if (INTEGRAL_TYPE_P (endtype))
{ {
tree op0, op1; tree op0, op1;
op0 = TREE_OPERAND (value, 0); op0 = TREE_OPERAND (value, 0);
op1 = TREE_OPERAND (value, 1); op1 = TREE_OPERAND (value, 1);
...@@ -3609,11 +3617,25 @@ initializer_constant_valid_p (tree value, tree endtype) ...@@ -3609,11 +3617,25 @@ initializer_constant_valid_p (tree value, tree endtype)
op1 = inner; op1 = inner;
} }
if (TREE_CODE (op0) == ADDR_EXPR op0 = initializer_constant_valid_p (op0, endtype);
&& TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL op1 = initializer_constant_valid_p (op1, endtype);
&& TREE_CODE (op1) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL) /* Both initializers must be known. */
return null_pointer_node; 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; break;
......
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