]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/101573 - improve uninit warning at -O0
authorRichard Biener <rguenther@suse.de>
Thu, 22 Jul 2021 10:26:16 +0000 (12:26 +0200)
committerRichard Biener <rguenther@suse.de>
Tue, 27 Jul 2021 08:46:22 +0000 (10:46 +0200)
We can improve uninit warnings from the early pass by looking
at PHI arguments on fallthru edges that are uninitialized and
have uses that are before a possible loop exit.  This catches
some cases earlier that we'd only warn in a more confusing
way after early inlining as seen by testcase adjustments.

It introduces

FAIL: gcc.dg/uninit-23.c (test for excess errors)

where we additionally warn

gcc.dg/uninit-23.c:21:13: warning: 't4' is used uninitialized [-Wuninitialized]

which I think is OK even if it's not obvious that the new
warning is an improvement when you look at the obvious source.

Somehow for all cases I never get the `'foo' was declared here`
notes, I didn't dig why that happens but it's odd.

2021-07-22  Richard Biener  <rguenther@suse.de>

PR tree-optimization/101573
* tree-ssa-uninit.c (warn_uninit_phi_uses): New function
looking at uninitialized PHI arg defs in some constrained cases.
(warn_uninitialized_vars): Call it.
(execute_early_warn_uninitialized): Calculate dominators.

* gcc.dg/uninit-pr101573.c: New testcase.
* gcc.dg/uninit-15-O0.c: Adjust.
* gcc.dg/uninit-15.c: Likewise.
* gcc.dg/uninit-23.c: Likewise.
* c-c++-common/uninit-17.c: Likewise.

gcc/testsuite/c-c++-common/uninit-17.c
gcc/testsuite/gcc.dg/uninit-15-O0.c
gcc/testsuite/gcc.dg/uninit-15.c
gcc/testsuite/gcc.dg/uninit-23.c
gcc/testsuite/gcc.dg/uninit-pr101573.c [new file with mode: 0644]
gcc/tree-ssa-uninit.c

index fd773da78ad3019a11a99e336a30a691082b64e1..b5495366c5bc20aefdea8e6251fd30f48abf4a98 100644 (file)
@@ -9,11 +9,11 @@ static void bar(int a, int *ptr)
 {
   do
   {
-    int b;   /* { dg-message "declared" } */
+    int b;
     if (b < 40) {
-      ptr[0] = b; /* { dg-warning "may be used uninitialized" } */
+      ptr[0] = b;
     }
-    b += 1;
+    b += 1; /* { dg-warning "is used uninitialized" } */
     ptr++;
   }
   while (--a != 0);
index a3fd2b63ba71f416cfda3d877f1bc26c6c68a09b..36d963486175ba7353e7f9bb85cea6ccf9bdb935 100644 (file)
@@ -15,6 +15,6 @@ void baz();
 void bar()
 {
     int j;           /* { dg-message "was declared here" {} { xfail *-*-* } } */
-    for (; foo(j); ++j)
+    for (; foo(j); ++j) /* { dg-warning "is used uninitialized" } */
         baz();
 }
index 8ee10c27aba17cde00a37a51039011d9e4084036..85cb116f349458466d8a09f3565f95f01cf13a3e 100644 (file)
@@ -1,7 +1,7 @@
 /* PR tree-optimization/17506
-   We issue an uninitialized variable warning at a wrong location at
+   We used to issue an uninitialized variable warning at a wrong location at
    line 11, which is very confusing.  Make sure we print out a note to
-   make it less confusing.  (not xfailed alternative)
+   make it less confusing.  (xfailed alternative)
    But it is of course ok if we warn in bar about uninitialized use
    of j.  (not xfailed alternative)  */
 /* { dg-do compile } */
@@ -10,7 +10,7 @@
 inline int
 foo (int i)
 {
-  if (i) /* { dg-warning "used uninitialized" } */
+  if (i) /* { dg-warning "used uninitialized" "" { xfail *-*-* } } */
     return 1;
   return 0;
 }
@@ -20,7 +20,7 @@ void baz (void);
 void
 bar (void)
 {
-  int j; /* { dg-message "note: 'j' was declared here" "" } */
-  for (; foo (j); ++j)  /* { dg-warning "'j' is used uninitialized" "" { xfail *-*-* } } */
+  int j; /* { dg-message "note: 'j' was declared here" "" { xfail *-*-* } } */
+  for (; foo (j); ++j)  /* { dg-warning "'j' is used uninitialized" } */
     baz ();
 }
index d64eb7d2ee9c893e80aaa112c0adbf61a68c392d..87b4e989b5370a9fc3c4e4690e93dac7a85a682a 100644 (file)
@@ -18,7 +18,7 @@ ql (void)
         int *t4 = go; /* { dg-warning "is used uninitialized" } */
 
  l1:
-        *t4 = (*t4 != 0) ? 0 : 2;
+        *t4 = (*t4 != 0) ? 0 : 2; /* { dg-warning "is used uninitialized" } */
       }
 
     if (ij != 0)
