}
}
+void removeFieldInitialized(const FieldDecl *M,
+ SmallPtrSetImpl<const FieldDecl *> &FieldDecls) {
+ const RecordDecl *R = M->getParent();
+ if (R && R->isUnion()) {
+ // Erase all members in a union if any member of it is initialized.
+ for (const auto *F : R->fields())
+ FieldDecls.erase(F);
+ } else
+ FieldDecls.erase(M);
+}
+
void removeFieldsInitializedInBody(
const Stmt &Stmt, ASTContext &Context,
SmallPtrSetImpl<const FieldDecl *> &FieldDecls) {
hasLHS(memberExpr(member(fieldDecl().bind("fieldDecl")))))),
Stmt, Context);
for (const auto &Match : Matches)
- FieldDecls.erase(Match.getNodeAs<FieldDecl>("fieldDecl"));
+ removeFieldInitialized(Match.getNodeAs<FieldDecl>("fieldDecl"), FieldDecls);
}
StringRef getName(const FieldDecl *Field) { return Field->getName(); }
// Gather all fields (direct and indirect) that need to be initialized.
SmallPtrSet<const FieldDecl *, 16> FieldsToInit;
- forEachField(ClassDecl, ClassDecl.fields(), [&](const FieldDecl *F) {
+ bool AnyMemberHasInitPerUnion = false;
+ forEachFieldWithFilter(ClassDecl, ClassDecl.fields(),
+ AnyMemberHasInitPerUnion, [&](const FieldDecl *F) {
if (IgnoreArrays && F->getType()->isArrayType())
return;
+ if (F->hasInClassInitializer() && F->getParent()->isUnion()) {
+ AnyMemberHasInitPerUnion = true;
+ removeFieldInitialized(F, FieldsToInit);
+ }
if (!F->hasInClassInitializer() &&
utils::type_traits::isTriviallyDefaultConstructible(F->getType(),
Context) &&
- !isEmpty(Context, F->getType()) && !F->isUnnamedBitfield())
+ !isEmpty(Context, F->getType()) && !F->isUnnamedBitfield() &&
+ !AnyMemberHasInitPerUnion)
FieldsToInit.insert(F);
});
if (FieldsToInit.empty())
if (Init->isAnyMemberInitializer() && Init->isWritten()) {
if (IsUnion)
return; // We can only initialize one member of a union.
- FieldsToInit.erase(Init->getAnyMember());
+ removeFieldInitialized(Init->getAnyMember(), FieldsToInit);
}
}
removeFieldsInitializedInBody(*Ctor->getBody(), Context, FieldsToInit);
// Collect all fields but only suggest a fix for the first member of unions,
// as initializing more than one union member is an error.
SmallPtrSet<const FieldDecl *, 16> FieldsToFix;
- bool AnyMemberHasInitPerUnion = false;
+ AnyMemberHasInitPerUnion = false;
forEachFieldWithFilter(ClassDecl, ClassDecl.fields(),
AnyMemberHasInitPerUnion, [&](const FieldDecl *F) {
if (!FieldsToInit.count(F))