From: Jason Merrill Date: Fri, 12 Dec 2014 03:48:55 +0000 (-0500) Subject: re PR c++/57510 (subobjects not destroyed when exception thrown during list-initializ... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=89631a43369a94bcce9a3a3b3063a75972754a5a;p=gcc.git re PR c++/57510 (subobjects not destroyed when exception thrown during list-initialization) PR c++/57510 * typeck2.c (split_nonconstant_init_1): Handle arrays here. (store_init_value): Not here. (split_nonconstant_init): Look through TARGET_EXPR. No longer static. * cp-tree.h: Declare split_nonconstant_init. * call.c (set_up_extended_ref_temp): Use split_nonconstant_init. From-SVN: r218653 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0442ef3a8c7..be8f3a00cde 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2014-12-11 Jason Merrill + + PR c++/57510 + * typeck2.c (split_nonconstant_init_1): Handle arrays here. + (store_init_value): Not here. + (split_nonconstant_init): Look through TARGET_EXPR. No longer static. + * cp-tree.h: Declare split_nonconstant_init. + * call.c (set_up_extended_ref_temp): Use split_nonconstant_init. + 2014-12-11 Paolo Carlini * typeck.c (maybe_warn_about_useless_cast): Remove unnecessary diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d8075bd97ea..312dfdf2421 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -9574,7 +9574,7 @@ set_up_extended_ref_temp (tree decl, tree expr, vec **cleanups, else /* Create the INIT_EXPR that will initialize the temporary variable. */ - init = build2 (INIT_EXPR, type, var, expr); + init = split_nonconstant_init (var, expr); if (at_function_scope_p ()) { add_decl_expr (var); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d41a834ac0a..ad1cc71162f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6291,6 +6291,7 @@ extern int abstract_virtuals_error_sfinae (tree, tree, tsubst_flags_t); extern int abstract_virtuals_error_sfinae (abstract_class_use, tree, tsubst_flags_t); extern tree store_init_value (tree, tree, vec**, int); +extern tree split_nonconstant_init (tree, tree); extern bool check_narrowing (tree, tree, tsubst_flags_t); extern tree digest_init (tree, tree, tsubst_flags_t); extern tree digest_init_flags (tree, tree, int); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 92c04178c21..c53a9b52923 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -604,6 +604,17 @@ split_nonconstant_init_1 (tree dest, tree init) case ARRAY_TYPE: inner_type = TREE_TYPE (type); array_type_p = true; + if ((TREE_SIDE_EFFECTS (init) + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + || array_of_runtime_bound_p (type)) + { + /* For an array, we only need/want a single cleanup region rather + than one per element. */ + tree code = build_vec_init (dest, NULL_TREE, init, false, 1, + tf_warning_or_error); + add_stmt (code); + return true; + } /* FALLTHRU */ case RECORD_TYPE: @@ -721,11 +732,13 @@ split_nonconstant_init_1 (tree dest, tree init) perform the non-constant part of the initialization to DEST. Returns the code for the runtime init. */ -static tree +tree split_nonconstant_init (tree dest, tree init) { tree code; + if (TREE_CODE (init) == TARGET_EXPR) + init = TARGET_EXPR_INITIAL (init); if (TREE_CODE (init) == CONSTRUCTOR) { code = push_stmt_list (); @@ -830,17 +843,7 @@ store_init_value (tree decl, tree init, vec** cleanups, int flags) && (TREE_SIDE_EFFECTS (value) || array_of_runtime_bound_p (type) || ! reduced_constant_expression_p (value))) - { - if (TREE_CODE (type) == ARRAY_TYPE - && (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)) - || array_of_runtime_bound_p (type))) - /* For an array, we only need/want a single cleanup region rather - than one per element. */ - return build_vec_init (decl, NULL_TREE, value, false, 1, - tf_warning_or_error); - else - return split_nonconstant_init (decl, value); - } + return split_nonconstant_init (decl, value); /* If the value is a constant, just put it in DECL_INITIAL. If DECL is an automatic variable, the middle end will turn this into a dynamic initialization later. */ diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist90.C b/gcc/testsuite/g++.dg/cpp0x/initlist90.C new file mode 100644 index 00000000000..330517af697 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist90.C @@ -0,0 +1,35 @@ +// PR c++/57510 +// { dg-do run { target c++11 } } + +#include + +struct counter +{ + static int n; + + counter() { ++n; } + counter(const counter&) { ++n; } + ~counter() { --n; } +}; + +int counter::n = 0; + +struct X +{ + X () { if (counter::n > 1) throw 1; } + + counter c; +}; + +int main () +{ + try + { + auto x = { X{}, X{} }; + } + catch (...) + { + if ( counter::n != 0 ) + throw; + } +}