https://github.com/gamesh411 updated 
https://github.com/llvm/llvm-project/pull/198345

From 7a868ce932ce706d2bd808a24854199f9288f843 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <[email protected]>
Date: Mon, 18 May 2026 15:59:01 +0200
Subject: [PATCH 1/3] [analyzer] Fix misleading 'initialized here' note for
 uninitialized declarations

When a variable is declared without an initializer, the BugReporterVisitor
would emit 'initialized here' as a note, which is confusing because the
variable was never initialized.

Change the note to 'declared without an initial value' for declarations
that have no initializer. Global-storage variables are are also taken
into consideration.
---
 .../Core/BugReporterVisitors.cpp              | 30 +++++++++----------
 .../test/Analysis/cstring-uninitread-notes.c  |  2 +-
 clang/test/Analysis/placement-new.cpp         | 22 +++++++-------
 ...functions-arg-constraints-tracking-notes.c |  4 +--
 .../std-c-library-functions-arg-constraints.c |  8 ++---
 clang/test/Analysis/uninit-const.c            | 10 +++----
 clang/test/Analysis/uninit-vals.m             |  8 ++---
 7 files changed, 41 insertions(+), 43 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 5294a0bedf898..2892c12261515 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1281,23 +1281,21 @@ static void showBRDiagnostics(llvm::raw_svector_ostream 
&OS, StoreInfo SI) {
     // We don't need to check here, all these conditions were
     // checked by StoreSiteFinder, when it figured out that it is
     // initialization.
-    const auto *DS =
-        cast<DeclStmt>(SI.StoreSite->getLocationAs<PostStmt>()->getStmt());
-
-    if (SI.Value.isUndef()) {
-      if (isa<VarRegion>(SI.Dest)) {
-        const auto *VD = cast<VarDecl>(DS->getSingleDecl());
-
-        if (VD->getInit()) {
-          OS << (HasPrefix ? "initialized" : "Initializing")
-             << " to a garbage value";
-        } else {
-          OS << (HasPrefix ? "declared" : "Declaring")
-             << " without an initial value";
-        }
+    const auto *VR = dyn_cast<VarRegion>(SI.Dest);
+    if (VR) {
+      const auto *VD = VR->getDecl();
+      bool HasInit = VD->getInit();
+      bool HasGlobalStorage = VD->hasGlobalStorage();
+
+      if (SI.Value.isUndef() && HasInit) {
+        OS << (HasPrefix ? "initialized" : "Initializing")
+           << " to a garbage value";
+      } else if (!HasInit && !HasGlobalStorage) {
+        OS << (HasPrefix ? "declared" : "Declared")
+           << " without an initial value";
+      } else {
+        OS << (HasPrefix ? "initialized" : "Initialized") << " here";
       }
-    } else {
-      OS << (HasPrefix ? "initialized" : "Initialized") << " here";
     }
   }
 }
diff --git a/clang/test/Analysis/cstring-uninitread-notes.c 
b/clang/test/Analysis/cstring-uninitread-notes.c
index b62519a85c8cc..087ab2ba6260a 100644
--- a/clang/test/Analysis/cstring-uninitread-notes.c
+++ b/clang/test/Analysis/cstring-uninitread-notes.c
@@ -14,7 +14,7 @@ void maybeWrite(const char *src, unsigned size, int *dst) {
 } // expected-note{{Returning without writing to '*dst'}}
 
 void returning_without_writing_to_memcpy(const char *src, unsigned size) {
-  int block[8 * 8]; // expected-note{{'block' initialized here}}
+  int block[8 * 8]; // expected-note{{'block' declared without an initial 
value}}
                                 // expected-note@+1{{Calling 'maybeWrite'}}
   maybeWrite(src, size, block); // expected-note{{Returning from 'maybeWrite'}}
 
diff --git a/clang/test/Analysis/placement-new.cpp 
b/clang/test/Analysis/placement-new.cpp
index 50bbde29cfd59..292ea40b150b8 100644
--- a/clang/test/Analysis/placement-new.cpp
+++ b/clang/test/Analysis/placement-new.cpp
@@ -38,7 +38,7 @@ void f(void *place) {
   (void)lp;
 }
 void g() {
-  char buf[2]; // expected-note {{'buf' initialized here}}
+  char buf[2]; // expected-note {{'buf' declared without an initial value}}
   f(&buf);     // expected-note 2 {{}}
 }
 } // namespace testArrayBuffer
