re PR c++/67557 (Calling copy constructor of base class in constructor of derived...
authorJason Merrill <jason@redhat.com>
Mon, 12 Oct 2015 07:58:43 +0000 (03:58 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 12 Oct 2015 07:58:43 +0000 (03:58 -0400)
PR c++/67557

* expr.c (store_field): Call store_constructor directly when
storing a CONSTRUCTOR into a target smaller than its type.
Guard against unsafe bitwise copy.

From-SVN: r228704

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/g++.dg/init/vbase1.C

index 5d38bf67c982916cadb9d90d72b9a567d3c38390..1ce0fbb896a679d5e9ebfc76dcde7386f3ca4e96 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-11  Jason Merrill  <jason@redhat.com>
+
+       PR c++/67557
+       * expr.c (store_field): Call store_constructor directly when
+       storing a CONSTRUCTOR into a target smaller than its type.
+       Guard against unsafe bitwise copy.
+
 2015-10-11  Jan Hubicka  <hubicka@ucw.cz>
 
        * cgraphbuild.c (compute_call_stmt_bb_frequency): Use
index 6f6554d25c0088149c652e68c61f79682ba444a3..595324dc3959ba491ea4526b99ff05f9f3b7a734 100644 (file)
@@ -6616,7 +6616,11 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
         operations.  */
       || (bitsize >= 0
          && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
-         && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0)
+         && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0
+         /* Except for initialization of full bytes from a CONSTRUCTOR, which
+            we will handle specially below.  */
+         && !(TREE_CODE (exp) == CONSTRUCTOR
+              && bitsize % BITS_PER_UNIT == 0))
       /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
          decl we must use bitfield operations.  */
       || (bitsize >= 0
@@ -6629,6 +6633,9 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
       rtx temp;
       gimple *nop_def;
 
+      /* Using bitwise copy is not safe for TREE_ADDRESSABLE types.  */
+      gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (exp)));
+
       /* If EXP is a NOP_EXPR of precision less than its mode, then that
         implies a mask operation.  If the precision is the same size as
         the field we're storing into, that mask is redundant.  This is
@@ -6743,6 +6750,15 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
       if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
        set_mem_alias_set (to_rtx, alias_set);
 
+      /* Above we avoided using bitfield operations for storing a CONSTRUCTOR
+        into a target smaller than its type; handle that case now.  */
+      if (TREE_CODE (exp) == CONSTRUCTOR && bitsize >= 0)
+       {
+         gcc_assert (bitsize % BITS_PER_UNIT == 0);
+         store_constructor (exp, to_rtx, 0, bitsize/BITS_PER_UNIT);
+         return to_rtx;
+       }
+
       return store_expr (exp, to_rtx, 0, nontemporal);
     }
 }
index bbfd58f5c348daf7db991e23cd66c80d54280728..bcd6b42586d82f51d2317d4dfbb5cc282fab1361 100644 (file)
@@ -1,4 +1,5 @@
 // PR c++/50618
+// { dg-options "-fdump-rtl-expand" }
 // { dg-do run }
 
 struct Base
@@ -37,3 +38,8 @@ int main(int, char**)
     Diamond x(2);
     x.printText();
 }
+
+// Verify that the SubB() mem-initializer is storing 0 directly into
+// this->D.whatever rather than into a stack temp that is then copied into the
+// base field.
+// { dg-final { scan-rtl-dump "set \[^\n\]*\n\[^\n\]*this\[^\n\]*\n\[^\n\]*const_int 0" "expand" } }