[clang] 58936cb - [Clang] Diagnose require_explicit_initialization for C tentative definitions (#234210)

via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 22 08:06:48 PDT 2026


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;
+}


        


More information about the cfe-commits mailing list