This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
-Wswitch-default -Wswitch-enum ...
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gcc at gcc dot gnu dot org
- Cc: Tom Tromey <tromey at redhat dot com>
- Date: Sat, 12 Jan 2002 19:39:28 -0500
- Subject: -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,