Skip to content

Commit 20fd7df

Browse files
Fix false negative when value initializing a field annotated with [[clang::require_field_initialization]] (llvm#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.
1 parent 72efe15 commit 20fd7df

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

clang/lib/Sema/SemaInit.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4573,7 +4573,9 @@ static void TryConstructorInitialization(Sema &S,
45734573

45744574
CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
45754575
if (Result != OR_Deleted) {
4576-
if (!IsListInit && Kind.getKind() == InitializationKind::IK_Default &&
4576+
if (!IsListInit &&
4577+
(Kind.getKind() == InitializationKind::IK_Default ||
4578+
Kind.getKind() == InitializationKind::IK_Direct) &&
45774579
DestRecordDecl != nullptr && DestRecordDecl->isAggregate() &&
45784580
DestRecordDecl->hasUninitializedExplicitInitFields()) {
45794581
S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init)

clang/test/SemaCXX/uninitialized.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// 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
33
// 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
44

5+
void* operator new(__SIZE_TYPE__, void*);
6+
57
// definitions for std::move
68
namespace std {
79
inline namespace foo {
@@ -1540,6 +1542,48 @@ void aggregate() {
15401542
};
15411543
};
15421544

1545+
struct Embed {
1546+
int embed1; // #FIELD_EMBED1
1547+
int embed2 [[clang::require_explicit_initialization]]; // #FIELD_EMBED2
1548+
};
1549+
struct EmbedDerived : Embed {};
1550+
struct F {
1551+
Embed f1;
1552+
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1553+
explicit F(const char(&)[1]) : f1() {
1554+
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1555+
::new(static_cast<void*>(&f1)) decltype(f1);
1556+
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1557+
::new(static_cast<void*>(&f1)) decltype(f1)();
1558+
#if __cplusplus >= 202002L
1559+
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1560+
::new(static_cast<void*>(&f1)) decltype(f1)(1);
1561+
#endif
1562+
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1563+
::new(static_cast<void*>(&f1)) decltype(f1){1};
1564+
}
1565+
#if __cplusplus >= 202002L
1566+
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1567+
explicit F(const char(&)[2]) : f1(1) {}
1568+
#else
1569+
explicit F(const char(&)[2]) : f1{1, 2} { }
1570+
#endif
1571+
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1572+
explicit F(const char(&)[3]) : f1{} {}
1573+
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1574+
explicit F(const char(&)[4]) : f1{1} {}
1575+
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1576+
explicit F(const char(&)[5]) : f1{.embed1 = 1} {}
1577+
};
1578+
F ctors[] = {
1579+
F(""),
1580+
F("_"),
1581+
F("__"),
1582+
F("___"),
1583+
F("____")
1584+
};
1585+
(void)ctors;
1586+
15431587
S::foo(S{1, 2, 3, 4});
15441588
S::foo(S{.s1 = 100, .s4 = 100});
15451589
S::foo(S{.s1 = 100}); // expected-warning {{field 's4' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_S4 {{'s4' declared here}}

0 commit comments

Comments
 (0)