https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89785

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2019-03-22
     Ever confirmed|0                           |1

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The bug is then in potential_constant_expression_1:
    case SWITCH_STMT:
      if (!RECUR (SWITCH_STMT_COND (t), rval))
        return false;
      /* FIXME we don't check SWITCH_STMT_BODY currently, because even
         unreachable labels would be checked.  */
      return true;

This is not conservatively correct as the testcases show.
The question is how much effort we do want to spend on that.

The simplest might be to add *jump_target = integer_zero_node; before the
return true; above, that will just assume any switch can return and not check
both the switch body (which isn't checked even now) nor anything after the
switch.

Another option, slightly more involved, is say cp_walk_tree on
SWITCH_STMT_BODY, looking for any RETURN_EXPRs or CONTINUE_STMTs (the latter
only when not nested inside of a FOR_STMT, DO_STMT, WHILE_STMT and
RANGE_FOR_STMT) and if we find a RETURN_EXPR, set jump_target to that, if we
don't, but find a CONTINUE_STMT not nested in further looping constructs, set
*jump_target to that CONTINUE_STMT, otherwise keep it unchanged.  To me this
looks like the best approach for now.

Another option is try to do something for the case when SWITCH_STMT_COND is
constant, but already for that we'd need to greatly extend the simplified:
  if (*jump_target)
    /* If we are jumping, ignore everything.  This is simpler than the
       cxx_eval_constant_expression handling because we only need to be
       conservatively correct, and we don't necessarily have a constant value
       available, so we don't bother with switch tracking.  */
    return true;
so that we do walk statements that can embed other statements like
cxx_eval_constant_expression does and all of that stuff, with label_matches
etc.

And if the above is done, we could have some also some mode in which for
non-constant SWITCH_STMT_COND we could say set *jump_target to the SWITCH_STMT
itself and treat it as a walk which walks the switch body, if it finds some
CASE_LABEL_EXPR, it will change it to some other mode which will start
processing all the expressions; if we detect something that is not a potential
constant expression, we would at the level of whole stmts switch back to that
*jump_target = SWITCH_STMT mode and keep looking for another CASE_LABEL_EXPR
and that way, if for any of the switch condition values there would be a
potential constant expression, we'd succeed, otherwise fail, and even set
jump_target properly based on that.  But this would be quite a lot of work.

Jason, any preferences here?

Reply via email to