https://github.com/AaronBallman created 
https://github.com/llvm/llvm-project/pull/137166

Unlike C++, C allows the definition of an uninitialized `const` object. If the 
object has static or thread storage duration, it is still zero-initialized, 
otherwise, the object is left uninitialized. In either case, the code is not 
compatible with C++.

This adds a new diagnostic group, `-Wdefault-const-init-unsafe`, which is on by 
default and diagnoses any definition of a `const` object which remains 
uninitialized.

It also adds another new diagnostic group, `-Wdefault-const-init` (which also 
enabled the `unsafe` variant) that diagnoses any definition of a `const` object 
(including ones which are zero-initialized). This diagnostic is off by default.

Finally, it adds `-Wdefault-const-init` to `-Wc++-compat`. GCC diagnoses these 
situations under this flag.

Fixes #19297

>From bb184fc38d13126f244615425cfefe7368ca71b8 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Wed, 23 Apr 2025 13:40:44 -0400
Subject: [PATCH 1/5] Add -Wdefault-const-init

---
 clang/docs/ReleaseNotes.rst                   |  3 ++
 clang/include/clang/Basic/DiagnosticGroups.td |  3 +-
 .../clang/Basic/DiagnosticSemaKinds.td        |  6 +++
 clang/lib/Sema/Sema.cpp                       | 10 ++++
 clang/lib/Sema/SemaDecl.cpp                   |  8 +++
 clang/lib/Sema/SemaInit.cpp                   | 36 ++++++++++---
 clang/test/Sema/typedef-retain.c              |  3 +-
 clang/test/Sema/warn-default-const-init.c     | 54 +++++++++++++++++++
 8 files changed, 115 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/Sema/warn-default-const-init.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bec670e573ca6..1885acec12bae 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -140,6 +140,9 @@ C Language Changes
 - Clang now allows an ``inline`` specifier on a typedef declaration of a
   function type in Microsoft compatibility mode. #GH124869
 - Clang now allows ``restrict`` qualifier for array types with pointer 
