https://github.com/Snape3058 updated 
https://github.com/llvm/llvm-project/pull/187530

>From 1d87171dc76bab8fd78e60deb9b239874c5fd83b Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Thu, 19 Mar 2026 14:15:11 +0100
Subject: [PATCH 1/9] wip-2026-03-19_16:24:09

---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 14 +++++++++
 .../Analysis/issue-173210-self-assign-init.c  | 29 +++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 clang/test/Analysis/issue-173210-self-assign-init.c

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 67beed5dbb6fb..214f266e21e4c 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -624,6 +624,20 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, 
ExplodedNode *Pred,
     return;
   }
 
+  // Bypass a nop initialization that assign to itself at variable declaration.
+  // I.e., int x = x;
+  // This is an idiom in C code and GCC will not generate any assemblies for
+  // this self initialization, even under -O0, but Clang will.
+  // Since the frontend will warn in C++ code, and it is ill-formed for C++
+  // reference types, the bypass is effected to C code only.
+  if (getContext().getLangOpts().getCLangStd())
+    if (const Expr *EI = VD->getInit())
+      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(EI->IgnoreImpCasts()))
+        if (VD == DR->getDecl()) {
+          Dst.insert(Pred);
+          return;
+        }
+
   // FIXME: all pre/post visits should eventually be handled by ::Visit().
   ExplodedNodeSet dstPreVisit;
   getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
new file mode 100644
index 0000000000000..c9e5e2be58875
--- /dev/null
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -0,0 +1,29 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -verify
+
+// Self assignment initialization in C code will be treated as nop.
+// We will not report the VarDecl, but the following DeclRefExpr if it has not
+// yet been initialized then.
+
+void clang_analyzer_warnIfReached();
+
+struct S { int x; };
+union U { int x; };
+
+void nowarn() {
+  int x = x; // no-warning
+  int *p = p; // no-warning
+  struct S s = s; // no-warning
+  union U u = u; // no-warning
+  // Ensure the analysis is not terminated sliently.
+  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+}
+
+int warn() {
+  int x = x;
+  return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
+}
+
+// NOTE: The self assignment of reference type is tested with 
stack-addr-ps.cpp.
+// I.e., `int& i = i;` in function f5

>From 90734881a4366bfcc80e05e1407caadbcec3056a Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Fri, 15 May 2026 14:40:46 +0200
Subject: [PATCH 2/9] wip-2026-05-15_14:40:41

---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 24 +++++++++++-------
 .../Analysis/issue-173210-self-assign-init.c  | 25 +++++++++++++------
 2 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 214f266e21e4c..c003ad015bb1b 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -626,15 +626,21 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, 
ExplodedNode *Pred,
 
   // Bypass a nop initialization that assign to itself at variable declaration.
   // I.e., int x = x;
-  // This is an idiom in C code and GCC will not generate any assemblies for
-  // this self initialization, even under -O0, but Clang will.
-  // Since the frontend will warn in C++ code, and it is ill-formed for C++
-  // reference types, the bypass is effected to C code only.
-  if (getContext().getLangOpts().getCLangStd())
-    if (const Expr *EI = VD->getInit())
-      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(EI->IgnoreImpCasts()))
-        if (VD == DR->getDecl()) {
-          Dst.insert(Pred);
+  // This is an idiom in C code, and GCC will not generate any assemblies for
+  // this self initialization, even under -O0, although Clang will.
+  // We therefore ignore all types for C code.
+  // For C++ code, Sema will not report for fundamental types and pointers.
+  // We hence also ignore them as in C, but leave the uninitialized variable
+  // report of references to the checker. For record types, as their AST
+  // structures are different in C++, they will not hit the filter here and
+  // will be checked by the checker.
+  if (const Expr *EI = VD->getInit())
+    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(EI->IgnoreImpCasts()))
+      if (VD == DR->getDecl())
+        if (getContext().getLangOpts().getCLangStd() ||
+            (getContext().getLangOpts().getCPlusPlusLangStd() &&
+             !VD->getType()->isReferenceType())) {
+          Dst.Add(Pred);
           return;
         }
 
diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
index c9e5e2be58875..bf943554f18a9 100644
--- a/clang/test/Analysis/issue-173210-self-assign-init.c
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -1,6 +1,9 @@
-// RUN: %clang_analyze_cc1 %s \
+// RUN: %clang_analyze_cc1 -xc %s \
 // RUN:   -analyzer-checker=core,debug.ExprInspection \
 // RUN:   -verify
