This is the mail archive of the gcc@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]

-Wswitch-default -Wswitch-enum ...


Hello,

(as already reported -Wswitch is broken)

Attached is a work-in-progress patch for adding options:

-Wswitch-default
	warn when there is no ``default:'' case in the switch.
	Works.

-Wswitch-enum
	warn when there is a missing enum case, regardless of
	the presence or otherwise of a default clause.
	Broken by existing -Wswitch I think.

If these are basicly ok, I'll come up with proper patches (tweeking the 
doco takes a while).

Now, about -Wswitch-fallthrough (warn of fallthrough switches) .... :-)


Andrew
2002-01-12  Andrew Cagney  <ac131313@redhat.com>

	* toplev.c (W_options): Add -Wswitch-enum and -Wswitch-default.
	Update comment on -Wswitch.
	(warn_switch_default, warn_switch_enum): Define variables.
	* flags.h (warn_switch_default, warn_switch_enum): Declare
	variables.

	* stmt.c (check_for_full_enumeration_handling): Remove tests of
	warn_switch.  Update description.
	(expand_end_case): Call check_for_full_enumeration_handling when
	warn_switch and no default or warn_switch_enum.
	(expand_end_case): Check for and, when warn_switch_no_default,
	warn of a missing default case.
	
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.76
diff -p -r1.76 flags.h
*** flags.h	2002/01/10 18:51:14	1.76
--- flags.h	2002/01/13 00:30:09
*************** extern int warn_unknown_pragmas;
*** 126,134 ****
  
  extern int warn_shadow;
  
! /* Warn if a switch on an enum fails to have a case for every enum value.  */
  
  extern int warn_switch;
  
  /* Nonzero means warn about function definitions that default the return type
     or that use a null return and have a return-type other than void.  */
--- 126,144 ----
  
  extern int warn_shadow;
  
! /* Warn if a switch on an enum that does not have a default case fails
!    to have a case for every enum value.  */
  
  extern int warn_switch;
+ 
+ /* Warn if a switch does not have a default case.  */
+ 
+ extern int warn_switch_default;
+ 
+ /* Warn if a switch on an enum fails to have a case for every enum
+    value (regardless of the presence or otherwise of a default case).  */
+ 
+ extern int warn_switch_enum;
  
  /* Nonzero means warn about function definitions that default the return type
     or that use a null return and have a return-type other than void.  */
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.242
diff -p -r1.242 stmt.c
*** stmt.c	2002/01/04 21:03:18	1.242
--- stmt.c	2002/01/13 00:30:22
*************** mark_seen_cases (type, cases_seen, count
*** 5225,5241 ****
      }
  }
  
! /* Called when the index of a switch statement is an enumerated type
!    and there is no default label.
  
     Checks that all enumeration literals are covered by the case
     expressions of a switch.  Also, warn if there are any extra
     switch cases that are *not* elements of the enumerated type.
  
!    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.  */
  
  void
  check_for_full_enumeration_handling (type)
       tree type;
--- 5225,5249 ----
      }
  }
  
! /* Called when the index of a switch statement is an enumerated type.
  
     Checks that all enumeration literals are covered by the case
     expressions of a switch.  Also, warn if there are any extra
     switch cases that are *not* elements of the enumerated type.
  
!    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 since:
+ 
+      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 (type)
       tree type;
*************** check_for_full_enumeration_handling (typ
*** 5256,5263 ****
    /* The allocated size of cases_seen, in chars.  */
    HOST_WIDE_INT bytes_needed;
  
!   if (! warn_switch)
!     return;
  
    size = all_cases_count (type, &sparseness);
    bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
--- 5264,5270 ----
    /* The allocated size of cases_seen, in chars.  */
    HOST_WIDE_INT bytes_needed;
  
!   /* assert (warn_switch || warn_switch_enum).  */
  
    size = all_cases_count (type, &sparseness);
    bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
*************** check_for_full_enumeration_handling (typ
*** 5296,5344 ****
        && 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);
