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]

[tree-ssa] fix Wswitch warnings


So I decided to go ahead and do this in c/c++ language specific code.

It turns out to be fantastically easier here than even in stmt.c, as
evidenced by diffstat:

 c-common.c                |  142 ++++++++++++++++
 stmt.c                    |  333 --------------------------------------

Previously we had large gyrations with bitmaps and enum scanning when
checking enum->case to achieve O(E+C) time, only to do nothing special
when checking case->enum, yielding O(C*E) time.

The new implemetation, worst case, is also O(C*E).  But in the common
case of no case ranges, we drop to O(E*lg(C)), and in the usual case
of monotonic enumerators, we get down to O(E+C).  We should do both
checks in the same time as the old code did one.

This is all due to the very nice properties of the splay tree that we
were already using to detect duplicates.

Another side effect of the new implemetation is that I generate the
proper line number for the "case value not in enumerated type" warnings.

If new languages are added to tree-ssa that support enumerations, then
we can see what might need doing to share data structures, but until
then it didn't seem worthwhile to be overly generic.


r~


        * c-common.c (match_case_to_enum_1, match_case_to_enum): New.
        (c_do_switch_warnings): New.
        * c-common.h (c_do_switch_warnings): Declare.
        * c-typeck.c (c_finish_case): Call it.
        * stmt.c (all_cases_count, BITARRAY_TEST, BITARRAY_SET,
        mark_seen_cases, check_for_full_enumeration_handling): Remove.
        (expand_end_case_type): Don't do warn_switch handling.
        * expr.h, tree.h: Remove dead decls.
cp/
        * decl.c (pop_switch): Call c_do_switch_warnings.
testsuite/
        * g++.dg/warn/Wswitch-1.C: Move "case value not in enumerated type"
        warning to the proper line.
        * gcc.dg/Wswitch-enum.c: Likewise.
        * gcc.dg/Wswitch.c: Likewise.

Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.344.2.46
diff -c -p -d -r1.344.2.46 c-common.c
*** c-common.c	30 Oct 2003 02:49:39 -0000	1.344.2.46
--- c-common.c	31 Oct 2003 07:03:49 -0000
*************** c_add_case_label (splay_tree cases, tree
*** 4026,4031 ****
--- 4026,4173 ----
    return error_mark_node;
  }
  
+ /* Subroutines of c_do_switch_warnings, called via splay_tree_foreach.
+    Used to verify that case values match up with enumerator values.  */
+ 
+ static void
+ match_case_to_enum_1 (tree key, tree type, tree label)
+ {
+   char buf[2 + 2*HOST_BITS_PER_WIDE_INT/4 + 1];
+ 
+   /* ??? Not working too hard to print the double-word value.
+      Should perhaps be done with %lwd in the diagnostic routines?  */
+   if (TREE_INT_CST_HIGH (key) == 0)
+     snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED,
+ 	      TREE_INT_CST_LOW (key));
+   else if (!TREE_UNSIGNED (type)
+ 	   && TREE_INT_CST_HIGH (key) == -1
+ 	   && TREE_INT_CST_LOW (key) != 0)
+     snprintf (buf, sizeof (buf), "-" HOST_WIDE_INT_PRINT_UNSIGNED,
+ 	      -TREE_INT_CST_LOW (key));
+   else
+     snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ 	      TREE_INT_CST_HIGH (key), TREE_INT_CST_LOW (key));
+ 
+   if (TYPE_NAME (type) == 0)
+     warning ("%Jcase value `%s' not in enumerated type",
+ 	     CASE_LABEL_DECL (label), buf);
+   else
+     warning ("%Jcase value `%s' not in enumerated type `%T'",
+ 	     CASE_LABEL_DECL (label), buf, type);
+ }
+ 
+ static int
+ match_case_to_enum (splay_tree_node node, void *data)
+ {
+   tree label = (tree) node->value;
+   tree type = data;
+ 
+   /* Skip default case.  */
+   if (!CASE_LOW (label))
+     return 0;
+ 
+   /* If TREE_ADDRESSABLE is not set, that means CASE_LOW did not appear
+      when we did our enum->case scan.  Reset our scratch bit after.  */
+   if (!TREE_ADDRESSABLE (label))
+     match_case_to_enum_1 (CASE_LOW (label), type, label);
+   else
+     TREE_ADDRESSABLE (label) = 0;
+ 
+   /* If CASE_HIGH is non-null, we have a range.  Here we must search.
+      Note that the old code in stmt.c did not check for the values in
+      the range either, just the endpoints.  */
+   if (CASE_HIGH (label))
+     {
+       tree chain, key = CASE_HIGH (label);
+ 
+       for (chain = TYPE_VALUES (type);
+ 	   chain && !tree_int_cst_equal (key, TREE_VALUE (chain));
+ 	   chain = TREE_CHAIN (chain))
+ 	continue;
+       if (!chain)
+ 	match_case_to_enum_1 (key, type, label);
+     }
+ 
+   return 0;
+ }
+ 
+ /* Handle -Wswitch*.  Called from the front end after parsing the switch
+    construct.  */
+ /* ??? Should probably be somewhere generic, since other languages besides
+    C and C++ would want this.  We'd want to agree on the datastructure,
+    however, which is a problem.  Alternately, we operate on gimplified
+    switch_exprs, which I don't especially like.  At the moment, however,
+    C/C++ are the only tree-ssa languages that support enumerations at all,
+    so the point is moot.  */
+ 
+ void
+ c_do_switch_warnings (splay_tree cases, tree switch_stmt)
+ {
+   splay_tree_node default_node;  
+   location_t switch_locus;
+   tree type;
+ 
+   if (!warn_switch && !warn_switch_enum && !warn_switch_default)
+     return;
+ 
+   switch_locus.file = input_filename;
+   switch_locus.line = STMT_LINENO (switch_stmt);
+   type = SWITCH_TYPE (switch_stmt);
+ 
+   default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
+   if (warn_switch_default && !default_node)
+     warning ("%Hswitch missing default case", &switch_locus);
+ 
+   /* If the switch expression was an enumerated type, check that
+      exactly all enumeration literals are covered by the cases.
+      The check is made when -Wswitch was specified and there is no
+      default case, or when -Wswitch-enum was specified.  */
+   if (((warn_switch && !default_node) || warn_switch_enum)
+       && type && TREE_CODE (type) == ENUMERAL_TYPE
+       && TREE_CODE (SWITCH_COND (switch_stmt)) != INTEGER_CST)
+     {
+       tree chain;
+ 
+       /* The time complexity here is O(N*lg(N)) worst case, but for the
+ 	 common case of monotonically increasing enumerators, it is 
+ 	 O(N), since the nature of the splay tree will keep the next
+ 	 element adjacent to the root at all times.  */
+ 
+       for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
+ 	{
+ 	  splay_tree_node node
+ 	    = splay_tree_lookup (cases, (splay_tree_key) TREE_VALUE (chain));
+ 
+ 	  if (node)
+ 	    {
+ 	      /* Mark the CASE_LOW part of the case entry as seen, so
+ 		 that we save time later.  Choose TREE_ADDRESSABLE 
+ 		 randomly as a bit that won't have been set to-date.  */
+ 	      tree label = (tree) node->value;
+ 	      TREE_ADDRESSABLE (label) = 1;
+ 	    }
+ 	  else
+ 	    {
+ 	      /* Warn if there are enumerators that don't correspond to
+ 		 case expressions.  */
+ 	      warning ("%Henumeration value `%E' not handled in switch",
+ 		       &switch_locus, TREE_PURPOSE (chain));
+ 	    }
+ 	}
+ 
+       /* Warn if there are case expressions that don't correspond to
+ 	 enumerators.  This can occur since C and C++ don't enforce
+ 	 type-checking of assignments to enumeration variables.
+ 
+ 	 The time complexity here is O(N**2) worst case, since we've
+ 	 not sorted the enumeration values.  However, in the absence
+ 	 of case ranges this is O(N), since all single cases that 
+ 	 corresponded to enumerations have been marked above.  */
+ 
+       splay_tree_foreach (cases, match_case_to_enum, type);
+     }
+ }
+ 
  /* Finish an expression taking the address of LABEL (an
     IDENTIFIER_NODE).  Returns an expression for the address.  */
  
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.141.2.36
diff -c -p -d -r1.141.2.36 c-common.h
*** c-common.h	25 Oct 2003 19:42:52 -0000	1.141.2.36
--- c-common.h	31 Oct 2003 07:03:50 -0000
*************** extern int case_compare (splay_tree_key,
*** 1242,1247 ****
--- 1242,1249 ----
  
  extern tree c_add_case_label (splay_tree, tree, tree, tree);
  
+ extern void c_do_switch_warnings (splay_tree, tree);
+ 
  extern tree build_function_call (tree, tree);
  
  extern tree finish_label_address_expr (tree);
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.196.2.30
diff -c -p -d -r1.196.2.30 c-typeck.c
*** c-typeck.c	28 Oct 2003 14:56:10 -0000	1.196.2.30
--- c-typeck.c	31 Oct 2003 07:03:50 -0000
*************** c_finish_case (void)
*** 6469,6474 ****
--- 6469,6477 ----
  {
    struct c_switch *cs = switch_stack;
  
+   /* Emit warnings as needed.  */
+   c_do_switch_warnings (cs->cases, cs->switch_stmt);
+ 
    /* Rechain the next statements to the SWITCH_STMT.  */
    last_tree = cs->switch_stmt;
  
Index: expr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.h,v
retrieving revision 1.117.2.18
diff -c -p -d -r1.117.2.18 expr.h
*** expr.h	6 Oct 2003 17:36:31 -0000	1.117.2.18
--- expr.h	31 Oct 2003 07:03:50 -0000
*************** extern void do_jump_by_parts_equality_rt
*** 783,790 ****
  extern void do_jump_by_parts_greater_rtx (enum machine_mode, int, rtx, rtx,
  					  rtx, rtx);
  
- extern void mark_seen_cases (tree, unsigned char *, HOST_WIDE_INT, int);
- 
  extern int vector_mode_valid_p (enum machine_mode);
  
  extern tree placeholder_list;
--- 783,788 ----
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.267.2.38
diff -c -p -d -r1.267.2.38 stmt.c
*** stmt.c	30 Oct 2003 02:49:40 -0000	1.267.2.38
--- stmt.c	31 Oct 2003 07:03:50 -0000
*************** add_case_node (tree low, tree high, tree
*** 4919,5244 ****
    return 0;
  }
  
- /* Returns the number of possible values of TYPE.
-    Returns -1 if the number is unknown, variable, or if the number does not
-    fit in a HOST_WIDE_INT.
-    Sets *SPARSENESS to 2 if TYPE is an ENUMERAL_TYPE whose values
-    do not increase monotonically (there may be duplicates);
-    to 1 if the values increase monotonically, but not always by 1;
-    otherwise sets it to 0.  */
- 
- HOST_WIDE_INT
- all_cases_count (tree type, int *sparseness)
- {
-   tree t;
-   HOST_WIDE_INT count, minval, lastval;
- 
-   *sparseness = 0;
- 
-   switch (TREE_CODE (type))
-     {
-     case BOOLEAN_TYPE:
-       count = 2;
-       break;
- 
-     case CHAR_TYPE:
-       count = 1 << BITS_PER_UNIT;
-       break;
- 
-     default:
-     case INTEGER_TYPE:
-       if (TYPE_MAX_VALUE (type) != 0
- 	  && 0 != (t = fold (build (MINUS_EXPR, type, TYPE_MAX_VALUE (type),
- 				    TYPE_MIN_VALUE (type))))
- 	  && 0 != (t = fold (build (PLUS_EXPR, type, t,
- 				    convert (type, integer_zero_node))))
- 	  && host_integerp (t, 1))
- 	count = tree_low_cst (t, 1);
-       else
- 	return -1;
-       break;
- 
-     case ENUMERAL_TYPE:
-       /* Don't waste time with enumeral types with huge values.  */
-       if (! host_integerp (TYPE_MIN_VALUE (type), 0)
- 	  || TYPE_MAX_VALUE (type) == 0
- 	  || ! host_integerp (TYPE_MAX_VALUE (type), 0))
- 	return -1;
- 
-       lastval = minval = tree_low_cst (TYPE_MIN_VALUE (type), 0);
-       count = 0;
- 
-       for (t = TYPE_VALUES (type); t != NULL_TREE; t = TREE_CHAIN (t))
- 	{
- 	  HOST_WIDE_INT thisval = tree_low_cst (TREE_VALUE (t), 0);
- 
- 	  if (*sparseness == 2 || thisval <= lastval)
- 	    *sparseness = 2;
- 	  else if (thisval != minval + count)
- 	    *sparseness = 1;
- 
- 	  lastval = thisval;
- 	  count++;
- 	}
-     }
- 
-   return count;
- }
- 
- #define BITARRAY_TEST(ARRAY, INDEX) \
-   ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
- 			  & (1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR)))
- #define BITARRAY_SET(ARRAY, INDEX) \
-   ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
- 			  |= 1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR))
- 
- /* Set the elements of the bitstring CASES_SEEN (which has length COUNT),
-    with the case values we have seen, assuming the case expression
-    has the given TYPE.
-    SPARSENESS is as determined by all_cases_count.
- 
-    The time needed is proportional to COUNT, unless
-    SPARSENESS is 2, in which case quadratic time is needed.  */
- 
- void
- mark_seen_cases (tree type, unsigned char *cases_seen, HOST_WIDE_INT count,
- 		 int sparseness)
- {
-   tree next_node_to_try = NULL_TREE;
-   HOST_WIDE_INT next_node_offset = 0;
- 
-   struct case_node *n, *root = case_stack->data.case_stmt.case_list;
-   tree val = make_node (INTEGER_CST);
- 
-   TREE_TYPE (val) = type;
-   if (! root)
-     /* Do nothing.  */
-     ;
-   else if (sparseness == 2)
-     {
-       tree t;
-       unsigned HOST_WIDE_INT xlo;
- 
-       /* This less efficient loop is only needed to handle
- 	 duplicate case values (multiple enum constants
- 	 with the same value).  */
-       TREE_TYPE (val) = TREE_TYPE (root->low);
-       for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
- 	   t = TREE_CHAIN (t), xlo++)
- 	{
- 	  TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (TREE_VALUE (t));
- 	  TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (TREE_VALUE (t));
- 	  n = root;
- 	  do
- 	    {
- 	      /* Keep going past elements distinctly greater than VAL.  */
- 	      if (tree_int_cst_lt (val, n->low))
- 		n = n->left;
- 
- 	      /* or distinctly less than VAL.  */
- 	      else if (tree_int_cst_lt (n->high, val))
- 		n = n->right;
- 
- 	      else
- 		{
- 		  /* We have found a matching range.  */
- 		  BITARRAY_SET (cases_seen, xlo);
- 		  break;
- 		}
- 	    }
- 	  while (n);
- 	}
-     }
-   else
-     {
-       if (root->left)
- 	case_stack->data.case_stmt.case_list = root = case_tree2list (root, 0);
- 
-       for (n = root; n; n = n->right)
- 	{
- 	  TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
- 	  TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
- 	  while (! tree_int_cst_lt (n->high, val))
- 	    {
- 	      /* Calculate (into xlo) the "offset" of the integer (val).
- 		 The element with lowest value has offset 0, the next smallest
- 		 element has offset 1, etc.  */
- 
- 	      unsigned HOST_WIDE_INT xlo;
- 	      HOST_WIDE_INT xhi;
- 	      tree t;
- 
- 	      if (sparseness && TYPE_VALUES (type) != NULL_TREE)
- 		{
- 		  /* The TYPE_VALUES will be in increasing order, so
- 		     starting searching where we last ended.  */
- 		  t = next_node_to_try;
- 		  xlo = next_node_offset;
- 		  xhi = 0;
- 		  for (;;)
- 		    {
- 		      if (t == NULL_TREE)
- 			{
- 			  t = TYPE_VALUES (type);
- 			  xlo = 0;
- 			}
- 		      if (tree_int_cst_equal (val, TREE_VALUE (t)))
- 			{
- 			  next_node_to_try = TREE_CHAIN (t);
- 			  next_node_offset = xlo + 1;
- 			  break;
- 			}
- 		      xlo++;
- 		      t = TREE_CHAIN (t);
- 		      if (t == next_node_to_try)
- 			{
- 			  xlo = -1;
- 			  break;
- 			}
- 		    }
- 		}
- 	      else
- 		{
- 		  t = TYPE_MIN_VALUE (type);
- 		  if (t)
- 		    neg_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t),
- 				&xlo, &xhi);
- 		  else
- 		    xlo = xhi = 0;
- 		  add_double (xlo, xhi,
- 			      TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
- 			      &xlo, &xhi);
- 		}
- 
- 	      if (xhi == 0 && xlo < (unsigned HOST_WIDE_INT) count)
- 		BITARRAY_SET (cases_seen, xlo);
- 
- 	      add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
- 			  1, 0,
- 			  &TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
- 	    }
- 	}
-     }
- }
- 
- /* Given a switch statement with an expression that is an enumeration
-    type, warn if any of the enumeration type's literals are not
-    covered by the case expressions of the switch.  Also, warn if there
-    are any extra switch cases that are *not* elements of the
-    enumerated type.
- 
-    Historical note:
- 
-    At one stage this function would: ``If all enumeration literals
-    were covered by the case expressions, turn one of the expressions
-    into the default expression since it should not be possible to fall
-    through such a switch.''
- 
-    That code has since been removed as: ``This optimization is
-    disabled because it causes valid programs to fail.  ANSI C does not
-    guarantee that an expression with enum type will have a value that
-    is the same as one of the enumeration literals.''  */
- 
- void
- check_for_full_enumeration_handling (tree type)
- {
-   struct case_node *n;
-   tree chain;
- 
-   /* True iff the selector type is a numbered set mode.  */
-   int sparseness = 0;
- 
-   /* The number of possible selector values.  */
-   HOST_WIDE_INT size;
- 
-   /* For each possible selector value. a one iff it has been matched
-      by a case value alternative.  */
-   unsigned char *cases_seen;
- 
-   /* The allocated size of cases_seen, in chars.  */
-   HOST_WIDE_INT bytes_needed;
- 
-   size = all_cases_count (type, &sparseness);
-   bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
- 
-   if (size > 0 && size < 600000
-       /* We deliberately use calloc here, not cmalloc, so that we can suppress
- 	 this optimization if we don't have enough memory rather than
- 	 aborting, as xmalloc would do.  */
-       && (cases_seen = really_call_calloc (bytes_needed, 1)) != NULL)
-     {
-       HOST_WIDE_INT i;
-       tree v = TYPE_VALUES (type);
- 
-       /* The time complexity of this code is normally O(N), where
- 	 N being the number of members in the enumerated type.
- 	 However, if type is an ENUMERAL_TYPE whose values do not
- 	 increase monotonically, O(N*log(N)) time may be needed.  */
- 
-       mark_seen_cases (type, cases_seen, size, sparseness);
- 
-       for (i = 0; v != NULL_TREE && i < size; i++, v = TREE_CHAIN (v))
- 	if (BITARRAY_TEST (cases_seen, i) == 0)
- 	  warning ("enumeration value `%s' not handled in switch",
- 		   IDENTIFIER_POINTER (TREE_PURPOSE (v)));
- 
-       free (cases_seen);
-     }
- 
-   /* Now we go the other way around; we warn if there are case
-      expressions that don't correspond to enumerators.  This can
-      occur since C and C++ don't enforce type-checking of
-      assignments to enumeration variables.  */
- 
-   if (case_stack->data.case_stmt.case_list
-       && case_stack->data.case_stmt.case_list->left)
-     case_stack->data.case_stmt.case_list
-       = case_tree2list (case_stack->data.case_stmt.case_list, 0);
-   for (n = case_stack->data.case_stmt.case_list; n; n = n->right)
-     {
-       for (chain = TYPE_VALUES (type);
- 	   chain && !tree_int_cst_equal (n->low, TREE_VALUE (chain));
- 	   chain = TREE_CHAIN (chain))
- 	;
- 
-       if (!chain)
- 	{
- 	  if (TYPE_NAME (type) == 0)
- 	    warning ("case value `%ld' not in enumerated type",
- 		     (long) TREE_INT_CST_LOW (n->low));
- 	  else
- 	    warning ("case value `%ld' not in enumerated type `%s'",
- 		     (long) TREE_INT_CST_LOW (n->low),
- 		     IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
- 					  == IDENTIFIER_NODE)
- 					 ? TYPE_NAME (type)
- 					 : DECL_NAME (TYPE_NAME (type))));
- 	}
-       if (!tree_int_cst_equal (n->low, n->high))
- 	{
- 	  for (chain = TYPE_VALUES (type);
- 	       chain && !tree_int_cst_equal (n->high, TREE_VALUE (chain));
- 	       chain = TREE_CHAIN (chain))
- 	    ;
- 
- 	  if (!chain)
- 	    {
- 	      if (TYPE_NAME (type) == 0)
- 		warning ("case value `%ld' not in enumerated type",
- 			 (long) TREE_INT_CST_LOW (n->high));
- 	      else
- 		warning ("case value `%ld' not in enumerated type `%s'",
- 			 (long) TREE_INT_CST_LOW (n->high),
- 			 IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
- 					      == IDENTIFIER_NODE)
- 					     ? TYPE_NAME (type)
- 					     : DECL_NAME (TYPE_NAME (type))));
- 	    }
- 	}
-     }
- }
- 
- 
  /* Maximum number of case bit tests.  */
  #define MAX_CASE_BIT_TESTS  3
  
