re PR c++/68727 (invalid offsetof expressions accepted)
authorJakub Jelinek <jakub@redhat.com>
Thu, 26 Jan 2017 19:39:40 +0000 (20:39 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 26 Jan 2017 19:39:40 +0000 (20:39 +0100)
PR c++/68727
* cp-tree.def (OFFSETOF_EXPR): Bump number of operands to 2.
* cp-tree.h (finish_offsetof): Add OBJECT_PTR argument.
* parser.c (cp_parser_builtin_offsetof): Pass result of
build_static_cast of null_pointer_node to finish_offsetof.
* semantics.c (finish_offsetof): Add OBJECT_PTR argument, use
it for -Winvalid-offsetof pedwarn instead of trying to guess
original offsetof type from EXPR.  Save OBJECT_PTR as a new
second operand to OFFSETOF_EXPR.
* pt.c (tsubst_copy_and_build) <case OFFSETOF_EXPR>: Adjust
finish_offsetof caller, pass the second operand of OFFSETOF_EXPR
as OBJECT_PTR.

* g++.dg/other/offsetof8.C: Add expected error.
* g++.dg/other/offsetof9.C: New test.

From-SVN: r244949

gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/offsetof8.C
gcc/testsuite/g++.dg/other/offsetof9.C [new file with mode: 0644]

index 48d695254259fb40c8032f2061b31e0bb4e762cf..443df6980eaa485bb919d72198cddd68f1d2defe 100644 (file)
@@ -1,3 +1,18 @@
+2017-01-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/68727
+       * cp-tree.def (OFFSETOF_EXPR): Bump number of operands to 2.
+       * cp-tree.h (finish_offsetof): Add OBJECT_PTR argument.
+       * parser.c (cp_parser_builtin_offsetof): Pass result of
+       build_static_cast of null_pointer_node to finish_offsetof.
+       * semantics.c (finish_offsetof): Add OBJECT_PTR argument, use
+       it for -Winvalid-offsetof pedwarn instead of trying to guess
+       original offsetof type from EXPR.  Save OBJECT_PTR as a new
+       second operand to OFFSETOF_EXPR.
+       * pt.c (tsubst_copy_and_build) <case OFFSETOF_EXPR>: Adjust
+       finish_offsetof caller, pass the second operand of OFFSETOF_EXPR
+       as OBJECT_PTR.
+
 2017-01-26  Jason Merrill  <jason@redhat.com>
 
        * name-lookup.c (parse_using_directive): Deprecate strong using.
index ff4f4ef4698739487547b3d20153fa6cddaa90cd..c51c5c1dc21a3719e65ffa6c0e52baeebe80a42d 100644 (file)
@@ -333,7 +333,7 @@ DEFTREECODE (EXPR_STMT, "expr_stmt", tcc_expression, 1)
 DEFTREECODE (TAG_DEFN, "tag_defn", tcc_expression, 0)
 
 /* Represents an 'offsetof' expression during template expansion.  */
-DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 1)
+DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 2)
 
 /* Represents an '__builtin_addressof' expression during template
    expansion.  This is similar to ADDR_EXPR, but it doesn't invoke
index 57833c5884cf9eb8fff39b63711a66a7f4c6735d..f91b83027aa24be60fccf4da5b641b1005236715 100644 (file)
@@ -6487,7 +6487,7 @@ extern tree finish_underlying_type                (tree);
 extern tree calculate_bases                     (tree);
 extern tree finish_bases                        (tree, bool);
 extern tree calculate_direct_bases              (tree);
-extern tree finish_offsetof                    (tree, location_t);
+extern tree finish_offsetof                    (tree, tree, location_t);
 extern void finish_decl_cleanup                        (tree, tree);
 extern void finish_eh_cleanup                  (tree);
 extern void emit_associated_thunks             (tree);
index 372a01e147a3fa5ab6d1ccf1caa89801aab85119..9a61eb1604bc387665e384baf9c898f89203ed58 100644 (file)
@@ -9498,11 +9498,12 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
-  expr = build_static_cast (build_pointer_type (type), null_pointer_node,
-                            tf_warning_or_error);
+  tree object_ptr
+    = build_static_cast (build_pointer_type (type), null_pointer_node,
+                        tf_warning_or_error);
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
-  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
+  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, object_ptr,
                                                 true, &dummy, token->location);
   while (true)
     {
@@ -9554,7 +9555,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   loc = make_location (loc, start_loc, finish_loc);
   /* The result will be an INTEGER_CST, so we need to explicitly
      preserve the location.  */
-  expr = cp_expr (finish_offsetof (expr, loc), loc);
+  expr = cp_expr (finish_offsetof (object_ptr, expr, loc), loc);
 
  failure:
   parser->integral_constant_expression_p = save_ice_p;
