https://github.com/higher-performance updated https://github.com/llvm/llvm-project/pull/141133
>From f384cb655ca7412f80427fafb47a26c74917b9ff Mon Sep 17 00:00:00 2001 From: higher-performance <higher.performance.git...@gmail.com> Date: Thu, 22 May 2025 16:30:29 -0400 Subject: [PATCH 1/2] Include [[clang::require_explicit_initialization]] warnings in system headers Fixes #141103 --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++- clang/test/SemaCXX/uninitialized.cpp | 27 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0b2553d82153c..934f4453f02b9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2479,7 +2479,8 @@ def note_uninit_reference_member : Note< "uninitialized reference member is here">; def warn_field_requires_explicit_init : Warning< "field %select{%1|in %1}0 requires explicit initialization but is not " - "explicitly initialized">, InGroup<UninitializedExplicitInit>; + "explicitly initialized">, InGroup<UninitializedExplicitInit>, + ShowInSystemHeader; def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">, InGroup<Uninitialized>; def warn_base_class_is_uninit : Warning< diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp index c7cef3e06fb2b..98e1e93ec53cc 100644 --- a/clang/test/SemaCXX/uninitialized.cpp +++ b/clang/test/SemaCXX/uninitialized.cpp @@ -2,6 +2,23 @@ // 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 +#if defined(BE_THE_HEADER) + +// Wuninitialized-explicit-init should warn in system headers (std::construct_at...) too. + +#pragma clang system_header +namespace std { +template <class T, class... U> +constexpr T* construct_at(T* ptr, U&&... args) { + return ::new (static_cast<void*>(ptr)) T(static_cast<U&&>(args)...); // #FIELD_EMBED2_CONSTRUCT_AT +} +} + +#else + +#define BE_THE_HEADER +#include __FILE__ + void* operator new(__SIZE_TYPE__, void*); // definitions for std::move @@ -1564,11 +1581,11 @@ void aggregate() { 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)(); + // expected-warning@#FIELD_EMBED2_CONSTRUCT_AT {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@+1 {{in instantiation of function template specialization 'std::construct_at<Embed>' requested here}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}} + std::construct_at(&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); + // expected-warning@#FIELD_EMBED2_CONSTRUCT_AT {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@+1 {{in instantiation of function template specialization 'std::construct_at<Embed, int>' requested here}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}} + std::construct_at(&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}; @@ -1726,3 +1743,5 @@ void aggregate() { InheritWithExplicit<Special> specialized_implicit; // no-warning (void)specialized_implicit; } + +#endif >From c5d3605436197426f08724369c6e0acf534b6cab Mon Sep 17 00:00:00 2001 From: higher-performance <higher.performance.git...@gmail.com> Date: Tue, 27 May 2025 16:37:01 -0400 Subject: [PATCH 2/2] Suppress [[clang::require_explicit_initialization]] in unevaluated operands --- clang/include/clang/Basic/AttrDocs.td | 6 +++--- clang/lib/Sema/SemaInit.cpp | 14 +++++++++----- clang/test/Sema/uninit-variables.c | 2 ++ clang/test/SemaCXX/uninitialized.cpp | 2 ++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 43442f177ab7b..fefdaba7f8bf5 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1750,9 +1750,9 @@ to guard against use of uninitialized memory. Rather, it is intended for use in "parameter-objects", used to simulate, for example, the passing of named parameters. -The attribute generates a warning when explicit initializers for such -variables are not provided (this occurs regardless of whether any in-class field -initializers exist): +Except inside unevaluated contexts, the attribute generates a warning when +explicit initializers for such variables are not provided (this occurs +regardless of whether any in-class field initializers exist): .. code-block:: c++ diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 0844cb4d6c3cd..95746b35f71ef 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -790,7 +790,8 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, return; } - if (!VerifyOnly && Field->hasAttr<ExplicitInitAttr>()) { + if (!VerifyOnly && Field->hasAttr<ExplicitInitAttr>() && + !SemaRef.isUnevaluatedContext()) { SemaRef.Diag(ILE->getExprLoc(), diag::warn_field_requires_explicit_init) << /* Var-in-Record */ 0 << Field; SemaRef.Diag(Field->getLocation(), diag::note_entity_declared_at) @@ -4631,7 +4632,8 @@ static void TryConstructorInitialization(Sema &S, Kind.getKind() == InitializationKind::IK_Direct) && !(CtorDecl->isCopyOrMoveConstructor() && CtorDecl->isImplicit()) && DestRecordDecl->isAggregate() && - DestRecordDecl->hasUninitializedExplicitInitFields()) { + DestRecordDecl->hasUninitializedExplicitInitFields() && + !S.isUnevaluatedContext()) { S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init) << /* Var-in-Record */ 1 << DestRecordDecl; emitUninitializedExplicitInitFields(S, DestRecordDecl); @@ -5995,7 +5997,8 @@ static void TryOrBuildParenListInitialization( } else { // We've processed all of the args, but there are still members that // have to be initialized. - if (!VerifyOnly && FD->hasAttr<ExplicitInitAttr>()) { + if (!VerifyOnly && FD->hasAttr<ExplicitInitAttr>() && + !S.isUnevaluatedContext()) { S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init) << /* Var-in-Record */ 0 << FD; S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD; @@ -6617,7 +6620,7 @@ void InitializationSequence::InitializeFrom(Sema &S, if (RecordDecl *Rec = DestType->getAsRecordDecl()) { VarDecl *Var = dyn_cast_or_null<VarDecl>(Entity.getDecl()); if (Rec->hasUninitializedExplicitInitFields()) { - if (Var && !Initializer) { + if (Var && !Initializer && !S.isUnevaluatedContext()) { S.Diag(Var->getLocation(), diag::warn_field_requires_explicit_init) << /* Var-in-Record */ 1 << Rec; emitUninitializedExplicitInitFields(S, Rec); @@ -7481,7 +7484,8 @@ PerformConstructorInitialization(Sema &S, if (RD && RD->isAggregate() && RD->hasUninitializedExplicitInitFields()) { unsigned I = 0; for (const FieldDecl *FD : RD->fields()) { - if (I >= ConstructorArgs.size() && FD->hasAttr<ExplicitInitAttr>()) { + if (I >= ConstructorArgs.size() && FD->hasAttr<ExplicitInitAttr>() && + !S.isUnevaluatedContext()) { S.Diag(Loc, diag::warn_field_requires_explicit_init) << /* Var-in-Record */ 0 << FD; S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD; diff --git a/clang/test/Sema/uninit-variables.c b/clang/test/Sema/uninit-variables.c index 6d79d419f72e7..17e83de5f489a 100644 --- a/clang/test/Sema/uninit-variables.c +++ b/clang/test/Sema/uninit-variables.c @@ -580,4 +580,6 @@ void aggregate() { struct with_explicit_flex_array f = {2}; // expected-warning {{field 'flex_arr' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_FLEX_ARR {{'flex_arr' declared here}} (void)f; + + (void)sizeof({ struct with_explicit_field a; a; }); // no warning -- unevaluated operand } diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp index 98e1e93ec53cc..251e888f73973 100644 --- a/clang/test/SemaCXX/uninitialized.cpp +++ b/clang/test/SemaCXX/uninitialized.cpp @@ -1642,6 +1642,8 @@ void aggregate() { 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}} + (void)sizeof(S{}); // no warning -- unevaluated operand + S s{.s1 = 100, .s4 = 100}; (void)s; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits