https://github.com/a-tarasyuk updated 
https://github.com/llvm/llvm-project/pull/148988

>From 5db59d5b7f9b834762f86aa69040314e8faeb649 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com>
Date: Wed, 16 Jul 2025 02:09:37 +0300
Subject: [PATCH 1/7] [Analyzer] support parenthesized list initialization

---
 clang/docs/ReleaseNotes.rst                   |  2 +
 .../Core/PathSensitive/ExprEngine.h           |  3 ++
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp  |  7 ++-
 .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 31 ++++++++++++
 clang/test/Analysis/div-zero.cpp              | 50 ++++++++++++++++---
 5 files changed, 86 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1eb3e369a302e..06a41700081a9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1199,6 +1199,8 @@ Static Analyzer
 ---------------
 - Fixed a crash when C++20 parenthesized initializer lists are used. This issue
   was causing a crash in clang-tidy. (#GH136041)
+- The Clang Static Analyzer now handles parenthesized initialization.
+  (#GH148875)
 
 New features
 ^^^^^^^^^^^^
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 6370586e218ef..79d86aef8a0c6 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -586,6 +586,9 @@ class ExprEngine {
   void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
                           ExplodedNodeSet &Dst);
 
+  void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE,
+                                 ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
   /// Create a C++ temporary object for an rvalue.
   void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
                                 ExplodedNode *Pred,
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index c77ef26da568d..8f0cdd46045d0 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1941,7 +1941,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::ConceptSpecializationExprClass:
     case Stmt::CXXRewrittenBinaryOperatorClass:
     case Stmt::RequiresExprClass:
-    case Expr::CXXParenListInitExprClass:
     case Stmt::EmbedExprClass:
       // Fall through.
 
@@ -2321,6 +2320,12 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       Bldr.addNodes(Dst);
       break;
 
+    case Expr::CXXParenListInitExprClass:
+      Bldr.takeNodes(Pred);
+      VisitCXXParenListInitExpr(cast<CXXParenListInitExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
+      break;
+
     case Stmt::MemberExprClass:
       Bldr.takeNodes(Pred);
       VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 85353848aa124..059a435bd3e9e 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -1233,3 +1233,34 @@ void ExprEngine::VisitAttributedStmt(const 
AttributedStmt *A,
 
   getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
 }
+
+void ExprEngine::VisitCXXParenListInitExpr(const CXXParenListInitExpr *E,
+                                           ExplodedNode *Pred,
+                                           ExplodedNodeSet &Dst) {
+  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+
+  ProgramStateRef S = Pred->getState();
+  QualType T = getContext().getCanonicalType(E->getType());
+
+  const LocationContext *LCtx = Pred->getLocationContext();
+
+  SmallVector<SVal, 4> ArgVals;
+  for (Expr *Arg : E->getInitExprs())
+    ArgVals.push_back(S->getSVal(Arg, LCtx));
+
+  if (!E->isGLValue() && (T->isRecordType() || T->isArrayType())) {
+    llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();
+
+    for (const SVal &V : llvm::reverse(ArgVals))
+      ArgList = getBasicVals().prependSVal(V, ArgList);
+
+    Bldr.generateNode(
+        E, Pred, S->BindExpr(E, LCtx, svalBuilder.makeCompoundVal(T, 
ArgList)));
+  } else {
+    Bldr.generateNode(E, Pred,
+                      S->BindExpr(E, LCtx,
+                                  ArgVals.empty()
+                                      ? getSValBuilder().makeZeroVal(T)
+                                      : ArgVals.front()));
+  }
+}
diff --git a/clang/test/Analysis/div-zero.cpp b/clang/test/Analysis/div-zero.cpp
index 063450d8883b0..2a44ad132d4a5 100644
--- a/clang/test/Analysis/div-zero.cpp
+++ b/clang/test/Analysis/div-zero.cpp
@@ -1,13 +1,51 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core.DivideZero -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core.DivideZero -std=c++20 
-verify %s
 
-int fooPR10616 (int qX ) {
+namespace GH10616 {
+int foo(int qX) {
   int a, c, d;
 
-  d = (qX-1);
-  while ( d != 0 ) {
-    d = c - (c/d) * d;
+  d = (qX - 1);
+  while (d != 0) {
+    d = c - (c / d) * d;
   }
 
-  return (a % (qX-1)); // expected-warning {{Division by zero}}
+  return (a % (qX - 1)); // expected-warning {{Division by zero}}
+}
+} // namespace GH10616
+
+namespace GH148875 {
+struct A {
+  int x;
+  A(int v) : x(v) {}
+};
+
+struct B {
+  int x;
+  B() : x(0) {}
+};
+
+struct C {
+  int x, y;
+  C(int a, int b) : x(a), y(b) {}
+};
+
+int t1() {
+  A a(42);
+  return 1 / (a.x - 42); // expected-warning {{Division by zero}}
+}
+
+int t2() {
+  B b;
+  return 1 / b.x; // expected-warning {{Division by zero}}
+}
+
+int t3() {
+  C c1(1, -1);
+  return 1 / (c1.x + c1.y); // expected-warning {{Division by zero}}
+}
 
+int t4() {
+  C c2(0, 0);
+  return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}}
 }
+} // namespace GH148875

>From a2a7346a4770e5a857b2e6234124170f71019695 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com>
Date: Wed, 16 Jul 2025 16:44:25 +0300
Subject: [PATCH 2/7] add additinal tests

---
 clang/test/Analysis/div-zero.cpp | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/clang/test/Analysis/div-zero.cpp b/clang/test/Analysis/div-zero.cpp
index 2a44ad132d4a5..cdfac210e174e 100644
--- a/clang/test/Analysis/div-zero.cpp
+++ b/clang/test/Analysis/div-zero.cpp
@@ -29,6 +29,15 @@ struct C {
   C(int a, int b) : x(a), y(b) {}
 };
 
+struct D {
+  int x;
+};
+
+struct E {
+  D d;
+  E(int a) : d(a) {}
+};
+
 int t1() {
   A a(42);
   return 1 / (a.x - 42); // expected-warning {{Division by zero}}
@@ -48,4 +57,9 @@ int t4() {
   C c2(0, 0);
   return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}}
 }
+
+int t5() {
+  E e = 32;
+  return 1 / (e.d.x - 32); // expected-warning {{Division by zero}}
+}
 } // namespace GH148875

>From 8bb56ceae99e43b62b6635b8c8143e530313efb4 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com>
Date: Wed, 16 Jul 2025 16:46:06 +0300
Subject: [PATCH 3/7] remove redundant vector

---
 .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 27 +++++++++----------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 059a435bd3e9e..fde3939a07e29 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -1237,30 +1237,27 @@ void ExprEngine::VisitAttributedStmt(const 
AttributedStmt *A,
 void ExprEngine::VisitCXXParenListInitExpr(const CXXParenListInitExpr *E,
                                            ExplodedNode *Pred,
                                            ExplodedNodeSet &Dst) {
-  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+  const LocationContext *LC = Pred->getLocationContext();
 
+  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
   ProgramStateRef S = Pred->getState();
-  QualType T = getContext().getCanonicalType(E->getType());
 
-  const LocationContext *LCtx = Pred->getLocationContext();
+  QualType T = E->getType().getCanonicalType();
+  ArrayRef<Expr *> Inits = E->getInitExprs();
 
-  SmallVector<SVal, 4> ArgVals;
-  for (Expr *Arg : E->getInitExprs())
-    ArgVals.push_back(S->getSVal(Arg, LCtx));
-
-  if (!E->isGLValue() && (T->isRecordType() || T->isArrayType())) {
+  if (Inits.size() > 1 ||
+      (E->isPRValue() && (T->isRecordType() || T->isArrayType()))) {
     llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();
-
-    for (const SVal &V : llvm::reverse(ArgVals))
-      ArgList = getBasicVals().prependSVal(V, ArgList);
+    for (Expr *E : llvm::reverse(Inits))
+      ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList);
 
     Bldr.generateNode(
-        E, Pred, S->BindExpr(E, LCtx, svalBuilder.makeCompoundVal(T, 
ArgList)));
+        E, Pred, S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, ArgList)));
   } else {
     Bldr.generateNode(E, Pred,
-                      S->BindExpr(E, LCtx,
-                                  ArgVals.empty()
+                      S->BindExpr(E, LC,
+                                  Inits.size() == 0
                                       ? getSValBuilder().makeZeroVal(T)
-                                      : ArgVals.front()));
+                                      : S->getSVal(Inits.front(), LC)));
   }
 }

