aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorPodchishchaeva, Mariya <mariya.podchishchaeva@intel.com>2023-12-18 06:25:22 -0800
committerPodchishchaeva, Mariya <mariya.podchishchaeva@intel.com>2023-12-18 07:08:27 -0800
commit5cda366221236a43fdd89bca59e153b4384eaba8 (patch)
treeb888fc6a8d236d4a822c82ebf54fb8066f0b7664 /clang/lib/Sema/SemaInit.cpp
parentcd1038a46a337042da7685973332481eb9c37707 (diff)
downloadllvm-5cda366221236a43fdd89bca59e153b4384eaba8.zip
llvm-5cda366221236a43fdd89bca59e153b4384eaba8.tar.gz
llvm-5cda366221236a43fdd89bca59e153b4384eaba8.tar.bz2
Revert "[clang] Fix false positive -Wmissing-field-initializer for anonymous unions (#70829)"
This reverts commit a01307a6ee788fc6ac2e09e58f0f52e5666def86 and its follow-up fix 32d5221ec4810dd723ccebaabbda1df5d3b4cfcf. It caused unexpected warnings emitted for nested designators in C.
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r--clang/lib/Sema/SemaInit.cpp153
1 files changed, 62 insertions, 91 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 035eaae..d6459fd 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -465,8 +465,7 @@ class InitListChecker {
void FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE, bool &RequiresSecondPass,
- bool FillWithNoInit = false,
- bool WarnIfMissing = false);
+ bool FillWithNoInit = false);
void FillInEmptyInitializations(const InitializedEntity &Entity,
InitListExpr *ILE, bool &RequiresSecondPass,
InitListExpr *OuterILE, unsigned OuterIndex,
@@ -655,16 +654,11 @@ void InitListChecker::FillInEmptyInitForBase(
}
}
-static bool hasAnyDesignatedInits(const InitListExpr *IL) {
- return llvm::any_of(*IL, [=](const Stmt *Init) {
- return isa_and_nonnull<DesignatedInitExpr>(Init);
- });
-}
-
-void InitListChecker::FillInEmptyInitForField(
- unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity,
- InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit,
- bool WarnIfMissing) {
+void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
+ const InitializedEntity &ParentEntity,
+ InitListExpr *ILE,
+ bool &RequiresSecondPass,
+ bool FillWithNoInit) {
SourceLocation Loc = ILE->getEndLoc();
unsigned NumInits = ILE->getNumInits();
InitializedEntity MemberEntity
@@ -732,52 +726,15 @@ void InitListChecker::FillInEmptyInitForField(
if (hadError || VerifyOnly) {
// Do nothing
- } else {
- 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()) {
- FieldDecl *UninitializedFieldInF = nullptr;
- 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;
- }
- return Uninitialized;
- };
-
- FieldDecl *FieldToDiagnose = nullptr;
- if (Field->isAnonymousStructOrUnion())
- FieldToDiagnose = CheckAnonMember(Field, CheckAnonMember);
- else if (!Field->isUnnamedBitfield() &&
- !Field->getType()->isIncompleteArrayType())
- FieldToDiagnose = Field;
-
- if (FieldToDiagnose)
- SemaRef.Diag(Loc, diag::warn_missing_field_initializers)
- << FieldToDiagnose;
- }
-
- if (Init < NumInits) {
- ILE->setInit(Init, MemberInit.getAs<Expr>());
- } else if (!isa<ImplicitValueInitExpr>(MemberInit.get())) {
- // Empty initialization requires a constructor call, so
- // extend the initializer list to include the constructor
- // call and make a note that we'll need to take another pass
- // through the initializer list.
- ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs<Expr>());
- RequiresSecondPass = true;
- }
+ } else if (Init < NumInits) {
+ ILE->setInit(Init, MemberInit.getAs<Expr>());
+ } else if (!isa<ImplicitValueInitExpr>(MemberInit.get())) {
+ // Empty initialization requires a constructor call, so
+ // extend the initializer list to include the constructor
+ // call and make a note that we'll need to take another pass
+ // through the initializer list.
+ ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs<Expr>());
+ RequiresSecondPass = true;
}
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init))) {
@@ -845,36 +802,9 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
}
}
} else {
- InitListExpr *SForm =
- ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm();
// The fields beyond ILE->getNumInits() are default initialized, so in
// order to leave them uninitialized, the ILE is expanded and the extra
// fields are then filled with NoInitExpr.
-
- // Some checks that are required for missing fields warning are bound to
- // how many elements the initializer list originally was provided; perform
- // them before the list is expanded.
- bool WarnIfMissingField =
- !SForm->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
- ILE->getNumInits();
-
- // Disable check for missing fields when designators are used in C to
- // match gcc behaviour.
- // FIXME: Should we emulate possible gcc warning bug?
- WarnIfMissingField &=
- SemaRef.getLangOpts().CPlusPlus || !hasAnyDesignatedInits(SForm);
-
- if (OuterILE) {
- // When nested designators are present, there might be two nested init
- // lists created and only outer will contain designated initializer
- // expression, so check outer list as well.
- InitListExpr *OuterSForm = OuterILE->isSyntacticForm()
- ? OuterILE
- : OuterILE->getSyntacticForm();
- WarnIfMissingField &= SemaRef.getLangOpts().CPlusPlus ||
- !hasAnyDesignatedInits(OuterSForm);
- }
-
unsigned NumElems = numStructUnionElements(ILE->getType());
if (!RDecl->isUnion() && RDecl->hasFlexibleArrayMember())
++NumElems;
@@ -902,7 +832,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
return;
FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass,
- FillWithNoInit, WarnIfMissingField);
+ FillWithNoInit);
if (hadError)
return;
@@ -1017,6 +947,13 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
}
}
+static bool hasAnyDesignatedInits(const InitListExpr *IL) {
+ for (const Stmt *Init : *IL)
+ if (isa_and_nonnull<DesignatedInitExpr>(Init))
+ return true;
+ return false;
+}
+
InitListChecker::InitListChecker(
Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T,
bool VerifyOnly, bool TreatUnavailableAsInvalid, bool InOverloadResolution,
@@ -2288,8 +2225,12 @@ void InitListChecker::CheckStructUnionTypes(
size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
return isa<FieldDecl>(D) || isa<RecordDecl>(D);
});
+ bool CheckForMissingFields =
+ !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
bool HasDesignatedInit = false;
+ llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
+
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
SourceLocation InitLoc = Init->getBeginLoc();
@@ -2313,17 +2254,24 @@ void InitListChecker::CheckStructUnionTypes(
// Find the field named by the designated initializer.
DesignatedInitExpr::Designator *D = DIE->getDesignator(0);
- if (!VerifyOnly && D->isFieldDesignator() && !DesignatedInitFailed) {
+ if (!VerifyOnly && D->isFieldDesignator()) {
FieldDecl *F = D->getFieldDecl();
- QualType ET = SemaRef.Context.getBaseElementType(F->getType());
- if (checkDestructorReference(ET, InitLoc, SemaRef)) {
- hadError = true;
- return;
+ InitializedFields.insert(F);
+ if (!DesignatedInitFailed) {
+ QualType ET = SemaRef.Context.getBaseElementType(F->getType());
+ if (checkDestructorReference(ET, InitLoc, SemaRef)) {
+ hadError = true;
+ return;
+ }
}
}
InitializedSomething = true;
+ // Disable check for missing fields when designators are used.
+ // This matches gcc behaviour.
+ if (!SemaRef.getLangOpts().CPlusPlus)
+ CheckForMissingFields = false;
continue;
}
@@ -2402,6 +2350,7 @@ void InitListChecker::CheckStructUnionTypes(
CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
StructuredList, StructuredIndex);
InitializedSomething = true;
+ InitializedFields.insert(*Field);
if (RD->isUnion() && StructuredList) {
// Initialize the first field within the union.
@@ -2411,6 +2360,28 @@ void InitListChecker::CheckStructUnionTypes(
++Field;
}
+ // Emit warnings for missing struct field initializers.
+ if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
+ !RD->isUnion()) {
+ // It is possible we have one or more unnamed bitfields remaining.
+ // Find first (if any) named field and emit warning.
+ for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
+ : Field,
+ end = RD->field_end();
+ it != end; ++it) {
+ if (HasDesignatedInit && InitializedFields.count(*it))
+ continue;
+
+ if (!it->isUnnamedBitfield() && !it->hasInClassInitializer() &&
+ !it->getType()->isIncompleteArrayType()) {
+ SemaRef.Diag(IList->getSourceRange().getEnd(),
+ diag::warn_missing_field_initializers)
+ << *it;
+ break;
+ }
+ }
+ }
+
// Check that any remaining fields can be value-initialized if we're not
// building a structured list. (If we are, we'll check this later.)
if (!StructuredList && Field != FieldEnd && !RD->isUnion() &&