On 6/10/21 10:44 AM, Jakub Jelinek wrote:
On Thu, Jun 10, 2021 at 10:09:26AM -0400, Jason Merrill wrote:
--- gcc/cp/parser.c.jj  2021-06-09 21:54:39.482193853 +0200
+++ gcc/cp/parser.c     2021-06-10 10:09:23.753052980 +0200
@@ -10902,6 +10902,11 @@ cp_parser_lambda_expression (cp_parser*
       bool discarded = in_discarded_stmt;
       in_discarded_stmt = 0;
+    /* Similarly the body of a lambda in immediate function context is not
+       in immediate function context.  */
+    bool immediate_fn_ctx_p = in_immediate_fn_ctx_p;

It's hard to distinguish between these two names when reading the code;
let's give the local variable a name including "saved".

Will do.

+           if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+             error ("%<if consteval%> requires compound statement");
+
+           in_immediate_fn_ctx_p |= ce > 0;
+           cp_parser_implicitly_scoped_statement (parser, NULL, guard_tinfo);

Maybe use cp_parser_compound_statement directly instead of this and checking
CPP_OPEN_BRACE above?  Either way is fine.

I thought doing it this way will provide better diagnostics for what I think
can be a common bug - people so used to normal if not requiring compound
statements forgetting those {}s from time to time.

What the patch currently diagnoses is:
consteval-if2.C:13:6: error: ‘if consteval’ requires compound statement
   13 |   if consteval if (true) {}     // { dg-error "'if consteval' requires 
compound statement" }
      |      ^~~~~~~~~
while with cp_parser_compound_statement directly it diagnoses:
consteval-if2.C:13:16: error: expected ‘{’ before ‘if’
   13 |   if consteval if (true) {}     // { dg-error "'if consteval' requires 
compound statement" }
      |                ^~
What do you prefer?

The second is clearer about the fix, the first is clearer about the problem. Maybe add a fixit to the first error?

Dunno if the fine detail that in the grammar only one of the statements
is compound-statement and then there is a requirement that the other
statement has to be a compound-statement shouldn't affect how it is
reported.

The difference was to prevent "else ;" from binding to an enclosing if rather than the if consteval.

+  if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t))
+    {
+      /* Evaluate the condition as if it was
+        if (__builtin_is_constant_evaluated ()).  */
+      if (ctx->manifestly_const_eval)
+       val = boolean_true_node;
+      else
+       {
+         *non_constant_p = true;
+         return t;
+       }

Why set *non_constant_p?  Shouldn't this just be

val = boolean_false_node;

so we constant-evaluate the else clause when we are trying to
constant-evaluate in a non-manifestly-constant-evaluated context?

It matches what we do for CP_BUILT_IN_IS_CONSTANT_EVALUATED calls:
   /* For __builtin_is_constant_evaluated, defer it if not
      ctx->manifestly_const_eval, otherwise fold it to true.  */
   if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
                          BUILT_IN_FRONTEND))
     {
       if (!ctx->manifestly_const_eval)
         {
           *non_constant_p = true;
           return t;
         }
       return boolean_true_node;
     }
I believe we sometimes try to constexpr evaluate something without
having manifestly_const_eval = true even on expressions that
are in manifestly constant evaluated contexts and am worried if
we just folded it to boolean_false_node we could get a constant expression
and replace the expression with that, even before we actually try to
constant evaluate it with manifestly_const_eval = true.

If I do (for the CP_BUILT_IN_IS_CONSTANT_EVALUATED):
--- gcc/cp/constexpr.c.jj       2021-06-10 15:27:31.123353594 +0200
+++ gcc/cp/constexpr.c  2021-06-10 16:26:38.368168281 +0200
@@ -1320,10 +1320,7 @@ cxx_eval_builtin_function_call (const co
                         BUILT_IN_FRONTEND))
      {
        if (!ctx->manifestly_const_eval)
-       {
-         *non_constant_p = true;
-         return t;
-       }
+       return boolean_false_node;
        return boolean_true_node;
      }
then
FAIL: g++.dg/cpp2a/is-constant-evaluated1.C  -std=c++14 execution test
FAIL: g++.dg/cpp2a/is-constant-evaluated1.C  -std=c++17 execution test
FAIL: g++.dg/cpp2a/is-constant-evaluated1.C  -std=c++2a execution test
FAIL: g++.dg/cpp2a/is-constant-evaluated1.C  -std=c++17 -fconcepts execution 
test
FAIL: g++.dg/cpp2a/is-constant-evaluated2.C  -std=c++14 execution test
FAIL: g++.dg/cpp2a/is-constant-evaluated2.C  -std=c++17 execution test
FAIL: g++.dg/cpp2a/is-constant-evaluated2.C  -std=c++2a execution test
FAIL: g++.dg/cpp2a/is-constant-evaluated2.C  -std=c++17 -fconcepts execution 
test
FAIL: g++.dg/cpp2a/is-constant-evaluated9.C  -std=gnu++2a (test for excess 
errors)
at least regresses.

OK, just add a comment then.

+      if (TREE_CODE (t) != IF_STMT || !IF_STMT_CONSTEVAL_P (t))
+       {
+         if (integer_zerop (tmp))
+           return RECUR (TREE_OPERAND (t, 2), want_rval);
+         else if (TREE_CODE (tmp) == INTEGER_CST)
+           return RECUR (TREE_OPERAND (t, 1), want_rval);
+       }

Don't we still want to shortcut consideration of one of the arms for if
consteval?

potential_constant_expression_p{,_1} doesn't get passed whether it is
manifestly_const_eval or not.

OK, just add a comment then.

--- gcc/cp/cp-gimplify.c.jj     2021-06-09 21:54:39.473193977 +0200
+++ gcc/cp/cp-gimplify.c        2021-06-10 09:49:35.898557178 +0200
@@ -161,7 +161,9 @@ genericize_if_stmt (tree *stmt_p)
     if (!else_)
       else_ = build_empty_stmt (locus);
-  if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
+  if (IF_STMT_CONSTEVAL_P (stmt))
+    stmt = else_;

This seems redundant, since you're using boolean_false_node for the
condition.

It is only when !TREE_SIDE_EFFECTS (else_).
I think that is about having labels in the then_/else_ blocks and
gotos jumping into those from outside.
But IF_STMT_CONSTEVAL_P guarantees that is not the case (and we verify
earlier), so we can do that (and in fact, for IF_STMT_CONSTEVAL_P have
to, because then_ could contain consteval calls not constant expression
evaluated).
I guess we could do that for IF_STMT_CONSTEXPR_P too, that also
doesn't allow gotos/switch into the branches.

--- gcc/cp/call.c.jj    2021-06-09 21:54:39.436194489 +0200
+++ gcc/cp/call.c       2021-06-10 09:49:35.949556470 +0200
@@ -8840,6 +8840,7 @@ immediate_invocation_p (tree fn, int nar
              || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))
          && (current_binding_level->kind != sk_function_parms
              || !current_binding_level->immediate_fn_ctx_p)
+         && !in_immediate_fn_ctx_p

Now that we have this flag, shouldn't we set it in actual immediate function
context?  Or rename the flag to match when it's actually set.

I guess I can try that.  Though, I'm not sure if we could also get rid of
the current_binding_level->immediate_fn_ctx_p for sk_function_parms case.

        Jakub


Reply via email to