>From 6d3dd39d4c68f1b0cfbb6f51b4cc2c6acd4d7318 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com>
Date: Wed, 16 Jul 2025 18:20:04 +0300
Subject: [PATCH 4/7] revert test

---
 clang/test/Analysis/div-zero.cpp | 64 +++-----------------------------
 1 file changed, 6 insertions(+), 58 deletions(-)

diff --git a/clang/test/Analysis/div-zero.cpp b/clang/test/Analysis/div-zero.cpp
index cdfac210e174e..063450d8883b0 100644
--- a/clang/test/Analysis/div-zero.cpp
+++ b/clang/test/Analysis/div-zero.cpp
@@ -1,65 +1,13 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core.DivideZero -std=c++20 
-verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core.DivideZero -verify %s
 
-namespace GH10616 {
-int foo(int qX) {
+int fooPR10616 (int qX ) {
   int a, c, d;
 
-  d = (qX - 1);
-  while (d != 0) {
-    d = c - (c / d) * d;
+  d = (qX-1);
+  while ( d != 0 ) {
+    d = c - (c/d) * d;
   }
 
-  return (a % (qX - 1)); // expected-warning {{Division by zero}}
-}
-} // namespace GH10616
-
-namespace GH148875 {
-struct A {
-  int x;
-  A(int v) : x(v) {}
-};
-
-struct B {
-  int x;
-  B() : x(0) {}
-};
-
-struct C {
-  int x, y;
-  C(int a, int b) : x(a), y(b) {}
-};
-
-struct D {
-  int x;
-};
-
-struct E {
-  D d;
-  E(int a) : d(a) {}
-};
-
-int t1() {
-  A a(42);
-  return 1 / (a.x - 42); // expected-warning {{Division by zero}}
-}
-
-int t2() {
-  B b;
-  return 1 / b.x; // expected-warning {{Division by zero}}
-}
-
-int t3() {
-  C c1(1, -1);
-  return 1 / (c1.x + c1.y); // expected-warning {{Division by zero}}
-}
-
-int t4() {
-  C c2(0, 0);
-  return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}}
-}
+  return (a % (qX-1)); // expected-warning {{Division by zero}}
 
-int t5() {
-  E e = 32;
-  return 1 / (e.d.x - 32); // expected-warning {{Division by zero}}
 }
-} // namespace GH148875