@@ -78,7 +78,7 @@ void g() {
 namespace testPtrToArrayAsPlace {
 void f() {
   //char *st = new char [8];
-  char buf[3];                // expected-note {{'buf' initialized here}}
+  char buf[3];                // expected-note {{'buf' declared without an 
initial value}}
   void *st = buf;             // expected-note {{'st' initialized here}}
   long *lp = ::new (st) long; // expected-warning{{Storage provided to 
placement new is only 3 bytes, whereas the allocated type requires 8 bytes}} 
expected-note 1 {{}}
   (void)lp;
@@ -87,7 +87,7 @@ void f() {
 
 namespace testPtrToArrayWithOffsetAsPlace {
 void f() {
-  int buf[3];                      // expected-note {{'buf' initialized here}}
+  int buf[3];                      // expected-note {{'buf' declared without 
an initial value}}
   long *lp = ::new (buf + 2) long; // expected-warning{{Storage provided to 
placement new is only 4 bytes, whereas the allocated type requires 8 bytes}} 
expected-note 1 {{}}
   (void)lp;
 }
@@ -95,7 +95,7 @@ void f() {
 
 namespace testZeroSize {
 void f() {
-  int buf[3];                      // expected-note {{'buf' initialized here}}
+  int buf[3];                      // expected-note {{'buf' declared without 
an initial value}}
   long *lp = ::new (buf + 3) long; // expected-warning{{Storage provided to 
placement new is only 0 bytes, whereas the allocated type requires 8 bytes}} 
expected-note 1 {{}}
   (void)lp;
 }
@@ -103,7 +103,7 @@ void f() {
 
 namespace testNegativeSize {
 void f() {
-  int buf[3];                      // expected-note {{'buf' initialized here}}
+  int buf[3];                      // expected-note {{'buf' declared without 
an initial value}}
   long *lp = ::new (buf + 4) long; // expected-warning{{Storage provided to 
placement new is only -4 bytes, whereas the allocated type requires 8 bytes}} 
expected-note 1 {{}}
   (void)lp;
 }
@@ -123,7 +123,7 @@ void g2() {
 
 namespace testMultiDimensionalArray {
 void f() {
-  char buf[2][3];              // expected-note {{'buf' initialized here}}
+  char buf[2][3];              // expected-note {{'buf' declared without an 
initial value}}
   long *lp = ::new (buf) long; // expected-warning{{Storage provided to 
placement new is only 6 bytes, whereas the allocated type requires 8 bytes}} 
expected-note 1 {{}}
   (void)lp;
 }
@@ -131,7 +131,7 @@ void f() {
 
 namespace testMultiDimensionalArray2 {
 void f() {
-  char buf[2][3];                  // expected-note {{'buf' initialized here}}
+  char buf[2][3];                  // expected-note {{'buf' declared without 
an initial value}}
   long *lp = ::new (buf + 1) long; // expected-warning{{Storage provided to 
placement new is only 3 bytes, whereas the allocated type requires 8 bytes}} 
expected-note 1 {{}}
   (void)lp;
 }
@@ -139,7 +139,7 @@ void f() {
 
 namespace testMultiDimensionalArray3 {
 void f() {
-  char buf[2][3];                     // expected-note {{'buf' initialized 
here}}
+  char buf[2][3];                     // expected-note {{'buf' declared 
without an initial value}}
   long *lp = ::new (&buf[1][1]) long; // expected-warning{{Storage provided to 
placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} 
expected-note 1 {{}}
   (void)lp;
 }
@@ -251,13 +251,13 @@ void f4() {
 }
 
 void f5() {
-  short b[10]; // expected-note {{'b' initialized here}}
+  short b[10]; // expected-note {{'b' declared without an initial value}}
 
   ::new (&b) long; // expected-warning{{Storage type is aligned to 2 bytes but 
allocated type is aligned to 8 bytes}} expected-note 1 {{}}
 }
 
 void f6() {
-  short b[10]; // expected-note {{'b' initialized here}}
+  short b[10]; // expected-note {{'b' declared without an initial value}}
 
   // bad (same as previous but checks ElementRegion case)
   ::new (&b[0]) long; // expected-warning{{Storage type is aligned to 2 bytes 
but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
@@ -271,7 +271,7 @@ void f7() {
 }
 
 void f8() {
-  alignas(alignof(long)) short b[10]; // expected-note {{'b' initialized here}}
+  alignas(alignof(long)) short b[10]; // expected-note {{'b' declared without 
an initial value}}
 
   // ok. aligned to long(ok). offset 3*2(ok)
   ::new (&b[3]) long; // expected-warning{{Storage type is aligned to 6 bytes 
