[clang] [clang-tools-extra] [llvm] [clang] Fix false positive -Wmissing-field-initializer for anonymous unions (PR #70829)
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 6 13:55:25 PST 2023
================
@@ -727,6 +729,44 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
if (hadError || VerifyOnly) {
// Do nothing
} else if (Init < NumInits) {
+ if (MaybeEmitMFIWarning) {
+ auto CheckAnonMember = [&](const FieldDecl *FD,
+ auto &&CheckAnonMember) -> bool {
+ FieldDecl *FirstUninitialized = nullptr;
+ RecordDecl *RD = FD->getType()->getAsRecordDecl();
+ assert(RD && "Not anonymous member checked?");
+ for (auto *F : RD->fields()) {
+ bool AllSet = false;
+ if (F->isAnonymousStructOrUnion())
+ AllSet = CheckAnonMember(F, CheckAnonMember);
+
+ if (AllSet || F->hasInClassInitializer()) {
+ if (RD->isUnion())
+ return true;
+ continue;
+ }
+
+ if (!F->isUnnamedBitfield() &&
+ !F->getType()->isIncompleteArrayType() &&
+ !F->isAnonymousStructOrUnion() && !FirstUninitialized)
+ FirstUninitialized = F;
+ }
+
+ if (FirstUninitialized) {
+ SemaRef.Diag(Loc, diag::warn_missing_field_initializers)
+ << FirstUninitialized;
+ return false;
----------------
zygoloid wrote:
I think you should return `FirstUninitialized` here, and produce the warning at the top level if necessary. Right now it looks like this would produce a bogus warning for:
```
struct A {
union {
struct { int n; };
int m = 0;
};
int z;
};
A a = {.z = 1};
```
... because you'd visit the anonymous union, then recurse to the anonymous struct, then warn about `n`, then return to the anonymous union and find it's actually initialized.
https://github.com/llvm/llvm-project/pull/70829
More information about the cfe-commits
mailing list