>From 64de252d3d87e87a9c1aa05b5f22fe51b099fcfc Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com>
Date: Wed, 16 Jul 2025 18:20:20 +0300
Subject: [PATCH 5/7] add test relaetd to c++20 only

---
 clang/test/Analysis/div-zero-cxx20.cpp | 52 ++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 clang/test/Analysis/div-zero-cxx20.cpp

diff --git a/clang/test/Analysis/div-zero-cxx20.cpp 
b/clang/test/Analysis/div-zero-cxx20.cpp
new file mode 100644
index 0000000000000..efc54a275e874
--- /dev/null
+++ b/clang/test/Analysis/div-zero-cxx20.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core.DivideZero -std=c++20 
-verify %s
+
+namespace GH148875 {
+struct A {
+  int x;
+  A(int v) : x(v) {}
+};
+
+struct B {
+  int x;
+  B() : x(0) {}
+};
+
+struct C {
+  int x, y;
+  C(int a, int b) : x(a), y(b) {}
+};
+
+struct D {
+  int x;
+};
+
+struct E {
+  D d;
+  E(int a) : d(a) {}
+};
+
+int t1() {
+  A a(42);
+  return 1 / (a.x - 42); // expected-warning {{Division by zero}}
+}
+
+int t2() {
+  B b;
+  return 1 / b.x; // expected-warning {{Division by zero}}
+}
+
+int t3() {
+  C c1(1, -1);
+  return 1 / (c1.x + c1.y); // expected-warning {{Division by zero}}
+}
+
+int t4() {
+  C c2(0, 0);
+  return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}}
+}
+
+int t5() {
+  E e = 32;
+  return 1 / (e.d.x - 32); // expected-warning {{Division by zero}}
+}
+} // namespace GH148875

