diff options
author | Jason Merrill <jason@redhat.com> | 2014-12-11 22:48:55 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-12-11 22:48:55 -0500 |
commit | 89631a43369a94bcce9a3a3b3063a75972754a5a (patch) | |
tree | 957668d11d15ae27eea8fc37f49bc6c98e00cb03 /gcc | |
parent | 923e09ee92afd63f0e6aff37ed796952196bb60b (diff) | |
download | gcc-89631a43369a94bcce9a3a3b3063a75972754a5a.zip gcc-89631a43369a94bcce9a3a3b3063a75972754a5a.tar.gz gcc-89631a43369a94bcce9a3a3b3063a75972754a5a.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist90.C | 35 |
5 files changed, 61 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0442ef3..be8f3a0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2014-12-11 Jason Merrill <jason@redhat.com> + + 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 <paolo.carlini@oracle.com> * typeck.c (maybe_warn_about_useless_cast): Remove unnecessary diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d8075bd..312dfdf 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<tree, va_gc> **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 d41a834..ad1cc71 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<tree, va_gc>**, 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 92c0417..c53a9b5 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<tree, va_gc>** 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 0000000..330517a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist90.C @@ -0,0 +1,35 @@ +// PR c++/57510 +// { dg-do run { target c++11 } } + +#include <initializer_list> + +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; + } +} |