From 32f579f6ebde02d94ac8fbd0379b1d0207dd9ac5 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Tue, 5 May 2009 23:09:16 +0200
Subject: [PATCH] re PR middle-end/39666 (spurious warning with ranged-switch
 statements)

	PR middle-end/39666
	* gimplify.c (gimplify_switch_expr): If case labels cover the whole
	range of the type, but default label is missing, add it with one
	of the existing labels instead of adding a new label for it.

	* gcc.dg/pr39666-1.c: New test.
	* gcc.dg/pr39666-2.c: Likewise.
	* g++.dg/warn/Wuninitialized-4.C: Likewise.
	* g++.dg/warn/Wuninitialized-5.C: Likewise.
	* gfortran.dg/pr39666-1.f90: Likewise.
	* gfortran.dg/pr39666-2.f90: Likewise.

From-SVN: r147136
---
 gcc/ChangeLog                                |  5 ++
 gcc/gimplify.c                               | 61 +++++++++++++++++---
 gcc/testsuite/ChangeLog                      | 10 ++++
 gcc/testsuite/g++.dg/warn/Wuninitialized-4.C | 22 +++++++
 gcc/testsuite/g++.dg/warn/Wuninitialized-5.C | 22 +++++++
 gcc/testsuite/gcc.dg/pr39666-1.c             | 22 +++++++
 gcc/testsuite/gcc.dg/pr39666-2.c             | 22 +++++++
 gcc/testsuite/gfortran.dg/pr39666-1.f90      | 14 +++++
 gcc/testsuite/gfortran.dg/pr39666-2.f90      | 14 +++++
 9 files changed, 183 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wuninitialized-4.C
 create mode 100644 gcc/testsuite/g++.dg/warn/Wuninitialized-5.C
 create mode 100644 gcc/testsuite/gcc.dg/pr39666-1.c
 create mode 100644 gcc/testsuite/gcc.dg/pr39666-2.c
 create mode 100644 gcc/testsuite/gfortran.dg/pr39666-1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/pr39666-2.f90

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a4271b052ace..9ab24dbad9e0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -12,6 +12,11 @@
 	(gen_variable_die): Likewise.  Check TREE_PRIVATE/TREE_PROTECTED
 	unconditionally.
 
+	PR middle-end/39666
+	* gimplify.c (gimplify_switch_expr): If case labels cover the whole
+	range of the type, but default label is missing, add it with one
+	of the existing labels instead of adding a new label for it.
+
 2009-05-05  Joseph Myers  <joseph@codesourcery.com>
 
 	* dwarf.h: Remove.
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 0909d3173689..0c33dab479af 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1604,20 +1604,63 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
 	}
       len = i;
 
+      if (!VEC_empty (tree, labels))
+	sort_case_labels (labels);
+
       if (!default_case)
 	{
-	  gimple new_default;
+	  tree type = TREE_TYPE (switch_expr);
 
 	  /* If the switch has no default label, add one, so that we jump
-	     around the switch body.  */
-	  default_case = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
-	                         NULL_TREE, create_artificial_label ());
-	  new_default = gimple_build_label (CASE_LABEL (default_case));
-	  gimplify_seq_add_stmt (&switch_body_seq, new_default);
-	}
+	     around the switch body.  If the labels already cover the whole
+	     range of type, add the default label pointing to one of the
+	     existing labels.  */
+	  if (type == void_type_node)
+	    type = TREE_TYPE (SWITCH_COND (switch_expr));
+	  if (len
+	      && INTEGRAL_TYPE_P (type)
+	      && TYPE_MIN_VALUE (type)
+	      && TYPE_MAX_VALUE (type)
+	      && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)),
+				     TYPE_MIN_VALUE (type)))
+	    {
+	      tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1));
+	      if (!high)
+		high = CASE_LOW (VEC_index (tree, labels, len - 1));
+	      if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type)))
+		{
+		  for (i = 1; i < len; i++)
+		    {
+		      high = CASE_LOW (VEC_index (tree, labels, i));
+		      low = CASE_HIGH (VEC_index (tree, labels, i - 1));
+		      if (!low)
+			low = CASE_LOW (VEC_index (tree, labels, i - 1));
+		      if ((TREE_INT_CST_LOW (low) + 1
+			   != TREE_INT_CST_LOW (high))
+			  || (TREE_INT_CST_HIGH (low)
+			      + (TREE_INT_CST_LOW (high) == 0)
+			      != TREE_INT_CST_HIGH (high)))
+			break;
+		    }
+		  if (i == len)
+		    default_case = build3 (CASE_LABEL_EXPR, void_type_node,
+					   NULL_TREE, NULL_TREE,
+					   CASE_LABEL (VEC_index (tree,
+								  labels, 0)));
+		}
+	    }
 