>From db6f5d6a90b7fe1ed49983d181bc0fae4daa5297 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com>
Date: Thu, 17 Jul 2025 17:38:15 +0300
Subject: [PATCH 6/7] share initializer list modeling between VisitInitListExpr
 and VisitCXXParenListInitExpr

---
 .../Core/PathSensitive/ExprEngine.h           |  4 +
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 77 ++++++++-----------
 .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 25 +-----
 clang/test/Analysis/div-zero-cxx20.cpp        | 10 +--
 clang/test/Analysis/div-zero.cpp              | 51 ++++++++++++
 5 files changed, 96 insertions(+), 71 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 79d86aef8a0c6..2810e10e0bec8 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -594,6 +594,10 @@ class ExprEngine {
                                 ExplodedNode *Pred,
                                 ExplodedNodeSet &Dst);
 
+  void CreateInitializationList(const Expr *Source, ArrayRef<Expr *> Args,
+                                bool IsTransparent, ExplodedNode *Pred,
+                                ExplodedNodeSet &Dst);
+
   /// evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume
   /// concrete boolean values for 'Ex', storing the resulting nodes in 'Dst'.
   void evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index fa8e669b6bb2f..997d8f0186765 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -774,49 +774,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, 
ExplodedNode *Pred,
 void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
                                    ExplodedNode *Pred,
                                    ExplodedNodeSet &Dst) {
-  StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
-
-  ProgramStateRef state = Pred->getState();
-  const LocationContext *LCtx = Pred->getLocationContext();
-  QualType T = getContext().getCanonicalType(IE->getType());
-  unsigned NumInitElements = IE->getNumInits();
-
-  if (!IE->isGLValue() && !IE->isTransparent() &&
-      (T->isArrayType() || T->isRecordType() || T->isVectorType() ||
-       T->isAnyComplexType())) {
-    llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList();
-
-    // Handle base case where the initializer has no elements.
-    // e.g: static int* myArray[] = {};
-    if (NumInitElements == 0) {
-      SVal V = svalBuilder.makeCompoundVal(T, vals);
-      B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V));
-      return;
-    }
-
-    for (const Stmt *S : llvm::reverse(*IE)) {
-      SVal V = state->getSVal(cast<Expr>(S), LCtx);
-      vals = getBasicVals().prependSVal(V, vals);
-    }
-
-    B.generateNode(IE, Pred,
-                   state->BindExpr(IE, LCtx,
-                                   svalBuilder.makeCompoundVal(T, vals)));
-    return;
-  }
-
-  // Handle scalars: int{5} and int{} and GLvalues.
-  // Note, if the InitListExpr is a GLvalue, it means that there is an address
-  // representing it, so it must have a single init element.
-  assert(NumInitElements <= 1);
-
-  SVal V;
-  if (NumInitElements == 0)
-    V = getSValBuilder().makeZeroVal(T);
-  else
-    V = state->getSVal(IE->getInit(0), LCtx);
-
-  B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V));
+  CreateInitializationList(IE, IE->inits(), IE->isTransparent(), Pred, Dst);
 }
 
 void ExprEngine::VisitGuardedExpr(const Expr *Ex,
@@ -1197,3 +1155,36 @@ void ExprEngine::VisitIncrementDecrementOperator(const 
UnaryOperator* U,
   }
   Dst.insert(Dst2);
 }