+// RUN: %clang_analyze_cc1 -xc++ %s \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -verify -w
 
 // Self assignment initialization in C code will be treated as nop.
 // We will not report the VarDecl, but the following DeclRefExpr if it has not
@@ -12,18 +15,24 @@ struct S { int x; };
 union U { int x; };
 
 void nowarn() {
-  int x = x; // no-warning
-  int *p = p; // no-warning
-  struct S s = s; // no-warning
-  union U u = u; // no-warning
+  int x = x; // no-warnings for C/C++
+  int *p = p; // no-warnings for C/C++
+  struct S s = s; // no-warning for C, but C++ will not report
+  union U u = u; // no-warning for C, but C++ will not report
   // Ensure the analysis is not terminated sliently.
   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 }
 
 int warn() {
-  int x = x;
+  int x = x; // no-warnings for C/C++
   return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
 }
 
-// NOTE: The self assignment of reference type is tested with 
stack-addr-ps.cpp.
-// I.e., `int& i = i;` in function f5
+// NOTE: The self assignment of reference type is also tested in 
stack-addr-ps.cpp.
+// E.g., `int& i = i;` in function f5
+// We only keep a simple regression confirmation here.
+#ifdef __cplusplus
+void warnref() {
+  int &x = x; // expected-warning{{Assigned value is uninitialized}}
+}
+#endif // __cplusplus

>From 832c8ab35525b2690db00269ad3b231ab1486087 Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Fri, 15 May 2026 15:41:52 +0200
Subject: [PATCH 3/9] Add or insert? I am really confused :(

---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index c003ad015bb1b..e418423e2cccb 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -640,7 +640,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, 
ExplodedNode *Pred,
         if (getContext().getLangOpts().getCLangStd() ||
             (getContext().getLangOpts().getCPlusPlusLangStd() &&
              !VD->getType()->isReferenceType())) {
-          Dst.Add(Pred);
+          Dst.insert(Pred);
           return;
         }
 

>From b233e4b9a00ed5791e338bd45bfdb3fbc3744071 Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Wed, 27 May 2026 19:30:20 +0200
Subject: [PATCH 4/9] add the fix for deadcode.DeadStores, reusing the test
 case

---
 clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | 6 ++++++
 clang/test/Analysis/issue-173210-self-assign-init.c     | 4 ++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index 48e358c1e6242..0d693a3e3ff3d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -431,6 +431,12 @@ class DeadStoreObs : public LiveVariables::Observer {
                   //  bug.
                   if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
                     return;
+                  // Special case: check for self-initializations.
+                  //
+                  //  e.g. int x = x;
+                  //
+                  if (VD == V)
+                    return;
                 }
 
               PathDiagnosticLocation Loc =
diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
index bf943554f18a9..50e47d3e1238b 100644
--- a/clang/test/Analysis/issue-173210-self-assign-init.c
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -1,8 +1,8 @@
 // RUN: %clang_analyze_cc1 -xc %s \
-// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores \
 // RUN:   -verify
 // RUN: %clang_analyze_cc1 -xc++ %s \
-// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores \
 // RUN:   -verify -w
 
 // Self assignment initialization in C code will be treated as nop.

>From 19da6560c9bd16324e08a08affbe0ffefe9f08a6 Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Fri, 12 Jun 2026 13:55:15 +0200
Subject: [PATCH 5/9] address the reviews

---
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 23 ++++----
 .../Analysis/issue-173210-self-assign-init.c  | 53 ++++++++++++++-----
 2 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 8cd13b3655c09..c8a78c434acfe 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -620,25 +620,20 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, 
ExplodedNode *Pred,
     return;
   }
 
-  // Bypass a nop initialization that assign to itself at variable declaration.
-  // I.e., int x = x;
-  // This is an idiom in C code, and GCC will not generate any assemblies for
-  // this self initialization, even under -O0, although Clang will.
-  // We therefore ignore all types for C code.
-  // For C++ code, Sema will not report for fundamental types and pointers.
-  // We hence also ignore them as in C, but leave the uninitialized variable
-  // report of references to the checker. For record types, as their AST
-  // structures are different in C++, they will not hit the filter here and
-  // will be checked by the checker.
-  if (const Expr *EI = VD->getInit())
+  // Self-assignment initialization in variable declaration,
+  // i.e., `int x = x;`,
+  // is a C idiom to suppress warnings of unused variables.
+  // This filter will not match variables of C++ record types, but will match
+  // C++ references. Allow references continuing here to make the undefined
+  // value checker report self-assignments of C++ references.
+  if (const Expr *EI = VD->getInit()) {
     if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(EI->IgnoreImpCasts()))
       if (VD == DR->getDecl())
