-
Notifications
You must be signed in to change notification settings - Fork 13.5k
No -Wc++-compat warning on uninitialized const field in struct #19297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This also happens to global const variable. $: cat s.c |
Unlike C++, C allows the definition of an uninitialized `const` object. If the object has static or thread storage duration, it is still zero-initialized, otherwise, the object is left uninitialized. In either case, the code is not compatible with C++. This adds a new diagnostic group, `-Wdefault-const-init-unsafe`, which is on by default and diagnoses any definition of a `const` object which remains uninitialized. It also adds another new diagnostic group, `-Wdefault-const-init` (which also enabled the `unsafe` variant) that diagnoses any definition of a `const` object (including ones which are zero-initialized). This diagnostic is off by default. Finally, it adds `-Wdefault-const-init` to `-Wc++-compat`. GCC diagnoses these situations under this flag. Fixes llvm#19297
Unlike C++, C allows the definition of an uninitialized `const` object. If the object has static or thread storage duration, it is still zero-initialized, otherwise, the object is left uninitialized. In either case, the code is not compatible with C++. This adds a new diagnostic group, `-Wdefault-const-init-unsafe`, which is on by default and diagnoses any definition of a `const` object which remains uninitialized. It also adds another new diagnostic group, `-Wdefault-const-init` (which also enabled the `unsafe` variant) that diagnoses any definition of a `const` object (including ones which are zero-initialized). This diagnostic is off by default. Finally, it adds `-Wdefault-const-init` to `-Wc++-compat`. GCC diagnoses these situations under this flag. Fixes llvm#19297
Unlike C++, C allows the definition of an uninitialized `const` object. If the object has static or thread storage duration, it is still zero-initialized, otherwise, the object is left uninitialized. In either case, the code is not compatible with C++. This adds a new diagnostic group, `-Wdefault-const-init-unsafe`, which is on by default and diagnoses any definition of a `const` object which remains uninitialized. It also adds another new diagnostic group, `-Wdefault-const-init` (which also enabled the `unsafe` variant) that diagnoses any definition of a `const` object (including ones which are zero-initialized). This diagnostic is off by default. Finally, it adds `-Wdefault-const-init` to `-Wc++-compat`. GCC diagnoses these situations under this flag. Fixes llvm#19297
Unlike C++, C allows the definition of an uninitialized `const` object. If the object has static or thread storage duration, it is still zero-initialized, otherwise, the object is left uninitialized. In either case, the code is not compatible with C++. This adds a new diagnostic group, `-Wdefault-const-init-unsafe`, which is on by default and diagnoses any definition of a `const` object which remains uninitialized. It also adds another new diagnostic group, `-Wdefault-const-init` (which also enabled the `unsafe` variant) that diagnoses any definition of a `const` object (including ones which are zero-initialized). This diagnostic is off by default. Finally, it adds `-Wdefault-const-init` to `-Wc++-compat`. GCC diagnoses these situations under this flag. Fixes llvm#19297
The changes to fix this bug seem to have introduced a spurious warning when the uninitialized const object is a C flexible array. In this case there is nothing to initialize: https://godbolt.org/z/xPYa3E7vx
(and the C99 spec specifically says it would be an error to try to initialize the flexible-array member), but clang head-of-trunk now complains:
GCC trunk doesn't complain about this, and nor does clang 20.1.0. (Noticed originally because this provokes a warning for QEMU: https://gitlab.com/qemu-project/qemu/-/issues/2970 . The repro above is a cut down version of that.) |
I think the warning should maybe be silenced in the case of a FAM, though stack allocating an object with a FAM is already pretty tenuous ground. But I also think the warning should be silenced in FAM-like constructs, such as #140578 is the PR for updating this. |
Agreed that stack-allocating the object with a FAM is a bit odd (slightly surprising the compiler doesn't warn about that, but perhaps it's too widespread a practice to complain about?). In this case the actual QEMU code is writing data structures out to a file, so it fills in the stack-allocated debug_entry, fwrite()s that to the file, and then separately fwrite()s the string that corresponds to the name[] field. That lets it avoid dynamically re-allocating the memory every time round the loop. https://gitlab.com/qemu-project/qemu/-/blob/757a34115e7491744a63dfc3d291fd1de5297ee2/tcg/perf.c#L244 is the actual usage if you're interested. In this case we could simply define the struct without the FAM on the end, since we never actually use that member. However, the reason we have it is that the debug_entry struct is the same definition as the kernel's one in tools/perf/util/jitdump.h. The definition of struct jr_code_debug_info (again, borrowed from jitdump.h) as ending with a FAM whose entries are structs ending with a FAM is also a construct I'm surprised the compiler doesn't complain about :-) |
Thanks for the explanation, that's good to know! |
Extended Description
At trunk 201801. I am not sure whether clang support the warning flag -Wc++-compat. Currently it does not warn on the uninitialized field in a struct.
$: cat s.c
struct S{const int i;};
void f() {struct S s;}
$: clang-trunk -Wc++-compat -c s.c
$: clang++ -c s.c
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
s.c:1:8: error: implicit default constructor for 'S' must explicitly initialize the const member 'i'
struct S{const int i;};
^
s.c:1:20: note: declared here
struct S{const int i;};
^
s.c:2:20: note: implicit default constructor for 'S' first required here
void f() {struct S s;}
^
1 error generated.
$:
$: gcc-trunk -Wc++-compat -c s.c
s.c: In function ‘f’:
s.c:2:20: warning: uninitialized const member in ‘struct S’ is invalid in C++ [-Wc++-compat]
void f() {struct S s;}
^
s.c:1:20: note: ‘i’ should be initialized
struct S{const int i;};
^
The text was updated successfully, but these errors were encountered: