Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -9142,9 +9142,9 @@ return; case NK_Type_Narrowing: - // This was a floating-to-integer conversion, which is always considered a - // narrowing conversion even if the value is a constant and can be - // represented exactly as an integer. + // This was a floating-to-integer conversion or a boolean conversion from a + // pointer, which is always considered a narrowing conversion even if the + // value is a constant and can be represented exactly as an integer. S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_type_narrowing : diag::warn_init_list_type_narrowing) Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -314,8 +314,8 @@ if (FromType->isIntegralOrUnscopedEnumerationType()) goto IntegralConversion; // Boolean conversions can be from pointers and pointers to members - // [conv.bool], and those aren't considered narrowing conversions. - return NK_Not_Narrowing; + // [conv.bool], which are considered narrowing conversions. + return NK_Type_Narrowing; // -- from a floating-point type to an integer type, or // Index: test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp =================================================================== --- test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp +++ test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp @@ -19,6 +19,7 @@ int ii = {2.0}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} float f1 { x }; // expected-error {{ cannot be narrowed }} expected-note {{silence}} float f2 { 7 }; // OK: 7 can be exactly represented as a float + bool b = {"meow"}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} int f(int); int a[] = { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level @@ -143,7 +144,7 @@ // cannot represent all the values of the original type, except where the // source is a constant expression and the actual value after conversion will // fit into the target type and will produce the original value when converted -// back to the original type. +// back to the original type, or void shrink_int() { // Not a constant expression. short s = 1; @@ -180,10 +181,6 @@ Agg b2 = {1}; // OK Agg b3 = {-1}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} - // Conversions from pointers to booleans aren't narrowing conversions. - Agg* ptr = &b1; - Agg b = {ptr}; // OK - Agg ce1 = { Convert(100000) }; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} expected-note {{silence}} expected-warning {{changes value from 100000 to -31072}} Agg ce2 = { ConvertVar() }; // expected-error {{non-constant-expression cannot be narrowed from type 'short' to 'char'}} expected-note {{silence}} @@ -202,6 +199,20 @@ unsigned short usc3 = { (signed char)-1 }; // expected-error {{ -1 which cannot be narrowed}} expected-note {{silence}} } +// * from a pointer type or a pointer-to-member type to bool. +void pointer_to_bool() { + Agg obj; + Agg *p1 = &obj; + constexpr void *p2 = nullptr; + + Agg b1 = {p1}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + Agg b2 = {p2}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + Agg b3 = {&Agg::t}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + + Agg b4 = {ConvertVar()}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + Agg b5 = {ConvertVar::*>()}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} +} + // Be sure that type- and value-dependent expressions in templates get the error // too. Index: test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp =================================================================== --- test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp +++ test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp @@ -20,6 +20,7 @@ int ii = {2.0}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} float f1 { x }; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} float f2 { 7 }; // OK: 7 can be exactly represented as a float + bool b = {"meow"}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} int f(int); int a[] = { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level @@ -131,7 +132,7 @@ // cannot represent all the values of the original type, except where the // source is a constant expression and the actual value after conversion will // fit into the target type and will produce the original value when converted -// back to the original type. +// back to the original type, or void shrink_int() { // Not a constant expression. short s = 1; @@ -163,14 +164,24 @@ Agg b2 = {1}; // OK Agg b3 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} - // Conversions from pointers to booleans aren't narrowing conversions. - Agg* ptr = &b1; - Agg b = {ptr}; // OK - Agg ce1 = { Convert(100000) }; // expected-warning {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} expected-note {{silence}} expected-warning {{changes value from 100000 to -31072}} Agg ce2 = { ConvertVar() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'short' to 'char'}} expected-note {{silence}} } +// * from a pointer type or a pointer-to-member type to bool. +void pointer_to_bool() { + Agg obj; + Agg *p1 = &obj; + constexpr void *p2 = nullptr; + + Agg b1 = {p1}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + Agg b2 = {p2}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + Agg b3 = {&Agg::t}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + + Agg b4 = {ConvertVar()}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + Agg b5 = {ConvertVar::*>()}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} +} + // Be sure that type- and value-dependent expressions in templates get the warning // too.