https://gcc.gnu.org/g:acbbdaf829a056ec1a20405742a3b6494db64dc7

commit r16-7710-gacbbdaf829a056ec1a20405742a3b6494db64dc7
Author: Roger Sayle <[email protected]>
Date:   Thu Feb 26 08:03:25 2026 +0000

    PR c/119651: Fix some unexpected error_mark_node ICEs.
    
    This patch resolves PR c/119651 and PR c/123472 P4 regressions.
    
    2026-02-26  Roger Sayle  <[email protected]>
    
    gcc/ChangeLog
            PR c/119651
            PR c/123472
            * fold-const.cc (tree_nonzero_bits): Rename the original as a
            static function taking an additional precision parameter.  Make
            this implementation robust to error_mark_node.  Preserve the
            original API by checking for error_operand_p before invoking the
            static helper function.
    
    gcc/testsuite/ChangeLog
            PR c/119651
            PR c/123472
            * gcc.dg/pr119651.c: New test case.
            * gcc.dg/pr123472.c: Likewise.

Diff:
---
 gcc/fold-const.cc               | 70 ++++++++++++++++++++++++++---------------
 gcc/testsuite/gcc.dg/pr119651.c | 10 ++++++
 gcc/testsuite/gcc.dg/pr123472.c | 16 ++++++++++
 3 files changed, 70 insertions(+), 26 deletions(-)

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 41681d38570f..19f25d40d7f7 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -16708,10 +16708,11 @@ c_getstr (tree str)
   return getbyterep (str, NULL);
 }
 
-/* Given a tree T, compute which bits in T may be nonzero.  */
+/* Helper for tree_nonzero_bits.  Given a tree T, compute which bits in T
+   may be nonzero, with precision PREC, the precision of T's type.  */
 
