https://github.com/higher-performance created https://github.com/llvm/llvm-project/pull/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. >From a85c75382c275d9fee409dc0c768f2aced973cdf Mon Sep 17 00:00:00 2001 From: higher-performance <higher.performance.git...@gmail.com> Date: Fri, 24 Jan 2025 14:14:27 -0500 Subject: [PATCH] Fix false negative when value initializing a field annotated with [[clang::require_field_initialization]] --- clang/lib/Sema/SemaInit.cpp | 4 ++- clang/test/SemaCXX/uninitialized.cpp | 44 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index b95cbbf4222056..450edcb52ae15b 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -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) diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp index 52d9897cf9be6e..7578b288d7b3fe 100644 --- a/clang/test/SemaCXX/uninitialized.cpp +++ b/clang/test/SemaCXX/uninitialized.cpp @@ -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 { @@ -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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits