===================================================================
@@ -1311,15 +1311,15 @@ 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
|| TYPE_PTRMEM_P (from)
- || NULLPTR_TYPE_P (from))
+ || (NULLPTR_TYPE_P (from) && !(flags & LOOKUP_ONLYCONVERTING)))
{
conv = build_conv (ck_std, to, conv);
if (fcode == POINTER_TYPE
@@ -2056,7 +2056,10 @@ add_function_candidate (struct z_candidate **candi
&& BRACE_ENCLOSED_INITIALIZER_P (arg))
lflags |= LOOKUP_NO_CONVERSION;
}
- else
+ /* Per 8.5/16, certainly the initialization that occurs in
+ base initializers is direct-initialization, thus don't
+ set the flag in that case. */
+ else if (!(cfun && cp_function_chain && in_base_initializer))
lflags |= LOOKUP_ONLYCONVERTING;
t = implicit_conversion (parmtype, argtype, arg,
===================================================================
@@ -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 "no matching" }
decltype(nullptr) mynull = 0;
- type_equal<bool>(i(mynull));
+ type_equal<bool>(i(mynull)); // { dg-error "no matching" }
}
===================================================================
@@ -0,0 +1,11 @@
+// DR 1423, PR c++/52174
+// { dg-do compile { target c++11 } }
+
+bool b1 = nullptr; // { dg-error "cannot convert" }
+
+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" }
===================================================================
@@ -0,0 +1,30 @@
+// DR 1423, PR c++/52174
+// { dg-do compile { target c++11 } }
+
+struct Base
+{
+ Base(bool);
+};
+
+struct Derived
+: Base
+{
+ Derived()
+ : Base(nullptr) { }
+};
+
+template<typename>
+struct TBase
+{
+ TBase(bool);
+};
+
+template<typename T>
+struct TDerived
+: TBase<T>
+{
+ TDerived()
+ : TBase<T>(nullptr) { }
+};
+
+template class TDerived<int>;
===================================================================
@@ -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, "");
===================================================================
@@ -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");