elements (#GH92847).
+- Clang now diagnoses ``const``-qualified object definitions without an
+  initializer, under the new warning ``-Wdefault-const-init`` (which is grouped
+  under ``-Wc++-compat``, as this construct is not compatible with C++). 
#GH19297
 
 C2y Feature Support
 ^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 59036b695da85..3686e65c9102a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -154,8 +154,9 @@ def BuiltinRequiresHeader : 
DiagGroup<"builtin-requires-header">;
 def C99Compat : DiagGroup<"c99-compat">;
 def C23Compat : DiagGroup<"c23-compat">;
 def : DiagGroup<"c2x-compat", [C23Compat]>;
+def DefaultConstInit : DiagGroup<"default-const-init">;
 
-def CXXCompat: DiagGroup<"c++-compat">;
+def CXXCompat: DiagGroup<"c++-compat", [DefaultConstInit]>;
 def ExternCCompat : DiagGroup<"extern-c-compat">;
 def KeywordCompat : DiagGroup<"keyword-compat">;
 def GNUCaseRange : DiagGroup<"gnu-case-range">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c562802efba57..d97b2feb1b379 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8197,6 +8197,12 @@ def err_address_space_qualified_new : Error<
 def err_address_space_qualified_delete : Error<
   "'delete' cannot delete objects of type %0 in address space '%1'">;
 
+def note_default_init_const_member : Note<
+  "member %0 declared 'const' here">;
+def warn_default_init_const : Warning<
+  "default initialization of an object of type %0%select{| with const member}1"
+  "%select{| leaves the object unitialized and}2 is incompatible with C++">,
+  InGroup<DefaultConstInit>;
 def err_default_init_const : Error<
   "default initialization of an object of const type %0"
   "%select{| without a user-provided default constructor}1">;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 4039601612c62..d09f94d10b5e0 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1448,6 +1448,16 @@ void Sema::ActOnEndOfTranslationUnit() {
     // No initialization is performed for a tentative definition.
     CheckCompleteVariableDeclaration(VD);
 
+    // In C, if the definition is const-qualified and has no initializer, it
+    // is left uninitialized unless it has static or thread storage duration.
+    QualType Type = VD->getType();
+    if (!VD->isInvalidDecl() && !getLangOpts().CPlusPlus &&
+        Type.isConstQualified() && !VD->getAnyInitializer())
+      Diag(VD->getLocation(), diag::warn_default_init_const)
+          << Type << /*not a field*/0
+          << (VD->getStorageDuration() != SD_Static &&
+              VD->getStorageDuration() != SD_Thread);
+
     // Notify the consumer that we've completed a tentative definition.
     if (!VD->isInvalidDecl())
       Consumer.CompleteTentativeDefinition(VD);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d28a2107d58a9..747e9e6d9ac74 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14333,6 +14333,14 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
       return;
     }
 
+    // In C, if the definition is const-qualified and has no initializer, it
+    // is left uninitialized unless it has static or thread storage duration.
+    if (!getLangOpts().CPlusPlus && Type.isConstQualified())
+      Diag(Var->getLocation(), diag::warn_default_init_const)
+          << Type << /*not a field*/0
+          << (Var->getStorageDuration() != SD_Static &&
+              Var->getStorageDuration() != SD_Thread);
+
     // Check for jumps past the implicit initializer.  C++0x
     // clarifies that this applies to a "variable with automatic
     // storage duration", not a "local variable".
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0910a820438b0..5c45980ad3dff 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6496,6 +6496,17 @@ static bool canPerformArrayCopy(const InitializedEntity 
&Entity) {
   return false;
 }
 
+static const FieldDecl *GetConstField(const RecordDecl *RD) {
+  for (const FieldDecl *FD : RD->fields()) {
+    QualType QT = FD->getType();
+    if (QT.isConstQualified())
+      return FD;
+    if (const auto *RD = QT->getAsRecordDecl())
+      return GetConstField(RD);
+  }
+  return nullptr;
+}
+
 void InitializationSequence::InitializeFrom(Sema &S,
                                             const InitializedEntity &Entity,
                                             const InitializationKind &Kind,
@@ -6563,13 +6574,26 @@ void InitializationSequence::InitializeFrom(Sema &S,
 
   if (!S.getLangOpts().CPlusPlus &&
       Kind.getKind() == InitializationKind::IK_Default) {
-    RecordDecl *Rec = DestType->getAsRecordDecl();
-    if (Rec && Rec->hasUninitializedExplicitInitFields()) {
+    if (RecordDecl *Rec = DestType->getAsRecordDecl()) {
       VarDecl *Var = dyn_cast_or_null<VarDecl>(Entity.getDecl());
-      if (Var && !Initializer) {
-        S.Diag(Var->getLocation(), diag::warn_field_requires_explicit_init)
-            << /* Var-in-Record */ 1 << Rec;
-        emitUninitializedExplicitInitFields(S, Rec);
+      if (Rec->hasUninitializedExplicitInitFields()) {
+        if (Var && !Initializer) {
+          S.Diag(Var->getLocation(), diag::warn_field_requires_explicit_init)
+              << /* Var-in-Record */ 1 << Rec;
+          emitUninitializedExplicitInitFields(S, Rec);
+        }
+      }
+      // If the record has any members which are const (recursively checked),
+      // then we want to diagnose those as being unitialized if there is no
+      // initializer present.
+      if (!Initializer) {
+        if (const FieldDecl *FD = GetConstField(Rec)) {
+          S.Diag(Var->getLocation(), diag::warn_default_init_const)
+              << Var->getType() << /*member*/ 1
+              << (Var->getStorageDuration() != SD_Static &&
+                  Var->getStorageDuration() != SD_Thread);
+          S.Diag(FD->getLocation(), diag::note_default_init_const_member) << 
FD;
+        }
       }
     }
   }
diff --git a/clang/test/Sema/typedef-retain.c b/clang/test/Sema/typedef-retain.c
index 2d94a8f665fe3..603867ee3080d 100644
--- a/clang/test/Sema/typedef-retain.c
+++ b/clang/test/Sema/typedef-retain.c
@@ -16,7 +16,8 @@ void test2(float4 a, int4p result, int i) {
 typedef int a[5];
 void test3(void) {
   typedef const a b;
-  b r;       // expected-note {{variable 'r' declared const here}}
+  b r;       // expected-note {{variable 'r' declared const here}} \
+                expected-warning {{default initialization of an object of type 
'b' (aka 'const int[5]') leaves the object unitialized and is incompatible with 
C++}}
   r[0] = 10; // expected-error {{cannot assign to variable 'r' with 
const-qualified type 'b' (aka 'const int[5]')}}
 }
 
diff --git a/clang/test/Sema/warn-default-const-init.c 
b/clang/test/Sema/warn-default-const-init.c
new file mode 100644
index 0000000000000..5a9a1219bf6ab
--- /dev/null
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=c -Wdefault-const-init %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c -Wc++-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c %s
+// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only -verify=good -Wc++-compat 
-Wno-default-const-init %s
+// good-no-diagnostics
+
+struct A { int i; };
+struct S{ const int i; };              // c-note 2 {{member 'i' declared 
'const' here}} \
+                                          cxx-note 3 {{default constructor of 
'S' is implicitly deleted because field 'i' of const-qualified type 'const int' 
would not be initialized}}
+struct T { struct S s; };              // cxx-note {{default constructor of 
'T' is implicitly deleted because field 's' has a deleted default constructor}}
+struct U { struct S s; const int j; };
+struct V { int i; const struct A a; }; // c-note {{member 'a' declared 'const' 
here}} \
+                                          cxx-note {{default constructor of 
'V' is implicitly deleted because field 'a' of const-qualified type 'const 
struct A' would not be initialized}}
+
+void f() {
+  struct S s1; // c-warning {{default initialization of an object of type 
'struct S' with const member leaves the object unitialized and is incompatible 
with C++}} \
+                  cxx-error {{call to implicitly-deleted default constructor 
of 'struct S'}}
+  struct S s2 = { 0 };
+}
+void g() {
+  struct T t1; // c-warning {{default initialization of an object of type 
'struct T' with const member leaves the object unitialized and is incompatible 
with C++}} \
+                  cxx-error {{call to implicitly-deleted default constructor 
of 'struct T'}}
+  struct T t2 = { { 0 } };
+}
+void h() {
+  struct U u1 = { { 0 } };
+  struct U u2 = { { 0 }, 0 };
+}
+void x() {
+  struct V v1; // c-warning {{default initialization of an object of type 
'struct V' with const member leaves the object unitialized and is incompatible 
with C++}} \
+                  cxx-error {{call to implicitly-deleted default constructor 
of 'struct V'}}
+  struct V v2 = { 0 };
+  struct V v3 = { 0, { 0 } };
+}
+
+// Test a tentative definition which does eventually get an initializer.
+extern const int i;
+const int i = 12;
+
+static const int j; // c-warning {{default initialization of an object of type 
'const int' is incompatible with C++}} \
+                       cxx-error {{default initialization of an object of 
const type 'const int'}}
+const int k;        // c-warning {{default initialization of an object of type 
'const int' is incompatible with C++}} \
+                       cxx-error {{default initialization of an object of 
const type 'const int'}}
+const struct S s;   // c-warning {{default initialization of an object of type 
'const struct S' is incompatible with C++}} \
+                       cxx-error {{call to implicitly-deleted default 
constructor of 'const struct S'}}
+
+void func() {
+  const int a;        // c-warning {{default initialization of an object of 
type 'const int' leaves the object unitialized and is incompatible with C++}} \
+                         cxx-error {{default initialization of an object of 
const type 'const int'}}
+  static const int b; // c-warning {{default initialization of an object of 
type 'const int' is incompatible with C++}} \
+                         cxx-error {{default initialization of an object of 
const type 'const int'}}
+}
+

>From c3aef4903deefec36ddec049489f40f8f2543e0e Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Wed, 23 Apr 2025 13:55:38 -0400
Subject: [PATCH 2/5] Fix typo

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
 clang/lib/Sema/SemaInit.cpp                      | 2 +-
 clang/test/Sema/typedef-retain.c                 | 2 +-
 clang/test/Sema/warn-default-const-init.c        | 8 ++++----
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d97b2feb1b379..d2c1422173532 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8201,7 +8201,7 @@ def note_default_init_const_member : Note<
   "member %0 declared 'const' here">;
 def warn_default_init_const : Warning<
   "default initialization of an object of type %0%select{| with const member}1"