!   if (warn_switch)
!     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))));
! 	      }
! 	  }
!       }
  }
  
  /* Free CN, and its children.  */
--- 5303,5350 ----
        && 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))));
! 	    }
! 	}
!     }
  }
  
  /* Free CN, and its children.  */
*************** expand_end_case (orig_index)
*** 5402,5415 ****
    /* An ERROR_MARK occurs for various reasons including invalid data type.  */
    if (index_type != error_mark_node)
      {
!       /* If switch expression was an enumerated type, check that all
! 	 enumeration literals are covered by the cases.
! 	 No sense trying this if there's a default case, however.  */
! 
!       if (!thiscase->data.case_stmt.default_label
  	  && TREE_CODE (TREE_TYPE (orig_index)) == ENUMERAL_TYPE
  	  && TREE_CODE (index_expr) != INTEGER_CST)
  	check_for_full_enumeration_handling (TREE_TYPE (orig_index));
  
        /* If we don't have a default-label, create one here,
  	 after the body of the switch.  */
--- 5408,5427 ----
    /* An ERROR_MARK occurs for various reasons including invalid data type.  */
    if (index_type != error_mark_node)
      {
!       /* If switch expression was an enumerated type, check that
! 	 exactly all enumeration literals are covered by the cases.
! 	 The check is made always (-Wswitch-enum) or only when there
! 	 is no default (-Wswitch).  */
! 
!       if ((warn_switch && !thiscase->data.case_stmt.default_label
! 	   || warn_switch_enum
! 	   || 1)
  	  && TREE_CODE (TREE_TYPE (orig_index)) == ENUMERAL_TYPE
  	  && TREE_CODE (index_expr) != INTEGER_CST)
  	check_for_full_enumeration_handling (TREE_TYPE (orig_index));
+ 
+       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.  */
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.570
diff -p -r1.570 toplev.c
*** toplev.c	2002/01/10 22:21:36	1.570
--- toplev.c	2002/01/13 00:31:39
*************** int warn_uninitialized;
*** 1413,1422 ****
  
  int warn_shadow;
  
! /* Warn if a switch on an enum fails to have a case for every enum value.  */
  
  int warn_switch;
  
  /* Nonzero means warn about function definitions that default the return type
     or that use a null return and have a return-type other than void.  */
  
--- 1413,1432 ----
  
  int warn_shadow;
  
! /* Warn if a switch on an enum that does not have a default case fails
!    to have a case for every enum value.  */
  
  int warn_switch;
  
+ /* Warn if a switch does not have a default case.  */
+ 
+ int warn_switch_default;
+ 
+ /* Warn if a switch on an enum fails to have a case for every enum
+    value (regardless of the presence or otherwise of a default case).  */
+ 
+ int warn_switch_enum;
+ 
  /* Nonzero means warn about function definitions that default the return type
     or that use a null return and have a return-type other than void.  */
  
*************** static const lang_independent_options W_
*** 1486,1492 ****
    {"shadow", &warn_shadow, 1,
     N_("Warn when one local variable shadows another") },
    {"switch", &warn_switch, 1,
!    N_("Warn about enumerated switches missing a specific case") },
    {"aggregate-return", &warn_aggregate_return, 1,
     N_("Warn about returning structures, unions or arrays") },
    {"cast-align", &warn_cast_align, 1,
--- 1496,1506 ----
    {"shadow", &warn_shadow, 1,
     N_("Warn when one local variable shadows another") },
    {"switch", &warn_switch, 1,
!    N_("Warn about enumerated switches, with no default, missing a case") },
!   {"switch-default", &warn_switch_default, 1,
!    N_("Warn about enumerated switches missing a default case") },
!   {"switch-enum", &warn_switch_enum, 1,
!    N_("Warn about all enumerated switches missing a specific case") },
    {"aggregate-return", &warn_aggregate_return, 1,
     N_("Warn about returning structures, unions or arrays") },
    {"cast-align", &warn_cast_align, 1,

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