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
This commit is contained in:
Jason Merrill 2014-12-11 22:48:55 -05:00 committed by Jason Merrill
parent 923e09ee92
commit 89631a4336
5 changed files with 61 additions and 13 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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. */

View File

@ -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;
}
}