+
+void ExprEngine::CreateInitializationList(const Expr *E, ArrayRef<Expr *> Args,
+                                          bool IsTransparent,
+                                          ExplodedNode *Pred,
+                                          ExplodedNodeSet &Dst) {
+  assert((isa<InitListExpr>(E) || isa<CXXParenListInitExpr>(E)) &&
+         "Expected InitListExpr or CXXParenListInitExpr");
+
+  const LocationContext *LC = Pred->getLocationContext();
+
+  StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
+  ProgramStateRef S = Pred->getState();
+  QualType T = E->getType().getCanonicalType();
+
+  bool IsCompound =
+      E->isPRValue() && (T->isArrayType() || T->isRecordType() ||
+                         T->isAnyComplexType() || T->isVectorType());
+
+  if (Args.size() > 1 || (IsCompound && !IsTransparent)) {
+    llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();
+    for (Expr *E : llvm::reverse(Args))
+      ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList);
+
+    B.generateNode(E, Pred,
+                   S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, 
ArgList)));
+  } else {
+    B.generateNode(E, Pred,
+                   S->BindExpr(E, LC,
+                               Args.size() == 0
+                                   ? getSValBuilder().makeZeroVal(T)
+                                   : S->getSVal(Args.front(), LC)));
+  }
+}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index fde3939a07e29..08b334ec1f13b 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -1237,27 +1237,6 @@ void ExprEngine::VisitAttributedStmt(const 
AttributedStmt *A,
 void ExprEngine::VisitCXXParenListInitExpr(const CXXParenListInitExpr *E,
                                            ExplodedNode *Pred,
                                            ExplodedNodeSet &Dst) {
-  const LocationContext *LC = Pred->getLocationContext();
-
-  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
-  ProgramStateRef S = Pred->getState();
-
-  QualType T = E->getType().getCanonicalType();
-  ArrayRef<Expr *> Inits = E->getInitExprs();
-
-  if (Inits.size() > 1 ||
-      (E->isPRValue() && (T->isRecordType() || T->isArrayType()))) {
-    llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();
-    for (Expr *E : llvm::reverse(Inits))
-      ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList);
-
-    Bldr.generateNode(
-        E, Pred, S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, ArgList)));
-  } else {
-    Bldr.generateNode(E, Pred,
-                      S->BindExpr(E, LC,
-                                  Inits.size() == 0
-                                      ? getSValBuilder().makeZeroVal(T)
-                                      : S->getSVal(Inits.front(), LC)));
-  }
+  CreateInitializationList(E, E->getInitExprs(), /*IsTransparent*/ false, Pred,
+                           Dst);
 }
diff --git a/clang/test/Analysis/div-zero-cxx20.cpp 
b/clang/test/Analysis/div-zero-cxx20.cpp
index efc54a275e874..adc75344970d2 100644
--- a/clang/test/Analysis/div-zero-cxx20.cpp
+++ b/clang/test/Analysis/div-zero-cxx20.cpp
@@ -26,27 +26,27 @@ struct E {
 };
 
 int t1() {
-  A a(42);
+  A a{42};
   return 1 / (a.x - 42); // expected-warning {{Division by zero}}
 }
 
 int t2() {
-  B b;
+  B b{};
   return 1 / b.x; // expected-warning {{Division by zero}}
 }
 
 int t3() {
-  C c1(1, -1);
+  C c1{1, -1};
   return 1 / (c1.x + c1.y); // expected-warning {{Division by zero}}
 }
 
 int t4() {
-  C c2(0, 0);
+  C c2{0, 0};
   return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}}
 }
 
 int t5() {
-  E e = 32;
+  E e{32};
   return 1 / (e.d.x - 32); // expected-warning {{Division by zero}}
 }
 } // namespace GH148875
diff --git a/clang/test/Analysis/div-zero.cpp b/clang/test/Analysis/div-zero.cpp
index 063450d8883b0..498ad159afab0 100644
--- a/clang/test/Analysis/div-zero.cpp
+++ b/clang/test/Analysis/div-zero.cpp
@@ -11,3 +11,54 @@ int fooPR10616 (int qX ) {
   return (a % (qX-1)); // expected-warning {{Division by zero}}
 
 }