but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
diff --git 
a/clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c 
b/clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c
index 0a66e49be9b2a..f63cd5d9b48f7 100644
--- 
a/clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c
+++ 
b/clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c
@@ -12,7 +12,7 @@ typedef typeof(sizeof(int)) size_t;
 
 int __buf_size_arg_constraint(const void *, size_t);
 void test_buf_size_concrete(void) {
-  char buf[3];                       // bugpath-note{{'buf' initialized here}}
+  char buf[3];                       // bugpath-note{{'buf' declared without 
an initial value}}
   int s = 4;                         // bugpath-note{{'s' initialized to 4}}
   __buf_size_arg_constraint(buf, s); // \
   // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is a 
buffer with size 3 but should be a buffer with size equal to or greater than 
the value of the 2nd argument}} \
@@ -21,7 +21,7 @@ void test_buf_size_concrete(void) {
 
 int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
 void test_buf_size_concrete_with_multiplication(void) {
-  short buf[3];                               // bugpath-note{{'buf' 
initialized here}}
+  short buf[3];                               // bugpath-note{{'buf' declared 
without an initial value}}
   int s1 = 4;                                 // bugpath-note{{'s1' 
initialized to 4}}
   int s2 = sizeof(short);                     // bugpath-note{{'s2' 
initialized to}}
   __buf_size_arg_constraint_mul(buf, s1, s2); // \
diff --git a/clang/test/Analysis/std-c-library-functions-arg-constraints.c 
b/clang/test/Analysis/std-c-library-functions-arg-constraints.c
index 0b817dda98c72..2cefa80341fc4 100644
--- a/clang/test/Analysis/std-c-library-functions-arg-constraints.c
+++ b/clang/test/Analysis/std-c-library-functions-arg-constraints.c
@@ -237,7 +237,7 @@ void test_no_node_after_bug(FILE *fp, size_t size, size_t 
n, void *buf) {
 // This is one test case for the ARR38-C SEI-CERT rule.
 void ARR38_C_F(FILE *file) {
   enum { BUFFER_SIZE = 1024 };
-  wchar_t wbuf[BUFFER_SIZE]; // bugpath-note{{'wbuf' initialized here}}
+  wchar_t wbuf[BUFFER_SIZE]; // bugpath-note{{'wbuf' declared without an 
initial value}}
 
   const size_t size = sizeof(*wbuf);   // bugpath-note{{'size' initialized to}}
   const size_t nitems = sizeof(wbuf);  // bugpath-note{{'nitems' initialized 
to}}
@@ -287,7 +287,7 @@ void test_arg_constraint_on_variadic_fun(void) {
 
 int __buf_size_arg_constraint(const void *, size_t);
 void test_buf_size_concrete(void) {
-  char buf[3];                       // bugpath-note{{'buf' initialized here}}
+  char buf[3];                       // bugpath-note{{'buf' declared without 
an initial value}}
   __buf_size_arg_constraint(buf, 4); // \
   // report-warning{{The 1st argument to '__buf_size_arg_constraint' is a 
buffer with size 3 but should be a buffer with size equal to or greater than 
the value of the 2nd argument (which is 4)}} \
   // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is a 
buffer with size 3 but should be a buffer with size equal to or greater than 
the value of the 2nd argument (which is 4)}} \
@@ -314,7 +314,7 @@ void test_buf_size_symbolic_and_offset(int s) {
 
 int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
 void test_buf_size_concrete_with_multiplication(void) {
-  short buf[3];                                         // bugpath-note{{'buf' 
initialized here}}
+  short buf[3];                                         // bugpath-note{{'buf' 
declared without an initial value}}
   __buf_size_arg_constraint_mul(buf, 4, sizeof(short)); // \
   // report-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a 
buffer with size 6 but should be a buffer with size equal to or greater than 
the value of the 2nd argument (which is 4) times the 3rd argument (which is 
2)}} \
   // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a 
