https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126848
--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <[email protected]>: https://gcc.gnu.org/g:cb9d160c4dab693a3fc214736db2441ebbee6c35 commit r17-4631-gcb9d160c4dab693a3fc214736db2441ebbee6c35 Author: Jakub Jelinek <[email protected]> Date: Thu Sep 24 18:42:28 2026 +0200 middle-end: Fix up C++26 P2795R5 - Erroneous behavior for uninitialized reads [PR126848] As the following new testcases show, I've messed up the C++26 P2795R5 - Erroneous behavior for uninitialized reads implementation. What the paper requires for C++26 and later (unless user opts out of it with -ftrivial-auto-var-init=uninitialized, which effectively pretends everything that accepts [[indeterminate]] attribute has that attribute) is that multiple reads of the same uninitialized variable yield the same value (whatever it is) and as QoI that such uses are diagnosed with -Wuninitialized or -Wmaybe-uninitialized. The implementation implemented it as a new mode (not directly requestable by users using an option) of -ftrivial-auto-var-init= (the new mode used just for the case where -ftrivial-auto-var-init={zero,pattern} isn't used), with extra code in the FE to deal with vacuous initialization in switch bodies etc. for C++26 and some small changes during gimplification for the new AUTO_INIT_CXX26 mode. On various testcases it worked fine, but this bugreport shows that in the middle-end optimizations we actually need to treat it differently. In order to fullfill the C++26 requirements, we can't treat .DEFERRED_INIT for C++26 and later as something returning something uninitialized where optimizations happily optimize say a PHI with such uninitialized value and some other value as that other value, or some passes consider the result as UNDEFINED rather than VARYING. There is an option to come up with a different internal function for these C++26 uses of .DEFERRED_INIT, but because it has also many similarities with .DEFERRED_INIT (e.g. same expansion) and because the internal function already has an argument which is the flag_trivial_auto_var_init value, this patch just changes AUTO_INIT_CXX26 value from 3 to 4 so that it can be used as a mask, so now we have 6 different modes: AUTO_INIT_UNINITIALIZED (the default for non-C++ or C++ < 26) AUTO_INIT_ZERO (-ftrivial-auto-var-init=zero for non-C++ or C++ < 26) AUTO_INIT_PATTERN (-ftrivial-auto-var-init=pattern for non-C++ or C++ < 26) AUTO_INIT_CXX26 (the default for C++ >= 26) AUTO_INIT_ZERO | AUTO_INIT_CXX26 (-ftrivial-auto-var-init=zero for C++ >= 26) AUTO_INIT_PATTERN | AUTO_INIT_CXX26 (-ftrivial-auto-var-init=pattern for C++ >= 26) The option handling ensures to or in AUTO_INIT_CXX26 for C++26/29 unless -ftrivial-auto-var-init=uninitialized is used explicitly, and the ccp pass and ssa_undefined_value_p is changed so that it treats the AUTO_INIT_CXX26 modes of .DEFERRED_INIT differently (basically as a source of VARYING value). Because the uninit pass uses ssa_undefined_value_p, I had to change also has_undefined_value_p because for -Wuninitialized purposes we want to treat all .DEFERRED_INIT calls the same. 2026-09-24 Jakub Jelinek <[email protected]> PR c++/126848 gcc/ * flag-types.h (enum auto_init_type): Change AUTO_INIT_CXX26 value from 3 to 4. * gimplify.cc (gimplify_decl_expr): Mask off AUTO_INIT_CXX26 bit before comparing to AUTO_INIT_PATTERN. (gimplify_target_expr): Likewise. * internal-fn.cc (expand_DEFERRED_INIT): Likewise. Formatting fix. * opts.cc (finish_options): For -fhardened or in AUTO_INIT_CXX26 bit from previous value if it was set. Mask off AUTO_INIT_CXX26 bit before comparing to AUTO_INIT_ZERO. * tree-ssa-ccp.cc (likely_value): Return VARYING rather than UNDEFINED for .DEFERRED_INIT call with AUTO_INIT_CXX26 bit set in the second argument. * tree-ssa.cc (ssa_undefined_value_p): Return false rather than true for .DEFERRED_INIT call with AUTO_INIT_CXX26 bit set in the second argument. * tree-ssa-uninit.cc (has_undefined_value_p): Return true for SSA_NAMEs with .DEFERRED_INIT call as SSA_NAME_DEF_STMT. gcc/c-family/ * c-opts.cc (c_common_post_options): For -ftrivial-auto-var-init=zero or -ftrivial-auto-var-init=pattern in C++26 or later mode set AUTO_INIT_CXX26 bit in flag_auto_var_init. gcc/testsuite/ * c-c++-common/auto-init-1.c: Use [15] instead of 1 or [26] instead of 2 in regexps matching second .DEFERRED_INIT arguments. * c-c++-common/auto-init-2.c: Likewise. * c-c++-common/auto-init-3.c: Likewise. * c-c++-common/auto-init-4.c: Likewise. * c-c++-common/auto-init-5.c: Likewise. * c-c++-common/auto-init-6.c: Likewise. * c-c++-common/auto-init-7.c: Likewise. * c-c++-common/auto-init-8.c: Likewise. * c-c++-common/auto-init-9.c: Likewise. * c-c++-common/auto-init-10.c: Likewise. * c-c++-common/auto-init-11.c: Likewise. * c-c++-common/auto-init-12.c: Likewise. * c-c++-common/auto-init-13.c: Likewise. * c-c++-common/auto-init-14.c: Likewise. * c-c++-common/auto-init-15.c: Likewise. * c-c++-common/auto-init-16.c: Likewise. * c-c++-common/auto-init-esra.c: Likewise. * c-c++-common/auto-init-padding-1.c: Likewise. * g++.dg/cpp26/erroneous7.C: New test. * g++.dg/cpp26/erroneous8.C: New test. * g++.dg/cpp26/erroneous9.C: New test. Reviewed-by: Richard Biener <[email protected]> Reviewed-by: Jason Merrill <[email protected]>