+
+namespace GH148875 {
+  struct A {
+  int x;
+  A(int v) : x(v) {}
+};
+
+struct B {
+  int x;
+  B() : x(0) {}
+};
+
+struct C {
+  int x, y;
+  C(int a, int b) : x(a), y(b) {}
+};
+
+struct D {
+  int x;
+};
+
+struct E {
+  D d;
+  E(int a) : d{a} {}
+};
+
+int t1() {
+  A a{42};
+  return 1 / (a.x - 42); // expected-warning {{Division by zero}}
+}
+
+int t2() {
+  B b{};
+  return 1 / b.x; // expected-warning {{Division by zero}}
+}
+
+int t3() {
+  C c1{1, -1};
+  return 1 / (c1.x + c1.y); // expected-warning {{Division by zero}}
+}
+
+int t4() {
+  C c2{0, 0};
+  return 1 / (c2.x + c2.y); // expected-warning {{Division by zero}}
+}
+
+int t5() {
+  E e{32};
+  return 1 / (e.d.x - 32); // expected-warning {{Division by zero}}
+}
+}

>From ab541b09b39b64a702a7fb5a0de4f8988c34e7ed Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.taras...@outlook.com>
Date: Thu, 17 Jul 2025 20:13:35 +0300
Subject: [PATCH 7/7] refactor visitors to use common helper

---
 .../Core/PathSensitive/ExprEngine.h           | 12 ++---
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp  | 45 +++++++++++++++++--
 clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 39 ----------------
 .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp |  7 ---
 4 files changed, 44 insertions(+), 59 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 2810e10e0bec8..fbb34340a5c67 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -499,9 +499,6 @@ class ExprEngine {
   void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,
                         ExplodedNode *Pred, ExplodedNodeSet &Dst);
 
-  void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
-                         ExplodedNodeSet &Dst);
-
   /// VisitAttributedStmt - Transfer function logic for AttributedStmt.
   void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred,
                            ExplodedNodeSet &Dst);
@@ -586,17 +583,14 @@ class ExprEngine {
   void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
                           ExplodedNodeSet &Dst);
 
-  void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE,
-                                 ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
   /// Create a C++ temporary object for an rvalue.
   void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
                                 ExplodedNode *Pred,
                                 ExplodedNodeSet &Dst);
 
-  void CreateInitializationList(const Expr *Source, ArrayRef<Expr *> Args,
-                                bool IsTransparent, ExplodedNode *Pred,
-                                ExplodedNodeSet &Dst);
+  void ConstructInitList(const Expr *Source, ArrayRef<Expr *> Args,
+                         bool IsTransparent, ExplodedNode *Pred,
+                         ExplodedNodeSet &Dst);
 
   /// evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume
   /// concrete boolean values for 'Ex', storing the resulting nodes in 'Dst'.
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 8f0cdd46045d0..bd00d47f161ff 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2314,17 +2314,22 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode 
*Pred,
       break;
     }
 
-    case Stmt::InitListExprClass:
+    case Stmt::InitListExprClass: {
+      const InitListExpr *E = cast<InitListExpr>(S);
       Bldr.takeNodes(Pred);
-      VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
+      ConstructInitList(E, E->inits(), E->isTransparent(), Pred, Dst);
       Bldr.addNodes(Dst);
       break;
+    }
 
-    case Expr::CXXParenListInitExprClass:
+    case Expr::CXXParenListInitExprClass: {
+      const CXXParenListInitExpr *E = cast<CXXParenListInitExpr>(S);
       Bldr.takeNodes(Pred);
-      VisitCXXParenListInitExpr(cast<CXXParenListInitExpr>(S), Pred, Dst);
+      ConstructInitList(E, E->getInitExprs(), /*IsTransparent*/ false, Pred,
+                        Dst);
       Bldr.addNodes(Dst);
       break;
+    }
 
     case Stmt::MemberExprClass:
       Bldr.takeNodes(Pred);
