Hello, Consider this short code snippet:
struct A { ~A(); }; struct B { A a; constexpr B() {} }; As explained in the audit trail, this is valid code. G++ ICEs on it because build_constexpr_constructor_member_initializers chokes on a CLEANUP_STMT. The CLEANUP_STMT is put into the constructor of B to ensure that the destructor for 'a' is called. As this CLEANUP_STMT is not related to the representation of mem-initializer-list that build_constexpr_constructor_member_initializers was expecting to see as part of its analysis of the constructor body my understanding is that it should just ignore it. I noted that build_data_member_initialization that is called elsewhere in build_constexpr_constructor_member_initializers already knows how to ignore those CLEANUP_STMT, so I tried in this patch to take advantage of that function. The other case of ICE reported in this issue is in: struct A2 { constexpr A2() {} ~A2(); }; struct B2 { A2 a; constexpr B2() { return;} }; where check_constexpr_ctor_body fails to recognize that the body of the constexpr constructor B2 is not empty. It turned out this is because it's not passed the proper last statement of the constructor, before the body (as written in the source code) is parsed. Fixed thus. Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. gcc/cp/ * semantics.c (cp_parser_ctor_initializer_opt_and_function_body): Set the pointer to the last block of the constructor to the current statement. (build_constexpr_constructor_member_initializers): Get build_data_member_initialization a chance to deal with more statements before we choke. gcc/testsuite/ * g++.dg/cpp0x/constexpr-diag4.C: New test. --- gcc/cp/parser.c | 2 +- gcc/cp/semantics.c | 2 + gcc/testsuite/g++.dg/cpp0x/constexpr-diag4.C | 28 +++++++++++++++ gcc/testsuite/g++.dg/cpp0x/constexpr-diag5.C | 48 ++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-diag4.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-diag5.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0ae55a2..ea9ccfc 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -17418,7 +17418,7 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser) cp_parser_function_body changed its state. */ if (check_body_p) { - list = body; + list = cur_stmt_list; if (TREE_CODE (list) == BIND_EXPR) list = BIND_EXPR_BODY (list); if (TREE_CODE (list) == STATEMENT_LIST diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index fbb74e1..9369179 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5930,6 +5930,8 @@ build_constexpr_constructor_member_initializers (tree type, tree body) break; } } + else if (EXPR_P (body)) + ok = build_data_member_initialization (body, &vec); else gcc_assert (errorcount > 0); if (ok) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag4.C new file mode 100644 index 0000000..08373c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag4.C @@ -0,0 +1,28 @@ +// Origin: PR c++/51633 +// { dg-options "-std=c++11" } + +struct A +{ + ~A(); +}; + +struct B +{ + A a; + constexpr B() {} +}; + +struct A1 +{ + int a; + ~A1(); +}; + +struct B1 +{ + A1 a1; + constexpr B1() {} // { dg-error "uninitialized member" } +}; + + + diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag5.C new file mode 100644 index 0000000..c0cbfdd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag5.C @@ -0,0 +1,48 @@ +// Origin: PR c++/51633 +// { dg-options "-std=c++11" } + +struct A +{ + constexpr A() {} + ~A(); +}; + +struct B +{ + A a; + A b; + A c; + constexpr B() {} +}; + +struct C +{ + A a; + constexpr C() {} +}; + +struct D +{ + constexpr D() { return;} // { dg-error "does not have empty body" } +}; + +struct D1 +{ + A a; + constexpr D1() { return;} // { dg-error "does not have empty body" } +}; + +struct D2 +{ + A a; + A b; + constexpr D2() { return;} // { dg-error "does not have empty body" } +}; + +struct D3 +{ + A a; + A b; + A c; + constexpr D3() { return;} // { dg-error "does not have empty body" } +}; -- 1.7.6.4 -- Dodji