[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
https://github.com/steakhal approved this pull request. Lets land this. Thank you! https://github.com/llvm/llvm-project/pull/148988 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
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
Date: Wed, 16 Jul 2025 02:09:37 +0300
Subject: [PATCH 1/9] [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(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+
case Stmt::MemberExprClass:
Bldr.takeNodes(Pred);
VisitMemberExpr(cast(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 ArgVals;
+ for (Expr *Arg : E->getInitExprs())
+ArgVals.push_back(S->getSVal(Arg, LCtx));
+
+ if (!E->isGLValue() && (T->isRecordType() || T->isArrayType())) {
+llvm::ImmutableList 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 =
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
a-tarasyuk wrote: @steakhal should other test cases be removed? https://github.com/llvm/llvm-project/pull/148988 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
@@ -4114,3 +4124,35 @@ void
*ProgramStateTrait::GDMIndex() {
}
void ExprEngine::anchor() { }
+
+void ExprEngine::ConstructInitList(const Expr *E, ArrayRef Args,
+ bool IsTransparent, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ assert((isa(E) || isa(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());
a-tarasyuk wrote:
@steakhal thanks, I've updated this condition
https://github.com/llvm/llvm-project/pull/148988
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
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
Date: Wed, 16 Jul 2025 02:09:37 +0300
Subject: [PATCH 1/8] [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(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+
case Stmt::MemberExprClass:
Bldr.takeNodes(Pred);
VisitMemberExpr(cast(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 ArgVals;
+ for (Expr *Arg : E->getInitExprs())
+ArgVals.push_back(S->getSVal(Arg, LCtx));
+
+ if (!E->isGLValue() && (T->isRecordType() || T->isArrayType())) {
+llvm::ImmutableList 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 =
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
steakhal wrote: @a-tarasyuk Could you also add the test case from the issue as-is? https://github.com/llvm/llvm-project/pull/148988 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
@@ -4114,3 +4124,35 @@ void
*ProgramStateTrait::GDMIndex() {
}
void ExprEngine::anchor() { }
+
+void ExprEngine::ConstructInitList(const Expr *E, ArrayRef Args,
+ bool IsTransparent, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ assert((isa(E) || isa(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());
steakhal wrote:
By judging the name `IsCompound`, I was expecting `E->isPRValue()` being
separated.
https://github.com/llvm/llvm-project/pull/148988
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
https://github.com/steakhal commented: Looks really good. Thanks for going the extra mile with the refactor. https://github.com/llvm/llvm-project/pull/148988 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
https://github.com/steakhal edited https://github.com/llvm/llvm-project/pull/148988 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
@@ -4114,3 +4124,35 @@ void
*ProgramStateTrait::GDMIndex() {
}
void ExprEngine::anchor() { }
+
+void ExprEngine::ConstructInitList(const Expr *E, ArrayRef Args,
+ bool IsTransparent, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ assert((isa(E) || isa(E)) &&
+ "Expected InitListExpr or CXXParenListInitExpr");
steakhal wrote:
```suggestion
assert((isa(E)));
```
https://github.com/llvm/llvm-project/pull/148988
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
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
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(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+
case Stmt::MemberExprClass:
Bldr.takeNodes(Pred);
VisitMemberExpr(cast(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 ArgVals;
+ for (Expr *Arg : E->getInitExprs())
+ArgVals.push_back(S->getSVal(Arg, LCtx));
+
+ if (!E->isGLValue() && (T->isRecordType() || T->isArrayType())) {
+llvm::ImmutableList 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 =
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
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
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(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+
case Stmt::MemberExprClass:
Bldr.takeNodes(Pred);
VisitMemberExpr(cast(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 ArgVals;
+ for (Expr *Arg : E->getInitExprs())
+ArgVals.push_back(S->getSVal(Arg, LCtx));
+
+ if (!E->isGLValue() && (T->isRecordType() || T->isArrayType())) {
+llvm::ImmutableList 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 =
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
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
Date: Wed, 16 Jul 2025 02:09:37 +0300
Subject: [PATCH 1/6] [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(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ break;
+
case Stmt::MemberExprClass:
Bldr.takeNodes(Pred);
VisitMemberExpr(cast(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 ArgVals;
+ for (Expr *Arg : E->getInitExprs())
+ArgVals.push_back(S->getSVal(Arg, LCtx));
+
+ if (!E->isGLValue() && (T->isRecordType() || T->isArrayType())) {
+llvm::ImmutableList 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 =
[clang] [analyzer] Support parenthesized list initialization (CXXParenListInitExpr) (PR #148988)
https://github.com/steakhal edited https://github.com/llvm/llvm-project/pull/148988 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