-wide_int
-tree_nonzero_bits (const_tree t)
+static wide_int
+tree_nonzero_bits (const_tree t, unsigned prec)
 {
   switch (TREE_CODE (t))
     {
@@ -16721,59 +16722,76 @@ tree_nonzero_bits (const_tree t)
       return get_nonzero_bits (t);
     case NON_LVALUE_EXPR:
     case SAVE_EXPR:
-      return tree_nonzero_bits (TREE_OPERAND (t, 0));
+      return tree_nonzero_bits (TREE_OPERAND (t, 0), prec);
     case BIT_AND_EXPR:
-      return wi::bit_and (tree_nonzero_bits (TREE_OPERAND (t, 0)),
-                         tree_nonzero_bits (TREE_OPERAND (t, 1)));
+      return wi::bit_and (tree_nonzero_bits (TREE_OPERAND (t, 0), prec),
+                         tree_nonzero_bits (TREE_OPERAND (t, 1), prec));
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
-      return wi::bit_or (tree_nonzero_bits (TREE_OPERAND (t, 0)),
-                        tree_nonzero_bits (TREE_OPERAND (t, 1)));
+      return wi::bit_or (tree_nonzero_bits (TREE_OPERAND (t, 0), prec),
+                        tree_nonzero_bits (TREE_OPERAND (t, 1), prec));
     case COND_EXPR:
-      return wi::bit_or (tree_nonzero_bits (TREE_OPERAND (t, 1)),
-                        tree_nonzero_bits (TREE_OPERAND (t, 2)));
+      return wi::bit_or (tree_nonzero_bits (TREE_OPERAND (t, 1), prec),
+                        tree_nonzero_bits (TREE_OPERAND (t, 2), prec));
     CASE_CONVERT:
-      return wide_int::from (tree_nonzero_bits (TREE_OPERAND (t, 0)),
-                            TYPE_PRECISION (TREE_TYPE (t)),
-                            TYPE_SIGN (TREE_TYPE (TREE_OPERAND (t, 0))));
+      if (TREE_TYPE (t) != error_mark_node
+         && !error_operand_p (TREE_OPERAND (t, 0)))
+       {
+         tree op0 = TREE_OPERAND (t, 0);
+         tree inner_type = TREE_TYPE (op0);
+         unsigned inner_prec = TYPE_PRECISION (inner_type);
+         return wide_int::from (tree_nonzero_bits (op0, inner_prec),
+                                prec, TYPE_SIGN (inner_type));
+       }
+      break;
     case PLUS_EXPR:
       if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
        {
-         wide_int nzbits1 = tree_nonzero_bits (TREE_OPERAND (t, 0));
-         wide_int nzbits2 = tree_nonzero_bits (TREE_OPERAND (t, 1));
+         wide_int nzbits1 = tree_nonzero_bits (TREE_OPERAND (t, 0), prec);
+         wide_int nzbits2 = tree_nonzero_bits (TREE_OPERAND (t, 1), prec);
          if (wi::bit_and (nzbits1, nzbits2) == 0)
            return wi::bit_or (nzbits1, nzbits2);
        }
       break;
     case LSHIFT_EXPR:
-      if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
+      if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
+         && TREE_TYPE (t) != error_mark_node)
        {
          tree type = TREE_TYPE (t);
-         wide_int nzbits = tree_nonzero_bits (TREE_OPERAND (t, 0));
-         wide_int arg1 = wi::to_wide (TREE_OPERAND (t, 1),
-                                      TYPE_PRECISION (type));
+         wide_int nzbits = tree_nonzero_bits (TREE_OPERAND (t, 0), prec);
+         wide_int arg1 = wi::to_wide (TREE_OPERAND (t, 1), prec);
          return wi::neg_p (arg1)
                 ? wi::rshift (nzbits, -arg1, TYPE_SIGN (type))
                 : wi::lshift (nzbits, arg1);
        }
       break;
     case RSHIFT_EXPR:
-      if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
-        {
+      if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
+         && TREE_TYPE (t) != error_mark_node)
+       {
          tree type = TREE_TYPE (t);
-         wide_int nzbits = tree_nonzero_bits (TREE_OPERAND (t, 0));
-         wide_int arg1 = wi::to_wide (TREE_OPERAND (t, 1),
-                                      TYPE_PRECISION (type));
+         wide_int nzbits = tree_nonzero_bits (TREE_OPERAND (t, 0), prec);
+         wide_int arg1 = wi::to_wide (TREE_OPERAND (t, 1), prec);
          return wi::neg_p (arg1)
                 ? wi::lshift (nzbits, -arg1)
                 : wi::rshift (nzbits, arg1, TYPE_SIGN (type));
-        }
+       }
       break;
     default:
       break;
     }
 
-  return wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (t)));
+  return wi::shwi (-1, prec);
+}
+
+/* Given a tree T, compute which bits in T may be nonzero.  */
+
+wide_int
+tree_nonzero_bits (const_tree t)
+{
+  if (error_operand_p (t))
+    return wi::shwi (-1, 64);
+  return tree_nonzero_bits (t, TYPE_PRECISION (TREE_TYPE (t)));
 }
 
 /* Helper function for address compare simplifications in match.pd.
diff --git a/gcc/testsuite/gcc.dg/pr119651.c b/gcc/testsuite/gcc.dg/pr119651.c
new file mode 100644
index 000000000000..d89c3c2b8cf8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119651.c
@@ -0,0 +1,10 @@
+/* PR c/119651 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+int main() {
+   int r = 0;
+   while (r % 2 == 0) {
+   }
+   double r = (double) sizeof(int);  /* { dg-error "conflicting type" } */
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr123472.c b/gcc/testsuite/gcc.dg/pr123472.c
new file mode 100644
index 000000000000..2f690c03db97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr123472.c
@@ -0,0 +1,16 @@
+/* PR c/123472 */
+/* { dg-do compile } */
+/* { do-options "-O2" } */
+
+int a , b , c ;
+__attribute__ ( ( __noinline__ ) ) int fn1 ( ) {
+if ( ( b | ( a != ( a & c ) ) ) == 1 )
+__builtin_abort ( ) ;
+return 0 ;
+}
+int c ( void ) {  /* { dg-error "redeclared as different kind" } */
+a = 5 ;
+c = 1 ; /* { dg-error "lvalue required" } */
+b = 6 ;
+return fn1 ( ) ;
+}

Reply via email to