Hi,

On 06/03/2014 05:41 PM, Jason Merrill wrote:
On 06/03/2014 11:24 AM, Paolo Carlini wrote:
+      if (NULLPTR_TYPE_P (from) && (flags & LOOKUP_ONLYCONVERTING))
+        conv->bad_p = true;

Thanks. What kind of error message do we get with this change? Would adding something to convert_like_real provide a more helpful diagnostic?
We get the default:

invalid conversion from ‘std::nullptr_t’ to ‘bool’ [-fpermissive]

Maybe something like the below then?!?

Thanks,
Paolo.

/////////////////////
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c       (revision 211162)
+++ gcc/cp/call.c       (working copy)
@@ -1311,10 +1311,10 @@ standard_conversion (tree to, tree from, tree expr
     {
       /* [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
                  && 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, t
            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)
Index: gcc/testsuite/g++.dg/cpp0x/nullptr17.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/nullptr17.C      (revision 211162)
+++ gcc/testsuite/g++.dg/cpp0x/nullptr17.C      (working copy)
@@ -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 <typename T, typename U> struct tType_equal;
 template <typename T> struct tType_equal<T, T> { typedef void type; };
@@ -16,7 +17,7 @@ bool i( bool );
 void test_i()
 {
   // Overload to bool, not int
-  type_equal<bool>(i(nullptr));
+  type_equal<bool>(i(nullptr));  // { dg-error "direct" }
   decltype(nullptr) mynull = 0;
-  type_equal<bool>(i(mynull));
+  type_equal<bool>(i(mynull));   // { dg-error "direct" }
 }
Index: gcc/testsuite/g++.dg/cpp0x/nullptr31.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/nullptr31.C      (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/nullptr31.C      (working copy)
@@ -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" }
Index: gcc/testsuite/g++.dg/cpp0x/sfinae-nullptr1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/sfinae-nullptr1.C        (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/sfinae-nullptr1.C        (working copy)
@@ -0,0 +1,18 @@
+// DR 1423, PR c++/52174
+// { dg-do compile { target c++11 } }
+
+template<class T>
+T&& make();
+
+template<class T>
+void sink(T);
+
+template<class T1, class T2,
+  class = decltype(sink<T2>(make<T1>()))
+>
+auto f(int) -> char(&)[1];
+
+template<class, class>
+auto f(...) -> char(&)[2];
+
+static_assert(sizeof(f<decltype(nullptr), bool>(0)) != 1, "");
Index: libstdc++-v3/testsuite/20_util/is_assignable/value.cc
===================================================================
--- libstdc++-v3/testsuite/20_util/is_assignable/value.cc       (revision 
211151)
+++ libstdc++-v3/testsuite/20_util/is_assignable/value.cc       (working copy)
@@ -174,7 +174,7 @@ static_assert(!std::is_assignable<bool&, SE>::valu
 static_assert(std::is_assignable<bool&, void*>::value, "Error");
 static_assert(std::is_assignable<bool&, int B::*>::value, "Error");
 static_assert(std::is_assignable<bool&, void*>::value, "Error");
-static_assert(std::is_assignable<bool&, std::nullptr_t>::value, "Error");
+static_assert(!std::is_assignable<bool&, std::nullptr_t>::value, "Error");
 
 static_assert(std::is_assignable<std::nullptr_t&,
 std::nullptr_t>::value, "Error");

Reply via email to