From: Jason Merrill Date: Sat, 24 Oct 2015 02:58:10 +0000 (-0400) Subject: DR 1518 DR 1630 PR c++/54835 PR c++/60417 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e7838ec9d2ea06e844ef23660862781b81a26329;p=gcc.git 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): Value-initialization can't use explicit constructors in C++11 and up. From-SVN: r229283 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e3dbe6b7090..5434dd27795 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2015-10-23 Jason Merrill + DR 1518 + DR 1630 + PR c++/54835 + PR c++/60417 + * call.c (convert_like_real): Value-initialization can't use + explicit constructors in C++11 and up. + PR c++/67813 * constexpr.c (cxx_eval_store_expression): Always use *valp if set. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 5b57dc97b54..1223dcd3b14 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6341,9 +6341,32 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree convfn = cand->fn; unsigned i; - /* If we're initializing from {}, it's value-initialization. Note - that under the resolution of core 1630, value-initialization can - use explicit constructors. */ + /* 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) + /* And in C++98 a default constructor can't be explicit. */ + && cxx_dialect >= cxx11) + { + if (!(complain & tf_error)) + return error_mark_node; + location_t loc = location_of (expr); + if (CONSTRUCTOR_NELTS (expr) == 0 + && FUNCTION_FIRST_USER_PARMTYPE (convfn) != void_list_node) + { + if (pedwarn (loc, 0, "converting to %qT from initializer list " + "would use explicit constructor %qD", + totype, convfn)) + inform (loc, "in C++11 and above a default constructor " + "can be explicit"); + } + else + error ("converting to %qT from initializer list would use " + "explicit constructor %qD", totype, convfn); + } + + /* If we're initializing from {}, it's value-initialization. */ if (BRACE_ENCLOSED_INITIALIZER_P (expr) && CONSTRUCTOR_NELTS (expr) == 0 && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)) @@ -6359,18 +6382,6 @@ 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/testsuite/g++.dg/cpp0x/explicit10.C b/gcc/testsuite/g++.dg/cpp0x/explicit10.C new file mode 100644 index 00000000000..f31f85640bb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/explicit10.C @@ -0,0 +1,40 @@ +// 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 = {}; // { dg-error "explicit" } +} +template void g() { + void x(T t); + x({}); // { dg-error "explicit" } +} + +int main() +{ + f(); // { dg-bogus "required from here" } + f(); // { dg-message "required from here" } + f(); // { dg-message "required from here" } + f(); // { dg-message "required from here" } + + g(); // { dg-bogus "required from here" } + g(); // { dg-message "required from here" } + g(); // { dg-message "required from here" } + g(); // { dg-message "required from here" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist40.C b/gcc/testsuite/g++.dg/cpp0x/initlist40.C index de2e19d3adc..6e6a11a6454 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 = { }; + A a1 = { }; // { dg-error "explicit" } A a2 = { 24 }; // { dg-error "explicit" } } diff --git a/gcc/testsuite/g++.dg/init/explicit1.C b/gcc/testsuite/g++.dg/init/explicit1.C index f376df23648..328e8673198 100644 --- a/gcc/testsuite/g++.dg/init/explicit1.C +++ b/gcc/testsuite/g++.dg/init/explicit1.C @@ -1,9 +1,10 @@ // PR c++/60417 +// { dg-options -pedantic } struct A { explicit A(int = 0); }; struct B { A a; }; int main() { - B b = {}; + B b = {}; // { dg-warning "explicit" "" { target c++11 } } } diff --git a/gcc/testsuite/g++.dg/init/explicit2.C b/gcc/testsuite/g++.dg/init/explicit2.C index d1dbb39fc61..604426ae6d2 100644 --- a/gcc/testsuite/g++.dg/init/explicit2.C +++ b/gcc/testsuite/g++.dg/init/explicit2.C @@ -1,8 +1,9 @@ // PR c++/60417 +// { dg-options -pedantic } struct A { explicit A(int = 0); }; int main() { - A a[1] = { }; + A a[1] = { }; // { dg-warning "explicit" "" { target c++11 } } }