-  "%select{| leaves the object unitialized and}2 is incompatible with C++">,
+  "%select{| leaves the object uninitialized and}2 is incompatible with C++">,
   InGroup<DefaultConstInit>;
 def err_default_init_const : Error<
   "default initialization of an object of const type %0"
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 5c45980ad3dff..29890929e4e69 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6584,7 +6584,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
         }
       }
       // If the record has any members which are const (recursively checked),
-      // then we want to diagnose those as being unitialized if there is no
+      // then we want to diagnose those as being uninitialized if there is no
       // initializer present.
       if (!Initializer) {
         if (const FieldDecl *FD = GetConstField(Rec)) {
diff --git a/clang/test/Sema/typedef-retain.c b/clang/test/Sema/typedef-retain.c
index 603867ee3080d..76715ca360cbe 100644
--- a/clang/test/Sema/typedef-retain.c
+++ b/clang/test/Sema/typedef-retain.c
@@ -17,7 +17,7 @@ typedef int a[5];
 void test3(void) {
   typedef const a b;
   b r;       // expected-note {{variable 'r' declared const here}} \
-                expected-warning {{default initialization of an object of type 
'b' (aka 'const int[5]') leaves the object unitialized and is incompatible with 
C++}}
+                expected-warning {{default initialization of an object of type 
'b' (aka 'const int[5]') leaves the object uninitialized and is incompatible 
with C++}}
   r[0] = 10; // expected-error {{cannot assign to variable 'r' with 
const-qualified type 'b' (aka 'const int[5]')}}
 }
 
diff --git a/clang/test/Sema/warn-default-const-init.c 
b/clang/test/Sema/warn-default-const-init.c
index 5a9a1219bf6ab..d216065e13dc5 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -14,12 +14,12 @@ struct V { int i; const struct A a; }; // c-note {{member 
'a' declared 'const' h
                                           cxx-note {{default constructor of 
'V' is implicitly deleted because field 'a' of const-qualified type 'const 
struct A' would not be initialized}}
 
 void f() {
-  struct S s1; // c-warning {{default initialization of an object of type 
'struct S' with const member leaves the object unitialized and is incompatible 
with C++}} \
+  struct S s1; // c-warning {{default initialization of an object of type 
'struct S' with const member leaves the object uninitialized and is 
incompatible with C++}} \
                   cxx-error {{call to implicitly-deleted default constructor 
of 'struct S'}}
   struct S s2 = { 0 };
 }
 void g() {
-  struct T t1; // c-warning {{default initialization of an object of type 
'struct T' with const member leaves the object unitialized and is incompatible 
with C++}} \
+  struct T t1; // c-warning {{default initialization of an object of type 
'struct T' with const member leaves the object uninitialized and is 
incompatible with C++}} \
                   cxx-error {{call to implicitly-deleted default constructor 
of 'struct T'}}
   struct T t2 = { { 0 } };
 }
@@ -28,7 +28,7 @@ void h() {
   struct U u2 = { { 0 }, 0 };
 }
 void x() {
-  struct V v1; // c-warning {{default initialization of an object of type 
'struct V' with const member leaves the object unitialized and is incompatible 
with C++}} \
+  struct V v1; // c-warning {{default initialization of an object of type 
'struct V' with const member leaves the object uninitialized and is 
incompatible with C++}} \
                   cxx-error {{call to implicitly-deleted default constructor 
of 'struct V'}}
   struct V v2 = { 0 };
   struct V v3 = { 0, { 0 } };
@@ -46,7 +46,7 @@ const struct S s;   // c-warning {{default initialization of 
an object of type '
                        cxx-error {{call to implicitly-deleted default 
constructor of 'const struct S'}}
 
 void func() {
-  const int a;        // c-warning {{default initialization of an object of 
type 'const int' leaves the object unitialized and is incompatible with C++}} \
+  const int a;        // c-warning {{default initialization of an object of 
type 'const int' leaves the object uninitialized and is incompatible with C++}} 
\
                          cxx-error {{default initialization of an object of 
const type 'const int'}}
   static const int b; // c-warning {{default initialization of an object of 
type 'const int' is incompatible with C++}} \
                          cxx-error {{default initialization of an object of 
const type 'const int'}}

>From f8e1760ca5d20261ecdd2e89ee432d091c6dbfa6 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Wed, 23 Apr 2025 14:30:31 -0400
Subject: [PATCH 3/5] Split the diagnostic into two groups

The unsafe variant is on by default, the other one is not.
---
 clang/docs/ReleaseNotes.rst                   |  8 +++++--
 clang/include/clang/Basic/DiagnosticGroups.td |  3 ++-
 .../clang/Basic/DiagnosticSemaKinds.td        | 10 ++++++---
 clang/lib/Sema/Sema.cpp                       | 13 +++++++-----
 clang/lib/Sema/SemaDecl.cpp                   | 12 ++++++-----
 clang/lib/Sema/SemaInit.cpp                   | 10 +++++----
 clang/test/Sema/warn-default-const-init.c     | 21 ++++++++++---------
 7 files changed, 47 insertions(+), 30 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1885acec12bae..4f98325fecb75 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -141,8 +141,12 @@ C Language Changes
   function type in Microsoft compatibility mode. #GH124869
 - Clang now allows ``restrict`` qualifier for array types with pointer 
