While adding a new match pattern, g++.dg/cpp2a/consteval36.C started to ICE and 
that was
because we would call fold even if one of the operands of the comparison was an 
error_mark_node.
I found a new testcase which also ICEs before this patch too so show the issue 
was latent.

So there is code in cp_fold to avoid calling fold when one of the operands 
become error_mark_node
but with the addition of consteval, the replacement of an invalid call is 
replaced before the call
to cp_fold and there is no way to pop up the error_mark. So this patch changes 
the current code to
check if the operands of the expression are error_mark_node before checking if 
the folded operand
is different from the previous one.

Bootstrapped and tested on x86_64-linux-gnu.

        PR c++/118525

gcc/cp/ChangeLog:

        * cp-gimplify.cc (cp_fold): Check operands of unary, binary, 
cond/vec_cond
        and array_ref for error_mark before checking if the operands had 
changed.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/consteval38.C: New test.

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
 gcc/cp/cp-gimplify.cc                    | 99 ++++++++++--------------
 gcc/testsuite/g++.dg/cpp2a/consteval38.C | 11 +++
 2 files changed, 53 insertions(+), 57 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval38.C

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index c7074b00cef..4ec3de13008 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -3005,19 +3005,16 @@ cp_fold (tree x, fold_flags_t flags)
       loc = EXPR_LOCATION (x);
       op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops, flags);
 
-      if (code == CONVERT_EXPR
+      if (op0 == error_mark_node)
+       x = error_mark_node;
+      else if (code == CONVERT_EXPR
          && SCALAR_TYPE_P (TREE_TYPE (x))
          && op0 != void_node)
        /* During parsing we used convert_to_*_nofold; re-convert now using the
           folding variants, since fold() doesn't do those transformations.  */
        x = fold (convert (TREE_TYPE (x), op0));
       else if (op0 != TREE_OPERAND (x, 0))
-       {
-         if (op0 == error_mark_node)
-           x = error_mark_node;
-         else
-           x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
-       }
+       x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
       else
        x = fold (x);
 
@@ -3087,20 +3084,17 @@ cp_fold (tree x, fold_flags_t flags)
       op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops, flags);
 
     finish_unary:
-      if (op0 != TREE_OPERAND (x, 0))
+      if (op0 == error_mark_node)
+       x = error_mark_node;
+      else if (op0 != TREE_OPERAND (x, 0))
        {
-         if (op0 == error_mark_node)
-           x = error_mark_node;
-         else
+         x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
+         if (code == INDIRECT_REF
+             && (INDIRECT_REF_P (x) || TREE_CODE (x) == MEM_REF))
            {
-             x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
-             if (code == INDIRECT_REF
-                 && (INDIRECT_REF_P (x) || TREE_CODE (x) == MEM_REF))
-               {
-                 TREE_READONLY (x) = TREE_READONLY (org_x);
-                 TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
-                 TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
-               }
+             TREE_READONLY (x) = TREE_READONLY (org_x);
+             TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
+             TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
            }
        }
       else
@@ -3190,13 +3184,10 @@ cp_fold (tree x, fold_flags_t flags)
                                        op0, op1);
        }
 
-      if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
-       {
-         if (op0 == error_mark_node || op1 == error_mark_node)
-           x = error_mark_node;
-         else
-           x = fold_build2_loc (loc, code, TREE_TYPE (x), op0, op1);
-       }
+      if (op0 == error_mark_node || op1 == error_mark_node)
+       x = error_mark_node;
+      else if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
+       x = fold_build2_loc (loc, code, TREE_TYPE (x), op0, op1);
       else
        x = fold (x);
 
@@ -3268,17 +3259,14 @@ cp_fold (tree x, fold_flags_t flags)
            }
        }
 
-      if (op0 != TREE_OPERAND (x, 0)
-         || op1 != TREE_OPERAND (x, 1)
-         || op2 != TREE_OPERAND (x, 2))
-       {
-         if (op0 == error_mark_node
-             || op1 == error_mark_node
-             || op2 == error_mark_node)
-           x = error_mark_node;
-         else
-           x = fold_build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
-       }
+      if (op0 == error_mark_node
+         || op1 == error_mark_node
+         || op2 == error_mark_node)
+       x = error_mark_node;
+      else if (op0 != TREE_OPERAND (x, 0)
+              || op1 != TREE_OPERAND (x, 1)
+              || op2 != TREE_OPERAND (x, 2))
+       x = fold_build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
       else
        x = fold (x);
 
@@ -3462,14 +3450,14 @@ cp_fold (tree x, fold_flags_t flags)
        FOR_EACH_VEC_SAFE_ELT (elts, i, p)
          {
            tree op = cp_fold (p->value, flags);
-           if (op != p->value)
+           if (op == error_mark_node)
+             {
+               x = error_mark_node;
+               vec_free (nelts);
+               break;
+             }
+           else if (op != p->value)
              {
-               if (op == error_mark_node)
-                 {
-                   x = error_mark_node;
-                   vec_free (nelts);
-                   break;
-                 }
                if (nelts == NULL)
                  nelts = elts->copy ();
                (*nelts)[i].value = op;
@@ -3516,23 +3504,20 @@ cp_fold (tree x, fold_flags_t flags)
       op2 = cp_fold (TREE_OPERAND (x, 2), flags);
       op3 = cp_fold (TREE_OPERAND (x, 3), flags);
 
-      if (op0 != TREE_OPERAND (x, 0)
+      if (op0 == error_mark_node
+         || op1 == error_mark_node
+         || op2 == error_mark_node
+         || op3 == error_mark_node)
+       x = error_mark_node;
+      else if (op0 != TREE_OPERAND (x, 0)
          || op1 != TREE_OPERAND (x, 1)
          || op2 != TREE_OPERAND (x, 2)
          || op3 != TREE_OPERAND (x, 3))
        {
-         if (op0 == error_mark_node
-             || op1 == error_mark_node
-             || op2 == error_mark_node
-             || op3 == error_mark_node)
-           x = error_mark_node;
-         else
-           {
-             x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3);
-             TREE_READONLY (x) = TREE_READONLY (org_x);
-             TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
-             TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
-           }
+         x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3);
+         TREE_READONLY (x) = TREE_READONLY (org_x);
+         TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
+         TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
        }
 
       x = fold (x);
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval38.C 
b/gcc/testsuite/g++.dg/cpp2a/consteval38.C
new file mode 100644
index 00000000000..cc9f7ba8c82
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval38.C
@@ -0,0 +1,11 @@
+// PR c++/118525
+// { dg-do compile { target c++20 } }
+
+// Make sure we don't ICE
+consteval int id (int i) { return i; }
+
+void
+g (int i)
+{
+    1 ? 1 : id (i) ^ 1; // { dg-error "call to consteval function|'i' is not a 
constant expression" }
+}
-- 
2.43.0

Reply via email to