buffer with size 6 but should be a buffer with size equal to or greater than 
the value of the 2nd argument (which is 4) times the 3rd argument (which is 
2)}} \
@@ -340,7 +340,7 @@ void 
test_buf_size_symbolic_and_offset_with_multiplication(size_t s) {
 // The minimum buffer size for this function is set to 10.
 int __buf_size_arg_constraint_concrete(const void *);
 void test_min_buf_size(void) {
-  char buf[9];// bugpath-note{{'buf' initialized here}}
+  char buf[9];// bugpath-note{{'buf' declared without an initial value}}
   __buf_size_arg_constraint_concrete(buf); // \
   // report-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' 
is a buffer with size 9 but should be a buffer with size equal to or greater 
than 10}} \
   // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' 
is a buffer with size 9 but should be a buffer with size equal to or greater 
than 10}} \
diff --git a/clang/test/Analysis/uninit-const.c 
b/clang/test/Analysis/uninit-const.c
index 1ddf2c89ae59a..f8c89644dd306 100644
--- a/clang/test/Analysis/uninit-const.c
+++ b/clang/test/Analysis/uninit-const.c
@@ -69,14 +69,14 @@ void f_4(void) {
 }
 
 void f_5(void) {
-  int ta[5];           // expected-note {{'ta' initialized here}}
+  int ta[5];           // expected-note {{'ta' declared without an initial 
value}}
   int *tp = ta;        // expected-note {{'tp' initialized here}}
   doStuff_pointerToConstInt(tp);  // expected-warning {{1st function call 
argument is a pointer to uninitialized value}}
                        // expected-note@-1 {{1st function call argument is a 
pointer to uninitialized value}}
 }
 
 void f_5_1(void) {
-  int ta[5];        // expected-note {{'ta' initialized here}}
+  int ta[5];        // expected-note {{'ta' declared without an initial value}}
   doStuff_pointerToConstInt(ta);  // expected-warning {{1st function call 
argument is a pointer to uninitialized value}}
                        // expected-note@-1 {{1st function call argument is a 
pointer to uninitialized value}}
 }
@@ -106,20 +106,20 @@ void f_8(void) {
 }
 
 void f_9(void) {
-  int a[6];                        // expected-note {{'a' initialized here}}
+  int a[6];                        // expected-note {{'a' declared without an 
initial value}}
   int const *ptau = a;             // expected-note {{'ptau' initialized here}}
   doStuff_arrayOfConstInt(ptau);    // expected-warning {{1st function call 
argument is a pointer to uninitialized value}}
                                    // expected-note@-1 {{1st function call 
argument is a pointer to uninitialized value}}
 }
 
 void f_10(void) {
-  int  a[6];                     // expected-note {{'a' initialized here}}
+  int  a[6];                     // expected-note {{'a' declared without an 
initial value}}
   doStuff_arrayOfConstInt(a);    // expected-warning {{1st function call 
argument is a pointer to uninitialized value}}
                                  // expected-note@-1 {{1st function call 
argument is a pointer to uninitialized value}}
 }
 
 void f_11(void) {
-  int t[10];                    //expected-note {{'t' initialized here}}
+  int t[10];                    //expected-note {{'t' declared without an 
initial value}}
   doStuff_constStaticSizedArray(t);  // expected-warning {{1st function call 
argument is a pointer to uninitialized value}}
                                 // expected-note@-1 {{1st function call 
argument is a pointer to uninitialized value}}
 }
diff --git a/clang/test/Analysis/uninit-vals.m 
b/clang/test/Analysis/uninit-vals.m
index eef2600b97f56..f754f65605d1a 100644
--- a/clang/test/Analysis/uninit-vals.m
+++ b/clang/test/Analysis/uninit-vals.m
@@ -59,7 +59,7 @@ void test_uninit_neg(void) {
 
 extern void test_uninit_struct_arg_aux(struct TestUninit arg);
 void test_uninit_struct_arg(void) {
-  struct TestUninit x; // expected-note{{'x' initialized here}}
+  struct TestUninit x; // expected-note{{'x' declared without an initial 
value}}
   test_uninit_struct_arg_aux(x); // expected-warning{{Passed-by-value struct 
argument contains uninitialized data (e.g., field: 'x')}}
                                  // expected-note@-1{{Passed-by-value struct 
argument contains uninitialized data (e.g., field: 'x')}}
 }
@@ -68,7 +68,7 @@ @interface Foo
 - (void) passVal:(struct TestUninit)arg;
 @end
 void testFoo(Foo *o) {
-  struct TestUninit x; // expected-note{{'x' initialized here}}
+  struct TestUninit x; // expected-note{{'x' declared without an initial 
value}}
   [o passVal:x]; // expected-warning{{Passed-by-value struct argument contains 
uninitialized data (e.g., field: 'x')}}
                  // expected-note@-1{{Passed-by-value struct argument contains 
