diff options
author | Jason Merrill <jason@redhat.com> | 2011-11-04 23:28:14 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-11-04 23:28:14 -0400 |
commit | e2df21bfc6c81b4bc410a42002c8427454ffa628 (patch) | |
tree | 7b439ecb9236581bd4b64ccf943c6d9a7ce82aa0 /gcc/cp | |
parent | 8dc1dc7975a3d8dd3ffdfd6fcc992419cc358af7 (diff) | |
download | gcc-e2df21bfc6c81b4bc410a42002c8427454ffa628.zip gcc-e2df21bfc6c81b4bc410a42002c8427454ffa628.tar.gz gcc-e2df21bfc6c81b4bc410a42002c8427454ffa628.tar.bz2 |
re PR c++/26714 (violation of [class.temporary]/5)
PR c++/26714
* init.c (perform_member_init): Strip TARGET_EXPR around NSDMI.
Do temporary lifetime extension.
From-SVN: r181002
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/init.c | 46 |
2 files changed, 49 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6c68d87..200621e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2011-11-04 Jason Merrill <jason@redhat.com> + PR c++/26714 + * init.c (perform_member_init): Strip TARGET_EXPR around NSDMI. + Do temporary lifetime extension. + PR c++/48370 * decl.c (cp_finish_decl): Run cleanups in the right order. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3881275..ca4f590 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -507,7 +507,15 @@ perform_member_init (tree member, tree init) tf_warning_or_error, member, /*function_p=*/false, /*integral_constant_expression_p=*/false)); else - init = break_out_target_exprs (DECL_INITIAL (member)); + { + init = DECL_INITIAL (member); + /* Strip redundant TARGET_EXPR so we don't need to remap it, and + so the aggregate init code below will see a CONSTRUCTOR. */ + if (init && TREE_CODE (init) == TARGET_EXPR + && !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (init)))) + init = TARGET_EXPR_INITIAL (init); + init = break_out_target_exprs (init); + } } /* Effective C++ rule 12 requires that all data members be @@ -565,6 +573,42 @@ perform_member_init (tree member, tree init) finish_expr_stmt (init); } } + else if (init + && (TREE_CODE (type) == REFERENCE_TYPE + /* Pre-digested NSDMI. */ + || (((TREE_CODE (init) == CONSTRUCTOR + && TREE_TYPE (init) == type) + /* { } mem-initializer. */ + || (TREE_CODE (init) == TREE_LIST + && TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR + && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))) + && (CP_AGGREGATE_TYPE_P (type) + || is_std_init_list (type))))) + { + /* With references and list-initialization, we need to deal with + extending temporary lifetimes. 12.2p5: "A temporary bound to a + reference member in a constructor’s ctor-initializer (12.6.2) + persists until the constructor exits." */ + unsigned i; tree t; + VEC(tree,gc) *cleanups = make_tree_vector (); + if (TREE_CODE (init) == TREE_LIST) + init = build_x_compound_expr_from_list (init, ELK_MEM_INIT, + tf_warning_or_error); + if (TREE_TYPE (init) != type) + init = digest_init (type, init, tf_warning_or_error); + if (init == error_mark_node) + return; + /* Use 'this' as the decl, as it has the lifetime we want. */ + init = extend_ref_init_temps (current_class_ptr, init, &cleanups); + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))) + init = build_vec_init_expr (type, init, tf_warning_or_error); + init = build2 (INIT_EXPR, type, decl, init); + finish_expr_stmt (init); + FOR_EACH_VEC_ELT (tree, cleanups, i, t) + push_cleanup (decl, t, false); + release_tree_vector (cleanups); + } else if (type_build_ctor_call (type) || (init && CLASS_TYPE_P (strip_array_types (type)))) { |