-        if (getContext().getLangOpts().getCLangStd() ||
-            (getContext().getLangOpts().getCPlusPlusLangStd() &&
-             !VD->getType()->isReferenceType())) {
+        if (!VD->getType()->isReferenceType()) {
           Dst.insert(Pred);
           return;
         }
+  }
 
   // FIXME: all pre/post visits should eventually be handled by ::Visit().
   ExplodedNodeSet dstPreVisit;
diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
index 50e47d3e1238b..c53b9afdd0f30 100644
--- a/clang/test/Analysis/issue-173210-self-assign-init.c
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -6,30 +6,57 @@
 // RUN:   -verify -w
 
 // Self assignment initialization in C code will be treated as nop.
-// We will not report the VarDecl, but the following DeclRefExpr if it has not
-// yet been initialized then.
+// We will report the VarDecl only if it was left uninitialized by the time of
+// a subsequent DeclRefExpr.
+
+// NOTE: No warnings from the deadcode.DeadStores checker.
 
 void clang_analyzer_warnIfReached();
 
 struct S { int x; };
 union U { int x; };
+enum T { TT };
 
-void nowarn() {
-  int x = x; // no-warnings for C/C++
-  int *p = p; // no-warnings for C/C++
-  struct S s = s; // no-warning for C, but C++ will not report
-  union U u = u; // no-warning for C, but C++ will not report
-  // Ensure the analysis is not terminated sliently.
-  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
-}
+// No need to test VarDecl of multiple variables, as they will be split into
+// single ones when constructing the CFG.
 
-int warn() {
-  int x = x; // no-warnings for C/C++
+int warnvar() {
+  int x = x; // no-warnings for C/C++, binding is skipped via the
+             // self-assignment filter.
   return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
 }
 
+int *warnptr() {
+  int *p = p; // Same as warnvar.
+  return p; // expected-warning{{Undefined or garbage value returned to 
caller}}
+}
+
+enum T warnenum() {
+  enum T t = t; // Same as warnvar.
+  return t; // expected-warning{{Undefined or garbage value returned to 
caller}}
+}
+
+int warnstruct() {
+  struct S s = s; // no-warnings for C/C++
+                  // In C, same as warnvar.
+                  // In C++, binding is handled in the ctor call and s.x is
+                  // bound to an Undefined.
+  return s.x; // expected-warning{{Undefined or garbage value returned to 
caller}}
+}
+
+#ifndef __cplusplus
+int warnunion() {
+  union U u = u; // no-warnings for C/C++
+                 // In C, same as warnvar.
+                 // In C++, binding is handled in the ctor call and u is bound
+                 // to a lazyCompoundVal, which will not trigger an undefined
+                 // usage warning.
+  return u.x; // expected-warning{{Undefined or garbage value returned to 
caller}}
+}
+#endif // not __cplusplus
+
 // NOTE: The self assignment of reference type is also tested in 
