This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C/C++ PATCH to smarten up -Wswitch-bool (PR c/66322)
- From: Marek Polacek <polacek at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Joseph Myers <joseph at codesourcery dot com>, Jason Merrill <jason at redhat dot com>
- Date: Thu, 18 Jun 2015 13:50:34 +0200
- Subject: Re: C/C++ PATCH to smarten up -Wswitch-bool (PR c/66322)
- Authentication-results: sourceware.org; auth=none
- References: <20150610180201 dot GW2756 at redhat dot com>
Ping.
On Wed, Jun 10, 2015 at 08:02:01PM +0200, Marek Polacek wrote:
> Linus's kind words here <https://lkml.org/lkml/2015/5/27/941> prodded
> me to improving the -Wswitch-bool warning. In particular, this patch
> makes the warning not warn when the case values aren't outside bool
> range. But it will still warn about
>
> switch (boolean)
> {
> case false ... true: ...
> default: ...
> }
>
> That of course means that the warning must be delayed to the point where
> all the case labels have been parsed. Then there are these annoying
> differences between C and C++ (type of a comparison), which means some
> splay trees fun. Another problem stems from the fact that case labels
> that are outside the range of the original type of the switch controlling
> expression are dropped on the floor, so I had to add the OUTSIDE_RANGE_P
> flag. Case ranges are fun as well.
>
> If this patch is approved, I'd like to backport it even to 5 branch after
> some time so it's fixed in 5.2.
>
> There's also the possibility to add -Wswitch-bool=2 that would warn every
> time the compiler sees a switch with a boolean controlling expr, i.e. do
> what we're doing now. But that would be something for trunk only.
>
> Thoughts?
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2015-06-10 Marek Polacek <polacek@redhat.com>
>
> PR c/66322
> * c-common.c (check_case_bounds): Add bool * parameter. Set
> OUTSIDE_RANGE_P.
> (c_add_case_label): Add bool * parameter. Pass it down to
> check_case_bounds.
> (c_do_switch_warnings): Add bool parameters. Implement -Wswitch-bool
> warning here.
> * c-common.h (c_add_case_label, c_do_switch_warnings): Update
> declarations.
>
> * c-typeck.c (struct c_switch): Add BOOL_COND_P and OUTSIDE_RANGE_P.
> (c_start_case): Set BOOL_COND_P and OUTSIDE_RANGE_P. Don't warn
> about -Wswitch-bool here.
> (do_case): Update c_add_case_label call.
> (c_finish_case): Update c_do_switch_warnings call.
>
> * decl.c (struct cp_switch): Add OUTSIDE_RANGE_P.
> (push_switch): Set OUTSIDE_RANGE_P.
> (pop_switch): Update c_do_switch_warnings call.
> (finish_case_label): Update c_add_case_label call.
> * semantics.c (finish_switch_cond): Don't warn about -Wswitch-bool
> here.
>
> * function.c (stack_protect_epilogue): Remove a cast to int.
> * doc/invoke.texi: Update -Wswitch-bool description.
>
> * c-c++-common/pr60439.c: Add dg-prune-output and add switch cases.
> * c-c++-common/pr66322.c: New test.
> * g++.dg/eh/scope1.C: Remove dg-warning.
>
> diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
> index 5903c75..3746de7 100644
> --- gcc/doc/invoke.texi
> +++ gcc/doc/invoke.texi
> @@ -4012,7 +4012,8 @@ warning about an omitted enumeration code even if there is a
> @item -Wswitch-bool
> @opindex Wswitch-bool
> @opindex Wno-switch-bool
> -Warn whenever a @code{switch} statement has an index of boolean type.
> +Warn whenever a @code{switch} statement has an index of boolean type
> +and the case values are outside the range of a boolean type.
> It is possible to suppress this warning by casting the controlling
> expression to a type other than @code{bool}. For example:
> @smallexample
> diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
> index 5b76567..6f9f056 100644
> --- gcc/c-family/c-common.c
> +++ gcc/c-family/c-common.c
> @@ -312,7 +312,8 @@ struct visibility_flags visibility_options;
>
> static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool);
> static tree check_case_value (location_t, tree);
> -static bool check_case_bounds (location_t, tree, tree, tree *, tree *);
> +static bool check_case_bounds (location_t, tree, tree, tree *, tree *,
> + bool *);
>
> static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
> static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
> @@ -3639,13 +3640,15 @@ check_case_value (location_t loc, tree value)
> bound of the case label, and CASE_HIGH_P is the upper bound or NULL
> if the case is not a case range.
> The caller has to make sure that we are not called with NULL for
> - CASE_LOW_P (i.e. the default case).
> + CASE_LOW_P (i.e. the default case). OUTSIDE_RANGE_P says whether there
> + was a case value that doesn't fit into the range of the ORIG_TYPE.
> Returns true if the case label is in range of ORIG_TYPE (saturated or
> untouched) or false if the label is out of range. */
>
> static bool
> check_case_bounds (location_t loc, tree type, tree orig_type,
> - tree *case_low_p, tree *case_high_p)
> + tree *case_low_p, tree *case_high_p,
> + bool *outside_range_p)
> {
> tree min_value, max_value;
> tree case_low = *case_low_p;
> @@ -3664,6 +3667,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
> {
> warning_at (loc, 0, "case label value is less than minimum value "
> "for type");
> + *outside_range_p = true;
> return false;
> }
>
> @@ -3672,6 +3676,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
> && tree_int_cst_compare (case_high, max_value) > 0)
> {
> warning_at (loc, 0, "case label value exceeds maximum value for type");
> + *outside_range_p = true;
> return false;
> }
>
> @@ -3681,6 +3686,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
> {
> warning_at (loc, 0, "lower value in case label range"
> " less than minimum value for type");
> + *outside_range_p = true;
> case_low = min_value;
> }
>
> @@ -3690,6 +3696,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
> {
> warning_at (loc, 0, "upper value in case label range"
> " exceeds maximum value for type");
> + *outside_range_p = true;
> case_high = max_value;
> }
>
> @@ -6383,13 +6390,14 @@ case_compare (splay_tree_key k1, splay_tree_key k2)
> HIGH_VALUE is NULL_TREE, then case label was declared using the
> usual C/C++ syntax, rather than the GNU case range extension.
> CASES is a tree containing all the case ranges processed so far;
> - COND is the condition for the switch-statement itself. Returns the
> - CASE_LABEL_EXPR created, or ERROR_MARK_NODE if no CASE_LABEL_EXPR
> - is created. */
> + COND is the condition for the switch-statement itself.
> + OUTSIDE_RANGE_P says whether there was a case value that doesn't
> + fit into the range of the ORIG_TYPE. Returns the CASE_LABEL_EXPR
> + created, or ERROR_MARK_NODE if no CASE_LABEL_EXPR is created. */
>
> tree
> c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
> - tree low_value, tree high_value)
> + tree low_value, tree high_value, bool *outside_range_p)
> {
> tree type;
> tree label;
> @@ -6450,7 +6458,8 @@ c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
> don't insert the case label and return NULL_TREE. */
> if (low_value
> && !check_case_bounds (loc, type, orig_type,
> - &low_value, high_value ? &high_value : NULL))
> + &low_value, high_value ? &high_value : NULL,
> + outside_range_p))
> return NULL_TREE;
>
> /* Look up the LOW_VALUE in the table of case labels we already
> @@ -6611,13 +6620,15 @@ match_case_to_enum (splay_tree_node node, void *data)
>
> void
> c_do_switch_warnings (splay_tree cases, location_t switch_location,
> - tree type, tree cond)
> + tree type, tree cond, bool bool_cond_p,
> + bool outside_range_p)
> {
> splay_tree_node default_node;
> splay_tree_node node;
> tree chain;
>
> - if (!warn_switch && !warn_switch_enum && !warn_switch_default)
> + if (!warn_switch && !warn_switch_enum && !warn_switch_default
> + && !warn_switch_bool)
> return;
>
> default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
> @@ -6625,6 +6636,52 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
> warning_at (switch_location, OPT_Wswitch_default,
> "switch missing default case");
>
> + /* There are certain cases where -Wswitch-bool warnings aren't
> + desirable, such as
> + switch (boolean)
> + {
> + case true: ...
> + case false: ...
> + }
> + so be careful here. */
> + if (warn_switch_bool && bool_cond_p)
> + {
> + splay_tree_node min_node;
> + /* If there's a default node, it's also the value with the minimal
> + key. So look at the penultimate key (if any). */
> + if (default_node)
> + min_node = splay_tree_successor (cases, (splay_tree_key) NULL);
> + else
> + min_node = splay_tree_min (cases);
> + tree min = min_node ? (tree) min_node->key : NULL_TREE;
> +
> + splay_tree_node max_node = splay_tree_max (cases);
> + /* This might be a case range, so look at the value with the
> + maximal key and then check CASE_HIGH. */
> + tree max = max_node ? (tree) max_node->value : NULL_TREE;
> + if (max)
> + max = CASE_HIGH (max) ? CASE_HIGH (max) : CASE_LOW (max);
> +
> + /* If there's a case value > 1 or < 0, that is outside bool
> + range, warn. */
> + if (outside_range_p
> + || (max && wi::gts_p (max, 1))
> + || (min && wi::lts_p (min, 0))
> + /* And handle the
> + switch (boolean)
> + {
> + case true: ...
> + case false: ...
> + default: ...
> + }
> + case, where we want to warn. */
> + || (default_node
> + && max && wi::eq_p (max, 1)
> + && min && wi::eq_p (min, 0)))
> + warning_at (switch_location, OPT_Wswitch_bool,
> + "switch condition has boolean value");
> + }
> +
> /* From here on, we only care about about enumerated types. */
> if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
> return;
> diff --git gcc/c-family/c-common.h gcc/c-family/c-common.h
> index 7ba81c4..3578929 100644
> --- gcc/c-family/c-common.h
> +++ gcc/c-family/c-common.h
> @@ -947,9 +947,11 @@ extern tree boolean_increment (enum tree_code, tree);
>
> extern int case_compare (splay_tree_key, splay_tree_key);
>
> -extern tree c_add_case_label (location_t, splay_tree, tree, tree, tree, tree);
> +extern tree c_add_case_label (location_t, splay_tree, tree, tree, tree, tree,
> + bool *);
>
> -extern void c_do_switch_warnings (splay_tree, location_t, tree, tree);
> +extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
> + bool);
>
> extern tree build_function_call (location_t, tree, tree);
>
> diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
> index 636e0bb..04a50c7 100644
> --- gcc/c/c-typeck.c
> +++ gcc/c/c-typeck.c
> @@ -9529,6 +9529,14 @@ struct c_switch {
>
> /* The next node on the stack. */
> struct c_switch *next;
> +
> + /* Remember whether the controlling expression had boolean type
> + before integer promotions for the sake of -Wswitch-bool. */
> + bool bool_cond_p;
> +
> + /* Remember whether there was a case value that is outside the
> + range of the ORIG_TYPE. */
> + bool outside_range_p;
> };
>
> /* A stack of the currently active switch statements. The innermost
> @@ -9542,7 +9550,7 @@ struct c_switch *c_switch_stack;
> /* Start a C switch statement, testing expression EXP. Return the new
> SWITCH_EXPR. SWITCH_LOC is the location of the `switch'.
> SWITCH_COND_LOC is the location of the switch's condition.
> - EXPLICIT_CAST_P is true if the expression EXP has explicit cast. */
> + EXPLICIT_CAST_P is true if the expression EXP has an explicit cast. */
>
> tree
> c_start_case (location_t switch_loc,
> @@ -9550,6 +9558,7 @@ c_start_case (location_t switch_loc,
> tree exp, bool explicit_cast_p)
> {
> tree orig_type = error_mark_node;
> + bool bool_cond_p = false;
> struct c_switch *cs;
>
> if (exp != error_mark_node)
> @@ -9579,8 +9588,7 @@ c_start_case (location_t switch_loc,
> /* Explicit cast to int suppresses this warning. */
> && !(TREE_CODE (type) == INTEGER_TYPE
> && explicit_cast_p))
> - warning_at (switch_cond_loc, OPT_Wswitch_bool,
> - "switch condition has boolean value");
> + bool_cond_p = true;
>
> if (!in_system_header_at (input_location)
> && (type == long_integer_type_node
> @@ -9604,6 +9612,8 @@ c_start_case (location_t switch_loc,
> cs->orig_type = orig_type;
> cs->cases = splay_tree_new (case_compare, NULL, NULL);
> cs->bindings = c_get_switch_bindings ();
> + cs->bool_cond_p = bool_cond_p;
> + cs->outside_range_p = false;
> cs->next = c_switch_stack;
> c_switch_stack = cs;
>
> @@ -9650,7 +9660,8 @@ do_case (location_t loc, tree low_value, tree high_value)
> label = c_add_case_label (loc, c_switch_stack->cases,
> SWITCH_COND (c_switch_stack->switch_expr),
> c_switch_stack->orig_type,
> - low_value, high_value);
> + low_value, high_value,
> + &c_switch_stack->outside_range_p);
> if (label == error_mark_node)
> label = NULL_TREE;
> return label;
> @@ -9671,7 +9682,8 @@ c_finish_case (tree body, tree type)
> switch_location = EXPR_LOCATION (cs->switch_expr);
> c_do_switch_warnings (cs->cases, switch_location,
> type ? type : TREE_TYPE (cs->switch_expr),
> - SWITCH_COND (cs->switch_expr));
> + SWITCH_COND (cs->switch_expr),
> + cs->bool_cond_p, cs->outside_range_p);
>
> /* Pop the stack. */
> c_switch_stack = cs->next;
> diff --git gcc/cp/decl.c gcc/cp/decl.c
> index 3bed538..c7b27ff 100644
> --- gcc/cp/decl.c
> +++ gcc/cp/decl.c
> @@ -3212,6 +3212,9 @@ struct cp_switch
> label. We need a tree, rather than simply a hash table, because
> of the GNU case range extension. */
> splay_tree cases;
> + /* Remember whether there was a case value that is outside the
> + range of the original type of the controlling expression. */
> + bool outside_range_p;
> };
>
> /* A stack of the currently active switch statements. The innermost
> @@ -3233,6 +3236,7 @@ push_switch (tree switch_stmt)
> p->next = switch_stack;
> p->switch_stmt = switch_stmt;
> p->cases = splay_tree_new (case_compare, NULL, NULL);
> + p->outside_range_p = false;
> switch_stack = p;
> }
>
> @@ -3244,10 +3248,14 @@ pop_switch (void)
>
> /* Emit warnings as needed. */
> switch_location = EXPR_LOC_OR_LOC (cs->switch_stmt, input_location);
> + const bool bool_cond_p
> + = (SWITCH_STMT_TYPE (cs->switch_stmt)
> + && TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE);
> if (!processing_template_decl)
> c_do_switch_warnings (cs->cases, switch_location,
> SWITCH_STMT_TYPE (cs->switch_stmt),
> - SWITCH_STMT_COND (cs->switch_stmt));
> + SWITCH_STMT_COND (cs->switch_stmt),
> + bool_cond_p, cs->outside_range_p);
>
> splay_tree_delete (cs->cases);
> switch_stack = switch_stack->next;
> @@ -3312,7 +3320,8 @@ finish_case_label (location_t loc, tree low_value, tree high_value)
> high_value = case_conversion (type, high_value);
>
> r = c_add_case_label (loc, switch_stack->cases, cond, type,
> - low_value, high_value);
> + low_value, high_value,
> + &switch_stack->outside_range_p);
>
> /* After labels, make any new cleanups in the function go into their
> own new (temporary) binding contour. */
> diff --git gcc/cp/semantics.c gcc/cp/semantics.c
> index 59ec9047..aa43022 100644
> --- gcc/cp/semantics.c
> +++ gcc/cp/semantics.c
> @@ -1161,11 +1161,6 @@ finish_switch_cond (tree cond, tree switch_stmt)
> orig_type = TREE_TYPE (cond);
> if (cond != error_mark_node)
> {
> - /* Warn if the condition has boolean value. */
> - if (TREE_CODE (orig_type) == BOOLEAN_TYPE)
> - warning_at (input_location, OPT_Wswitch_bool,
> - "switch condition has type bool");
> -
> /* [stmt.switch]
>
> Integral promotions are performed. */
> diff --git gcc/function.c gcc/function.c
> index 8baaed7..0b45abf 100644
> --- gcc/function.c
> +++ gcc/function.c
> @@ -4934,7 +4934,7 @@ stack_protect_epilogue (void)
>
> /* Allow the target to compare Y with X without leaking either into
> a register. */
> - switch ((int) (HAVE_stack_protect_test != 0))
> + switch (HAVE_stack_protect_test != 0)
> {
> case 1:
> tmp = gen_stack_protect_test (x, y, label);
> diff --git gcc/testsuite/c-c++-common/pr60439.c gcc/testsuite/c-c++-common/pr60439.c
> index 3368a0b..68bd33c 100644
> --- gcc/testsuite/c-c++-common/pr60439.c
> +++ gcc/testsuite/c-c++-common/pr60439.c
> @@ -1,5 +1,6 @@
> /* PR c/60439 */
> /* { dg-do compile } */
> +/* { dg-prune-output "case label value exceeds" } */
>
> #ifndef __cplusplus
> # define bool _Bool
> @@ -11,18 +12,30 @@ void
> f1 (bool b)
> {
> switch (b) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> }
>
> void
> f2 (int a, int b)
> {
> switch (a && b) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch ((bool) (a && b)) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch ((a && b) || a) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> /* No warnings on following. */
> switch ((int) (a && b))
> break;
> @@ -38,35 +51,65 @@ void
> f3 (int a)
> {
> switch (!!a) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (!a) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> }
>
> void
> f4 (void)
> {
> switch (foo ()) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> }
>
> void
> f5 (int a)
> {
> switch (a == 3) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (a != 3) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (a > 3) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (a < 3) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (a <= 3) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (a >= 3) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (foo (), foo (), a >= 42) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (a == 3, a & 4, a ^ 5, a)
> break;
> switch ((int) (a == 3))
> @@ -79,11 +122,20 @@ void
> f6 (bool b)
> {
> switch (b) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (!b) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> switch (b++) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> }
>
> void
> @@ -91,7 +143,10 @@ f7 (void)
> {
> bool b;
> switch (b = 1) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 3:
> + break;
> + }
> }
>
> void
> @@ -104,5 +159,8 @@ f8 (int i)
> switch ((unsigned int) i)
> break;
> switch ((bool) i) /* { dg-warning "switch condition has" } */
> - break;
> + {
> + case 11:
> + break;
> + }
> }
> diff --git gcc/testsuite/c-c++-common/pr66322.c gcc/testsuite/c-c++-common/pr66322.c
> index e69de29..eb1e9e4 100644
> --- gcc/testsuite/c-c++-common/pr66322.c
> +++ gcc/testsuite/c-c++-common/pr66322.c
> @@ -0,0 +1,144 @@
> +/* PR c/66322 */
> +/* { dg-do compile } */
> +
> +#ifndef __cplusplus
> +# define bool _Bool
> +# define true 1
> +# define false 0
> +#endif
> +
> +void
> +nowarn (bool b)
> +{
> + switch (b)
> + ;
> +
> + switch (b)
> + {
> + case true:
> + case false:
> + break;
> + }
> +
> + switch (b)
> + {
> + case true:
> + break;
> + }
> +
> + switch (b)
> + {
> + case true:
> + default:
> + break;
> + }
> +
> + switch (b)
> + {
> + case false:
> + break;
> + }
> +
> + switch (b)
> + {
> + case false:
> + default:
> + break;
> + }
> +
> + switch (b)
> + {
> + default:
> + break;
> + }
> +
> + switch (b)
> + {
> + case false ... true:
> + break;
> + }
> +
> + switch (b)
> + {
> + case 1:
> + switch (b)
> + {
> + case true:
> + default:
> + break;
> + }
> + default:
> + break;
> + }
> +}
> +
> +void
> +warn (bool b)
> +{
> + switch (b) /* { dg-warning "switch condition has" } */
> + {
> + case true:
> + case false:
> + default:
> + break;
> + }
> +
> + switch (b) /* { dg-warning "switch condition has" } */
> + {
> + case false ... true:
> + default:
> + break;
> + }
> +}
> +
> +void
> +warn2 (int n)
> +{
> + switch (n == 2) /* { dg-warning "switch condition has" } */
> + {
> + case 0 ... 2: /* { dg-warning "upper value" "" { target c++ } } */
> + default:
> + break;
> + }
> +
> + switch (n == 2) /* { dg-warning "switch condition has" } */
> + {
> + case 1 ... 10: /* { dg-warning "upper value" "" { target c++ } } */
> + default:
> + break;
> + }
> +
> + switch (n == 2) /* { dg-warning "switch condition has" } */
> + {
> + case 2: /* { dg-warning "case label" "" { target c++ } } */
> + break;
> + }
> +
> + switch (n == 2) /* { dg-warning "switch condition has" } */
> + {
> + case 0:
> + case 1:
> + case -1: /* { dg-warning "case label" "" { target c++ } } */
> + break;
> + }
> +
> + switch (n == 2) /* { dg-warning "switch condition has" } */
> + {
> + case -1 ... 1: /* { dg-warning "lower value" "" { target c++ } } */
> + break;
> + }
> +
> + switch (n == 2) /* { dg-warning "switch condition has" } */
> + {
> + case -1 ... 0: /* { dg-warning "lower value" "" { target c++ } } */
> + default:
> + break;
> + }
> +
> + switch (n == 2) /* { dg-warning "switch condition has" } */
> + {
> + case -10 ... -1: /* { dg-warning "case label" "" { target c++ } } */
> + default:
> + break;
> + }
> +}
> diff --git gcc/testsuite/g++.dg/eh/scope1.C gcc/testsuite/g++.dg/eh/scope1.C
> index 8d553d8..276e0d6 100644
> --- gcc/testsuite/g++.dg/eh/scope1.C
> +++ gcc/testsuite/g++.dg/eh/scope1.C
> @@ -31,7 +31,7 @@ void f3 ()
>
> void f4 ()
> {
> - switch (C br = C()) /* { dg-warning "switch condition has" } */
> + switch (C br = C())
> {
> default:
> abort ();
>
> Marek
Marek