[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