Skip to content

Commit

Permalink
Fix false negative when value initializing a field annotated with [[c…
Browse files Browse the repository at this point in the history
…lang::require_field_initialization]] (#124329)

It turns out we weren't handling one case: the value-initialization of a
field inside a struct.

I'm not sure why this falls under `IK_Direct` rather than `IK_Value` in
Clang, but it seems to work.
  • Loading branch information
higher-performance authored Jan 30, 2025
1 parent 72efe15 commit 20fd7df
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4573,7 +4573,9 @@ static void TryConstructorInitialization(Sema &S,

CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
if (Result != OR_Deleted) {
if (!IsListInit && Kind.getKind() == InitializationKind::IK_Default &&
if (!IsListInit &&
(Kind.getKind() == InitializationKind::IK_Default ||
Kind.getKind() == InitializationKind::IK_Direct) &&
DestRecordDecl != nullptr && DestRecordDecl->isAggregate() &&
DestRecordDecl->hasUninitializedExplicitInitFields()) {
S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init)
Expand Down
44 changes: 44 additions & 0 deletions clang/test/SemaCXX/uninitialized.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// RUN: %clang_cc1 -fsyntax-only -Wall -Wc++20-compat -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -Wno-uninitialized-const-reference -std=c++1z -verify %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -fsyntax-only -Wall -Wc++20-compat -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -Wno-uninitialized-const-reference -std=c++20 -verify %s

void* operator new(__SIZE_TYPE__, void*);

// definitions for std::move
namespace std {
inline namespace foo {
Expand Down Expand Up @@ -1540,6 +1542,48 @@ void aggregate() {
};
};

struct Embed {
int embed1; // #FIELD_EMBED1
int embed2 [[clang::require_explicit_initialization]]; // #FIELD_EMBED2
};
struct EmbedDerived : Embed {};
struct F {
Embed f1;
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
explicit F(const char(&)[1]) : f1() {
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1);
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1)();
#if __cplusplus >= 202002L
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1)(1);
#endif
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1){1};
}
#if __cplusplus >= 202002L
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
explicit F(const char(&)[2]) : f1(1) {}
#else
explicit F(const char(&)[2]) : f1{1, 2} { }
#endif
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
explicit F(const char(&)[3]) : f1{} {}
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
explicit F(const char(&)[4]) : f1{1} {}
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
explicit F(const char(&)[5]) : f1{.embed1 = 1} {}
};
F ctors[] = {
F(""),
F("_"),
F("__"),
F("___"),
F("____")
};
(void)ctors;

S::foo(S{1, 2, 3, 4});
S::foo(S{.s1 = 100, .s4 = 100});
S::foo(S{.s1 = 100}); // expected-warning {{field 's4' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_S4 {{'s4' declared here}}
Expand Down

0 comments on commit 20fd7df

Please sign in to comment.