]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/50608 (cannot apply 'offsetof' to a non-constant address)
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 4 Nov 2011 21:49:49 +0000 (21:49 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 4 Nov 2011 21:49:49 +0000 (21:49 +0000)
2011-11-04  Eric Botcazou  <ebotcazou@adacore.com>

PR c++/50608
* c-parser.c (c_parser_postfix_expression) <RID_OFFSETOF>: Adjust call
to fold_offsetof.
* c-typeck.c (build_unary_op) <ADDR_EXPR>: Call fold_offsetof_1.
c-family/
* c-common.c (c_fully_fold_internal) <ADDR_EXPR>: Call fold_offsetof_1.
(fold_offsetof_1): Make global.  Remove STOP_REF argument and adjust.
<INDIRECT_REF>: Return the argument.
<ARRAY_REF>: Remove special code for negative offset.
Call fold_build_pointer_plus instead of size_binop.
(fold_offsetof): Remove STOP_REF argument and adjust.
* c-common.h (fold_offsetof_1): Declare.
(fold_offsetof): Remove STOP_REF argument.
cp/
* semantics.c (finish_offsetof): Adjust call to fold_offsetof.
* typeck.c (cp_build_addr_expr_1): Call fold_offsetof_1.

From-SVN: r180988

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-parser.c
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/offsetof7.C [new file with mode: 0644]

index eb01d915dc0e492dd34e32ea62df073f14d18681..4e6dd87b55e70d080280181623a2f8c4cc982c57 100644 (file)
@@ -1,3 +1,10 @@
+2011-11-04  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR c++/50608
+       * c-parser.c (c_parser_postfix_expression) <RID_OFFSETOF>: Adjust call
+       to fold_offsetof.
+       * c-typeck.c (build_unary_op) <ADDR_EXPR>: Call fold_offsetof_1.
+
 2011-11-04  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR target/50979
index c4c7558115b4dc8c353e1bdee2bf614fbe6904a4..cb1d017caedd730aee06fb0030d226eef976baa3 100644 (file)
@@ -1,3 +1,15 @@
+2011-11-04  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR c++/50608
+       * c-common.c (c_fully_fold_internal) <ADDR_EXPR>: Call fold_offsetof_1.
+       (fold_offsetof_1): Make global.  Remove STOP_REF argument and adjust.
+       <INDIRECT_REF>: Return the argument.
+       <ARRAY_REF>: Remove special code for negative offset.
+       Call fold_build_pointer_plus instead of size_binop.
+       (fold_offsetof): Remove STOP_REF argument and adjust.
+       * c-common.h (fold_offsetof_1): Declare.
+       (fold_offsetof): Remove STOP_REF argument.
+
 2011-10-26  Release Manager
 
        * GCC 4.6.2 released.
index 04664a5745f9574b43c48caee530b04bf2cd3d95..eaf129340e6bde0300329c6849a2c6d834d100e8 100644 (file)
@@ -1236,13 +1236,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
          && (op1 = get_base_address (op0)) != NULL_TREE
          && TREE_CODE (op1) == INDIRECT_REF
          && TREE_CONSTANT (TREE_OPERAND (op1, 0)))
-       {
-         tree offset = fold_offsetof (op0, op1);
-         op1
-           = fold_convert_loc (loc, TREE_TYPE (expr), TREE_OPERAND (op1, 0));
-         ret = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (expr), op1,
-                                offset);
-       }
+       ret = fold_convert_loc (loc, TREE_TYPE (expr), fold_offsetof_1 (op0));
       else if (op0 != orig_op0 || in_init)
        ret = in_init
          ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0)
@@ -8459,20 +8453,15 @@ c_common_to_target_charset (HOST_WIDE_INT c)
     return uc;
 }
 
-/* Build the result of __builtin_offsetof.  EXPR is a nested sequence of
-   component references, with STOP_REF, or alternatively an INDIRECT_REF of
-   NULL, at the bottom; much like the traditional rendering of offsetof as a
-   macro.  Returns the folded and properly cast result.  */
+/* Fold an offsetof-like expression.  EXPR is a nested sequence of component
+   references with an INDIRECT_REF of a constant at the bottom; much like the
+   traditional rendering of offsetof as a macro.  Return the folded result.  */
 
-static tree
-fold_offsetof_1 (tree expr, tree stop_ref)
+tree
+fold_offsetof_1 (tree expr)
 {
-  enum tree_code code = PLUS_EXPR;
   tree base, off, t;
 
-  if (expr == stop_ref && TREE_CODE (expr) != ERROR_MARK)
-    return size_zero_node;
-
   switch (TREE_CODE (expr))
     {
     case ERROR_MARK:
@@ -8489,15 +8478,15 @@ fold_offsetof_1 (tree expr, tree stop_ref)
 
     case NOP_EXPR:
     case INDIRECT_REF:
-      if (!integer_zerop (TREE_OPERAND (expr, 0)))
+      if (!TREE_CONSTANT (TREE_OPERAND (expr, 0)))
        {
          error ("cannot apply %<offsetof%> to a non constant address");
          return error_mark_node;
        }
-      return size_zero_node;
+      return TREE_OPERAND (expr, 0);
 
     case COMPONENT_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
       if (base == error_mark_node)
        return base;
 
@@ -8515,21 +8504,14 @@ fold_offsetof_1 (tree expr, tree stop_ref)
       break;
 
     case ARRAY_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
       if (base == error_mark_node)
        return base;
 
       t = TREE_OPERAND (expr, 1);
-      if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
-       {
-         code = MINUS_EXPR;
-         t = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (t), t);
-       }
-      t = convert (sizetype, t);
-      off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
 
       /* Check if the offset goes beyond the upper bound of the array.  */
-      if (code == PLUS_EXPR && TREE_CODE (t) == INTEGER_CST)
+      if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
        {
          tree upbound = array_ref_up_bound (expr);
          if (upbound != NULL_TREE
@@ -8569,26 +8551,30 @@ fold_offsetof_1 (tree expr, tree stop_ref)
                }
            }
        }
