From: Iain Sandoe Date: Sat, 24 Jan 2026 14:22:43 +0000 (+0000) Subject: c++: Do not mark STATEMENT_LISTs as visited in genericization. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f5cb8a2382429383bc28dc52494cc47574df0e8;p=thirdparty%2Fgcc.git c++: Do not mark STATEMENT_LISTs as visited in genericization. This addresses a latent issue in C++ genericization (only seen in development code, so far). In the following code snippet using facilities from the proposed C++26 contracts implementation: while (!SWAPPER::isFinished()) { uc = SWAPPER::swapBytes(); if (0 != uc) { } } contract_assert( translator.d_capacity >= 1 ); During genericization, a statement list from the while loop is freed. The expansion of the contract_assert then requires a 'new' statement list. Since the statment list in the while has been visited, it was marked as such. A specific property of statement lists is that they are cached using a LIFO stack. So that the statement list picked for the contract_assert is the one freed from the while loop. However since that list entry has already been marked as visited, the newly created contract expansion is not visited (leading to an ICE). The solution here is to forgo marking STATEMENT_LISTs as visited in this code (which is provision for potential future cases, as well as resolving the specific instance seen). gcc/cp/ChangeLog: * cp-gimplify.cc (cp_genericize_r): Do not mark STATEMENT_LISTs as visited. Signed-off-by: Iain Sandoe --- diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 3c0f415fa87..30d6a07e376 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -2503,12 +2503,24 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) case OMP_TILE: case OMP_UNROLL: case OACC_LOOP: - case STATEMENT_LIST: /* These cases are handled by shared code. */ c_genericize_control_stmt (stmt_p, walk_subtrees, data, cp_genericize_r, cp_walk_subtrees); break; + case STATEMENT_LIST: + /* As above, handled by shared code. */ + c_genericize_control_stmt (stmt_p, walk_subtrees, data, + cp_genericize_r, cp_walk_subtrees); + /* If a statement list is freed as part of genericisation it will be + pushed onto the top of a statement list cache stack. A subsequent + action can cause a new statement list to be required - and the one + just pushed will be returned. If that is marked as visited, it can + prevent a tail recursion from processing the 'new' statement list, + so we do not mark statement lists as visited. */ + return NULL_TREE; + break; + case BIT_CAST_EXPR: *stmt_p = build1_loc (EXPR_LOCATION (stmt), VIEW_CONVERT_EXPR, TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));