diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2fa1549f963..9a22842bf17 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2014-06-03 Paolo Carlini + + DR 1423 + PR c++/52174 + * call.c (standard_conversion): Convert nullptr to bool only + in case of direct-initialization. + (convert_like_real): Provide informative error message. + 2014-06-03 Marek Polacek PR c/60439 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index b60bab775cd..75a6a4acc29 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1311,10 +1311,10 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, { /* [conv.bool] - An rvalue of arithmetic, unscoped enumeration, pointer, or - pointer to member type can be converted to an rvalue of type - bool. ... An rvalue of type std::nullptr_t can be converted - to an rvalue of type bool; */ + A prvalue of arithmetic, unscoped enumeration, pointer, or pointer + to member type can be converted to a prvalue of type bool. ... + For direct-initialization (8.5 [dcl.init]), a prvalue of type + std::nullptr_t can be converted to a prvalue of type bool; */ if (ARITHMETIC_TYPE_P (from) || UNSCOPED_ENUM_P (from) || fcode == POINTER_TYPE @@ -1328,6 +1328,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, && conv->rank < cr_pbool) || NULLPTR_TYPE_P (from)) conv->rank = cr_pbool; + if (NULLPTR_TYPE_P (from) && (flags & LOOKUP_ONLYCONVERTING)) + conv->bad_p = true; return conv; } @@ -6062,6 +6064,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, expr = CONSTRUCTOR_ELT (expr, 0)->value; } + /* Give a helpful error if this is bad because a conversion to bool + from std::nullptr_t requires direct-initialization. */ + if (NULLPTR_TYPE_P (TREE_TYPE (expr)) + && TREE_CODE (totype) == BOOLEAN_TYPE) + complained = permerror (loc, "converting to %qT from %qT requires " + "direct-initialization", + totype, TREE_TYPE (expr)); + for (; t ; t = next_conversion (t)) { if (t->kind == ck_user && t->cand->reason) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c409d99f211..d3af1482b17 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2014-06-03 Paolo Carlini + + DR 1423 + PR c++/52174 + * g++.dg/cpp0x/nullptr31.C: New. + * g++.dg/cpp0x/sfinae-nullptr1.C: Likewise. + * g++.dg/cpp0x/nullptr17.C: Update. + 2014-06-03 Marek Polacek PR c/60439 diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr17.C b/gcc/testsuite/g++.dg/cpp0x/nullptr17.C index 96fea44b228..616cd67581f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr17.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr17.C @@ -1,6 +1,7 @@ // { dg-do compile { target c++11 } } -// Test that bool is a better overload match than int +// Used to test that bool is a better overload match than int +// Updated for DR 1423 template struct tType_equal; template struct tType_equal { typedef void type; }; @@ -16,7 +17,7 @@ bool i( bool ); void test_i() { // Overload to bool, not int - type_equal(i(nullptr)); + type_equal(i(nullptr)); // { dg-error "direct" } decltype(nullptr) mynull = 0; - type_equal(i(mynull)); + type_equal(i(mynull)); // { dg-error "direct" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr31.C b/gcc/testsuite/g++.dg/cpp0x/nullptr31.C new file mode 100644 index 00000000000..01b8339b1c6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr31.C @@ -0,0 +1,11 @@ +// DR 1423, PR c++/52174 +// { dg-do compile { target c++11 } } + +bool b1 = nullptr; // { dg-error "direct" } + +bool b2(nullptr); +bool b3{nullptr}; + +int i1 = nullptr; // { dg-error "cannot convert" } +int i2(nullptr); // { dg-error "cannot convert" } +int i3{nullptr}; // { dg-error "cannot convert" } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae-nullptr1.C b/gcc/testsuite/g++.dg/cpp0x/sfinae-nullptr1.C new file mode 100644 index 00000000000..7f3c5c4eb3d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae-nullptr1.C @@ -0,0 +1,18 @@ +// DR 1423, PR c++/52174 +// { dg-do compile { target c++11 } } + +template +T&& make(); + +template +void sink(T); + +template(make())) +> +auto f(int) -> char(&)[1]; + +template +auto f(...) -> char(&)[2]; + +static_assert(sizeof(f(0)) != 1, ""); diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index df15a78672c..976ce975736 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2014-06-03 Paolo Carlini + + DR 1423 + PR c++/52174 + * testsuite/20_util/is_assignable/value.cc: Update. + 2014-06-02 Jonathan Wakely * include/std/condition_variable (condition_variable_any::_Unlock): Do diff --git a/libstdc++-v3/testsuite/20_util/is_assignable/value.cc b/libstdc++-v3/testsuite/20_util/is_assignable/value.cc index ddd73b48b9a..e9db58e6d16 100644 --- a/libstdc++-v3/testsuite/20_util/is_assignable/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_assignable/value.cc @@ -174,7 +174,7 @@ static_assert(!std::is_assignable::value, "Error"); static_assert(std::is_assignable::value, "Error"); static_assert(std::is_assignable::value, "Error"); static_assert(std::is_assignable::value, "Error"); -static_assert(std::is_assignable::value, "Error"); +static_assert(!std::is_assignable::value, "Error"); static_assert(std::is_assignable::value, "Error");