From: Richard Henderson Date: Mon, 30 Aug 2004 18:49:20 +0000 (-0700) Subject: c-typeck.c (build_unary_op): Don't expand ADDR_EXPR of a COMPONENT_REF to pointer... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5cc200fcf0b382bb7509f26eb8bd9cc6538e255d;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 13856adf6a3..15a9897ae95 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-08-30 Richard Henderson + + * 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 * expr.c (expand_expr_addr_expr): New. diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index aa04ac0d24a..6e7bbfe7ef7 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 ba25f6587f9..693196eaca8 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;