←back to thread

GCC 15.1

(gcc.gnu.org)
270 points jrepinc | 2 comments | | HN request time: 0s | source
Show context
Calavar ◴[] No.43792948[source]
> {0} initializer in C or C++ for unions no longer guarantees clearing of the whole union (except for static storage duration initialization), it just initializes the first union member to zero. If initialization of the whole union including padding bits is desirable, use {} (valid in C23 or C++) or use -fzero-init-padding-bits=unions option to restore old GCC behavior.

This is going to silently break so much existing code, especially union based type punning in C code. {0} used to guarantee full zeroing and {} did not, and step by step we've flipped the situation to the reverse. The only sensible thing, in terms of not breaking old code, would be to have both {0} and {} zero initialize the whole union.

I'm sure this change was discussed in depth on the mailing list, but it's absolutely mind boggling to me

replies(14): >>43793036 #>>43793080 #>>43793121 #>>43793150 #>>43793166 #>>43794045 #>>43794558 #>>43796460 #>>43798312 #>>43798826 #>>43800132 #>>43800234 #>>43800932 #>>43800975 #
mtklein ◴[] No.43793166[source]
This was my instinct too, until I got this little tickle in the back of my head that maybe I remembered that Clang was already acting like this, so maybe it won't be so bad. Notice 32-bit wzr vs 64-bit xzr:

    $ cat union.c && clang -O1 -c union.c -o union.o && objdump -d union.o
    union foo {
        float  f;
        double d;
    };

    void create_f(union foo *u) {
        *u = (union foo){0};
    }

    void create_d(union foo *u) {
        *u = (union foo){.d=0};
    }

    union.o: file format mach-o arm64

    Disassembly of section __TEXT,__text:

    0000000000000000 <ltmp0>:
           0: b900001f      str wzr, [x0]
           4: d65f03c0      ret

    0000000000000008 <_create_d>:
           8: f900001f      str xzr, [x0]
           c: d65f03c0      ret
replies(1): >>43793251 #
1. mtklein ◴[] No.43793251[source]
Ah, I can confirm what I see elsewhere in the thread, this is no longer true in Clang. That first clang was Apple Clang 17---who knows what version that actually is---and here is Clang 20:

    $ /opt/homebrew/opt/llvm/bin/clang-20 -O1 -c union.c -o union.o && objdump -d union.o

    union.o: file format mach-o arm64

    Disassembly of section __TEXT,__text:

    0000000000000000 <ltmp0>:
           0: f900001f      str xzr, [x0]
           4: d65f03c0      ret

    0000000000000008 <_create_d>:
           8: f900001f      str xzr, [x0]
           c: d65f03c0      ret
replies(1): >>43794157 #
2. dzaima ◴[] No.43794157[source]
Looks like that change is clang ≤19 to clang 20: https://godbolt.org/z/7zrocxGaq