@@ -4119,3 +4124,35 @@ void 
*ProgramStateTrait<ReplayWithoutInlining>::GDMIndex() {
 }
 
 void ExprEngine::anchor() { }
+
+void ExprEngine::ConstructInitList(const Expr *E, ArrayRef<Expr *> Args,
+                                   bool IsTransparent, ExplodedNode *Pred,
+                                   ExplodedNodeSet &Dst) {
+  assert((isa<InitListExpr>(E) || isa<CXXParenListInitExpr>(E)) &&
+         "Expected InitListExpr or CXXParenListInitExpr");
+
+  const LocationContext *LC = Pred->getLocationContext();
+
+  StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
+  ProgramStateRef S = Pred->getState();
+  QualType T = E->getType().getCanonicalType();
+
+  bool IsCompound =
+      E->isPRValue() && (T->isArrayType() || T->isRecordType() ||
+                         T->isAnyComplexType() || T->isVectorType());
+
+  if (Args.size() > 1 || (IsCompound && !IsTransparent)) {
+    llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();
+    for (Expr *E : llvm::reverse(Args))
+      ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList);
+
+    B.generateNode(E, Pred,
+                   S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, 
ArgList)));
+  } else {
+    B.generateNode(E, Pred,
+                   S->BindExpr(E, LC,
+                               Args.size() == 0
+                                   ? getSValBuilder().makeZeroVal(T)
+                                   : S->getSVal(Args.front(), LC)));
+  }
+}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 997d8f0186765..f1a25a750dd0d 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -771,12 +771,6 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, 
ExplodedNode *Pred,
   Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), 
X));
 }
 
-void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
-                                   ExplodedNode *Pred,
-                                   ExplodedNodeSet &Dst) {
-  CreateInitializationList(IE, IE->inits(), IE->isTransparent(), Pred, Dst);
-}
-
 void ExprEngine::VisitGuardedExpr(const Expr *Ex,
                                   const Expr *L,
                                   const Expr *R,
@@ -1155,36 +1149,3 @@ void ExprEngine::VisitIncrementDecrementOperator(const 
UnaryOperator* U,
   }
   Dst.insert(Dst2);
 }
-
-void ExprEngine::CreateInitializationList(const Expr *E, ArrayRef<Expr *> Args,
-                                          bool IsTransparent,
-                                          ExplodedNode *Pred,
-                                          ExplodedNodeSet &Dst) {
-  assert((isa<InitListExpr>(E) || isa<CXXParenListInitExpr>(E)) &&
-         "Expected InitListExpr or CXXParenListInitExpr");
-
-  const LocationContext *LC = Pred->getLocationContext();
-
-  StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
-  ProgramStateRef S = Pred->getState();
-  QualType T = E->getType().getCanonicalType();
-
-  bool IsCompound =
-      E->isPRValue() && (T->isArrayType() || T->isRecordType() ||
-                         T->isAnyComplexType() || T->isVectorType());
-
-  if (Args.size() > 1 || (IsCompound && !IsTransparent)) {
-    llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();
-    for (Expr *E : llvm::reverse(Args))
-      ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList);
-
-    B.generateNode(E, Pred,
-                   S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, 
ArgList)));
-  } else {
-    B.generateNode(E, Pred,
-                   S->BindExpr(E, LC,
-                               Args.size() == 0
-                                   ? getSValBuilder().makeZeroVal(T)
-                                   : S->getSVal(Args.front(), LC)));
-  }
-}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 08b334ec1f13b..85353848aa124 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -1233,10 +1233,3 @@ void ExprEngine::VisitAttributedStmt(const 
AttributedStmt *A,
 
   getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
 }
-
-void ExprEngine::VisitCXXParenListInitExpr(const CXXParenListInitExpr *E,
-                                           ExplodedNode *Pred,
-                                           ExplodedNodeSet &Dst) {
-  CreateInitializationList(E, E->getInitExprs(), /*IsTransparent*/ false, Pred,
-                           Dst);
-}

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

Reply via email to