Fix PR2972

Message ID alpine.LSU.2.20.1704211244470.24645@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener April 21, 2017, 10:45 a.m.
This adds handling of uninitialized uses of members in constructors
to the uninit warning machinery.

Bootstrap and regtest on x86_64-unknown-linux-gnu in progress together
with a bootstrap fix to the pass_manager.

Richard.

2017-04-21  Richard Biener  <rguenther@suse.de>

	PR c++/2972
	* tree-ssa-uninit.c (warn_uninitialized_vars): Handle some
	pointer-based references.

	* g++.dg/warn/Wuninitialized-10.C: New testcase.

Patch

Index: gcc/tree-ssa-uninit.c
===================================================================
--- gcc/tree-ssa-uninit.c	(revision 247049)
+++ gcc/tree-ssa-uninit.c	(working copy)
@@ -279,20 +279,22 @@  warn_uninitialized_vars (bool warn_possi
 	      ao_ref ref;
 	      ao_ref_init (&ref, rhs);
 
-	      /* Do not warn if it can be initialized outside this function.  */
+	      /* Do not warn if the base was marked so or this is a
+	         hard register var.  */
 	      tree base = ao_ref_base (&ref);
-	      if (!VAR_P (base)
-		  || DECL_HARD_REGISTER (base)
-		  || is_global_var (base)
+	      if ((VAR_P (base)
+		   && DECL_HARD_REGISTER (base))
 		  || TREE_NO_WARNING (base))
 		continue;
 
 	      /* Do not warn if the access is fully outside of the
 	         variable.  */
-	      if (ref.size != -1
+	      if (DECL_P (base)
+		  && ref.size != -1
 		  && ref.max_size == ref.size
 		  && (ref.offset + ref.size <= 0
 		      || (ref.offset >= 0
+			  && DECL_SIZE (base)
 			  && TREE_CODE (DECL_SIZE (base)) == INTEGER_CST
 			  && compare_tree_int (DECL_SIZE (base),
 					       ref.offset) <= 0)))
@@ -305,11 +307,12 @@  warn_uninitialized_vars (bool warn_possi
 		  && oracle_cnt > vdef_cnt * 2)
 		limit = 32;
 	      check_defs_data data;
+	      bool fentry_reached = false;
 	      data.found_may_defs = false;
 	      use = gimple_vuse (stmt);
 	      int res = walk_aliased_vdefs (&ref, use,
 					    check_defs, &data, NULL,
-					    NULL, limit);
+					    &fentry_reached, limit);
 	      if (res == -1)
 		{
 		  oracle_cnt += limit;
@@ -318,6 +321,16 @@  warn_uninitialized_vars (bool warn_possi
 	      oracle_cnt += res;
 	      if (data.found_may_defs)
 		continue;
+	      /* Do not warn if it can be initialized outside this function.
+	         If we did not reach function entry then we found killing
+		 clobbers on all paths to entry.  */
+	      if (fentry_reached
+		  /* ???  We'd like to use ref_may_alias_global_p but that
+		     excludes global readonly memory and thus we get bougs
+		     warnings from p = cond ? "a" : "b" for example.  */
+		  && (!VAR_P (base)
+		      || is_global_var (base)))
+		continue;
 
 	      /* We didn't find any may-defs so on all paths either
 	         reached function entry or a killing clobber.  */
Index: gcc/testsuite/g++.dg/warn/Wuninitialized-10.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wuninitialized-10.C	(nonexistent)
+++ gcc/testsuite/g++.dg/warn/Wuninitialized-10.C	(working copy)
@@ -0,0 +1,14 @@ 
+// { dg-do compile }
+// { dg-options "-Wuninitialized" }
+
+struct A
+{
+  int f,g;
+
+  A()
+    {
+      f = g; // { dg-warning "g. is used uninitialized" }
+    }
+};
+
+A a;