[cfe-dev] -ftrivial-auto-var-init=pattern vs =uninitialized and union initialization

Vitaly Buka via cfe-dev cfe-dev at lists.llvm.org
Mon Sep 23 16:10:52 PDT 2019


Thanks.
Somehow I read the same text but interpreted it differently. Now it makes
sense, it must be zeroed and trivial-auto-var-init needs improvement.
I'll will create a patch.


On Mon, Sep 23, 2019 at 2:36 PM JF Bastien <jfbastien at apple.com> wrote:

> Hi Vitaly,
>
> Indeed: there are cases where clang happened to honor the standard without
> intending to (through the magic of memcpy’ing globals), and
> auto-init=pattern broke this. I got a report about it a while ago and agree
> it’s an issue, I haven’t had time to fix it. It’s related to what C calls
> “designated initializers” to initialize structs. The relevant standardese
> from C17 are in 6.7.9 Initialization (the grammar has “designator” being
> either “ [ constant-expression ] ” or “ . identifier ”).
>
> The relevant rules are:
>
> “””
> Except where explicitly stated otherwise, for the purposes of this
> subclause unnamed members of objects of structure and union type do not
> participate in initialization. Unnamed members of structure objects have
> indeterminate value even after initialization.
>
> If an object that has automatic storage duration is not initialized
> explicitly, its value is indeterminate. If an object that has static or
> thread storage duration is not initialized explicitly, then:
> — if it has pointer type, it is initialized to a null pointer;
> — if it has arithmetic type, it is initialized to (positive or unsigned)
> zero;
> — if it is an aggregate, every member is initialized (recursively)
> according to these rules, and any padding is initialized to zero bits;
> — if it is a union, the first named member is initialized (recursively)
> according to these rules, and any padding is initialized to zero bits;
>
> The initialization shall occur in initializer list order, each initializer
> provided for a particular subobject overriding any previously listed
> initializer for the same subobject; all subobjects that are not
> initialized explicitly shall be initialized implicitly the same as objects
> that have static storage duration.
>
> If there are fewer initializers in a brace-enclosed list than there are
> elements or members of an aggregate, or fewer characters in a string
> literal used to initialize an array of known size than there are
> elements in the array, the remainder of the aggregate shall be initialized
> implicitly the same as objects that have static storage duration.
> “””
>
> I had fixed something in https://reviews.llvm.org/D61280 but it’s not
> sufficient.
>
>
> I don’t think fixing this is giving up: it’s doing what the standard
> mandates.
>
> Are you interested in fixing it?
>
>
>
> On Sep 23, 2019, at 2:20 PM, Vitaly Buka <vitalybuka at google.com> wrote:
>
> Hi everyone,
>
> I am trying to enable -ftrivial-auto-var-init=pattern on various code and
> noticed inconvenient inconsistency with code like [1].
>
> According standard, as I understand, only the first member of the union
> must be initialized and the tail of the second member can stay
> uninitialized. If we use -ftrivial-auto-var-init=pattern it fills the tail
> using our pattern. However by default GCC, clang (without
> -ftrivial-auto-var-init), msvc all initialize entire union with 0s. Not
> sure if it's just coincidence or guaranteed feature.
>
> So -ftrivial-auto-var-init=pattern breaks such code. Especially bad if you
> don't know that U is a union and ={} looks good there.
>
> Should we consider giving up here and using zeroes for union tails even
> with -ftrivial-auto-var-init=pattern?
>
> 1. Example:
> union U {
>   char small[2];
>   char large[100];
> };
> void f(void*);
> void test() {
>   union U u = {};
>   f(&u);
> }
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20190923/0128bbe3/attachment.html>


More information about the cfe-dev mailing list