From f5a8677b3756ff2278a3f094bca7575514d90655 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 12 Oct 2015 03:58:43 -0400 Subject: [PATCH] re PR c++/67557 (Calling copy constructor of base class in constructor of derived class produces crashing code) 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 | 7 +++++++ gcc/expr.c | 18 +++++++++++++++++- gcc/testsuite/g++.dg/init/vbase1.C | 6 ++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d38bf67c98..1ce0fbb896a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-10-11 Jason Merrill + + 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 * cgraphbuild.c (compute_call_stmt_bb_frequency): Use diff --git a/gcc/expr.c b/gcc/expr.c index 6f6554d25c0..595324dc395 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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); } } diff --git a/gcc/testsuite/g++.dg/init/vbase1.C b/gcc/testsuite/g++.dg/init/vbase1.C index bbfd58f5c34..bcd6b42586d 100644 --- a/gcc/testsuite/g++.dg/init/vbase1.C +++ b/gcc/testsuite/g++.dg/init/vbase1.C @@ -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" } } -- 2.30.2