https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121876
David Malcolm <dmalcolm at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Last reconfirmed| |2025-09-09
Ever confirmed|0 |1
Status|UNCONFIRMED |ASSIGNED
--- Comment #1 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
A read-through null crash (PR c++/121859) is happening here:
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
at ../../src/gcc/cp/constraint.cc:3363
3363 if (TREE_CODE (expr) == TRAIT_EXPR)
(gdb) list
3363 if (TREE_CODE (expr) == TRAIT_EXPR)
3364 {
3365 diagnose_trait_expr (loc, expr, args);
3366 return true;
3367 }
(gdb) p expr
$1 = <tree 0x0>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
where the diagnostics subsystem attempts to emit an ICE, but it's already
midway through handling a nested diagnostic, and so during the emission of the
internal error, we hit this assertion:
#1 0x0000000003e773dd in diagnostics::context::set_diagnostic_buffer
(this=0x51c6cc0 <global_diagnostic_context>,
buffer_=0x0) at ../../src/gcc/diagnostics/buffering.cc:49
47 /* Likewise, for simplicity, we only allow changing buffers
48 at nesting level 0. */
49 gcc_assert (m_diagnostic_groups.m_diagnostic_nesting_level == 0);
due to:
(gdb) up
#2 0x0000000003d6b460 in diagnostics::context::finish (this=0x51c6cc0
<global_diagnostic_context>)
at ../../src/gcc/diagnostics/context.cc:370
370 set_diagnostic_buffer (nullptr);
but the context's buffer is already null, leading to an ICE inside the ICE
handler (but bailing out after the initial recursion).
Adding this patch gets a non-recursive ICE:
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
diff --git a/gcc/diagnostics/buffering.cc b/gcc/diagnostics/buffering.cc
index a7747b5a8f0..35c2f872280 100644
--- a/gcc/diagnostics/buffering.cc
+++ b/gcc/diagnostics/buffering.cc
@@ -39,6 +39,11 @@ namespace diagnostics {
void
context::set_diagnostic_buffer (buffer *buffer_)
{
+ /* Early reject of no-op
+ (to avoid recursively crashing when handling ICEs; see PR c++/121859).
*/
+ if (buffer_ == m_diagnostic_buffer)
+ return;
+
/* We don't allow changing buffering within a diagnostic group
(to simplify handling of buffered diagnostics within the
diagnostic_format implementations). */
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
which avoids the ICE-inside-ICE and better highlights the crash in the C++
frontend.
Presumably an ICE report should *not* be part of the group or nesting that
we're already within. The SARIF sink partially does that already, by treating
it as a notification rather than as a result. Probably can test this via a
compiler plugin.