On 10/29/18 2:07 PM, Marek Polacek wrote:
On Wed, Oct 24, 2018 at 05:16:33PM -0400, Jason Merrill wrote:
On 10/11/18 8:56 PM, Marek Polacek wrote:
Here potential_constant_expression_1 rejects the testcase because the body of
the for loop calls a non-constexpr function.  But the range is empty so the
function would never get called.
The trick with evaluating the for-condition doesn't work here, because we're
dealing with a converted range-based for and can't evaluate

    __for_begin != __for_end

because the constexpr cache doesn't have the values of these two VAR_DECLs.


So either we can use this ugly hack (more specialized), or just not check the
body of the loop (more general), similarly to what we do (don't do) with
switch.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-10-11  Marek Polacek  <pola...@redhat.com>

        PR c++/87594 - constexpr rejects-valid with range-based for.
        * constexpr.c (potential_constant_expression_1) <case FOR_STMT>: Return
        true for a converted ange-based for-statement.

        * g++.dg/cpp1y/constexpr-loop8.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 4fa8c965a9d..685ca743859 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -5827,6 +5827,17 @@ potential_constant_expression_1 (tree t, bool want_rval, 
bool strict, bool now,
            tmp = cxx_eval_outermost_constant_expr (tmp, true);
          if (integer_zerop (tmp))
            return true;
+         /* See if this is
+            __for_begin != __for_end
+            cp_convert_range_for created for us.  If so, this is a converted
+            range-based for-statement, and we're not able to evaluate this
+            condition, so we might end up skipping the body entirely.  */
+         else if (TREE_CODE (tmp) == NE_EXPR
+                  && VAR_P (TREE_OPERAND (tmp, 0))
+                  && DECL_NAME (TREE_OPERAND (tmp, 0)) == for_begin_identifier
+                  && VAR_P (TREE_OPERAND (tmp, 1))
+                  && DECL_NAME (TREE_OPERAND (tmp, 1)) == for_end_identifier)
+           return true;

This seems over-specific; any other condition we can't immediately evaluate
also might not ever be true.  So I think we want to return here unless the
condition is always true.  Likewise for WHILE_STMT.

Yeah, that makes a lot of sense.  Thus:

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-10-29  Marek Polacek  <pola...@redhat.com>

        PR c++/87594 - constexpr rejects-valid with range-based for.
        * constexpr.c (potential_constant_expression_1): If the condition
        can't be evaluated, return true.

OK.

Jason

Reply via email to