> On Sep 3, 2025, at 09:38, Jakub Jelinek <[email protected]> wrote:
>
> On Tue, Sep 02, 2025 at 09:35:04PM +0000, Qing Zhao wrote:
>>> I think I've mentioned it earlier, but -ftrivial-auto-var-init= doesn't
>>> work at all for C++.
>> You mean that -ftrivial-auto-var-init hasn’t work at all for C++’s auto
>> variables with non-trivial ctors?
>
> Yeah. Actually, it probably also works if non-trivial ctors are constexpr
> and the ctors are actually optimized into TREE_CONSTANT DECL_INITIALIZER.
For such case, the CLOBBER (bob) is not emitted?
>
>>> With C++26 P2795R5 being voted in, if we were to default to say
>>> -ftrivial-auto-var-init=zero for -std=c++26/-std=gnu++26, that would mean
>>> the paper isn't really implemented.
>>
>> I briefly read C++26 P2795R5 this morning (still have some questions, not
>> fully understand yet), my major question is:
>>
>> When -ftrivial-auto-var-init=zero is combined with C++26 P2795R5, what’s the
>> correct behavior the user is expecting? When reading an uninitialized
>> variable
>> is considered an well-defined erroneous behavior, can the user still use
>> -ftrivial-auto-var-init to initialize the auto vairables?
>
> I think it is pretty much the same thing, we want -Wuninitialized to
> complain both in -std=c++26 and if -ftrivial-auto-var-init={zero,pattern}
> and still want to initialize (and either zero or pattern initialization is
> fine). So I'd go for -std={gnu,c}++26 implying
> flag_auto_var_init = AUTO_INIT_CXX26 if
> -ftrivial-auto-var-init={zero,pattern} has not been specified,
> and for that
> mode most likely just zero initialize and don't bother with padding bits.
You mean, under the new AUTO_INIT_CXX26 mode, ONLY all the fields of the
structure
are zero initialized, but leave the paddings uninitialized?
> Plus as Jason said, move the CLOBBER_OBJECT_BEGIN clobbers from ctors for
> flag_auto_var_init != AUTO_INIT_UNINITIALIZED && flag_lifetime_dse > 1
> to before the whole object is initialized in all places where we emit calls
> to the non-trivial ctors and if it initializes a VAR_DECL (rather than say
> heap) emit .DEFERRED_INIT calls after those.
A little confused with the above:
Currently, we have the following IR (t.cc <http://t.cc/>.006t.gimple): (with
-ftrivial-auto-var-init=zero)
Int foo ()
{
struct S s;
…
try
{
s = .DEFERRED_INIT (12, 2, &"s"[0]);
S::S (&s);
…
}
void S::S (struct S * const this)
{
*this = {CLOBBER(bob)};
{
this->a = 42;
}
}
Will the suggested new IR for the above be the following?
Int foo ()
{
struct S s;
…
try
{
s = {CLOBBER(bob));
S::S (&s);
s = .DEFFERRED_INIT (12, 2, &”s”[0]);
…
}
void S::S (struct S * const this)
{
this->a = 42;
}
Or something else?
>
> But there is one thing the paper doesn't care about, which looks like a show
> stopper to me, in particular the stuff -Wtrivial-auto-var-init warning warns
> about. Consider:
>
> template <typename T>
> void bar (T &);
>
> template <typename T>
> void
> foo (int x)
> {
> switch (x)
> {
> case 1:
> T t;
> bar (t);
> // FALLTHRU
> case 2:
> bar (t);
> break;
> default:
> break;
> }
> }
>
> struct S { S (); S (int); ~S (); int s; };
>
> void
> baz (int x)
> {
> foo <S> (x);
> foo <int> (x);
> }
>
> The foo <S> instantiation is invalid and we do diagnose that as
> error that the switch (but could be goto too) jumps across initialization
> of the t variable. Similarly if there is T t = 42; instead of T t;
> both foo <S> and foo <int> will be rejected. But with just T t; in there
> foo <int> is accepted as valid, one can jump across it but it used to be
> undefined behavior in both bar (t); calls, or say with t = 42; before the
> first bar just undefined behavior in case of foo <int> (2);
> But now it is supposed to be erroneous behavior but it is unclear where
> it can initialize the t variable to the erroneous value. Silently promote
> the variable to wider scope and initialize there, or add some wider scope
> flag which tracks if it is initialized or not and on any label initializes
> it if not yet initialized? It is unclear how such wider scope vars would
> play with say OpenMP/OpenACC.
>
> See http://eel.is/c++draft/stmt.dcl#2 and
> http://eel.is/c++draft/basic.life#2.sentence-2
Need to study the above a little bit more….
>
>>> One problem with this are [[indeterminate]] vars, if .DEFERRED_INIT is
>>> emitted in the ctors, the vars will be cleared even if they are
>>> [[indeterminate]] (unless the ctors are inlined and some optimization
>>> figures out, these vars are [[indeterminate]], let's drop all .DEFERRED_INIT
>>> calls for those and their subparts.
>>
>> If the value need to be kept as [[indeterminate]], what’s the purpose to use
>> -ftrivial-auto-var-init?
>
> I think even explicit -ftrivial-auto-var-init={zero,pattern} should treat
> [[indeterminate]] variables like those having the [[gnu::uninitialized]]
> attribute.
Okay, so [[indeterminate]] is a new attribute that will attached to the
variables, meaning
that the value of the variable is intended to be indeterminate?
Looks like it’s similar as the attribute uninitialized.
thanks.
Qing
>
> Jakub
>