On Mon, Feb 23, 2026 at 12:45 AM Roger Sayle <[email protected]> wrote:
>
>
> Hi Richard,
> Thanks for the suggestion (see more below).
>
> > > > > This patch resolves PR c/119651 and PR c/123716 P4 regressions.
> > > > > Tested on x86_64-pc-linux-gnu with make bootstrap and make -k
> > > > > check with no new regressions.  Ok for mainline?
> > > >
> > > > The tree_nop_conversion_p change looks OK.  I wonder where we build
> > > > the CONVERT_EXPR with error operands though, ideally we'd not do
> > > > this but build error_mark_node for itself.
>
> I've now committed the independent tree_nop_conversion_p change to resolve
> PR c/123716.  Thanks.  The remaining fold-const.cc changes are discussed 
> below.
>
> > > You've asked this question before (can we avoid building error_operand_p
> > nodes?).
> > > Here https://gcc.gnu.org/pipermail/gcc-patches/2024-April/650244.html
> > > The problem is tree sharing (similar to RTL sharing in the RTL 
> > > optimizers).
> > > VAR_DECLs are conceptually placed in a symbol table, and these trees
> > > are re-used in multiple expressions in a function/compilation unit.
> > > The redeclaration of a variable with conflicting type, causes us to
> > > set/update it's type to error_mark_node, poisoning not only future
> > > uses, but all prior uses of that variable.  This means that
> > > problematic expressions are not error_operand_p at the time that they
> > > are built, but "magically" become error_operands_p at a later point.
> > >
> > > This is a bit like changing the register number in an RTL pseudo
> > > register, where all references to that pseudo change [during register 
> > > allocation].
> > >
> > > I completely agree it's ugly.
> >
> > Ah yeah, I now remember ...
> >
> > > One approach might be to consider redeclaration of variables a fatal
> > > error, and refuse to attempt to continue compilation any further.  The
> > > alternative is the current whack-a-mole where we attempt to make the
> > > middle-end's tree optimizers robust to VAR_DECL's with TREE_TYPE
> > error_mark_node.
> > > Automatic fuzz testing finds these ICEs faster than we can review their 
> > > fixes.
> >
> > Right.
> >
> > > >      CASE_CONVERT:
> > > > +      if (TREE_TYPE (t) == error_mark_node
> > > >
> > > > this sub-check I'd check
> > > >
> > > >     if (!error_operand_p (t))
> > > >
> > > > around the switch.
> > > >
> > > > +         || TREE_TYPE (TREE_OPERAND (t, 0)) == error_mark_node)
> > > > +       break;
> > >
> > > Of course if we'd know that we had an error_operand_p at build time,
> > > we'd have returned error_mark_node instead of constructing a
> > > CASE_CONVERT.
> >
> > So the patch is OK with the above adjustment.
>
> Checking through some related error_mark_node ICEs that have been closed as
> duplicates, I came across PR c/123472 which reveals the version 1 patch (plus 
> the
> suggested error_operand_p before the switch) is insufficient.  The problem is 
> what
> to return from tree_nonzero_bits when the type is error_mark node.  
> Unfortunately,
> wide-int.cc doesn't permit a ~0 return value of infinite or undefined 
> precision.  My
> next attempt to use an arbitrary precision of 64 bits (consistent with host 
> wide int)
> revealed that the recursive nature of tree_nonzero_bits expects a bitset 
> result with
> a specific precision (to support bit_and/bit_ior operations).  The solution 
> is to hoist
> the suggested error_operand_p even earlier, before the recursion, after which 
> calls
> to tree_nozero_bits can pass a precision, effectively TYPE_PRECISION 
> (TREE_TYPE (t)),
> that can be used (in the default return case of -1) without requiring that
> TREE_TYPE is (locally) valid.  Hopefully, this all makes sense.
>
> What do you think of this revised patch, which now resolves both
> PR 119651 (as before) and (now also) PR 123472?
>
> Tested on x86_64-pc-linux-gnu with make bootstrap and make -k check
> with no new regressions.  Ok for mainline?

Ugh.  I guess it's OK from a pragmatic point of view, but of course
it would ask for callers to instead do

   if (error_operand_p (t))
     ...
   nz = tree_nonzero_bits (t);

given the API does not have a true failure mode.  I fear that if you
return fixed 64 bits precision -1 you just postpone the inevitable
followon ICE due to precision mismatch on wide-int operations ...
Like we have

match.pd:       && (tree_nonzero_bits (@6) & tree_nonzero_bits (@7)) == 0)

Callers would already have guards against vector types for example
(likely they check INTEGRAL_TYPE_P (...) or sth).  There are "only"
27 callers to tree_nonzero_bits ...

Richard.

>
> 2026-02-22  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.
>
>
>
> Thanks in advance,
> Roger
> --
>

Reply via email to