--- 4919,4924 ----
*************** expand_end_case_type (tree orig_index, t
*** 5433,5451 ****
    /* An ERROR_MARK occurs for various reasons including invalid data type.  */
    if (index_type != error_mark_node)
      {
-       /* If the switch expression was an enumerated type, check that
- 	 exactly all enumeration literals are covered by the cases.
- 	 The check is made when -Wswitch was specified and there is no
- 	 default case, or when -Wswitch-enum was specified.  */
-       if (((warn_switch && !thiscase->data.case_stmt.default_label)
- 	   || warn_switch_enum)
- 	  && TREE_CODE (orig_type) == ENUMERAL_TYPE
- 	  && TREE_CODE (index_expr) != INTEGER_CST)
- 	check_for_full_enumeration_handling (orig_type);
- 
-       if (warn_switch_default && !thiscase->data.case_stmt.default_label)
- 	warning ("switch missing default case");
- 
        /* If we don't have a default-label, create one here,
  	 after the body of the switch.  */
        if (thiscase->data.case_stmt.default_label == 0)
--- 5113,5118 ----
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.119
diff -c -p -d -r1.342.2.119 tree.h
*** tree.h	30 Oct 2003 02:49:41 -0000	1.342.2.119
--- tree.h	31 Oct 2003 07:03:50 -0000
*************** extern int expand_decl_cleanup (tree, tr
*** 3436,3443 ****
  extern int expand_decl_cleanup_eh (tree, tree, int);
  extern void expand_anon_union_decl (tree, tree, tree);
  extern void expand_start_case_dummy (void);
- extern HOST_WIDE_INT all_cases_count (tree, int *);
- extern void check_for_full_enumeration_handling (tree);
  extern void declare_nonlocal_label (tree);
  extern int containing_blocks_have_cleanups_or_stack_level (void);
  
--- 3436,3441 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.911.2.53
diff -c -p -d -r1.911.2.53 decl.c
*** cp/decl.c	28 Oct 2003 14:58:00 -0000	1.911.2.53
--- cp/decl.c	31 Oct 2003 07:03:51 -0000
*************** push_switch (tree switch_stmt)
*** 2408,2416 ****
  void
  pop_switch (void)
  {
!   struct cp_switch *cs;
  
-   cs = switch_stack;
    splay_tree_delete (cs->cases);
    switch_stack = switch_stack->next;
    free (cs);
--- 2408,2418 ----
  void
  pop_switch (void)
  {
!   struct cp_switch *cs = switch_stack;
! 
!   /* Emit warnings as needed.  */
!   c_do_switch_warnings (cs->cases, cs->switch_stmt);
  
    splay_tree_delete (cs->cases);
    switch_stack = switch_stack->next;
    free (cs);
Index: testsuite/g++.dg/warn/Wswitch-1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/warn/Wswitch-1.C,v
retrieving revision 1.1.18.2
diff -c -p -d -r1.1.18.2 Wswitch-1.C
*** testsuite/g++.dg/warn/Wswitch-1.C	27 May 2003 22:33:19 -0000	1.1.18.2
--- testsuite/g++.dg/warn/Wswitch-1.C	31 Oct 2003 07:03:51 -0000
*************** foo (int i, int j, enum e ei, enum e ej,
*** 46,56 ****
      case e2: return 2;
      default: break;
      }
!   switch (eo) /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3;
      }
    switch (ep)
      {
--- 46,56 ----
      case e2: return 2;
      default: break;
      }
!   switch (eo)
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      }
    switch (ep)
      {
Index: testsuite/gcc.dg/Wswitch-enum.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/Wswitch-enum.c,v
retrieving revision 1.1.12.2
diff -c -p -d -r1.1.12.2 Wswitch-enum.c
*** testsuite/gcc.dg/Wswitch-enum.c	26 May 2003 20:09:15 -0000	1.1.12.2
--- testsuite/gcc.dg/Wswitch-enum.c	31 Oct 2003 07:03:52 -0000
*************** foo (int i, int j, enum e ei, enum e ej,
*** 46,62 ****
      case e2: return 2;
      default: break;
      }
!   switch (eo) /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3;
      }
!   switch (ep) /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3;
      default: break;
      }
    return 0;
--- 46,62 ----
      case e2: return 2;
      default: break;
      }
!   switch (eo)
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      }
!   switch (ep)
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      default: break;
      }
    return 0;
Index: testsuite/gcc.dg/Wswitch.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/Wswitch.c,v
retrieving revision 1.2.18.2
diff -c -p -d -r1.2.18.2 Wswitch.c
*** testsuite/gcc.dg/Wswitch.c	26 May 2003 20:09:15 -0000	1.2.18.2
--- testsuite/gcc.dg/Wswitch.c	31 Oct 2003 07:03:52 -0000
*************** foo (int i, int j, enum e ei, enum e ej,
*** 46,56 ****
      case e2: return 2;
      default: break;
      }
!   switch (eo) /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3;
      }
    switch (ep)
      {
--- 46,56 ----
      case e2: return 2;
      default: break;
      }
!   switch (eo)
      {
      case e1: return 1;
      case e2: return 2;
!     case 3: return 3; /* { dg-warning "case value `3' not in enumerated type `e'" "excess 3" } */
      }
    switch (ep)
      {


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