Author: Pathri Vidya Praveen Date: 2026-10-22T15:06:40Z New Revision: 58936cb3678b4b5b96177f24cac3940b9a389fe3
URL: https://github.com/llvm/llvm-project/commit/58936cb3678b4b5b96177f24cac3940b9a389fe3 DIFF: https://github.com/llvm/llvm-project/commit/58936cb3678b4b5b96177f24cac3940b9a389fe3.diff LOG: [Clang] Diagnose require_explicit_initialization for C tentative definitions (#234210) In C, a tentative definition that is never completed is zero-initialized (C17 6.9.2p2). However, `-Wuninitialized-explicit-init` did not diagnose such definitions when they contained fields marked `require_explicit_initialization`. This patch adds a check in `Sema::ActOnEndOfTranslationUnit()` for tentative definitions that remain uncompleted. Definitions completed later retain their existing initialization checks. Added regression tests in `clang/test/Sema/attr-require-explicit-init-tentative.c`. Fixes #232483 AI assistance: Claude was used to understand parts of the existing code and assist with regression-test development, including some `expected-warning` annotations. I reviewed and verified the submitted changes. Added: clang/test/Sema/attr-require-explicit-init-tentative.c Modified: clang/docs/ReleaseNotes.md clang/lib/Sema/Sema.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 1620cef23970e..04a672f77c1a6 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -458,6 +458,10 @@ documentation](CIR/index.md) for more information regarding ClangIR's status and ### Improvements to Clang's diagnostics +- Fixed missing `-Wuninitialized-explicit-init` warnings for C file-scope + 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 9abab22e3809f..b121f17b96a28 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1550,6 +1550,20 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(VD->getLocation(), DiagID) << Type << EmitCppCompat; } + // Uninitialized 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 0000000000000..4f1ec95c2f350 --- /dev/null +++ b/clang/test/Sema/attr-require-explicit-init-tentative.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -Wuninitialized-explicit-init -verify %s + +struct ops { + int (*show)(void) __attribute__((require_explicit_initialization)); // #SHOW + int flags; +}; + +struct plain { + int a; +}; + +struct plain no_attribute; // no warning: no field requires explicit initialization + +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 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 initialized_ok; +struct ops initialized_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; +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
