[llvm] [clang-tools-extra] [clang] [clang] Fix false positive -Wmissing-field-initializer for anonymous unions (PR #70829)
Richard Smith via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 9 11:50:12 PST 2023
================
@@ -727,6 +734,38 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
if (hadError || VerifyOnly) {
// Do nothing
} else if (Init < NumInits) {
+ if (WarnIfMissing) {
+ auto CheckAnonMember = [&](const FieldDecl *FD,
+ auto &&CheckAnonMember) -> FieldDecl * {
+ FieldDecl *Uninitialized = nullptr;
+ RecordDecl *RD = FD->getType()->getAsRecordDecl();
+ assert(RD && "Not anonymous member checked?");
+ for (auto *F : RD->fields()) {
+ if (F->isAnonymousStructOrUnion())
+ Uninitialized = CheckAnonMember(F, CheckAnonMember);
+ else if (!F->isUnnamedBitfield() &&
+ !F->getType()->isIncompleteArrayType() && !Uninitialized &&
+ !F->hasInClassInitializer())
+ Uninitialized = F;
+
+ if (RD->isUnion() && (F->hasInClassInitializer() || !Uninitialized))
+ return nullptr;
+ }
----------------
zygoloid wrote:
I think this will not warn on
```c++
struct A {
int a;
struct {
int x;
struct { int y = 0; };
};
};
A a = A{.a = 0};
```
... because the `Uninitialized` value for `x` will get overwritten by the `nullptr` returned from the struct containing `y`. How about:
```suggestion
for (auto *F : RD->fields()) {
FieldDecl *UninitializedFieldInF;
if (F->isAnonymousStructOrUnion())
UninitializedFieldInF = CheckAnonMember(F, CheckAnonMember);
else if (!F->isUnnamedBitfield() &&
!F->getType()->isIncompleteArrayType() &&
!F->hasInClassInitializer())
UninitializedFieldInF = F;
if (RD->isUnion() && !UninitializedFieldInF)
return nullptr;
if (!Uninitialized)
Uninitialized = UninitializedFieldInF;
}
```
https://github.com/llvm/llvm-project/pull/70829
More information about the llvm-commits
mailing list