[RFC] PR middle-end/179 gcc -O2 -Wuninitialized missing warning with &var

Richard Guenther richard.guenther@gmail.com
Mon Aug 11 14:54:00 GMT 2008


On Mon, Aug 11, 2008 at 3:15 PM, Manuel López-Ibáñez
<lopezibanez@gmail.com> wrote:
> This is an initial attempt to handle VOPs in -Wuninitialized. Taking
> the address of a variable messes up uninitialized warnings because
> VOPs are completely ignored. The following patch tries to detect one
> particular case [http://gcc.gnu.org/ml/gcc/2007-08/msg00273.html]:
>
> extern void foo (int *);
> extern void bar (int);
>
> void
> baz (void)
> {
>  int i;
>  if (i) /* { dg-warning "uninit" "uninit i warning" { xfail *-*-* } } */
>    bar (i);
>  foo (&i);
> }
>
> For this example we create something like:
>
> baz (void) {
>  intD.0 iD.1283;
>  intD.0 i.0D.1284;
>
>  # BLOCK 0, starting at line 7
>  # PRED: ENTRY (fallthru)
>  #   VUSE <iD.1283_1>;
>  i.0D.1284_2 = iD.1283;
>
>
> And that is exactly what the new code tries to detect. I try hard to
> ignore every other case because they generate false positives while
> bootstrapping.
>
> Any comments? Can we do this better? Can the new code give false positives?

I think it is useful - however

+  if (TYPE_MODE (TREE_TYPE (var)) == BLKmode)
+    return false;
+
+  if (is_call_clobbered (var))
+    {
+      var_ann_t va = var_ann (var);
+      unsigned int escape_mask = va->escape_mask;
+      if (escape_mask & ESCAPE_TO_ASM)
+	return false;
+      if (escape_mask & ESCAPE_IS_GLOBAL)
+	return false;
+      if (escape_mask & ESCAPE_IS_PARM)
+	return false;
+    }

this should be not necessary at all (in fact I believe just excluding
PARM_DECLs and is_global_var should be enough).

Also the following

   if (!ssa_undefined_value_p (t))
-    return;
+    {
+      /*struct voptype_d *vdefs;*/
+      struct voptype_d *vuses;
+      /* Recurse into SSA virtual operands to check whether T is using
+	 a VDEF with default definition or it is VUSing another
+	 uninitialized variable.  */
+      gimple def = SSA_NAME_DEF_STMT (t);
+      tree op;

-  /* TREE_NO_WARNING either means we already warned, or the front end
-     wishes to suppress the warning.  */
-  if (TREE_NO_WARNING (var))
+      if (!gimple_references_memory_p (def))
+	return;
+
+      vuses = gimple_vuse_ops (def);
+      while (vuses)
+	{
+	  int i, n;

just should use

   def_stmt = SSA_NAME_DEF_STMT (t);
   FOR_EACH_SSA_USE_OPERAND (..., def_stmt, ..., SSA_OP_VIRTUAL_USES)
       if (ssa_maybe_uninitialized_var_p (SSA_NAME_VAR (USE_FROM_PTR (use)))
         warn ...

note that there may be false positives from like

int  *p, *q;

int foo (int b)
{
  int i, j = 0;
  int *x;
  p = &i;
  q = &j;
  if (b)
    x = &p;
  else
    x = &q;
  return *x;
}

if you pass in false only it will warn because *x may access
uninitialized i.  So in the end you may want to omit warnings
from defining load statements that load via a pointer.  Note
that using VOPs only works for the late uninitialized pass
(aliasing is not computed before).  Note also that using VOPs
is unreliable due to partitioning, etc., a better way is to iterate
over the LOADED_SYMS bitmap of the defining statement
(doesn't work for calls!) - this would work for the early pass as well.

Richard.



More information about the Gcc-patches mailing list