stack-addr-ps.cpp.
-// E.g., `int& i = i;` in function f5
+// I.e., `int& i = i;` in function f5
 // We only keep a simple regression confirmation here.
 #ifdef __cplusplus
 void warnref() {

>From 5b3b53e2bcb83f7fdebf7e183b7528743f6f9ad8 Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Fri, 19 Jun 2026 15:33:50 +0200
Subject: [PATCH 6/9] apply suggestions 2026-06-19

---
 .../Analysis/issue-173210-self-assign-init.c  | 30 +++++++++----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
index c53b9afdd0f30..daf4936d56756 100644
--- a/clang/test/Analysis/issue-173210-self-assign-init.c
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -1,9 +1,9 @@
-// RUN: %clang_analyze_cc1 -xc %s \
-// RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores \
-// RUN:   -verify
-// RUN: %clang_analyze_cc1 -xc++ %s \
-// RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores \
-// RUN:   -verify -w
+// RUN: %clang_analyze_cc1 %s -verify -xc \
+// RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores
+
+// Use -w to suppress the C++ -Wuninitialized warnings on struct and reference.
+// RUN: %clang_analyze_cc1 %s -verify -xc++ -w \
+// RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores
 
 // Self assignment initialization in C code will be treated as nop.
 // We will report the VarDecl only if it was left uninitialized by the time of
@@ -37,20 +37,20 @@ enum T warnenum() {
 }
 
 int warnstruct() {
-  struct S s = s; // no-warnings for C/C++
-                  // In C, same as warnvar.
-                  // In C++, binding is handled in the ctor call and s.x is
-                  // bound to an Undefined.
+  // no-warnings for C/C++:
+  // In C, same as warnvar.
+  // In C++, binding is handled in the ctor call and 's.x' is bound to an 
Undefined.
+  struct S s = s; // no-warnings
   return s.x; // expected-warning{{Undefined or garbage value returned to 
caller}}
 }
 
 #ifndef __cplusplus
 int warnunion() {
-  union U u = u; // no-warnings for C/C++
-                 // In C, same as warnvar.
-                 // In C++, binding is handled in the ctor call and u is bound
-                 // to a lazyCompoundVal, which will not trigger an undefined
-                 // usage warning.
+  // no-warnings for C/C++:
+  // In C, same as warnvar.
+  // In C++, binding is handled in the ctor call and 'u' is bound to a
+  // lazyCompoundVal, which will not trigger an undefined usage warning.
+  union U u = u; // no-warnings
   return u.x; // expected-warning{{Undefined or garbage value returned to 
caller}}
 }
 #endif // not __cplusplus

>From 6d39ce0468c9988e2b599b7524999cc8cb1cbf4a Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Mon, 22 Jun 2026 23:16:47 +0200
Subject: [PATCH 7/9] update C++ test case execution config for the
 -Wuninitialized warnings

---
 clang/test/Analysis/issue-173210-self-assign-init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
index daf4936d56756..60e3d7a082dd0 100644
--- a/clang/test/Analysis/issue-173210-self-assign-init.c
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -2,7 +2,7 @@
 // RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores
 
 // Use -w to suppress the C++ -Wuninitialized warnings on struct and reference.
-// RUN: %clang_analyze_cc1 %s -verify -xc++ -w \
+// RUN: %clang_analyze_cc1 %s -verify -xc++ -Wno-uninitialized \
 // RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores
 
 // Self assignment initialization in C code will be treated as nop.

>From a18513fb62ddbcbd7893cf475da8a0c2b922d0a6 Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Mon, 22 Jun 2026 23:35:20 +0200
Subject: [PATCH 8/9] fix comments

---
 clang/test/Analysis/issue-173210-self-assign-init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
index 60e3d7a082dd0..44e43a998022f 100644
--- a/clang/test/Analysis/issue-173210-self-assign-init.c
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -1,7 +1,7 @@
 // RUN: %clang_analyze_cc1 %s -verify -xc \
 // RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores
 
-// Use -w to suppress the C++ -Wuninitialized warnings on struct and reference.
+// Suppress the C++ -Wuninitialized warnings on struct and reference.
 // RUN: %clang_analyze_cc1 %s -verify -xc++ -Wno-uninitialized \
 // RUN:   -analyzer-checker=core,debug.ExprInspection,deadcode.DeadStores
 

>From d6a182036afc53256056e29676a0626874bf80c3 Mon Sep 17 00:00:00 2001
From: Ella Ma <[email protected]>
Date: Tue, 14 Jul 2026 13:51:09 +0200
Subject: [PATCH 9/9] wip-2026-07-14_13:51:04

---
 clang/docs/ReleaseNotes.md                    |  1 +
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 18 ++++--
 .../Analysis/issue-173210-self-assign-init.c  | 60 ++++++++++++++++---
 3 files changed, 66 insertions(+), 13 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 9063e54b3e692..c5fd872bb75ce 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1269,6 +1269,7 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 
 - Cross Translation Unit (CTU) import failures are now reported at the 
