lichray created this revision. lichray added reviewers: rsmith, EricWF. lichray added a project: clang. Herald added a subscriber: cfe-commits.
This change implements an upcoming Core issue to categorize boolean conversions from pointer and pointer-to-member as (always) narrowing conversion (you can tell the wording from this diff). MSVC does it slightly differently, for example, array-to-pointer conversion isn't applied before the test -- suspected a bug. Repository: rC Clang https://reviews.llvm.org/D64034 Files: lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp
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<bool> b2 = {1}; // OK Agg<bool> b3 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} - // Conversions from pointers to booleans aren't narrowing conversions. - Agg<bool>* ptr = &b1; - Agg<bool> b = {ptr}; // OK - Agg<short> ce1 = { Convert<int>(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<char> ce2 = { ConvertVar<short>() }; // 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<int> obj; + Agg<int> *p1 = &obj; + constexpr void *p2 = nullptr; + + Agg<bool> b1 = {p1}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + Agg<bool> b2 = {p2}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + Agg<bool> b3 = {&Agg<int>::t}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + + Agg<bool> b4 = {ConvertVar<int *>()}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} + Agg<bool> b5 = {ConvertVar<int Agg<int>::*>()}; // expected-warning {{ cannot be narrowed }} expected-note {{silence}} +} + // Be sure that type- and value-dependent expressions in templates get the warning // too. 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<bool> b2 = {1}; // OK Agg<bool> b3 = {-1}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} - // Conversions from pointers to booleans aren't narrowing conversions. - Agg<bool>* ptr = &b1; - Agg<bool> b = {ptr}; // OK - Agg<short> ce1 = { Convert<int>(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<char> ce2 = { ConvertVar<short>() }; // 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<int> obj; + Agg<int> *p1 = &obj; + constexpr void *p2 = nullptr; + + Agg<bool> b1 = {p1}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + Agg<bool> b2 = {p2}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + Agg<bool> b3 = {&Agg<int>::t}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + + Agg<bool> b4 = {ConvertVar<int *>()}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} + Agg<bool> b5 = {ConvertVar<int Agg<int>::*>()}; // expected-error {{ cannot be narrowed }} expected-note {{silence}} +} + // Be sure that type- and value-dependent expressions in templates get the error // too. 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: 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)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits