diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 41 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/explicit10.C | 40 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist40.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/explicit1.C | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/explicit2.C | 3 |
6 files changed, 78 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e3dbe6b..5434dd2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2015-10-23 Jason Merrill <jason@redhat.com> + 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 5b57dc9..1223dcd 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 0000000..f31f856 --- /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<typename T> void f() { + T t = {}; // { dg-error "explicit" } +} +template<typename T> void g() { + void x(T t); + x({}); // { dg-error "explicit" } +} + +int main() +{ + f<A>(); // { dg-bogus "required from here" } + f<B>(); // { dg-message "required from here" } + f<C>(); // { dg-message "required from here" } + f<D>(); // { dg-message "required from here" } + + g<A>(); // { dg-bogus "required from here" } + g<B>(); // { dg-message "required from here" } + g<C>(); // { dg-message "required from here" } + g<D>(); // { dg-message "required from here" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist40.C b/gcc/testsuite/g++.dg/cpp0x/initlist40.C index de2e19d..6e6a11a 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 f376df2..328e867 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 d1dbb39..604426a 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 } } } |