-      if (!VEC_empty (tree, labels))
-	sort_case_labels (labels);
+	  if (!default_case)
+	    {
+	      gimple new_default;
+
+	      default_case = build3 (CASE_LABEL_EXPR, void_type_node,
+				     NULL_TREE, NULL_TREE,
+				     create_artificial_label ());
+	      new_default = gimple_build_label (CASE_LABEL (default_case));
+	      gimplify_seq_add_stmt (&switch_body_seq, new_default);
+	    }
+	}
 
       gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr), 
                                                default_case, labels);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 376e4682cbe8..e5a6e5e2549a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2009-05-05  Jakub Jelinek  <jakub@redhat.com>
+
+	PR middle-end/39666
+	* gcc.dg/pr39666-1.c: New test.
+	* gcc.dg/pr39666-2.c: Likewise.
+	* g++.dg/warn/Wuninitialized-4.C: Likewise.
+	* g++.dg/warn/Wuninitialized-5.C: Likewise.
+	* gfortran.dg/pr39666-1.f90: Likewise.
+	* gfortran.dg/pr39666-2.f90: Likewise.
+
 2009-05-05  Adam Nemet  <anemet@caviumnetworks.com>
 
 	* gcc.target/mips/mips.exp: Add -mtune= to mips_option_groups.
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-4.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-4.C
new file mode 100644
index 000000000000..3d2543fb1758
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-4.C
@@ -0,0 +1,22 @@
+// PR middle-end/39666
+// { dg-do compile }
+// { dg-options "-O2 -Wuninitialized" }
+
+int
+foo (int i)
+{
+  int j;
+  switch (i)
+    {
+    case -__INT_MAX__ - 1 ... -1:
+      j = 6;
+      break;
+    case 0:
+      j = 5;
+      break;
+    case 1 ... __INT_MAX__:
+      j = 4;
+      break;
+    }
+  return j;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-5.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-5.C
new file mode 100644
index 000000000000..26add34945f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-5.C
@@ -0,0 +1,22 @@
+// PR middle-end/39666
+// { dg-do compile }
+// { dg-options "-O2 -Wuninitialized" }
+
+int
+foo (int i)
+{
+  int j;	// { dg-warning "may be used uninitialized" }
+  switch (i)
+    {
+    case -__INT_MAX__ - 1 ... -1:
+      j = 6;
+      break;
+    case 0:
+      j = 5;
+      break;
+    case 2 ... __INT_MAX__:
+      j = 4;
+      break;
+    }
+  return j;
+}
diff --git a/gcc/testsuite/gcc.dg/pr39666-1.c b/gcc/testsuite/gcc.dg/pr39666-1.c
new file mode 100644
index 000000000000..f1ba499c3311
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr39666-1.c
@@ -0,0 +1,22 @@
+/* PR middle-end/39666 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized" } */
+
+int
+foo (int i)
+{
+  int j;
+  switch (i)
+    {
+    case -__INT_MAX__ - 1 ... -1:
+      j = 6;
+      break;
+    case 0:
+      j = 5;
+      break;
+    case 1 ... __INT_MAX__:
+      j = 4;
+      break;
+    }
+  return j;
+}
diff --git a/gcc/testsuite/gcc.dg/pr39666-2.c b/gcc/testsuite/gcc.dg/pr39666-2.c
new file mode 100644
index 000000000000..e4ef1d5d2b72
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr39666-2.c
@@ -0,0 +1,22 @@
+/* PR middle-end/39666 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized" } */
+
+int
+foo (int i)
+{
+  int j;	/* { dg-warning "may be used uninitialized" } */
+  switch (i)
+    {
+    case -__INT_MAX__ - 1 ... -1:
+      j = 6;
+      break;
+    case 0:
+      j = 5;
+      break;
+    case 2 ... __INT_MAX__:
+      j = 4;
+      break;
+    }
+  return j;
+}
diff --git a/gcc/testsuite/gfortran.dg/pr39666-1.f90 b/gcc/testsuite/gfortran.dg/pr39666-1.f90
new file mode 100644
index 000000000000..31840ec1df82
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr39666-1.f90
@@ -0,0 +1,14 @@
+! PR middle-end/39666
+! { dg-do compile }
+! { dg-options "-O2 -Wuninitialized" }
+
+FUNCTION f(n)
+  INTEGER, INTENT(in) :: n
+  REAL                :: f
+
+  SELECT CASE (n)
+    CASE (:-1); f = -1.0
+    CASE (0);   f =  0.0
+    CASE (1:);  f =  1.0
+  END SELECT
+END FUNCTION
diff --git a/gcc/testsuite/gfortran.dg/pr39666-2.f90 b/gcc/testsuite/gfortran.dg/pr39666-2.f90
new file mode 100644
index 000000000000..720a716ae315
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr39666-2.f90
@@ -0,0 +1,14 @@
+! PR middle-end/39666
+! { dg-do compile }
+! { dg-options "-O2 -Wuninitialized" }
+
+FUNCTION f(n)	! { dg-warning "may be used uninitialized" }
+  INTEGER, INTENT(in) :: n
+  REAL                :: f
+
+  SELECT CASE (n)
+    CASE (:-1); f = -1.0
+    CASE (0);   f =  0.0
+    CASE (2:);  f =  1.0
+  END SELECT
+END FUNCTION
-- 
GitLab