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]

Re: C/C++ PATCH to smarten up -Wswitch-bool (PR c/66322)


Ping.

On Thu, Jun 18, 2015 at 01:50:34PM +0200, Marek Polacek wrote:
> 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


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