https://github.com/PathriVidyaPraveen updated https://github.com/llvm/llvm-project/pull/234210
>From fb92db652abb5800373db99febf79b03afc0fa99 Mon Sep 17 00:00:00 2001 From: PathriVidyaPraveen <[email protected]> Date: Wed, 21 Oct 2026 13:16:36 +0000 Subject: [PATCH 1/3] [Clang] Diagnose uninitialized C tentative definitions Diagnose tentative definitions that are never completed and contain fields marked require_explicit_initialization. Such definitions are zero-initialized under C17 6.9.2p2, bypassing the existing check. Fixes #232483 Assisted-by: Claude (regression test development) --- clang/docs/ReleaseNotes.md | 5 +++ clang/lib/Sema/Sema.cpp | 13 +++++++ .../attr-require-explicit-init-tentative.c | 35 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 clang/test/Sema/attr-require-explicit-init-tentative.c diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index ab5c116c3164a6..3bf2700bb42ac6 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -419,6 +419,11 @@ features cannot lower the translation-unit ABI level; ### Improvements to Clang's diagnostics +- `-Wuninitialized-explicit-init` now diagnoses C tentative definitions that are + never completed with an initializer, such as `struct S s;` at file scope, + which leave fields marked `require_explicit_initialization` zero-initialized. + (#GH232483) + - Fixed spurious `-Wimplicit-void-ptr-cast` warnings in C for parenthesized null pointer macros such as `(NULL)`. (#GH171874) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 9abab22e3809f3..9fc935c025141d 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1550,6 +1550,19 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(VD->getLocation(), DiagID) << Type << EmitCppCompat; } + // Uncompleted tentative definitions are zero-initialized (C17 6.9.2p2) so diagnose fields requiring explicit initialization. + if (!VD->isInvalidDecl() && !getLangOpts().CPlusPlus && + !VD->getAnyInitializer()) { + if (const RecordDecl *RD = Type->getAsRecordDecl(); + RD && RD->hasUninitializedExplicitInitFields()) { + Diag(VD->getLocation(), diag::warn_field_requires_explicit_init) + << /*Var-in-Record=*/1 << RD; + for (const FieldDecl *FD : RD->fields()) + if (FD->hasAttr<ExplicitInitAttr>()) + Diag(FD->getLocation(), diag::note_entity_declared_at) << FD; + } + } + // Notify the consumer that we've completed a tentative definition. if (!VD->isInvalidDecl()) Consumer.CompleteTentativeDefinition(VD); diff --git a/clang/test/Sema/attr-require-explicit-init-tentative.c b/clang/test/Sema/attr-require-explicit-init-tentative.c new file mode 100644 index 00000000000000..07de4ff793f616 --- /dev/null +++ b/clang/test/Sema/attr-require-explicit-init-tentative.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c17 -fsyntax-only -Wuninitialized-explicit-init -verify %s +// RUN: %clang_cc1 -std=c23 -fsyntax-only -Wuninitialized-explicit-init -verify %s + +struct ops { + int (*show)(void) __attribute__((require_explicit_initialization)); // #SHOW + int flags; +}; + +struct plain { + int a; +}; + +struct ops never_completed; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} +static struct ops never_completed_static; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} + +struct ops repeated; +struct ops repeated; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} + +struct ops completed_later; +struct ops completed_later = { .flags=1}; // expected-warning {{field 'show' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} + +struct ops completed_ok; +struct ops completed_ok = { .show=0}; + +extern struct ops ext; + +struct late g_late; // expected-warning {{field in 'late' requires explicit initialization but is not explicitly initialized}} expected-note@#LATE_X {{'x' declared here}} +struct late { + int x __attribute__((require_explicit_initialization)); // #LATE_X +}; + +void f(void){ + static struct ops local_static; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} + (void)&local_static; +} \ No newline at end of file >From d1a8d09352505a2b7a791e6e475da6eec3a96ca2 Mon Sep 17 00:00:00 2001 From: PathriVidyaPraveen <[email protected]> Date: Wed, 21 Oct 2026 17:03:28 +0000 Subject: [PATCH 2/3] Addressed review comments --- clang/docs/ReleaseNotes.md | 5 ++--- clang/lib/Sema/Sema.cpp | 3 ++- clang/test/Sema/attr-require-explicit-init-tentative.c | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 3bf2700bb42ac6..81a9e8c93f0bca 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -419,9 +419,8 @@ features cannot lower the translation-unit ABI level; ### Improvements to Clang's diagnostics -- `-Wuninitialized-explicit-init` now diagnoses C tentative definitions that are - never completed with an initializer, such as `struct S s;` at file scope, - which leave fields marked `require_explicit_initialization` zero-initialized. +- Fixed missing `-Wuninitialized-explicit-init` warnings for C file-scope + tentative definitions containing fields marked `require_explicit_initialization`. (#GH232483) - Fixed spurious `-Wimplicit-void-ptr-cast` warnings in C for parenthesized diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 9fc935c025141d..2e8a22bda240e2 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1550,7 +1550,8 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(VD->getLocation(), DiagID) << Type << EmitCppCompat; } - // Uncompleted tentative definitions are zero-initialized (C17 6.9.2p2) so diagnose fields requiring explicit initialization. + // Uncompleted tentative definitions are zero-initialized (C17 6.9.2p2) so + // diagnose fields requiring explicit initialization. if (!VD->isInvalidDecl() && !getLangOpts().CPlusPlus && !VD->getAnyInitializer()) { if (const RecordDecl *RD = Type->getAsRecordDecl(); diff --git a/clang/test/Sema/attr-require-explicit-init-tentative.c b/clang/test/Sema/attr-require-explicit-init-tentative.c index 07de4ff793f616..c8b62cea97cecf 100644 --- a/clang/test/Sema/attr-require-explicit-init-tentative.c +++ b/clang/test/Sema/attr-require-explicit-init-tentative.c @@ -10,6 +10,8 @@ struct plain { int a; }; +struct plain no_attribute; // no warning: no field requires explicit initialization + struct ops never_completed; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} static struct ops never_completed_static; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} >From cf0d42fccaeffbceca2e17f4ad709cdb62454805 Mon Sep 17 00:00:00 2001 From: PathriVidyaPraveen <[email protected]> Date: Thu, 22 Oct 2026 13:55:50 +0000 Subject: [PATCH 3/3] Address review comments from AaronBallman --- clang/docs/ReleaseNotes.md | 4 ++-- clang/lib/Sema/Sema.cpp | 2 +- .../Sema/attr-require-explicit-init-tentative.c | 17 ++++++++--------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 81a9e8c93f0bca..bbcb1b0e6bbfa3 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -420,8 +420,8 @@ features cannot lower the translation-unit ABI level; ### Improvements to Clang's diagnostics - Fixed missing `-Wuninitialized-explicit-init` warnings for C file-scope - tentative definitions containing fields marked `require_explicit_initialization`. - (#GH232483) + tentative definitions of structure types which contain a field marked with + the `require_explicit_initialization` attribute. (#GH232483) - Fixed spurious `-Wimplicit-void-ptr-cast` warnings in C for parenthesized null pointer macros such as `(NULL)`. (#GH171874) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2e8a22bda240e2..b121f17b96a288 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1550,7 +1550,7 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(VD->getLocation(), DiagID) << Type << EmitCppCompat; } - // Uncompleted tentative definitions are zero-initialized (C17 6.9.2p2) so + // Uninitialized tentative definitions are zero-initialized (C17 6.9.2p2) so // diagnose fields requiring explicit initialization. if (!VD->isInvalidDecl() && !getLangOpts().CPlusPlus && !VD->getAnyInitializer()) { diff --git a/clang/test/Sema/attr-require-explicit-init-tentative.c b/clang/test/Sema/attr-require-explicit-init-tentative.c index c8b62cea97cecf..4f1ec95c2f350b 100644 --- a/clang/test/Sema/attr-require-explicit-init-tentative.c +++ b/clang/test/Sema/attr-require-explicit-init-tentative.c @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -std=c17 -fsyntax-only -Wuninitialized-explicit-init -verify %s -// RUN: %clang_cc1 -std=c23 -fsyntax-only -Wuninitialized-explicit-init -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wuninitialized-explicit-init -verify %s struct ops { int (*show)(void) __attribute__((require_explicit_initialization)); // #SHOW @@ -12,17 +11,17 @@ struct plain { struct plain no_attribute; // no warning: no field requires explicit initialization -struct ops never_completed; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} -static struct ops never_completed_static; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} +struct ops never_initialized; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} +static struct ops never_initialized_static; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} struct ops repeated; struct ops repeated; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} -struct ops completed_later; -struct ops completed_later = { .flags=1}; // expected-warning {{field 'show' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} +struct ops initialized_later; +struct ops initialized_later = { .flags=1}; // expected-warning {{field 'show' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} -struct ops completed_ok; -struct ops completed_ok = { .show=0}; +struct ops initialized_ok; +struct ops initialized_ok = { .show=0}; extern struct ops ext; @@ -34,4 +33,4 @@ struct late { void f(void){ static struct ops local_static; // expected-warning {{field in 'ops' requires explicit initialization but is not explicitly initialized}} expected-note@#SHOW {{'show' declared here}} (void)&local_static; -} \ No newline at end of file +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
