From: Jason Merrill Date: Tue, 6 Jun 2023 03:58:32 +0000 (-0400) Subject: c++: fix contracts with NRV X-Git-Tag: releases/gcc-12.4.0~577 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11afe64fb71c83cef7d56fe6c411fb7adeee59cb;p=thirdparty%2Fgcc.git c++: fix contracts with NRV The NRV implementation was blindly replacing the operand of RETURN_EXPR, clobbering anything that check_return_expr might have added on to the actual initialization, such as checking the postcondition. GCC 12 note: There are no contracts in GCC 12, but this issue also broke setting current_retval_sentinel. gcc/cp/ChangeLog: * semantics.cc (finalize_nrv_r): [RETURN_EXPR]: Only replace the INIT_EXPR. --- diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 5289131e591e..d6351d2d8a32 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -4859,9 +4859,17 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) *walk_subtrees = 0; /* Change all returns to just refer to the RESULT_DECL; this is a nop, but differs from using NULL_TREE in that it indicates that we care - about the value of the RESULT_DECL. */ + about the value of the RESULT_DECL. But preserve anything appended + by check_return_expr. */ else if (TREE_CODE (*tp) == RETURN_EXPR) - TREE_OPERAND (*tp, 0) = dp->result; + { + tree *p = &TREE_OPERAND (*tp, 0); + while (TREE_CODE (*p) == COMPOUND_EXPR) + p = &TREE_OPERAND (*p, 0); + gcc_checking_assert (TREE_CODE (*p) == INIT_EXPR + && TREE_OPERAND (*p, 0) == dp->result); + *p = dp->result; + } /* Change all cleanups for the NRV to only run when an exception is thrown. */ else if (TREE_CODE (*tp) == CLEANUP_STMT