From b8dd691344db6be88a843242d1686e7266de631b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 5 May 2015 22:07:34 -0400 Subject: [PATCH] DR 1518 DR 1630 PR c++/54835 PR c++/60417 DR 1518 DR 1630 PR c++/54835 PR c++/60417 * call.c (convert_like_real): Check value-initialization before explicit. * typeck2.c (process_init_constructor_record): Don't set CONSTRUCTOR_IS_DIRECT_INIT. (process_init_constructor_array): Likewise. * init.c (build_vec_init): Likewise. From-SVN: r222836 --- gcc/cp/ChangeLog | 13 +++++++++ gcc/cp/call.c | 28 +++++++++++--------- gcc/cp/init.c | 1 - gcc/cp/typeck2.c | 4 --- gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C | 27 +++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/initlist40.C | 2 +- 6 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 17c2d1d9887..3276b76bbb3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2015-05-05 Jason Merrill + + DR 1518 + DR 1630 + PR c++/54835 + PR c++/60417 + * call.c (convert_like_real): Check value-initialization before + explicit. + * typeck2.c (process_init_constructor_record): Don't set + CONSTRUCTOR_IS_DIRECT_INIT. + (process_init_constructor_array): Likewise. + * init.c (build_vec_init): Likewise. + 2015-05-05 David Malcolm * parser.c (cp_parser_asm_definition): Only test for diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7bdf2365de6..b77f69a267e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6243,19 +6243,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree convfn = cand->fn; unsigned i; - /* When converting from an init list we consider explicit - constructors, but actually trying to call one is an error. */ - if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn) - /* Unless this is for direct-list-initialization. */ - && !DIRECT_LIST_INIT_P (expr)) - { - if (!(complain & tf_error)) - return error_mark_node; - error ("converting to %qT from initializer list would use " - "explicit constructor %qD", totype, convfn); - } - - /* If we're initializing from {}, it's value-initialization. */ + /* If we're initializing from {}, it's value-initialization. Note + that under the resolution of core 1630, value-initialization can + use explicit constructors. */ if (BRACE_ENCLOSED_INITIALIZER_P (expr) && CONSTRUCTOR_NELTS (expr) == 0 && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)) @@ -6271,6 +6261,18 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, return expr; } + /* When converting from an init list we consider explicit + constructors, but actually trying to call one is an error. */ + if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn) + /* Unless this is for direct-list-initialization. */ + && !DIRECT_LIST_INIT_P (expr)) + { + if (!(complain & tf_error)) + return error_mark_node; + error ("converting to %qT from initializer list would use " + "explicit constructor %qD", totype, convfn); + } + expr = mark_rvalue_use (expr); /* Set user_conv_p on the argument conversions, so rvalue/base diff --git a/gcc/cp/init.c b/gcc/cp/init.c index a4fc9ff33cd..c41e30cff5c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3720,7 +3720,6 @@ build_vec_init (tree base, tree maxindex, tree init, if (cxx_dialect >= cxx11 && AGGREGATE_TYPE_P (type)) { init = build_constructor (init_list_type_node, NULL); - CONSTRUCTOR_IS_DIRECT_INIT (init) = true; } else { diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index c0df8237a12..6e0c777eac1 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1285,7 +1285,6 @@ process_init_constructor_array (tree type, tree init, we can't rely on the back end to do it for us, so make the initialization explicit by list-initializing from T{}. */ next = build_constructor (init_list_type_node, NULL); - CONSTRUCTOR_IS_DIRECT_INIT (next) = true; next = massage_init_elt (TREE_TYPE (type), next, complain); if (initializer_zerop (next)) /* The default zero-initialization is fine for us; don't @@ -1396,9 +1395,6 @@ process_init_constructor_record (tree type, tree init, for us, so build up TARGET_EXPRs. If the type in question is a class, just build one up; if it's an array, recurse. */ next = build_constructor (init_list_type_node, NULL); - /* Call this direct-initialization pending DR 1518 resolution so - that explicit default ctors don't break valid C++03 code. */ - CONSTRUCTOR_IS_DIRECT_INIT (next) = true; next = massage_init_elt (TREE_TYPE (field), next, complain); /* Warn when some struct elements are implicitly initialized. */ diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C b/gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C new file mode 100644 index 00000000000..9f8ee0b1d23 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C @@ -0,0 +1,27 @@ +// DR 1518 +// { dg-do compile { target c++11 } } + +struct A { + explicit A() = default; +}; + +struct B : A { + explicit B() = default; +}; + +struct C { + explicit C(); +}; + +struct D : A { + C c; + explicit D() = default; +}; + +template void f() { + T t = {}; +} +template void g() { + void x(T t); + x({}); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist40.C b/gcc/testsuite/g++.dg/cpp0x/initlist40.C index 6e6a11a6454..de2e19d3adc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist40.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist40.C @@ -8,6 +8,6 @@ struct A int main() { - A a1 = { }; // { dg-error "explicit" } + A a1 = { }; A a2 = { 24 }; // { dg-error "explicit" } } -- 2.30.2