elements (#GH92847).
 - Clang now diagnoses ``const``-qualified object definitions without an
-  initializer, under the new warning ``-Wdefault-const-init`` (which is grouped
-  under ``-Wc++-compat``, as this construct is not compatible with C++). 
#GH19297
+  initializer. If the object is zero-initialized, it will be diagnosed under
+  the new warning ``-Wdefault-const-init`` (which is grouped under
+  ``-Wc++-compat`` because this construct is not compatible with C++). If the
+  object is left uninitialized, it will be diagnosed unsed the new warning
+  ``-Wdefault-const-init-unsafe`` (which is grouped under
+  ``-Wdefault-const-init``). #GH19297
 
 C2y Feature Support
 ^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 3686e65c9102a..6c5d21b721d33 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -154,7 +154,8 @@ def BuiltinRequiresHeader : 
DiagGroup<"builtin-requires-header">;
 def C99Compat : DiagGroup<"c99-compat">;
 def C23Compat : DiagGroup<"c23-compat">;
 def : DiagGroup<"c2x-compat", [C23Compat]>;
-def DefaultConstInit : DiagGroup<"default-const-init">;
+def DefaultConstInitUnsafe : DiagGroup<"default-const-init-unsafe">;
+def DefaultConstInit : DiagGroup<"default-const-init", 
[DefaultConstInitUnsafe]>;
 
 def CXXCompat: DiagGroup<"c++-compat", [DefaultConstInit]>;
 def ExternCCompat : DiagGroup<"extern-c-compat">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d2c1422173532..07fac362a8b71 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8200,9 +8200,13 @@ def err_address_space_qualified_delete : Error<
 def note_default_init_const_member : Note<
   "member %0 declared 'const' here">;
 def warn_default_init_const : Warning<
-  "default initialization of an object of type %0%select{| with const member}1"
-  "%select{| leaves the object uninitialized and}2 is incompatible with C++">,
-  InGroup<DefaultConstInit>;
+  "default initialization of an object of type %0%select{| with const member}1 
"
+  "is incompatible with C++">,
+  InGroup<DefaultConstInit>, DefaultIgnore;
+def warn_default_init_const_unsafe : Warning<
+  "default initialization of an object of type %0%select{| with const member}1 
"
+  "leaves the object uninitialized and is incompatible with C++">,
+  InGroup<DefaultConstInitUnsafe>;
 def err_default_init_const : Error<
   "default initialization of an object of const type %0"
   "%select{| without a user-provided default constructor}1">;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index d09f94d10b5e0..87670fe1953db 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1452,11 +1452,14 @@ void Sema::ActOnEndOfTranslationUnit() {
     // is left uninitialized unless it has static or thread storage duration.
     QualType Type = VD->getType();
     if (!VD->isInvalidDecl() && !getLangOpts().CPlusPlus &&
-        Type.isConstQualified() && !VD->getAnyInitializer())
-      Diag(VD->getLocation(), diag::warn_default_init_const)
-          << Type << /*not a field*/0
-          << (VD->getStorageDuration() != SD_Static &&
-              VD->getStorageDuration() != SD_Thread);
+        Type.isConstQualified() && !VD->getAnyInitializer()) {
+      unsigned DiagID = diag::warn_default_init_const_unsafe;
+      if (VD->getStorageDuration() == SD_Static ||
+          VD->getStorageDuration() == SD_Thread)
+        DiagID = diag::warn_default_init_const;
+      Diag(VD->getLocation(), DiagID) << Type << /*not a field*/ 0;
+    }
+
 
     // Notify the consumer that we've completed a tentative definition.
     if (!VD->isInvalidDecl())
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 747e9e6d9ac74..fa1f3bc732338 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14335,11 +14335,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
 
     // In C, if the definition is const-qualified and has no initializer, it
     // is left uninitialized unless it has static or thread storage duration.
-    if (!getLangOpts().CPlusPlus && Type.isConstQualified())
-      Diag(Var->getLocation(), diag::warn_default_init_const)
-          << Type << /*not a field*/0
-          << (Var->getStorageDuration() != SD_Static &&
-              Var->getStorageDuration() != SD_Thread);
+    if (!getLangOpts().CPlusPlus && Type.isConstQualified()) {
+      unsigned DiagID = diag::warn_default_init_const_unsafe;
+      if (Var->getStorageDuration() == SD_Static ||
+          Var->getStorageDuration() == SD_Thread)
+        DiagID = diag::warn_default_init_const;
+      Diag(Var->getLocation(), DiagID) << Type << /*not a field*/ 0;
+    }
 
     // Check for jumps past the implicit initializer.  C++0x
     // clarifies that this applies to a "variable with automatic
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 29890929e4e69..8c2ba46031ce9 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6588,10 +6588,12 @@ void InitializationSequence::InitializeFrom(Sema &S,
       // initializer present.
       if (!Initializer) {
         if (const FieldDecl *FD = GetConstField(Rec)) {
-          S.Diag(Var->getLocation(), diag::warn_default_init_const)
-              << Var->getType() << /*member*/ 1
-              << (Var->getStorageDuration() != SD_Static &&
-                  Var->getStorageDuration() != SD_Thread);
+          unsigned DiagID = diag::warn_default_init_const_unsafe;
+          if (Var->getStorageDuration() == SD_Static ||
+              Var->getStorageDuration() == SD_Thread)
+            DiagID = diag::warn_default_init_const;
+
+          S.Diag(Var->getLocation(), DiagID) << Var->getType() << /*member*/ 1;
           S.Diag(FD->getLocation(), diag::note_default_init_const_member) << 
FD;
         }
       }
diff --git a/clang/test/Sema/warn-default-const-init.c 
b/clang/test/Sema/warn-default-const-init.c
index d216065e13dc5..99773dbbb9450 100644
--- a/clang/test/Sema/warn-default-const-init.c
+++ b/clang/test/Sema/warn-default-const-init.c
@@ -1,25 +1,26 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=c -Wdefault-const-init %s
-// RUN: %clang_cc1 -fsyntax-only -verify=c -Wc++-compat %s
-// RUN: %clang_cc1 -fsyntax-only -verify=c %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wdefault-const-init %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c,unsafe -Wc++-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=unsafe %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c -Wdefault-const-init 
-Wno-default-const-init-unsafe %s
+// RUN: %clang_cc1 -fsyntax-only -verify=good -Wno-default-const-init-unsafe %s
 // RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
-// RUN: %clang_cc1 -fsyntax-only -verify=good -Wc++-compat 
-Wno-default-const-init %s
 // good-no-diagnostics
 
 struct A { int i; };
-struct S{ const int i; };              // c-note 2 {{member 'i' declared 
'const' here}} \
+struct S{ const int i; };              // unsafe-note 2 {{member 'i' declared 
'const' here}} \
                                           cxx-note 3 {{default constructor of 
'S' is implicitly deleted because field 'i' of const-qualified type 'const int' 
would not be initialized}}
 struct T { struct S s; };              // cxx-note {{default constructor of 
