From f339eb66071559a02a0c05b3ee89fc8352969bc9 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 1 Aug 2019 16:27:04 +0000 Subject: [PATCH] PR c++/90805 - detect narrowing in case values. * decl.c (case_conversion): Detect narrowing in case values. * c-c++-common/pr89888.c: Update expected dg-error. * g++.dg/cpp0x/Wnarrowing17.C: New test. * g++.dg/cpp0x/enum28.C: Update expected dg-error. From-SVN: r273976 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/decl.c | 23 +++++++++++++++-------- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/c-c++-common/pr89888.c | 4 ++-- gcc/testsuite/g++.dg/cpp0x/Wnarrowing17.C | 19 +++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/enum28.C | 4 ++-- 6 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wnarrowing17.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f374636ed27..9a6c2e30e7f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2019-08-01 Marek Polacek + + PR c++/90805 - detect narrowing in case values. + * decl.c (case_conversion): Detect narrowing in case values. + 2019-07-31 Paolo Carlini * decl2.c (delete_sanity): Improve diagnostic locations, use diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 9fa090c8767..c8b9e3b8fb9 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3631,16 +3631,23 @@ case_conversion (tree type, tree value) value = mark_rvalue_use (value); + if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type)) + type = type_promotes_to (type); + + tree ovalue = value; + /* The constant-expression VALUE shall be a converted constant expression + of the adjusted type of the switch condition, which doesn't allow + narrowing conversions. */ + value = build_converted_constant_expr (type, value, tf_warning_or_error); + if (cxx_dialect >= cxx11 && (SCOPED_ENUM_P (type) - || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value)))) - { - if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type)) - type = type_promotes_to (type); - value = (perform_implicit_conversion_flags - (type, value, tf_warning_or_error, - LOOKUP_IMPLICIT | LOOKUP_NO_NON_INTEGRAL)); - } + || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (ovalue)))) + /* Use the converted value. */; + else + /* The already integral case. */ + value = ovalue; + return cxx_constant_value (value); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8b0365a43b2..d16e123d61a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-08-01 Marek Polacek + + PR c++/90805 - detect narrowing in case values. + * c-c++-common/pr89888.c: Update expected dg-error. + * g++.dg/cpp0x/Wnarrowing17.C: New test. + * g++.dg/cpp0x/enum28.C: Update expected dg-error. + 2019-08-01 Wilco Dijkstra * gcc/testsuite/g++.dg/lto/pr89330_0.C: Add effective-target shared. diff --git a/gcc/testsuite/c-c++-common/pr89888.c b/gcc/testsuite/c-c++-common/pr89888.c index d9e11d6f26a..f14881ca052 100644 --- a/gcc/testsuite/c-c++-common/pr89888.c +++ b/gcc/testsuite/c-c++-common/pr89888.c @@ -11,8 +11,8 @@ foo (unsigned char x) { case -1: y = -1; break; /* { dg-message "previously used here" } */ /* { dg-warning "case label value is less than minimum value for type" "" { target *-*-* } .-1 } */ - case 0xffffffff: y = 0xffffffff; break; /* { dg-error "duplicate case value" } */ - case ~0U: y = ~0U; break; /* { dg-error "duplicate case value" } */ + case 0xffffffff: y = 0xffffffff; break; /* { dg-error "duplicate case value|narrowing" } */ + case ~0U: y = ~0U; break; /* { dg-error "duplicate case value|narrowing" } */ } } diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing17.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing17.C new file mode 100644 index 00000000000..064de531cb3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing17.C @@ -0,0 +1,19 @@ +// PR c++/90805 - detect narrowing in case values. +// { dg-do compile { target c++11 } } + +void f(int i, char c, unsigned u) +{ + switch (i) + { + case 2149056512u:; // { dg-error "narrowing conversion of .2149056512. from .unsigned int. to .int." } + case (long long int) 1e10:; // { dg-error "narrowing conversion of .10000000000. from .long long int. to .int." } + // { dg-warning "overflow in conversion" "overflow" { target *-*-* } .-1 } + } + + switch (c) + // No narrowing, the adjusted type is int. + case 300:; // { dg-warning "exceeds maximum value for type" } + + switch (u) + case -42:; // { dg-error "narrowing conversion of .-42. from .int. to .unsigned int." } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/enum28.C b/gcc/testsuite/g++.dg/cpp0x/enum28.C index 3967699dd03..bfebde57cb3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum28.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum28.C @@ -7,11 +7,11 @@ void f(int i) { switch (i) { - case 1.0:; // { dg-error "could not convert" } + case 1.0:; // { dg-error "could not convert|conversion from" } } switch (i) { - case g():; // { dg-error "could not convert" } + case g():; // { dg-error "could not convert|conversion from" } } } -- 2.30.2