We weren't complaining about narrowing when converting to bool because standard_conversion wasn't setting check_narrowing for the converting to bool case; it only sets it at the end of the function. Moreover, check_narrowing wasn't catching real_type -> boolean_type at all, which is wrong; [dcl.init.list] says that a narrowing conversion is an implicit conversion from a floating-point type to an integer type, and bool is an integer type.
Bootstrapped/regtested on x86_64-linux, ok for trunk? 2018-08-14 Marek Polacek <pola...@redhat.com> PR c++/65043 * call.c (standard_conversion): Set check_narrowing. * typeck2.c (check_narrowing): Use CP_INTEGRAL_TYPE_P rather than comparing with INTEGER_TYPE. * g++.dg/concepts/pr67595.C: Add dg-warning. * g++.dg/cpp0x/Wnarrowing11.C: New test. * g++.dg/cpp0x/Wnarrowing12.C: New test. * g++.dg/cpp0x/rv-cast5.C: Add static_cast. diff --git gcc/cp/call.c gcc/cp/call.c index 62654a9e407..ded279a0f43 100644 --- gcc/cp/call.c +++ gcc/cp/call.c @@ -1387,6 +1387,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, conv->rank = cr_pbool; if (NULLPTR_TYPE_P (from) && (flags & LOOKUP_ONLYCONVERTING)) conv->bad_p = true; + if (flags & LOOKUP_NO_NARROWING) + conv->check_narrowing = true; return conv; } diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c index 674d08762b5..b521f79e8c3 100644 --- gcc/cp/typeck2.c +++ gcc/cp/typeck2.c @@ -912,7 +912,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain, bool const_only) if (const_only && !TREE_CONSTANT (init)) return ok; - if (TREE_CODE (type) == INTEGER_TYPE + if (CP_INTEGRAL_TYPE_P (type) && TREE_CODE (ftype) == REAL_TYPE) ok = false; else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype) diff --git gcc/testsuite/g++.dg/concepts/pr67595.C gcc/testsuite/g++.dg/concepts/pr67595.C index 63162fb4c72..76d1fe62132 100644 --- gcc/testsuite/g++.dg/concepts/pr67595.C +++ gcc/testsuite/g++.dg/concepts/pr67595.C @@ -4,7 +4,7 @@ template <class X> concept bool allocatable = requires{{new X}->X * }; template <class X> concept bool semiregular = allocatable<X>; template <class X> concept bool readable = requires{requires semiregular<X>}; template <class> int weak_input_iterator = requires{{0}->readable}; -template <class X> bool input_iterator{weak_input_iterator<X>}; +template <class X> bool input_iterator{weak_input_iterator<X>}; // { dg-warning "narrowing conversion" } template <class X> bool forward_iterator{input_iterator<X>}; template <class X> bool bidirectional_iterator{forward_iterator<X>}; template <class X> diff --git gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C index e69de29bb2d..5b7323633c7 100644 --- gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C +++ gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C @@ -0,0 +1,30 @@ +// PR c++/65043 +// { dg-do compile { target c++11 } } + +struct X +{ + X(bool) { } +}; + +struct Y +{ + Y(char) { } +}; + +struct Z +{ + Z(char16_t) { } +}; + +struct W +{ + W(char32_t) { } +}; + +int main() +{ + X x{1.2}; // { dg-error "narrowing conversion" } + Y y{1.2}; // { dg-error "narrowing conversion" } + Z z{1.2}; // { dg-error "narrowing conversion" } + W w{1.2}; // { dg-error "narrowing conversion" } +} diff --git gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C index e69de29bb2d..83b4d3a58c6 100644 --- gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C +++ gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C @@ -0,0 +1,32 @@ +// PR c++/65043 +// { dg-do compile { target c++11 } } +// { dg-options "-Wnarrowing" } + +struct X +{ + X(bool) { } +}; + +struct Y +{ + Y(char) { } +}; + +struct Z +{ + Z(char16_t) { } +}; + +struct W +{ + W(char32_t) { } +}; + +int main() +{ + double d = 1.2; + X x{d}; // { dg-warning "narrowing conversion" } + Y y{d}; // { dg-warning "narrowing conversion" } + Z z{d}; // { dg-warning "narrowing conversion" } + W w{d}; // { dg-warning "narrowing conversion" } +} diff --git gcc/testsuite/g++.dg/cpp0x/rv-cast5.C gcc/testsuite/g++.dg/cpp0x/rv-cast5.C index c2473e266b6..5233078f7b4 100644 --- gcc/testsuite/g++.dg/cpp0x/rv-cast5.C +++ gcc/testsuite/g++.dg/cpp0x/rv-cast5.C @@ -8,5 +8,5 @@ struct hold { int main() { - hold<bool&&>{42}(); + hold<bool&&>{static_cast<bool>(42)}(); }