re PR c/66322 (Linus Torvalds: -Wswitch-bool produces dubious warnings, fails to...
authorMarek Polacek <polacek@redhat.com>
Mon, 29 Jun 2015 13:12:44 +0000 (13:12 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Mon, 29 Jun 2015 13:12:44 +0000 (13:12 +0000)
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.

From-SVN: r225116

15 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/semantics.c
gcc/doc/invoke.texi
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr60439.c
gcc/testsuite/c-c++-common/pr66322.c [new file with mode: 0644]
gcc/testsuite/g++.dg/eh/scope1.C

index 976e6894fa2c6c14c5d281fa0f9ad16de666a380..c33eff9c29a79c4e7f0e1074c4b1dc55eee70e11 100644 (file)
@@ -1,3 +1,9 @@
+2015-06-29  Marek Polacek  <polacek@redhat.com>
+
+       PR c/66322
+       * function.c (stack_protect_epilogue): Remove a cast to int.
+       * doc/invoke.texi: Update -Wswitch-bool description.
+
 2015-06-29  Richard Biener  <rguenther@suse.de>
 
        * genmatch.c (add_operator): Treat ADDR_EXPR as atom.
index ffad035ffefa87b8e86cdea69dc3825ca768d39a..2d6e3c5ec2a029e9dd8fd3dc8c018a2c58c51a43 100644 (file)
@@ -1,3 +1,15 @@
+2015-06-29  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.
+
 2015-06-27  Marek Polacek  <polacek@redhat.com>
 
        * c-common.c (check_main_parameter_types): Use VECTOR_TYPE_P
index 06d2abcd451fd799f5593eebfe8eb5d682144afb..8156d6a1e2a56fc009c25daf56abe09d0dc50854 100644 (file)
@@ -306,7 +306,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 *);
@@ -3633,13 +3634,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;
@@ -3658,6 +3661,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;
     }
 
@@ -3666,6 +3670,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;
     }
 
@@ -3675,6 +3680,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;
     }
 
@@ -3684,6 +3690,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;
     }
 
@@ -6391,13 +6398,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;
@@ -6458,7 +6466,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
@@ -6619,13 +6628,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);
@@ -6633,6 +6644,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;
index 8951c3f9fb61f69ae049a6fa71ea5fce9cc98029..2b03703af86a57ef6b5446faa90fb054b80b088f 100644 (file)
@@ -946,9 +946,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);
 
index edba3f1f51b696104d5bae3aebe166ffcbf2ea41..2c5ba6db6a4eae5777d1a89f1a037e37e82fd408 100644 (file)
@@ -1,3 +1,12 @@
+2015-06-29  Marek Polacek  <polacek@redhat.com>
+
+       PR c/66322
+       * 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.
+
 2015-06-27  Marek Polacek  <polacek@redhat.com>
 
        * c-typeck.c: Use VECTOR_TYPE_P throughout.
index 8e2696a7a212628c1bed4b298678b6cce5be681f..6ea35137d50ec62aad2d155c9d1937cd6ffc9c64 100644 (file)
@@ -9525,6 +9525,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
@@ -9538,7 +9546,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,
@@ -9546,6 +9554,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)
@@ -9575,8 +9584,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
@@ -9600,6 +9608,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;
 
@@ -9646,7 +9656,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;
@@ -9667,7 +9678,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;
index 4a3b2d8a071495bdc79297e3784ce117e3753cec..c16b068f8f23fe1b0498feab8afc81f066ef6a84 100644 (file)
@@ -1,3 +1,13 @@
+2015-06-29  Marek Polacek  <polacek@redhat.com>
+
+       PR c/66322
+       * 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.
+
 2015-06-27  Marek Polacek  <polacek@redhat.com>
 
        * call.c: Use VECTOR_TYPE_P.
index 0683f26b7a042216486d0df99ea8b5383f5cf43d..498ed71bcf92e9430e093cd17cd12a81ae79b518 100644 (file)
@@ -3208,6 +3208,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
@@ -3229,6 +3232,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;
 }
 
@@ -3240,10 +3244,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;
@@ -3308,7 +3316,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.  */
index 4b8ce3b35ce08eee5706f02f21d46e5101220a58..c23d9bef0c27f17c7a277d5013ae82dfca2ec4c4 100644 (file)
@@ -1156,11 +1156,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.  */
index 844d7edaecf2bc6642324ad8513f7c2add0ee486..a765df5936bfecdcac38f3c3db3d5288b80f4bab 100644 (file)
@@ -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
index cffe32322d2f00e46576b6ae076f925bfd85d219..4389bbd1aba6ef60bff632370c54cfdda26c05ee 100644 (file)
@@ -4891,7 +4891,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);
index b4bd5dae784e719ea00eefeed7d1a77ed17445e3..fc2b9bc0d7689bcbdbb2fad5f62901934292dd6c 100644 (file)
@@ -1,3 +1,10 @@
+2015-06-29  Marek Polacek  <polacek@redhat.com>
+
+       PR c/66322
+       * 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.
+
 2015-06-29  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/66677
index 3368a0b944d3e52a66144dcef439bf99003f09cb..68bd33c22cb3b7898ead0cf8e78c61ea5fac02fd 100644 (file)
@@ -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 a/gcc/testsuite/c-c++-common/pr66322.c b/gcc/testsuite/c-c++-common/pr66322.c
new file mode 100644 (file)
index 0000000..eb1e9e4
--- /dev/null
@@ -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;
+    }
+}
index 8d553d8295b26bcbc081402ccac46106423bbac5..276e0d6e588e8badb4aff5b9f137347adc05ddb9 100644 (file)
@@ -31,7 +31,7 @@ void f3 ()
 
 void f4 ()
 {
-  switch (C br = C()) /* { dg-warning "switch condition has" } */
+  switch (C br = C())
     {
     default:
       abort ();