location where the imported symbol would be used, making it easier to 
understand why a cross-TU bug was missed. (#GH188795)
 - Uninitialized-value diagnostics no longer emit a misleading "initialized 
here" note for a variable that was declared without an initializer; the note 
now reads "declared without an initial value". (#GH198345)
+- For self-assignments during initialization (`T v = v;`), 
`core.uninitialized.Assign` will not report them as uninitialized accesses 
(except C++ reference types), and the checks will be delayed until the first 
accesses of these variables; `deadcode.DeadStores` will not report them as dead 
stores. (#GH187530)
 
 (release-notes-sanitizers)=
 
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 327a3f5df5981..8eb1b42600a81 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -597,12 +597,18 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, 
ExplodedNode *Pred,
   // C++ references. Allow references continuing here to make the undefined
   // value checker report self-assignments of C++ references.
   if (const Expr *EI = VD->getInit()) {
-    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(EI->IgnoreImpCasts()))
-      if (VD == DR->getDecl())
-        if (!VD->getType()->isReferenceType()) {
-          Dst.insert(Pred);
-          return;
-        }
+    // Ignore InitListExpr if exists.
+    if (const auto *IL = dyn_cast<InitListExpr>(EI);
+        IL && IL->getNumInits() == 1)
+      EI = IL->getInit(0);
+
+    // Ignore parentheses and implict casts.
+    if (const auto *DR = dyn_cast<DeclRefExpr>(EI->IgnoreParenImpCasts())) {
+      if (VD == DR->getDecl() && !VD->getType()->isReferenceType()) {
+        Dst.insert(Pred);
+        return;
+      }
+    }
   }
 
   // FIXME: all pre/post visits should eventually be handled by ::Visit().
diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c 
b/clang/test/Analysis/issue-173210-self-assign-init.c
index 44e43a998022f..57f5c42bf69ab 100644
--- a/clang/test/Analysis/issue-173210-self-assign-init.c
+++ b/clang/test/Analysis/issue-173210-self-assign-init.c
@@ -20,23 +20,23 @@ enum T { TT };
 // No need to test VarDecl of multiple variables, as they will be split into
 // single ones when constructing the CFG.
 
-int warnvar() {
+int check_var() {
   int x = x; // no-warnings for C/C++, binding is skipped via the
              // self-assignment filter.
   return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
 }
 
-int *warnptr() {
+int *check_ptr() {
   int *p = p; // Same as warnvar.
   return p; // expected-warning{{Undefined or garbage value returned to 
caller}}
 }
 
-enum T warnenum() {
+enum T check_enum() {
   enum T t = t; // Same as warnvar.
   return t; // expected-warning{{Undefined or garbage value returned to 
caller}}
 }
 
-int warnstruct() {
+int check_struct() {
   // no-warnings for C/C++:
   // In C, same as warnvar.
   // In C++, binding is handled in the ctor call and 's.x' is bound to an 
Undefined.
@@ -45,7 +45,7 @@ int warnstruct() {
 }
 
 #ifndef __cplusplus
-int warnunion() {
+int check_union() {
   // no-warnings for C/C++:
   // In C, same as warnvar.
   // In C++, binding is handled in the ctor call and 'u' is bound to a
@@ -55,11 +55,57 @@ int warnunion() {
 }
 #endif // not __cplusplus
 
+#ifdef __cplusplus
+
 // NOTE: The self assignment of reference type is also tested in 
stack-addr-ps.cpp.
 // I.e., `int& i = i;` in function f5
 // We only keep a simple regression confirmation here.
-#ifdef __cplusplus
-void warnref() {
+void check_ref() {
   int &x = x; // expected-warning{{Assigned value is uninitialized}}
 }
+
+// Confirmation for default member initializer.
+struct struct_self_assign {
+  int x = x; // no-warnings
+};
+int check_struct_self_assign() {
+  struct_self_assign s; // no-warnings
+  return s.x; // FIXME: there should be a warning.
+}
+
+// Confirmation for constructor initialization list.
+struct struct_init_list {
+  int x;
+  struct_init_list()
+    : x(x) // expected-warning{{Assigned value is uninitialized}}
+  {}
+};
+void check_struct_init_list() {
+  // Trigger the ctor call.
+  struct_init_list s;
+}
+
+// The below two have the same AST structure.
+int check_copy_list_initialization() {
+  int x = {x}; // no-warnings
+  return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
+};
+int check_direct_list_initialization() {
+  int x {x}; // no-warnings
+  return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
+};
+
+// Having the same AST structure as `int x = x;`, rather than `int x = (x);`.
+int check_direct_initialization() {
+  int x (x); // no-warnings
+  return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
+}
+
 #endif // __cplusplus
+
+// Ignore parentheses for the initialization-with-a-macro cases, such as
+// #define VAR_INIT(x) (x) and int x = VAR_INIT(x);
+int check_paren_init() {
+  int x = (x); // no-warnings
+  return x; // expected-warning{{Undefined or garbage value returned to 
caller}}
+}

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

Reply via email to