'T' is implicitly deleted because field 's' has a deleted default constructor}}
 struct U { struct S s; const int j; };
-struct V { int i; const struct A a; }; // c-note {{member 'a' declared 'const' 
here}} \
+struct V { int i; const struct A a; }; // unsafe-note {{member 'a' declared 
'const' here}} \
                                           cxx-note {{default constructor of 
'V' is implicitly deleted because field 'a' of const-qualified type 'const 
struct A' would not be initialized}}
 
 void f() {
-  struct S s1; // c-warning {{default initialization of an object of type 
'struct S' with const member leaves the object uninitialized and is 
incompatible with C++}} \
+  struct S s1; // unsafe-warning {{default initialization of an object of type 
'struct S' with const member leaves the object uninitialized and is 
incompatible with C++}} \
                   cxx-error {{call to implicitly-deleted default constructor 
of 'struct S'}}
   struct S s2 = { 0 };
 }
 void g() {
-  struct T t1; // c-warning {{default initialization of an object of type 
'struct T' with const member leaves the object uninitialized and is 
incompatible with C++}} \
+  struct T t1; // unsafe-warning {{default initialization of an object of type 
'struct T' with const member leaves the object uninitialized and is 
incompatible with C++}} \
                   cxx-error {{call to implicitly-deleted default constructor 
of 'struct T'}}
   struct T t2 = { { 0 } };
 }
@@ -28,7 +29,7 @@ void h() {
   struct U u2 = { { 0 }, 0 };
 }
 void x() {
-  struct V v1; // c-warning {{default initialization of an object of type 
'struct V' with const member leaves the object uninitialized and is 
incompatible with C++}} \
+  struct V v1; // unsafe-warning {{default initialization of an object of type 
'struct V' with const member leaves the object uninitialized and is 
incompatible with C++}} \
                   cxx-error {{call to implicitly-deleted default constructor 
of 'struct V'}}
   struct V v2 = { 0 };
   struct V v3 = { 0, { 0 } };
@@ -46,7 +47,7 @@ const struct S s;   // c-warning {{default initialization of 
an object of type '
                        cxx-error {{call to implicitly-deleted default 
constructor of 'const struct S'}}
 
 void func() {
-  const int a;        // c-warning {{default initialization of an object of 
type 'const int' leaves the object uninitialized and is incompatible with C++}} 
\
+  const int a;        // unsafe-warning {{default initialization of an object 
of type 'const int' leaves the object uninitialized and is incompatible with 
C++}} \
                          cxx-error {{default initialization of an object of 
const type 'const int'}}
   static const int b; // c-warning {{default initialization of an object of 
type 'const int' is incompatible with C++}} \
                          cxx-error {{default initialization of an object of 
const type 'const int'}}

>From 32daa84fadc0b6117b2b2d917c644781732679eb Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Thu, 24 Apr 2025 06:37:27 -0400
Subject: [PATCH 4/5] Update tests

---
 clang/test/C/C23/n2607.c                           |  4 ++--
 clang/test/C/drs/dr1xx.c                           |  4 ++--
 clang/test/Parser/typeof.c                         |  4 ++--
 clang/test/Sema/assign.c                           |  4 ++--
 clang/test/Sema/atomic-ops.c                       | 14 +++++++-------
 clang/test/Sema/block-return.c                     |  2 +-
 clang/test/Sema/builtins-bpf.c                     |  2 +-
 clang/test/Sema/builtins-elementwise-math.c        | 10 +++++-----
 clang/test/Sema/builtins-overflow.c                |  2 +-
 clang/test/Sema/enable_if.c                        |  2 +-
 clang/test/Sema/implicit-decl.c                    |  2 +-
 clang/test/Sema/overloadable.c                     |  2 +-
 clang/test/Sema/sizeless-1.c                       |  4 ++--
 clang/test/Sema/varargs-x86-64.c                   |  2 +-
 clang/test/Sema/warn-unused-function.c             |  2 +-
 clang/test/SemaObjC/message.m                      |  2 +-
 clang/test/SemaOpenCL/cl20-device-side-enqueue.cl  |  2 +-
 clang/test/SemaOpenCL/invalid-block.cl             |  3 ++-
 .../SemaOpenMP/atomic-capture-const-no-crash.c     |  2 +-
 19 files changed, 35 insertions(+), 34 deletions(-)

