Fix excess warnings from -Wtype-limits with location wrappers (PR c++/88680)
authorDavid Malcolm <dmalcolm@redhat.com>
Sat, 16 Feb 2019 16:17:17 +0000 (16:17 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Sat, 16 Feb 2019 16:17:17 +0000 (16:17 +0000)
PR c++/88680 reports excess warnings from -Wtype-limits after the C++
FE's use of location wrappers was extended in r267272 for cases such as:

  const unsigned n = 8;
  static_assert (n >= 0 && n % 2 == 0, "");

t.C:3:18: warning: comparison of unsigned expression >= 0 is always true
  [-Wtype-limits]
    3 | static_assert (n >= 0 && n % 2 == 0, "");
      |                ~~^~~~

The root cause is that the location wrapper around "n" breaks the
suppression of the warning for the "if OP0 is a constant that is >= 0"
case.

This patch fixes it by calling fold_for_warn on OP0, extracting the
constant.

gcc/c-family/ChangeLog:
PR c++/88680
* c-common.c (shorten_compare): Call fold_for_warn on op0 when
implementing -Wtype-limits.

gcc/testsuite/ChangeLog:
PR c++/88680
* g++.dg/wrappers/pr88680.C: New test.

From-SVN: r268961

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/wrappers/pr88680.C [new file with mode: 0644]

index 7dae7bf530a88a23d4e49d1174746b773a93cd73..ed8026a33e098eed12567a745a61f8cddcbd2a75 100644 (file)
@@ -1,3 +1,9 @@
+2019-02-16  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/88680
+       * c-common.c (shorten_compare): Call fold_for_warn on op0 when
+       implementing -Wtype-limits.
+
 2019-02-11  Martin Sebor  <msebor@redhat.com>
 
        PR c++/87996
index ae23e59f65244be167569a51feced84903278231..c6856c9ad103402d12e784d498a995fffdc2af9f 100644 (file)
@@ -3117,6 +3117,12 @@ shorten_compare (location_t loc, tree *op0_ptr, tree *op1_ptr,
       primop0 = op0;
       primop1 = op1;
 
+      /* We want to fold unsigned comparisons of >= and < against zero.
+        For these, we may also issue a warning if we have a non-constant
+        compared against zero, where the zero was spelled as "0" (rather
+        than merely folding to it).
+        If we have at least one constant, then op1 is constant
+        and we may have a non-constant expression as op0.  */
       if (!real1 && !real2 && integer_zerop (primop1)
          && TYPE_UNSIGNED (*restype_ptr))
        {
@@ -3125,13 +3131,14 @@ shorten_compare (location_t loc, tree *op0_ptr, tree *op1_ptr,
             if OP0 is a constant that is >= 0, the signedness of
             the comparison isn't an issue, so suppress the
             warning.  */
+         tree folded_op0 = fold_for_warn (op0);
          bool warn = 
            warn_type_limits && !in_system_header_at (loc)
-           && !(TREE_CODE (primop0) == INTEGER_CST
+           && !(TREE_CODE (folded_op0) == INTEGER_CST
                 && !TREE_OVERFLOW (convert (c_common_signed_type (type),
-                                            primop0)))
+                                            folded_op0)))
            /* Do not warn for enumeration types.  */
-           && (TREE_CODE (expr_original_type (primop0)) != ENUMERAL_TYPE);
+           && (TREE_CODE (expr_original_type (folded_op0)) != ENUMERAL_TYPE);
          
          switch (code)
            {
index e68f969bcb277e65b57633e0306e1971533c53f2..45fbe7c0296ab34d52705c87989888bd3de17806 100644 (file)
@@ -1,3 +1,8 @@
+2019-02-16  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/88680
+       * g++.dg/wrappers/pr88680.C: New test.
+
 2019-02-17  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        PR fortran/71066
diff --git a/gcc/testsuite/g++.dg/wrappers/pr88680.C b/gcc/testsuite/g++.dg/wrappers/pr88680.C
new file mode 100644 (file)
index 0000000..5497cda
--- /dev/null
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wtype-limits" }
+
+const unsigned N = 8;
+const unsigned P = 0;
+
+enum { FOO, BAR };
+
+static_assert (N >= 0 && N % 2 == 0, "");
+static_assert (FOO >= 0, "");
+static_assert (FOO >= FOO, "");
+static_assert (FOO >= P, "");
+static_assert (BAR >= P, "");
+static_assert (N >= FOO, "");
+
+void test(unsigned n)
+{
+  if (N >= 0 && N % 2 == 0)
+    return;
+  if (FOO >= 0)
+    return;
+  if (FOO >= FOO)
+    return;
+  if (FOO >= P)
+    return;
+  if (BAR >= P)
+    return;
+  if (N >= FOO)
+    return;
+  if (n >= 0) // { dg-warning ">= 0 is always true" }
+    return;
+  if (n < 0) // { dg-warning "< 0 is always false" }
+    return;
+  if (n >= FOO)
+    return;
+  if (n < FOO)
+    return;
+  if (N >= 0)
+    return;
+  if (N < 0)
+    return;
+  if (N >= FOO)
+    return;
+  if (N < FOO)
+    return;
+  if (0 <= FOO)
+    return;
+  if (0 <= n) // { dg-warning ">= 0 is always true" }
+    return;
+  if (0 > n) // { dg-warning "< 0 is always false" }
+    return;
+  if (N <= FOO)
+    return;
+  if (N <= n)
+    return;
+}