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
This commit is contained in:
Jason Merrill 2015-10-23 22:58:10 -04:00 committed by Jason Merrill
parent a8c6dabc47
commit e7838ec9d2
6 changed files with 78 additions and 18 deletions

View file

@ -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.

View file

@ -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

View file

@ -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" }
}

View file

@ -8,6 +8,6 @@ struct A
int main()
{
A a1 = { };
A a1 = { }; // { dg-error "explicit" }
A a2 = { 24 }; // { dg-error "explicit" }
}

View file

@ -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 } }
}

View file

@ -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 } }
}