diff --git a/clang/test/C/C23/n2607.c b/clang/test/C/C23/n2607.c
index 9595aaed54c43..41e8b2ac4b2cd 100644
--- a/clang/test/C/C23/n2607.c
+++ b/clang/test/C/C23/n2607.c
@@ -24,7 +24,7 @@ void test1(void) {
 void test2(void) {
   typedef int array[1];
   array reg_array;
-  const array const_array;
+  const array const_array = { 0 };
 
   // An array and its elements are identically qualified. We have to test this
   // using pointers to the array and element, because the controlling
@@ -50,7 +50,7 @@ void test2(void) {
 void test3(void) {
   // Validate that we pick the correct composite type for a conditional
   // operator in the presence of qualifiers.
-  const int const_array[1];
+  const int const_array[1] = { 0 };
   int array[1];
 
   // FIXME: the type here should be `const int (*)[1]`, but for some reason,
diff --git a/clang/test/C/drs/dr1xx.c b/clang/test/C/drs/dr1xx.c
index 47538e44428c3..3e4c39cca62e4 100644
--- a/clang/test/C/drs/dr1xx.c
+++ b/clang/test/C/drs/dr1xx.c
@@ -289,7 +289,7 @@ void dr124(void) {
  */
 void dr126(void) {
   typedef int *IP;
-  const IP object; /* expected-note {{variable 'object' declared const here}} 
*/
+  const IP object = 0; /* expected-note {{variable 'object' declared const 
here}} */
 
   /* The root of the DR is whether 'object' is a pointer to a const int, or a
    * const pointer to int.
@@ -329,7 +329,7 @@ void dr129(void) {
 void dr131(void) {
   struct S {
     const int i; /* expected-note {{data member 'i' declared const here}} */
-  } s1, s2;
+  } s1 = { 0 }, s2 = { 0 };
   s1 = s2; /* expected-error {{cannot assign to variable 's1' with 
const-qualified data member 'i'}} */
 }
 
diff --git a/clang/test/Parser/typeof.c b/clang/test/Parser/typeof.c
index 08f3ca72ab942..f962bcf143957 100644
--- a/clang/test/Parser/typeof.c
+++ b/clang/test/Parser/typeof.c
@@ -12,8 +12,8 @@ static void test(void) {
   short TInt eee; // expected-error{{expected ';' at end of declaration}}
   void ary[7] fff; // expected-error{{array has incomplete element type 
'void'}} expected-error{{expected ';' at end of declaration}}
   typeof(void ary[7]) anIntError; // expected-error{{expected ')'}} 
expected-note {{to match this '('}}  expected-error {{variable has incomplete 
type 'typeof(void)' (aka 'void')}}
-  typeof(const int) aci; 
-  const typeof (*pi) aConstInt; 
+  typeof(const int) aci = 0;
+  const typeof (*pi) aConstInt = 0;
   int xx;
   int *i;
 }
diff --git a/clang/test/Sema/assign.c b/clang/test/Sema/assign.c
index fe2a9f1434479..13ea1062b9e1e 100644
--- a/clang/test/Sema/assign.c
+++ b/clang/test/Sema/assign.c
@@ -11,8 +11,8 @@ void test2 (const struct {int a;} *x) {
 
 typedef int arr[10];
 void test3(void) {
-  const arr b;      // expected-note {{variable 'b' declared const here}}
-  const int b2[10]; // expected-note {{variable 'b2' declared const here}}
+  const arr b = {};      // expected-note {{variable 'b' declared const here}}
+  const int b2[10] = {}; // expected-note {{variable 'b2' declared const here}}
   b[4] = 1;         // expected-error {{cannot assign to variable 'b' with 
const-qualified type 'const arr' (aka 'const int[10]')}}
   b2[4] = 1;        // expected-error {{cannot assign to variable 'b2' with 
const-qualified type 'const int[10]'}}
 }
diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c
index 725a12060d4e0..aae7aced2628a 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -1,20 +1,20 @@
 // RUN: %clang_cc1 %s -verify=expected,fp80,noi128 -fgnuc-version=4.2.1 
-ffreestanding \
-// RUN:   -fsyntax-only -triple=i686-linux-gnu -std=c11
+// RUN:   -Wno-default-const-init-unsafe -fsyntax-only -triple=i686-linux-gnu 
-std=c11
 // RUN: %clang_cc1 %s -verify=expected,noi128 -fgnuc-version=4.2.1 
-ffreestanding \
-// RUN:   -fsyntax-only -triple=i686-linux-android -std=c11
+// RUN:   -Wno-default-const-init-unsafe -fsyntax-only 
-triple=i686-linux-android -std=c11
 // RUN: %clang_cc1 %s -verify -fgnuc-version=4.2.1 -ffreestanding \
-// RUN:   -fsyntax-only -triple=powerpc64-linux-gnu -std=c11
+// RUN:   -Wno-default-const-init-unsafe -fsyntax-only 
-triple=powerpc64-linux-gnu -std=c11
 // RUN: %clang_cc1 %s -verify -fgnuc-version=4.2.1 -ffreestanding \
-// RUN:   -fsyntax-only -triple=powerpc64-linux-gnu -std=c11 \
+// RUN:   -Wno-default-const-init-unsafe -fsyntax-only 
-triple=powerpc64-linux-gnu -std=c11 \
 // RUN:   -target-cpu pwr7
 // RUN: %clang_cc1 %s -verify -fgnuc-version=4.2.1 -ffreestanding \
-// RUN:   -fsyntax-only -triple=powerpc64le-linux-gnu -std=c11 \
+// RUN:   -Wno-default-const-init-unsafe -fsyntax-only 
-triple=powerpc64le-linux-gnu -std=c11 \
 // RUN:   -target-cpu pwr8 -DPPC64_PWR8
 // RUN: %clang_cc1 %s -verify -fgnuc-version=4.2.1 -ffreestanding \
-// RUN:   -fsyntax-only -triple=powerpc64-unknown-aix -std=c11 \
+// RUN:   -Wno-default-const-init-unsafe -fsyntax-only 
-triple=powerpc64-unknown-aix -std=c11 \
 // RUN:   -target-cpu pwr8
 // RUN: %clang_cc1 %s -verify -fgnuc-version=4.2.1 -ffreestanding \
-// RUN:   -fsyntax-only -triple=powerpc64-unknown-aix -std=c11 \
+// RUN:   -Wno-default-const-init-unsafe -fsyntax-only 
-triple=powerpc64-unknown-aix -std=c11 \
 // RUN:   -mabi=quadword-atomics -target-cpu pwr8 -DPPC64_PWR8
 
 // Basic parsing/Sema tests for __c11_atomic_*
diff --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c
index 126fc6f953dea..312ded75b6a81 100644
--- a/clang/test/Sema/block-return.c
+++ b/clang/test/Sema/block-return.c
@@ -126,7 +126,7 @@ void foo7(void)
   int (^JJ) (void)  = ^{ return j; }; // OK
   int (^KK) (void)  = ^{ return j+1; }; // OK
 
-  __block const int k;
+  __block const int k = 0;
   const int cint = 100;
 
   int (^MM) (void)  = ^{ return k; };
diff --git a/clang/test/Sema/builtins-bpf.c b/clang/test/Sema/builtins-bpf.c
index fc540260c91c3..d6e17683d6898 100644
--- a/clang/test/Sema/builtins-bpf.c
+++ b/clang/test/Sema/builtins-bpf.c
@@ -69,7 +69,7 @@ unsigned invalid11(struct s *arg, int info_kind) {
 }
 
 unsigned valid12(void) {
-  const struct s t;
+  const struct s t = {};
   return __builtin_preserve_type_info(t, 0) +
          __builtin_preserve_type_info(*(struct s *)0, 1);
 }