diff --git a/gcc/testsuite/gcc.dg/uninit-pr101573.c b/gcc/testsuite/gcc.dg/uninit-pr101573.c
new file mode 100644 (file)
index 0000000..a574844
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -Wuninitialized" } */
+
+int main(int argc, char **argv)
+{
+  int a;
+  for(; a < 5; ++a) /* { dg-warning "is used uninitialized" } */
+    ;
+  return  0;
+}
index 148f3c2b31dda9a310298d762215f39e29854e34..718b32691c1ac2614cc4cf96a20e4e897209166d 100644 (file)
@@ -638,6 +638,76 @@ maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims)
   wlims.always_executed = save_always_executed;
 }
 
+/* Warn about an uninitialized PHI argument on the fallthru path to
+   an always executed block BB.  */
+
+static void
+warn_uninit_phi_uses (basic_block bb)
+{
+  edge_iterator ei;
+  edge e, found = NULL, found_back = NULL;
+  /* Look for a fallthru and possibly a single backedge.  */
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    {
+      /* Ignore backedges.  */
+      if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
+       {
+         if (found_back)
+           {
+             found = NULL;
+             break;
+           }
+         found_back = e;
+         continue;
+       }
+      if (found)
+       {
+         found = NULL;
+         break;
+       }
+      found = e;
+    }
+  if (!found)
+    return;
+
+  basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+  for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
+       gsi_next (&si))
+    {
+      gphi *phi = si.phi ();
+      tree def = PHI_ARG_DEF_FROM_EDGE (phi, found);
+      if (TREE_CODE (def) != SSA_NAME
+         || !SSA_NAME_IS_DEFAULT_DEF (def)
+         || virtual_operand_p (def))
+       continue;
+      /* If there's a default def on the fallthru edge PHI
+        value and there's a use that post-dominates entry
+        then that use is uninitialized and we can warn.  */
+      imm_use_iterator iter;
+      use_operand_p use_p;
+      gimple *use_stmt = NULL;
+      FOR_EACH_IMM_USE_FAST (use_p, iter, gimple_phi_result (phi))
+       {
+         use_stmt = USE_STMT (use_p);
+         if (gimple_location (use_stmt) != UNKNOWN_LOCATION
+             && dominated_by_p (CDI_POST_DOMINATORS, succ,
+                                gimple_bb (use_stmt))
+             /* If we found a non-fallthru edge make sure the
+                use is inside the loop, otherwise the backedge
+                can serve as initialization.  */
+             && (!found_back
+                 || dominated_by_p (CDI_DOMINATORS, found_back->src,
+                                    gimple_bb (use_stmt))))
+           break;
+         use_stmt = NULL;
+       }
+      if (use_stmt)
+       warn_uninit (OPT_Wuninitialized, def, SSA_NAME_VAR (def),
+                    SSA_NAME_VAR (def),
+                    "%qD is used uninitialized", use_stmt,
+                    UNKNOWN_LOCATION);
+    }
+}
 
 static unsigned int
 warn_uninitialized_vars (bool wmaybe_uninit)
@@ -652,6 +722,10 @@ warn_uninitialized_vars (bool wmaybe_uninit)
     {
       basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
       wlims.always_executed = dominated_by_p (CDI_POST_DOMINATORS, succ, bb);
+
+      if (wlims.always_executed)
+       warn_uninit_phi_uses (bb);
+
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          gimple *stmt = gsi_stmt (gsi);
@@ -3135,6 +3209,7 @@ execute_early_warn_uninitialized (void)
      optimization we want to warn about possible uninitialized as late
      as possible, thus don't do it here.  However, without
      optimization we need to warn here about "may be uninitialized".  */
+  calculate_dominance_info (CDI_DOMINATORS);
   calculate_dominance_info (CDI_POST_DOMINATORS);
 
   warn_uninitialized_vars (/*warn_maybe_uninitialized=*/!optimize);