Message ID | 4EB4AC8A.1070607@redhat.com |
---|---|
State | New |
Headers | show |
On 5 Nov 2011, at 03:24, Jason Merrill wrote: > After my previous patch for 48370 which adds extend_ref_init_temps, > it is straightforward to fix this issue as well by extending ref > init mem-initializers to match the lifetime of 'this'. > > Tested x86_64-pc-linux-gnu, applying to trunk. > commit 30ed5835a92df18afef71802b5fa95899ceca227 > Author: Jason Merrill <jason@redhat.com> > Date: Fri Nov 4 14:59:20 2011 -0400 > > PR c++/26714 > * init.c (perform_member_init): Strip TARGET_EXPR around NSDMI. > Do temporary lifetime extension. either this or the previous patch has broken (or exposed a problem which has broken) bootstrap on i686-darwin9 with: libtool: compile: /GCC/gcc-4-7-trunk-build/./gcc/xgcc -shared-libgcc - B/GCC/gcc-4-7-trunk-build/./gcc -nostdinc++ -L/GCC/gcc-4-7-trunk-build/ i686-apple-darwin9/x86_64/libstdc++-v3/src -L/GCC/gcc-4-7-trunk-build/ i686-apple-darwin9/x86_64/libstdc++-v3/src/.libs -B/GCC/gcc-4-7- install/i686-apple-darwin9/bin/ -B/GCC/gcc-4-7-install/i686-apple- darwin9/lib/ -isystem /GCC/gcc-4-7-install/i686-apple-darwin9/include - isystem /GCC/gcc-4-7-install/i686-apple-darwin9/sys-include -m64 -I/ GCC/gcc-4-7-trunk-build/i686-apple-darwin9/x86_64/libstdc++-v3/include/ i686-apple-darwin9 -I/GCC/gcc-4-7-trunk-build/i686-apple-darwin9/ x86_64/libstdc++-v3/include -I/GCC/gcc-live-trunk/libstdc++-v3/libsupc+ + -fno-implicit-templates -Wall -Wextra -Wwrite-strings -Wcast-qual - fdiagnostics-show-location=once -fvisibility-inlines-hidden -ffunction- sections -fdata-sections -frandom-seed=functexcept.lo -g -O2 -m64 - std=gnu++0x -c /GCC/gcc-live-trunk/libstdc++-v3/src/functexcept.cc - fno-common -DPIC -o .libs/functexcept.o In file included from /GCC/gcc-4-7-trunk-build/i686-apple-darwin9/ x86_64/libstdc++-v3/include/future:41:0, from /GCC/gcc-live-trunk/libstdc++-v3/src/ functexcept.cc:32: /GCC/gcc-4-7-trunk-build/i686-apple-darwin9/x86_64/libstdc++-v3/ include/thread:195:46: internal compiler error: Segmentation fault Please submit a full bug report, gdb: GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 Compiler executable checksum: d5643d919cac033598d9277e144abbda Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0xa5a5a5a5 0x00443fca in build_stmt (loc=6644384, code=CLEANUP_STMT) at /GCC/gcc- live-trunk/gcc/c-family/c-semantics.c:124 124 if (t && !TYPE_P (t)) (gdb) bt #0 0x00443fca in build_stmt (loc=6644384, code=CLEANUP_STMT) at /GCC/ gcc-live-trunk/gcc/c-family/c-semantics.c:124 #1 0x002da1f3 in push_cleanup (decl=0x2d36280, cleanup=0xa5a5a5a5, eh_only=0 '\0') at /GCC/gcc-live-trunk/gcc/cp/semantics.c:488 #2 0x00069fad in cp_finish_decl (decl=0x2d36280, init=0x428167b8, init_const_expr_p=0 '\0', asmspec_tree=0x0, flags=11) at /GCC/gcc-live- trunk/gcc/cp/decl.c:6320 #3 0x00223127 in cp_parser_init_declarator (parser=0x42827188, decl_specifiers=0xbfffe81c, checks=0x0, function_definition_allowed_p=1 '\001', member_p=0 '\0', declares_class_or_enum=0, function_definition_p=0xbfffe817 "", maybe_range_for_decl=0x0) at /GCC/gcc-live-trunk/gcc/cp/parser.c:15462 #4 0x00219e28 in cp_parser_simple_declaration (parser=0x42827188, function_definition_allowed_p=1 '\001', maybe_range_for_decl=0x0) at / GCC/gcc-live-trunk/gcc/cp/parser.c:10301 #5 0x00219c70 in cp_parser_block_declaration (parser=0x42827188, statement_p=0 '\0') at /GCC/gcc-live-trunk/gcc/cp/parser.c:10187 #6 0x00219a68 in cp_parser_declaration (parser=0x42827188) at /GCC/ gcc-live-trunk/gcc/cp/parser.c:10092 #7 0x002196dd in cp_parser_declaration_seq_opt (parser=0x42827188) at /GCC/gcc-live-trunk/gcc/cp/parser.c:9978 #8 0x00221c85 in cp_parser_namespace_body (parser=0x42827188) at /GCC/ gcc-live-trunk/gcc/cp/parser.c:14633 #9 0x00221c3b in cp_parser_namespace_definition (parser=0x42827188) at /GCC/gcc-live-trunk/gcc/cp/parser.c:14614 #10 0x002199b7 in cp_parser_declaration (parser=0x42827188) at /GCC/ gcc-live-trunk/gcc/cp/parser.c:10076 #11 0x002196dd in cp_parser_declaration_seq_opt (parser=0x42827188) at /GCC/gcc-live-trunk/gcc/cp/parser.c:9978 #12 0x0020c287 in cp_parser_translation_unit (parser=0x42827188) at / GCC/gcc-live-trunk/gcc/cp/parser.c:3739 #13 0x002416dc in c_parse_file () at /GCC/gcc-live-trunk/gcc/cp/ parser.c:26714 #14 0x0042edb3 in c_common_parse_file () at /GCC/gcc-live-trunk/gcc/c- family/c-opts.c:1122 #15 0x00e2a954 in compile_file () at /GCC/gcc-live-trunk/gcc/toplev.c: 565 #16 0x00e2d634 in do_compile () at /GCC/gcc-live-trunk/gcc/toplev.c:1930 #17 0x00e2d81d in toplev_main (argc=57, argv=0xbfffebe4) at /GCC/gcc- live-trunk/gcc/toplev.c:2006 #18 0x00458618 in main (argc=57, argv=0xbfffebe4) at /GCC/gcc-live- trunk/gcc/main.c:36 cheers Iain
On 11/05/2011 10:32 AM, Iain Sandoe wrote: > either this or the previous patch has broken (or exposed a problem which > has broken) bootstrap on i686-darwin9 with: I've mostly reverted the previous patch, does that fix bootstrap for you? I don't understand yet what the problem is. Jason
On 5 Nov 2011, at 21:30, Jason Merrill wrote: > On 11/05/2011 10:32 AM, Iain Sandoe wrote: >> either this or the previous patch has broken (or exposed a problem >> which >> has broken) bootstrap on i686-darwin9 with: > > I've mostly reverted the previous patch, does that fix bootstrap for > you? I don't understand yet what the problem is. I'll set it running now... try to report back today... looks like a GTY kinda issue from the pattern showing in the gdb output/ thanks, Iain
On 5 Nov 2011, at 21:32, Iain Sandoe wrote: > On 5 Nov 2011, at 21:30, Jason Merrill wrote: > >> On 11/05/2011 10:32 AM, Iain Sandoe wrote: >>> either this or the previous patch has broken (or exposed a problem >>> which >>> has broken) bootstrap on i686-darwin9 with: >> >> I've mostly reverted the previous patch, does that fix bootstrap >> for you? I don't understand yet what the problem is. > > I'll set it running now... try to report back today... we're on stage2 - so looking good. > looks like a GTY kinda issue from the pattern showing in the gdb > output/ two more data points - 1) doesn't fail on either powerpc-darwin9 or x86-64-darwin10. 2) doesn't fail if compiled "-save-temps" .. makes one think that it's sensitive to the headers used cheers Iain
commit 30ed5835a92df18afef71802b5fa95899ceca227 Author: Jason Merrill <jason@redhat.com> Date: Fri Nov 4 14:59:20 2011 -0400 PR c++/26714 * init.c (perform_member_init): Strip TARGET_EXPR around NSDMI. Do temporary lifetime extension. 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)))) { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C new file mode 100644 index 0000000..16ae1ac --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C @@ -0,0 +1,64 @@ +// Test that we properly extend the lifetime of the initializer_list +// array even if the initializer_list is a subobject. +// { dg-options -std=c++0x } +// { dg-do run } + +#include <initializer_list> + +extern "C" void abort(); +bool ok; + +bool do_throw; + +struct A { + A(int) { if (do_throw) throw 42; } + ~A() { if (!ok) abort(); } +}; + +typedef std::initializer_list<A> AL; +typedef std::initializer_list<AL> AL2; +typedef std::initializer_list<AL2> AL3; + +struct B { + AL al; + const AL& alr; +}; + +struct A2 +{ + const A& a1; + const A& a2; +}; + +struct C { + AL ar[2]; + B b; + AL3 al3; + A2 a2; + A2 a2r[2]; + C(): + ar{{1,2},{3,4}}, + b{{5,6},{7,8}}, + al3{{{1},{2},{3}}}, + a2{1,2}, + a2r{{1,2},{3,4}} + { ok = true; } +}; + +struct D { + AL ar[2] = {{1,2},{3,4}}; + B b = {{5,6},{7,8}}; + AL3 al3 = {{{1},{2},{3}}}; + A2 a2 = {1,2}; + A2 a2r[2] = {{1,2},{3,4}}; + D() { ok = true; } +}; + +int main(int argc, const char** argv) +{ + do_throw = (argc > 1); // always false, but optimizer can't tell + ok = false; + C c; + ok = false; + D d; +} diff --git a/gcc/testsuite/g++.dg/init/lifetime2.C b/gcc/testsuite/g++.dg/init/lifetime2.C new file mode 100644 index 0000000..293bd69 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/lifetime2.C @@ -0,0 +1,23 @@ +// PR c++/26714 +// { dg-do run } + +extern "C" void abort(); + +bool ok = false; +struct A +{ + A() { } + ~A() { if (!ok) abort(); } +}; + +struct B +{ + const A &a1; + const A &a2; + B() : a1(A()),a2(A()) { ok = true; } +}; + +int main() +{ + B b; +}