c-typeck.c (build_unary_op): Don't expand ADDR_EXPR of a COMPONENT_REF to pointer...
authorRichard Henderson <rth@redhat.com>
Mon, 30 Aug 2004 18:49:20 +0000 (11:49 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 30 Aug 2004 18:49:20 +0000 (11:49 -0700)
        * 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

gcc/ChangeLog
gcc/c-typeck.c
gcc/varasm.c

index 13856adf6a3047594b2a57d20d4d0ea4ffec0e67..15a9897ae95a67a515e8e0b3780a4063a952738a 100644 (file)
@@ -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.
index aa04ac0d24a76b23f2f3125c7b3cbb853d151743..6e7bbfe7ef79bd5ce7689c047c78deca598c9214 100644 (file)
@@ -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;
index ba25f6587f92dacfcd037625cdd68b2a4609df43..693196eaca8a3383800d31cbfb3f2c379146608f 100644 (file)
@@ -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;