diff --git a/clang/test/Sema/builtins-elementwise-math.c 
b/clang/test/Sema/builtins-elementwise-math.c
index 5c54202991a85..b5648a5e5c6e8 100644
--- a/clang/test/Sema/builtins-elementwise-math.c
+++ b/clang/test/Sema/builtins-elementwise-math.c
@@ -88,7 +88,7 @@ void test_builtin_elementwise_add_sat(int i, short s, double 
d, float4 v, int3 i
   _BitInt(32) ext; // expected-warning {{'_BitInt' in C17 and earlier is a 
Clang extension}}
   ext = __builtin_elementwise_add_sat(ext, ext);
 
-  const int ci;
+  const int ci = 0;
   i = __builtin_elementwise_add_sat(ci, i);
   i = __builtin_elementwise_add_sat(i, ci);
   i = __builtin_elementwise_add_sat(ci, ci);
@@ -154,7 +154,7 @@ void test_builtin_elementwise_sub_sat(int i, short s, 
double d, float4 v, int3 i
   _BitInt(32) ext; // expected-warning {{'_BitInt' in C17 and earlier is a 
Clang extension}}
   ext = __builtin_elementwise_sub_sat(ext, ext);
 
-  const int ci;
+  const int ci = 0;
   i = __builtin_elementwise_sub_sat(ci, i);
   i = __builtin_elementwise_sub_sat(i, ci);
   i = __builtin_elementwise_sub_sat(ci, ci);
@@ -214,7 +214,7 @@ void test_builtin_elementwise_max(int i, short s, double d, 
float4 v, int3 iv, u
   _BitInt(32) ext; // expected-warning {{'_BitInt' in C17 and earlier is a 
Clang extension}}
   ext = __builtin_elementwise_max(ext, ext);
 
-  const int ci;
+  const int ci = 0;
   i = __builtin_elementwise_max(ci, i);
   i = __builtin_elementwise_max(i, ci);
   i = __builtin_elementwise_max(ci, ci);
@@ -274,7 +274,7 @@ void test_builtin_elementwise_min(int i, short s, double d, 
float4 v, int3 iv, u
   _BitInt(32) ext; // expected-warning {{'_BitInt' in C17 and earlier is a 
Clang extension}}
   ext = __builtin_elementwise_min(ext, ext);
 
-  const int ci;
+  const int ci = 0;
   i = __builtin_elementwise_min(ci, i);
   i = __builtin_elementwise_min(i, ci);
   i = __builtin_elementwise_min(ci, ci);
@@ -1070,7 +1070,7 @@ void test_builtin_elementwise_copysign(int i, short s, 
double d, float f, float4
   ext = __builtin_elementwise_copysign(ext, ext);
   // expected-error@-1 {{1st argument must be a scalar or vector of 
floating-point types (was '_BitInt(32)')}}
 
-  const float cf32;
+  const float cf32 = 0.0f;
   f = __builtin_elementwise_copysign(cf32, f);
   f = __builtin_elementwise_copysign(f, cf32);
   f = __builtin_elementwise_copysign(cf32, f);
diff --git a/clang/test/Sema/builtins-overflow.c 
b/clang/test/Sema/builtins-overflow.c
index 302489c19e379..9928afbd17c6c 100644
--- a/clang/test/Sema/builtins-overflow.c
+++ b/clang/test/Sema/builtins-overflow.c
@@ -9,7 +9,7 @@ void test(void) {
   unsigned r;
   const char * c;
   float f;
-  const unsigned q;
+  const unsigned q = 0;
 
   __builtin_add_overflow();  // expected-error {{too few arguments to function 
call, expected 3, have 0}}
   __builtin_add_overflow(1, 1, 1, 1);  // expected-error {{too many arguments 
to function call, expected 3, have 4}}
diff --git a/clang/test/Sema/enable_if.c b/clang/test/Sema/enable_if.c
index 9d46c71274d69..3ef8310a2fef7 100644
--- a/clang/test/Sema/enable_if.c
+++ b/clang/test/Sema/enable_if.c
@@ -52,7 +52,7 @@ size_t strnlen(const char *s, size_t maxlen) // expected-note 
{{'strnlen' has be
 
 void test2(const char *s, int i) {
 // CHECK: define {{.*}}void @test2
-  const char c[123];
+  const char c[123] = { 0 };
   strnlen(s, i);
 // CHECK: call {{.*}}strnlen_real1
   strnlen(s, 999);
diff --git a/clang/test/Sema/implicit-decl.c b/clang/test/Sema/implicit-decl.c
index a3f35222d833c..03ee6cdcb204a 100644
--- a/clang/test/Sema/implicit-decl.c
+++ b/clang/test/Sema/implicit-decl.c
@@ -13,7 +13,7 @@ typedef unsigned char Boolean;
 extern int printf(__const char *__restrict __format, ...); // 
both-note{{'printf' declared here}}
 void func(void) {
    int32_t *vector[16];
-   const char compDesc[16 + 1];
+   const char compDesc[16 + 1] = { 0 };
    int32_t compCount = 0;
    if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // 
expected-error {{call to undeclared function 
'_CFCalendarDecomposeAbsoluteTimeV'; ISO C99 and later do not support implicit 
function declarations}} \
                                                                             
expected-note {{previous implicit declaration}} \
diff --git a/clang/test/Sema/overloadable.c b/clang/test/Sema/overloadable.c
index 9eecad18064e2..4c6fd0102c59a 100644
--- a/clang/test/Sema/overloadable.c
+++ b/clang/test/Sema/overloadable.c
@@ -155,7 +155,7 @@ void incompatible_pointer_type_conversions() {
 }
 
 void dropping_qualifiers_is_incompatible() {
-  const char ccharbuf[1];
+  const char ccharbuf[1] = {0};
   volatile char vcharbuf[1];
 
   void foo(char *c) __attribute__((overloadable));
diff --git a/clang/test/Sema/sizeless-1.c b/clang/test/Sema/sizeless-1.c
index 9ec884b9f1fda..af96023f4bff5 100644
--- a/clang/test/Sema/sizeless-1.c
+++ b/clang/test/Sema/sizeless-1.c
@@ -94,12 +94,12 @@ void func(int sel) {
   svint8_t bad_brace_init_int8_6 = {{local_int8, 0}};  // expected-warning 
{{too many braces around initializer}}
 
   const svint8_t const_int8 = local_int8; // expected-note {{declared const 
here}}
-  const svint8_t uninit_const_int8;
+  const svint8_t uninit_const_int8;       // expected-warning {{default 
initialization of an object of type 'const svint8_t' (aka 'const __SVInt8_t') 
leaves the object uninitialized and is incompatible with C++}};
 
   volatile svint8_t volatile_int8;
 
   const volatile svint8_t const_volatile_int8 = local_int8; // expected-note 
{{declared const here}}
-  const volatile svint8_t uninit_const_volatile_int8;
+  const volatile svint8_t uninit_const_volatile_int8;       // 
expected-warning {{default initialization of an object of type 'const volatile 
svint8_t' (aka 'const volatile __SVInt8_t') leaves the object uninitialized and 
is incompatible with C++}}
 
   _Atomic svint8_t atomic_int8;      // expected-error {{_Atomic cannot be 
applied to sizeless type 'svint8_t'}}
   __restrict svint8_t restrict_int8; // expected-error {{requires a pointer or 
