aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-08-30 11:49:20 -0700
committerRichard Henderson <rth@gcc.gnu.org>2004-08-30 11:49:20 -0700
commit5cc200fcf0b382bb7509f26eb8bd9cc6538e255d (patch)
treeb64b1c02953ecd652d493aee5e592cde95eaf88b
parent1c340cb66c5a3f1d3e0fcc88100ebacb33c78f1f (diff)
downloadgcc-5cc200fcf0b382bb7509f26eb8bd9cc6538e255d.zip
gcc-5cc200fcf0b382bb7509f26eb8bd9cc6538e255d.tar.gz
gcc-5cc200fcf0b382bb7509f26eb8bd9cc6538e255d.tar.bz2
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/c-typeck.c44
-rw-r--r--gcc/varasm.c42
3 files changed, 52 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 13856ad..15a9897 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
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.
(expand_expr_real_1) <case ADDR_EXPR>: Use it.
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index aa04ac0..6e7bbfe 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -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)
- {
- tree field = TREE_OPERAND (arg, 1);
-
- 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;
- }
+ 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;
+ }
- 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);
+ argtype = build_pointer_type (argtype);
+ val = build1 (ADDR_EXPR, argtype, arg);
- if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
- TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1;
+ if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
+ TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
- return addr;
- }
+ return val;
default:
break;
diff --git a/gcc/varasm.c b/gcc/varasm.c
index ba25f65..693196e 100644
--- a/gcc/varasm.c
+++ b/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;