+
+      t = convert (sizetype, t);
+      off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
       break;
 
     case COMPOUND_EXPR:
       /* Handle static members of volatile structs.  */
       t = TREE_OPERAND (expr, 1);
       gcc_assert (TREE_CODE (t) == VAR_DECL);
-      return fold_offsetof_1 (t, stop_ref);
+      return fold_offsetof_1 (t);
 
     default:
       gcc_unreachable ();
     }
 
-  return size_binop (code, base, off);
+  return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (base), base, off);
 }
 
+/* Likewise, but convert it to the return type of offsetof.  */
+
 tree
-fold_offsetof (tree expr, tree stop_ref)
+fold_offsetof (tree expr)
 {
-  /* Convert back from the internal sizetype to size_t.  */
-  return convert (size_type_node, fold_offsetof_1 (expr, stop_ref));
+  return convert (size_type_node, fold_offsetof_1 (expr));
 }
 
 /* Warn for A ?: C expressions (with B omitted) where A is a boolean 
index 406def96e16fb59e2c35c14e164ed1688f52cad3..456c7e58262bba12411f81db7b38690b07d34bbf 100644 (file)
@@ -916,7 +916,8 @@ extern bool c_dump_tree (void *, tree);
 
 extern void verify_sequence_points (tree);
 
-extern tree fold_offsetof (tree, tree);
+extern tree fold_offsetof_1 (tree);
+extern tree fold_offsetof (tree);
 
 /* Places where an lvalue, or modifiable lvalue, may be required.
    Used to select diagnostic messages in lvalue_error and
index 69ce2e50befdd2f210f8c34772462741efba10e6..083a29f6373e7e173578b3221a280f49ef78ebd1 100644 (file)
@@ -6294,7 +6294,7 @@ c_parser_postfix_expression (c_parser *parser)
              c_parser_error (parser, "expected identifier");
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
-           expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
+           expr.value = fold_offsetof (offsetof_ref);
          }
          break;
        case RID_CHOOSE_EXPR:
index aa5243265459e02c83893eb9ee47779612ee99a4..cd68a05a6cf2d2f4ef68f303e7d66f363803f971 100644 (file)
@@ -3802,11 +3802,7 @@ build_unary_op (location_t location,
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
-         tree op0 = fold_convert_loc (location, sizetype,
-                                      fold_offsetof (arg, val)), op1;
-
-         op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0));
-         ret = fold_build2_loc (location, POINTER_PLUS_EXPR, argtype, op1, op0);
+         ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
          goto return_build_unary_op;
        }
 
index 6262513c4485c26a54d3c570afcef87044a1c478..729462609d240f9769cda660161e8a69df3c84dc 100644 (file)
@@ -1,3 +1,9 @@
+2011-11-04  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR c++/50608
+       * semantics.c (finish_offsetof): Adjust call to fold_offsetof.
+       * typeck.c (cp_build_addr_expr_1): Call fold_offsetof_1.
+
 2011-10-29  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/50901
index ee9d85df0d2ccc551fbc084a6b2d3f1bb419edd6..e02bd53af1c66d2972780cec89583e953a7b270b 100644 (file)
@@ -3348,7 +3348,7 @@ finish_offsetof (tree expr)
     }
   if (TREE_CODE (expr) == INDIRECT_REF && REFERENCE_REF_P (expr))
     expr = TREE_OPERAND (expr, 0);
-  return fold_offsetof (expr, NULL_TREE);
+  return fold_offsetof (expr);
 }
 
 /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR.  This
index f6ce635cf17bccc768b7d8e65fccf62b90aa96de..73d57e9fc1fb2d777f7370cc7b2e7c9bc4a5ecee 100644 (file)
@@ -4835,9 +4835,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
       && TREE_CONSTANT (TREE_OPERAND (val, 0)))
     {
       tree type = build_pointer_type (argtype);
-      tree op0 = fold_convert (type, TREE_OPERAND (val, 0));
-      tree op1 = fold_convert (sizetype, fold_offsetof (arg, val));
-      return fold_build2 (POINTER_PLUS_EXPR, type, op0, op1);
+      return fold_convert (type, fold_offsetof_1 (arg));
     }
 
   /* Handle complex lvalues (when permitted)
index 89409d2085663ad1f8a6fc8a78b1f1d32db20c5c..ac5c6231b35ea524d3353e6b60abe77fd9d06e90 100644 (file)
@@ -1,3 +1,7 @@
+2011-11-04  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * g++.dg/other/offsetof7.C: New test.
+
 2011-11-02  Bernd Schmidt  <bernds@codesourcery.com>
 
        * gcc.c-torture/compile/20110907.c: New file.
diff --git a/gcc/testsuite/g++.dg/other/offsetof7.C b/gcc/testsuite/g++.dg/other/offsetof7.C
new file mode 100644 (file)
index 0000000..0ce2ee0
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/50608
+// Testcase by <dberger@oubliette.org>
+// { dg-do compile }
+
+struct A {
+    int offset;
+};
+
+struct B: public A {
+};
+
+struct C {
+    A a;
+    B b;
+};
+
+int fails = __builtin_offsetof (C, b.offset);