index 537d1073fa0ce24964694ba3adde9bf3f2211d70..57334b4c44e112bb20977af4da2a147a3095606f 100644 (file)
@@ -17707,8 +17707,15 @@ tsubst_copy_and_build (tree t,
       }
 
     case OFFSETOF_EXPR:
-      RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0)),
-                              EXPR_LOCATION (t)));
+      {
+       tree object_ptr
+         = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
+                                  in_decl, /*function_p=*/false,
+                                  /*integral_constant_expression_p=*/false);
+       RETURN (finish_offsetof (object_ptr,
+                                RECUR (TREE_OPERAND (t, 0)),
+                                EXPR_LOCATION (t)));
+      }
 
     case ADDRESSOF_EXPR:
       RETURN (cp_build_addressof (EXPR_LOCATION (t),
index 55710e64c97ea1902087ea3b2e6f826954efd9ba..6d5ea955db37eea1b785b8335872bf3804f1913e 100644 (file)
@@ -3995,13 +3995,13 @@ finish_bases (tree type, bool direct)
    fold_offsetof.  */
 
 tree
-finish_offsetof (tree expr, location_t loc)
+finish_offsetof (tree object_ptr, tree expr, location_t loc)
 {
   /* If we're processing a template, we can't finish the semantics yet.
      Otherwise we can fold the entire expression now.  */
   if (processing_template_decl)
     {
-      expr = build1 (OFFSETOF_EXPR, size_type_node, expr);
+      expr = build2 (OFFSETOF_EXPR, size_type_node, expr, object_ptr);
       SET_EXPR_LOCATION (expr, loc);
       return expr;
     }
@@ -4031,19 +4031,15 @@ finish_offsetof (tree expr, location_t loc)
     }
   if (REFERENCE_REF_P (expr))
     expr = TREE_OPERAND (expr, 0);
-  if (TREE_CODE (expr) == COMPONENT_REF)
-    {
-      tree object = TREE_OPERAND (expr, 0);
-      if (!complete_type_or_else (TREE_TYPE (object), object))
-       return error_mark_node;
-      if (warn_invalid_offsetof
-         && CLASS_TYPE_P (TREE_TYPE (object))
-         && CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (object))
-         && cp_unevaluated_operand == 0)
-       pedwarn (loc, OPT_Winvalid_offsetof,
-                "offsetof within non-standard-layout type %qT is undefined",
-                TREE_TYPE (object));
-    }
+  if (!complete_type_or_else (TREE_TYPE (TREE_TYPE (object_ptr)), object_ptr))
+    return error_mark_node;
+  if (warn_invalid_offsetof
+      && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (object_ptr)))
+      && CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (TREE_TYPE (object_ptr)))
+      && cp_unevaluated_operand == 0)
+    pedwarn (loc, OPT_Winvalid_offsetof,
+            "offsetof within non-standard-layout type %qT is undefined",
+            TREE_TYPE (TREE_TYPE (object_ptr)));
   return fold_offsetof (expr);
 }
 
index 876151b2aca19dc90d48b53bdda2d8aa8d806e8e..61551d119cad4549054423d1287d388fa3070e8e 100644 (file)
@@ -1,3 +1,9 @@
+2017-01-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/68727
+       * g++.dg/other/offsetof8.C: Add expected error.
+       * g++.dg/other/offsetof9.C: New test.
+
 2017-01-26  David Edelsohn  <dje.gcc@gmail.com>
 
        * g++.dg/opt/declone3.C: Require LTO.
index daca70a6fe4c24ee3e075c90cf1fbde69669c605..0668199b3669c494927714d794460a65f8c49ef2 100644 (file)
@@ -9,4 +9,4 @@ struct B: virtual A { };
 int a[]  = {
   !&((B*)0)->i,    // { dg-error "invalid access to non-static data member" }
   __builtin_offsetof (B, i)   // { dg-error "invalid access to non-static" }
-};
+};                           // { dg-error "offsetof within non-standard-layout type" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/other/offsetof9.C b/gcc/testsuite/g++.dg/other/offsetof9.C
new file mode 100644 (file)
index 0000000..bd80fa5
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/68727
+// { dg-do compile }
+// { dg-options "-Winvalid-offsetof" }
+
+struct A { int i; };
+struct B : virtual A { };
+__SIZE_TYPE__ s = __builtin_offsetof (B, A::i);        // { dg-warning "offsetof within non-standard-layout type" }
+
+template <typename T>
+__SIZE_TYPE__
+foo ()
+{
+  return __builtin_offsetof (T, A::i)          // { dg-warning "offsetof within non-standard-layout type" }
+        + __builtin_offsetof (B, A::i);        // { dg-warning "offsetof within non-standard-layout type" }
+}
+
+__SIZE_TYPE__ t = foo<B> ();