This was discussed in the review of changes to support C++26 contracts [1]. Since the proposed change is independent of the contracts implementation, I have split it out.
So far tested on powerpc64le-linux (and x86_64-darwin with the contracts code, to ensure it still fixes the latent issue there). comments? OK for trunk? thanks Iain [1] https://inbox.sourceware.org/gcc-patches/[email protected]/ --- 8< --- 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 <[email protected]> --- gcc/cp/cp-gimplify.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index d65f61a96b27..cce3e0aa71c3 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -2512,12 +2512,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)); -- 2.50.1 (Apple Git-155)