uninitialized data (e.g., field: 'x')}}
 }
@@ -402,7 +402,7 @@ void testSmallStructBitfieldsFirstUnnamed(void) {
   struct {
     int : 4;
     int y : 4;
-  } a, b, c; // expected-note{{'c' initialized here}}
+  } a, b, c; // expected-note{{'c' declared without an initial value}}
 
   a.y = 2;
 
@@ -419,7 +419,7 @@ void testSmallStructBitfieldsSecondUnnamed(void) {
   struct {
     int x : 4;
     int : 4;
-  } a, b, c; // expected-note{{'c' initialized here}}
+  } a, b, c; // expected-note{{'c' declared without an initial value}}
 
   a.x = 1;
 

From 56d9db0bfd53f4e694449ab8cc8a155e5b250dbf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <[email protected]>
Date: Mon, 18 May 2026 19:36:42 +0200
Subject: [PATCH 2/3] fixup: emit 'initialized here' for non-VarRegion
 destinations

Without this fallback, field regions (e.g., 'w.a') would get a note
with only the prefix and no message text.
---
 clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 2892c12261515..02a9c21e2945c 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1296,6 +1296,8 @@ static void showBRDiagnostics(llvm::raw_svector_ostream 
&OS, StoreInfo SI) {
       } else {
         OS << (HasPrefix ? "initialized" : "Initialized") << " here";
       }
+    } else {
+      OS << (HasPrefix ? "initialized" : "Initialized") << " here";
     }
   }
 }

From 0e63ad0a423948f34ea7fe7b02f140aec4138fb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <[email protected]>
Date: Wed, 20 May 2026 15:26:29 +0200
Subject: [PATCH 3/3] fixup: address review - spell out type, add garbage-value
 test

---
 .../StaticAnalyzer/Core/BugReporterVisitors.cpp    | 11 ++++-------
 clang/test/Analysis/uninit-val-init-from-garbage.c | 14 ++++++++++++++
 2 files changed, 18 insertions(+), 7 deletions(-)
 create mode 100644 clang/test/Analysis/uninit-val-init-from-garbage.c

diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp 
b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 02a9c21e2945c..4e133a9c81d91 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1281,16 +1281,13 @@ static void showBRDiagnostics(llvm::raw_svector_ostream 
&OS, StoreInfo SI) {
     // We don't need to check here, all these conditions were
     // checked by StoreSiteFinder, when it figured out that it is
     // initialization.
-    const auto *VR = dyn_cast<VarRegion>(SI.Dest);
-    if (VR) {
-      const auto *VD = VR->getDecl();
-      bool HasInit = VD->getInit();
-      bool HasGlobalStorage = VD->hasGlobalStorage();
+    if (const auto *VR = dyn_cast<VarRegion>(SI.Dest)) {
+      const VarDecl *VD = VR->getDecl();
 
-      if (SI.Value.isUndef() && HasInit) {
+      if (SI.Value.isUndef() && VD->getInit()) {
         OS << (HasPrefix ? "initialized" : "Initializing")
            << " to a garbage value";
-      } else if (!HasInit && !HasGlobalStorage) {
+      } else if (!VD->getInit() && !VD->hasGlobalStorage()) {
         OS << (HasPrefix ? "declared" : "Declared")
            << " without an initial value";
       } else {
diff --git a/clang/test/Analysis/uninit-val-init-from-garbage.c 
b/clang/test/Analysis/uninit-val-init-from-garbage.c
new file mode 100644
index 0000000000000..4ecfb3cd2a38f
--- /dev/null
+++ b/clang/test/Analysis/uninit-val-init-from-garbage.c
@@ -0,0 +1,14 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core.uninitialized.Branch \
+// RUN:   -analyzer-output=text -verify %s
+
+// Test that 'initialized to a garbage value' note is emitted when a variable
+// is initialized from an uninitialized source and later used in a branch.
+void testInitFromGarbage(int cond) {
+  int y;             // expected-note{{'y' declared without an initial value}}
+  if (cond)          // expected-note{{Assuming 'cond' is 0}}
+                     // expected-note@-1{{Taking false branch}}
+    y = 1;
+  int x = y;         // expected-note{{'x' initialized to a garbage value}}
+  if (x > 0) {}     // expected-warning{{Branch condition evaluates to a 
garbage value}}
+                     // expected-note@-1{{Branch condition evaluates to a 
garbage value}}
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to