PR c++/90805 - detect narrowing in case values.
authorMarek Polacek <polacek@redhat.com>
Thu, 1 Aug 2019 16:27:04 +0000 (16:27 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Thu, 1 Aug 2019 16:27:04 +0000 (16:27 +0000)
* 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
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr89888.c
gcc/testsuite/g++.dg/cpp0x/Wnarrowing17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/enum28.C

index f374636..9a6c2e3 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-01  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/90805 - detect narrowing in case values.
+       * decl.c (case_conversion): Detect narrowing in case values.
+
 2019-07-31  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * decl2.c (delete_sanity): Improve diagnostic locations, use
index 9fa090c..c8b9e3b 100644 (file)
@@ -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);
 }
 
index 8b0365a..d16e123 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-01  Marek Polacek  <polacek@redhat.com>
+
+       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  <wdijkstr@arm.com>
 
        * gcc/testsuite/g++.dg/lto/pr89330_0.C: Add effective-target shared.
index d9e11d6..f14881c 100644 (file)
@@ -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 (file)
index 0000000..064de53
--- /dev/null
@@ -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." }
+}
index 3967699..bfebde5 100644 (file)
@@ -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" }
     }
 }