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/2] 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/2] 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

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

Reply via email to