reference}}
diff --git a/clang/test/Sema/varargs-x86-64.c b/clang/test/Sema/varargs-x86-64.c
index ff7fdd533ab0b..f58bbc9682499 100644
--- a/clang/test/Sema/varargs-x86-64.c
+++ b/clang/test/Sema/varargs-x86-64.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-apple-darwin9
+// RUN: %clang_cc1 -fsyntax-only -Wno-default-const-init-unsafe -verify %s 
-triple x86_64-apple-darwin9
 
 void f1(void) {
   const __builtin_va_list args2;
diff --git a/clang/test/Sema/warn-unused-function.c 
b/clang/test/Sema/warn-unused-function.c
index 0a0133c21383d..97628b5b5399b 100644
--- a/clang/test/Sema/warn-unused-function.c
+++ b/clang/test/Sema/warn-unused-function.c
@@ -48,7 +48,7 @@ static void unused(void) { unused(); }  // 
expected-warning{{not needed and will
 
 static void cleanupMalloc(char * const * const allocation) { }
 void f13(void) {
-  char * const __attribute__((cleanup(cleanupMalloc))) a;
+  char * const __attribute__((cleanup(cleanupMalloc))) a = 0;
   (void)a;
 }
 
diff --git a/clang/test/SemaObjC/message.m b/clang/test/SemaObjC/message.m
index 20568ac201288..c769005b08f3e 100644
--- a/clang/test/SemaObjC/message.m
+++ b/clang/test/SemaObjC/message.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-default-const-init-unsafe -verify 
-Wno-objc-root-class %s
 
 typedef struct objc_object {
   Class isa;
diff --git a/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl 
b/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl
index 524de8ce2f7dc..a44d9dd86b86a 100644
--- a/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl
+++ b/clang/test/SemaOpenCL/cl20-device-side-enqueue.cl
@@ -14,7 +14,7 @@ typedef struct {int a;} ndrange_t;
 kernel void enqueue_kernel_tests(void) {
   queue_t default_queue;
   unsigned flags = 0;
-  QUALS ndrange_t ndrange;
+  QUALS ndrange_t ndrange = { 0 };
   clk_event_t evt;
   clk_event_t event_wait_list;
   clk_event_t event_wait_list2[] = {evt, evt};
diff --git a/clang/test/SemaOpenCL/invalid-block.cl 
b/clang/test/SemaOpenCL/invalid-block.cl
index 1605369000429..2214908f800a4 100644
--- a/clang/test/SemaOpenCL/invalid-block.cl
+++ b/clang/test/SemaOpenCL/invalid-block.cl
@@ -13,7 +13,8 @@ void f1(void) {
   f0(bl1);
   f0(bl2);
   bl1 = bl2;          // expected-error{{invalid operands to binary expression 
('int (__generic ^const __private)(void)' and 'int (__generic ^const 
__private)(void)')}}
-  int (^const bl3)(void); // expected-error{{invalid block variable 
declaration - must be initialized}}
+  int (^const bl3)(void); // expected-error{{invalid block variable 
declaration - must be initialized}} \
+                             expected-warning {{default initialization of an 
object of type 'int (__generic ^const __private)(void)' leaves the object 
uninitialized and is incompatible with C++}}
 }
 
 // A block with extern storage class is not allowed.
diff --git a/clang/test/SemaOpenMP/atomic-capture-const-no-crash.c 
b/clang/test/SemaOpenMP/atomic-capture-const-no-crash.c
index 8739d5c088c13..1e1ccf87ea09f 100644
--- a/clang/test/SemaOpenMP/atomic-capture-const-no-crash.c
+++ b/clang/test/SemaOpenMP/atomic-capture-const-no-crash.c
@@ -3,7 +3,7 @@
 // or https://github.com/llvm/llvm-project/pull/71480
 
 void test() {
-  int v; const int x; // expected-note {{variable 'x' declared const here}}
+  int v; const int x = 0; // expected-note {{variable 'x' declared const here}}
 #pragma omp atomic capture
   { 
     v = x; 

>From ef899624e1a20bca23e4eb65c5ce17b4f276f494 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Thu, 24 Apr 2025 07:46:27 -0400
Subject: [PATCH 5/5] Fix handling of Objective-C for...in statements

Without this change, we parse as though the initial declaration is an
uninitialized variable. With this change, we behave the same as we do
for range-based for loops in C++, which is not handled as an
uninitialized variable.

Note, ParseDeclGroup (which is what is eventually called as a result of
this change) was already expecting to be able to handle for...in loops,
so this appears to be fixing an oversight.
---
 clang/lib/Parse/ParseStmt.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 4a82d57fe566b..4e801f4ef890f 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2154,7 +2154,7 @@ StmtResult Parser::ParseForStatement(SourceLocation 
*TrailingElseLoc) {
       FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
     } else {
       // In C++0x, "for (T NS:a" might not be a typo for ::
-      bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
+      bool MightBeForRangeStmt = getLangOpts().CPlusPlus || getLangOpts().ObjC;
       ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
       ParsedAttributes DeclSpecAttrs(AttrFactory);
       DG = ParseSimpleDeclaration(

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to