On 9/17/25 6:08 PM, Jakub Jelinek wrote:
Hi!
Here is my current version of the C++26 P2795R5 support.
This now includes redirecting of forward/backward gotos
which cross vacuous initializations for -std=c++26 and
-ftrivial-auto-var-init={zero,pattern} by adding an artificial
if (0) { lab1: v1 = .DEFERRED_INIT (...); lab2: v2 = .DEFERRED_INIT (...); }
etc. hunk before the user label (or for case labels moving the case
label into it). Only one per adjacent set of labels, with perhaps
multiple artificial labels in it. I believe (and testing seems to
confirm that) that one only needs one set of such initialized vars
per the adjacent label group, if some forward or backward jump
crosses more vacuous inits, it will always cross a subset or superset
of the others and when the vars are ordered right, it can jump into
different positions in the same if (0).
Furthermore, -Wimplicit-fallthrough and -Wswitch-unreachable warnings
have been adjusted to deal with that.
-ftrivial-auto-var-init= also calls .DEFERRED_INIT for temporaries
if they have VOID_TYPE_P TARGET_EXPR_INITIAL (otherwise they are expanded
as INIT_EXPR of the TARGET_EXPR_SLOT and TARGET_EXPR_INITIAL and so
everything is initialized; trying to emit .DEFERRED_INIT in such a case
breaks a lot of stuff because e.g. const vars turned into static but
not static when .DEFERRED_INIT is done will try to write into .rodata).
-std=c++26 implies -ftrivial-auto-var-init= mode that doesn't have an
explicit user option and is like -ftrivial-auto-var-init=zero except
__builtin_clear_padding calls aren't added (C++26 doesn't make reads from
padding erroneous). User can still override it in both directions,
so -ftrivial-auto-var-init={zero,pattern} will behave like before (except
for the gotos/switches working for C++ right and temporaries being also
initialized), and -ftrivial-auto-var-init=uninitialized allows to get
C++23-ish behavior with other C++26 features enabled (if performance
is more important than some sanity of erroneous code).
The -flifetime-dse=2 {CLOBBER(bob)} clobbers aren't emitted anymore
at the start of (some) constructors but instead when gimplifying DECL_EXPRs
and TARGET_EXPRs. Haven't done it in gimplify.cc so that it roughly matches
previous behavior (C++ only, not all languages, and adding bob CLOBBERs
only on types which used them inside ctors for now (doing more breaks a lot
of stuff in the testsuite).
I understood you have a patch for {CLOBBER(bob)} for new expressions, there
are some regressions without that, see below.
Yes, my patches address those. It also runs into analyzer problems.
There are some regressions caused by the removal of {CLOBBER(bob)}
clobbers from the start of certain constructors, e.g. one testcase has
struct A
{
int f,g;
A() { f = g; // { dg-warning "g. is used uninitialized" } }
} a;
and this doesn't warn anymore for any C++ mode. Wonder what we could
do for the warnings, for code generation we have to assume the code
can read members in *this (for C++26 read there .DEFERRED_INIT, for
older C++ versions with -flifetime-dse=2 {CLOBBER(bob)}).
Perhaps we should add some artificial attribute to the functions we'd
add the -flifetime-dse=2 clobber to and treat *this reaching the start
of the function for those specially in the uninit pass?
Or some way to indicate in GIMPLE that whatever value is there, it's
poisoned?
Also there is one ICEs and various FAILs which reproduce even without
this patch with -ftrivial-auto-var-init=zero, I think I could temporarily
make those tests -ftrivial-auto-var-init=uninitialized until it is resolved.
Some tests got that already in the patch (e.g. ubsan/vla-1.c is testing UB
and will crash if one tries to write something into the -1 sized VLAs,
which -ftrivial-auto-var-init=zero or -std=c++26 do).
Makes sense.
So far only tested with
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-c++
and make check in libstdc++-v3.
The regressions (categorized) are below.
Your thoughts on this?
I hope the following would be fixed by your clobber new patch:
FAIL: g++.dg/opt/flifetime-dse2.C -std=gnu++11 execution test
FAIL: g++.dg/opt/flifetime-dse2.C -std=gnu++14 execution test
FAIL: g++.dg/opt/flifetime-dse2.C -std=gnu++17 execution test
FAIL: g++.dg/opt/flifetime-dse2.C -std=gnu++20 execution test
FAIL: g++.dg/opt/flifetime-dse2.C -std=gnu++23 execution test
FAIL: g++.dg/opt/flifetime-dse2.C -std=gnu++26 execution test
FAIL: g++.dg/opt/flifetime-dse2.C -std=gnu++98 execution test
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++11 brace (test for warnings,
line 29)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++11 LP64 note (test for
warnings, line 38)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++11 note (test for warnings,
line 48)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++14 brace (test for warnings,
line 29)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++14 LP64 note (test for
warnings, line 38)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++14 note (test for warnings,
line 48)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++17 brace (test for warnings,
line 29)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++17 LP64 note (test for
warnings, line 38)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++17 note (test for warnings,
line 48)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++20 brace (test for warnings,
line 29)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++20 LP64 note (test for
warnings, line 38)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++20 note (test for warnings,
line 48)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++23 brace (test for warnings,
line 29)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++23 LP64 note (test for
warnings, line 38)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++23 note (test for warnings,
line 48)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++26 brace (test for warnings,
line 29)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++26 LP64 note (test for
warnings, line 38)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++26 note (test for warnings,
line 48)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++98 brace (test for warnings,
line 29)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++98 LP64 note (test for
warnings, line 38)
FAIL: g++.dg/warn/Warray-bounds-20.C -std=gnu++98 note (test for warnings,
line 48)
Dunno what to do with these, see above.
FAIL: g++.dg/warn/Wuninitialized-10.C -std=gnu++11 (test for warnings, line
10)
FAIL: g++.dg/warn/Wuninitialized-10.C -std=gnu++14 (test for warnings, line
10)
FAIL: g++.dg/warn/Wuninitialized-10.C -std=gnu++17 (test for warnings, line
10)
FAIL: g++.dg/warn/Wuninitialized-10.C -std=gnu++20 (test for warnings, line
10)
FAIL: g++.dg/warn/Wuninitialized-10.C -std=gnu++23 (test for warnings, line
10)
FAIL: g++.dg/warn/Wuninitialized-10.C -std=gnu++26 (test for warnings, line
10)
FAIL: g++.dg/warn/Wuninitialized-10.C -std=gnu++98 (test for warnings, line
10)
FAIL: g++.dg/warn/Wuninitialized-pr111123-1.C -std=gnu++11 (test for
warnings, line 14)
FAIL: g++.dg/warn/Wuninitialized-pr111123-1.C -std=gnu++14 (test for
warnings, line 14)
FAIL: g++.dg/warn/Wuninitialized-pr111123-1.C -std=gnu++17 (test for
warnings, line 14)
FAIL: g++.dg/warn/Wuninitialized-pr111123-1.C -std=gnu++20 (test for
warnings, line 14)
FAIL: g++.dg/warn/Wuninitialized-pr111123-1.C -std=gnu++23 (test for
warnings, line 14)
FAIL: g++.dg/warn/Wuninitialized-pr111123-1.C -std=gnu++26 (test for
warnings, line 14)
PR121975 - perhaps I can just make those effective target c++23_down
temporarily with a comment
FAIL: c-c++-common/goacc-gomp/nesting-1.c -std=c++26 at line 30 (test for
warnings, line 31)
FAIL: c-c++-common/goacc-gomp/nesting-1.c -std=c++26 (test for excess errors)
FAIL: c-c++-common/goacc/kernels-decompose-2.c -std=c++26 at line 76 (test
for warnings, line 75)
FAIL: c-c++-common/goacc/kernels-decompose-2.c -std=c++26 (test for excess
errors)
FAIL: c-c++-common/goacc/kernels-decompose-pr100400-1-1.c -std=c++26 at line
23 (test for warnings, line 24)
FAIL: c-c++-common/goacc/kernels-decompose-pr100400-1-1.c -std=c++26 at line
28 (test for warnings, line 27)
FAIL: c-c++-common/goacc/kernels-decompose-pr100400-1-1.c -std=c++26 (test for
excess errors)
FAIL: c-c++-common/goacc/kernels-decompose-pr100400-1-3.c -std=c++26 at line
32 (test for warnings, line 33)
FAIL: c-c++-common/goacc/kernels-decompose-pr100400-1-3.c -std=c++26 at line
37 (test for warnings, line 36)
FAIL: c-c++-common/goacc/kernels-decompose-pr100400-1-3.c -std=c++26 (test for
excess errors)
FAIL: c-c++-common/goacc/kernels-decompose-pr100400-1-3.c -std=c++26 w/ debug
at line 29 (test for bogus messages, line 30)
FAIL: c-c++-common/goacc/kernels-decompose-pr104061-1-1.c -std=c++26 at line
26 (test for warnings, line 25)
FAIL: c-c++-common/goacc/kernels-decompose-pr104061-1-1.c -std=c++26 (test for
excess errors)
FAIL: c-c++-common/goacc/kernels-decompose-pr104061-1-3.c -std=c++26 at line
33 (test for warnings, line 32)
FAIL: c-c++-common/goacc/kernels-decompose-pr104061-1-3.c -std=c++26 w/ debug
at line 28 (test for bogus messages, line 29)
FAIL: c-c++-common/goacc/kernels-decompose-pr104061-1-4.c -std=c++26 at line
33 (test for warnings, line 32)
FAIL: c-c++-common/goacc/kernels-decompose-pr104061-1-4.c -std=c++26 w/ debug
at line 28 (test for bogus messages, line 29)
FAIL: c-c++-common/goacc/kernels-decompose-pr104132-1.c -std=c++26 (test for
excess errors)
FAIL: c-c++-common/goacc/kernels-decompose-pr104133-1.c -std=c++26 (test for
excess errors)
FAIL: c-c++-common/goacc/kernels-decompose-pr104774-1.c -std=c++26 (test for
excess errors)
FAIL: c-c++-common/goacc/mdc-1.c -std=c++26 scan-tree-dump-times omplower "pragma
omp target oacc_data map.tofrom:.z .len: 40.. map.struct:s .len: 1.. map.alloc:s.a .len:
8.. map.tofrom:._1 .len: 40.. map.attach:s.a .bias: 0.." 1
PR121977 - I'd like to fix this, but ideally separately from this patch, so
perhaps also c++23_down
FAIL: g++.dg/gomp/member-1.C -std=c++26 (internal compiler error: Segmentation
fault)
FAIL: g++.dg/gomp/member-1.C -std=c++26 (test for excess errors)
Dunno about these analyzer issues, will probably need David for that
FAIL: c-c++-common/analyzer/invalid-shift-1.c -std=c++26 (test for warnings,
line 15)
FAIL: c-c++-common/analyzer/invalid-shift-1.c -std=c++26 (test for warnings,
line 18)
FAIL: g++.dg/analyzer/exception-value-2.C -std=c++26 (test for excess errors)
FAIL: g++.dg/analyzer/exception-value-2.C -std=c++26 (test for warnings, line
34)
FAIL: g++.dg/analyzer/exception-value-2.C -std=c++26 (test for warnings, line
35)
With my patch I also see
FAIL: g++.dg/analyzer/new-2.C -std=c++26 (test for excess errors)
FAIL: g++.dg/analyzer/new-2.C -std=c++26 (test for warnings, line 62)
FAIL: g++.dg/analyzer/new-2.C -std=c++26 (test for warnings, line 64)
FAIL: g++.dg/analyzer/noexcept-new.C -std=c++26 at line 43 (test for
warnings, line 42)
FAIL: g++.dg/analyzer/noexcept-new.C -std=c++26 (test for excess errors)
FAIL: g++.dg/analyzer/noexcept-new.C -std=c++26 (test for warnings, line 20)
FAIL: g++.dg/analyzer/noexcept-new.C -std=c++26 (test for warnings, line 22)
FAIL: g++.dg/analyzer/noexcept-new.C -std=c++26 (test for warnings, line 40)
FAIL: g++.dg/analyzer/noexcept-new.C -std=c++26 (test for warnings, line 42)
...because the analyzer gets confused by the array clobbers, and warns
about that, and then says "NULL" instead of "possibly-NULL".
I'll check in most of my work today, and just leave out the change to
actually enable the clobber on non-placement new until we have a plan
for the analyzer issues.
Jason