This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PR c++/20008, middle-end] handle switch with all cases out-of-range


Sure enough, the testcase relied on undefined behavior, but that's no
reason for us to ICE at compile time.  I suppose it might be nice to
get the tree cfg cleanup code to detect that it can discard cases that
are out of range, but I'm not all that familiar with the cfg cleanup
code, so I figured I'd try this first.

Ok to install if regression testing passes on x86_64-linux-gnu?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/20008
	* stmt.c (expand_case): Don't assume cleanup_tree_cfg will remove
	cases that are out-of-range for the index type.

Index: gcc/stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.412
diff -u -p -r1.412 stmt.c
--- gcc/stmt.c 13 Dec 2004 16:03:38 -0000 1.412
+++ gcc/stmt.c 17 Feb 2005 16:12:31 -0000
@@ -1,6 +1,7 @@
 /* Expands front end tree to back end RTL for GCC
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+     Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -2393,8 +2394,14 @@ expand_case (tree exp)
       BITMAP_XFREE (label_bitmap);
 
       /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
-	 destination, such as one with a default case only.  */
-      gcc_assert (count != 0);
+	 destination, such as one with a default case only.  However,
+	 it doesn't remove cases that are out of range for the switch
+	 type, so we may still get a zero here.  */
+      if (count == 0)
+	{
+	  emit_jump (default_label);
+	  return;
+	}
 
       /* Compute span of values.  */
       range = fold (build2 (MINUS_EXPR, index_type, maxval, minval));
Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/20008
	* g++.dg/opt/switch3.C: New.

Index: gcc/testsuite/g++.dg/opt/switch3.C
===================================================================
RCS file: gcc/testsuite/g++.dg/opt/switch3.C
diff -N gcc/testsuite/g++.dg/opt/switch3.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/opt/switch3.C 17 Feb 2005 16:12:45 -0000
@@ -0,0 +1,30 @@
+// { dg-do compile }
+
+// PR c++/20008
+
+// We failed to compile this because CFG cleanup left the switch
+// statement intact, whereas expand_case expected at least one
+// in-range case to remain.
+
+typedef enum _SECStatus {
+  SECWouldBlock = -2,
+  SECFailure = -1,
+  SECSuccess = 0
+} SECStatus;
+
+typedef enum {
+  SEC_ERROR_BAD_SIGNATURE = (-0x2000) + 10
+} SECErrorCodes;
+
+void g(void);
+void f(SECStatus status)
+{
+  switch( status )
+    {
+    case SEC_ERROR_BAD_SIGNATURE :
+      // This case can be optimized away in C++ (but apparently not in
+      // C), because the enum type is defined with a narrow range.
+      g();
+      break ;
+    }
+}
-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]