https://github.com/fangyi-zhou updated https://github.com/llvm/llvm-project/pull/136041
>From a0b769ee35df18418ed410e30ac6cdde9024a4f1 Mon Sep 17 00:00:00 2001 From: Fangyi Zhou <m...@fangyi.io> Date: Wed, 16 Apr 2025 23:52:39 +0100 Subject: [PATCH 1/4] [clang][analyzer] Handle CXXParenInitListExpr alongside InitListExpr As reported in #135665, C++20 parenthesis initializer list expressions are not handled correctly and were causing crashes. This commit attempts to fix the issue by handing parenthesis initializer lists along side existing initializer lists. --- .../Checkers/DynamicTypePropagation.cpp | 10 ++++++---- .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 11 +++++++---- clang/test/Analysis/PR135665.cpp | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 clang/test/Analysis/PR135665.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index a0bf776b11f53..6fad0601e87ca 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -379,10 +379,12 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call, // aggregates, and in such case no top-frame constructor will be called. // Figure out if we need to do anything in this case. // FIXME: Instead of relying on the ParentMap, we should have the - // trigger-statement (InitListExpr in this case) available in this - // callback, ideally as part of CallEvent. - if (isa_and_nonnull<InitListExpr>( - LCtx->getParentMap().getParent(Ctor->getOriginExpr()))) + // trigger-statement (InitListExpr or CXXParenListInitExpr in this case) + // available in this callback, ideally as part of CallEvent. + const Stmt *Parent = + LCtx->getParentMap().getParent(Ctor->getOriginExpr()); + if (isa_and_nonnull<InitListExpr>(Parent) || + isa_and_nonnull<CXXParenListInitExpr>(Parent)) return; recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 7e878f922a939..914859861b948 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -644,9 +644,11 @@ void ExprEngine::handleConstructor(const Expr *E, // FIXME: For now this code essentially bails out. We need to find the // correct target region and set it. // FIXME: Instead of relying on the ParentMap, we should have the - // trigger-statement (InitListExpr in this case) passed down from CFG or - // otherwise always available during construction. - if (isa_and_nonnull<InitListExpr>(LCtx->getParentMap().getParent(E))) { + // trigger-statement (InitListExpr or CXXParenListInitExpr in this case) + // passed down from CFG or otherwise always available during construction. + if (isa_and_nonnull<InitListExpr>(LCtx->getParentMap().getParent(E)) || + isa_and_nonnull<CXXParenListInitExpr>( + LCtx->getParentMap().getParent(E))) { MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; @@ -1017,7 +1019,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // values are properly placed inside the required region, however if an // initializer list is used, this doesn't happen automatically. auto *Init = CNE->getInitializer(); - bool isInitList = isa_and_nonnull<InitListExpr>(Init); + bool isInitList = isa_and_nonnull<InitListExpr>(Init) || + isa_and_nonnull<CXXParenListInitExpr>(Init); QualType ObjTy = isInitList ? Init->getType() : CNE->getType()->getPointeeType(); diff --git a/clang/test/Analysis/PR135665.cpp b/clang/test/Analysis/PR135665.cpp new file mode 100644 index 0000000000000..124b8c9b97b04 --- /dev/null +++ b/clang/test/Analysis/PR135665.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_analyze_cc1 -std=c++20 -analyzer-checker=core -verify %s + +// expected-no-diagnostics + +template<typename... F> +struct overload : public F... +{ + using F::operator()...; +}; + +template<typename... F> +overload(F&&...) -> overload<F...>; + +int main() +{ + const auto l = overload([](const int* i) {}); + + return 0; +} >From 8b9159444418692b49b9eb4fb06bd5d9ee863354 Mon Sep 17 00:00:00 2001 From: Fangyi Zhou <m...@fangyi.io> Date: Thu, 17 Apr 2025 17:43:07 +0100 Subject: [PATCH 2/4] Fix isa_and_nonnull calls --- .../lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp | 6 ++---- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 6fad0601e87ca..e58329817d7cd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -381,10 +381,8 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call, // FIXME: Instead of relying on the ParentMap, we should have the // trigger-statement (InitListExpr or CXXParenListInitExpr in this case) // available in this callback, ideally as part of CallEvent. - const Stmt *Parent = - LCtx->getParentMap().getParent(Ctor->getOriginExpr()); - if (isa_and_nonnull<InitListExpr>(Parent) || - isa_and_nonnull<CXXParenListInitExpr>(Parent)) + if (isa_and_nonnull<InitListExpr, CXXParenListInitExpr>( + LCtx->getParentMap().getParent(Ctor->getOriginExpr()))) return; recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 914859861b948..7b0e24dbd5ee9 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -646,8 +646,7 @@ void ExprEngine::handleConstructor(const Expr *E, // FIXME: Instead of relying on the ParentMap, we should have the // trigger-statement (InitListExpr or CXXParenListInitExpr in this case) // passed down from CFG or otherwise always available during construction. - if (isa_and_nonnull<InitListExpr>(LCtx->getParentMap().getParent(E)) || - isa_and_nonnull<CXXParenListInitExpr>( + if (isa_and_nonnull<InitListExpr, CXXParenListInitExpr>( LCtx->getParentMap().getParent(E))) { MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); >From 553c116194a1661f43231f07346e17e8e31c9684 Mon Sep 17 00:00:00 2001 From: Fangyi Zhou <m...@fangyi.io> Date: Thu, 17 Apr 2025 17:47:53 +0100 Subject: [PATCH 3/4] Add a release note entry --- clang/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0891fd058bb57..b52812a507bb6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -426,6 +426,8 @@ Bug Fixes in This Version using C++23 "deducing this" did not have a diagnostic location (#GH135522) - Fixed a crash when a ``friend`` function is redefined as deleted. (#GH135506) +- Fixed a crash in clang analyzer when C++20 parenthesized initializer lists are + used. (#GH136041) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >From c5fcba3c3f8222eeaeba8f14206dab03dd6e6e79 Mon Sep 17 00:00:00 2001 From: Fangyi Zhou <m...@fangyi.io> Date: Thu, 17 Apr 2025 17:48:53 +0100 Subject: [PATCH 4/4] Fix another call to isa_and_nonnull --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 7b0e24dbd5ee9..92ce3fa2225c8 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -1018,8 +1018,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // values are properly placed inside the required region, however if an // initializer list is used, this doesn't happen automatically. auto *Init = CNE->getInitializer(); - bool isInitList = isa_and_nonnull<InitListExpr>(Init) || - isa_and_nonnull<CXXParenListInitExpr>(Init); + bool isInitList = + isa_and_nonnull<InitListExpr, CXXParenListInitExpr>(Init); QualType ObjTy = isInitList ? Init->getType() : CNE->getType()->getPointeeType(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits