Skip to content

Commit dc4c960

Browse files
fangyi-zhousteakhal
authored andcommitted
[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. (cherry picked from commit 13d4ea6)
1 parent 7b09d7b commit dc4c960

File tree

4 files changed

+32
-8
lines changed

4 files changed

+32
-8
lines changed

clang/docs/ReleaseNotes.rst

+2
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,8 @@ Crash and bug fixes
14671467
- The ``unix.BlockInCriticalSection`` now recognizes the ``lock()`` member function
14681468
as expected, even if it's inherited from a base class. Fixes (#GH104241).
14691469

1470+
- Fixed a crash when using the overloaded lambda pattern. Fixes (#GH135665, #139789).
1471+
14701472
Improvements
14711473
^^^^^^^^^^^^
14721474

clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,12 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
379379
// aggregates, and in such case no top-frame constructor will be called.
380380
// Figure out if we need to do anything in this case.
381381
// FIXME: Instead of relying on the ParentMap, we should have the
382-
// trigger-statement (InitListExpr in this case) available in this
383-
// callback, ideally as part of CallEvent.
384-
if (isa_and_nonnull<InitListExpr>(
385-
LCtx->getParentMap().getParent(Ctor->getOriginExpr())))
382+
// trigger-statement (InitListExpr or CXXParenListInitExpr in this case)
383+
// available in this callback, ideally as part of CallEvent.
384+
const Stmt *Parent =
385+
LCtx->getParentMap().getParent(Ctor->getOriginExpr());
386+
if (isa_and_nonnull<InitListExpr>(Parent) ||
387+
isa_and_nonnull<CXXParenListInitExpr>(Parent))
386388
return;
387389

388390
recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C);

clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -637,9 +637,11 @@ void ExprEngine::handleConstructor(const Expr *E,
637637
// FIXME: For now this code essentially bails out. We need to find the
638638
// correct target region and set it.
639639
// FIXME: Instead of relying on the ParentMap, we should have the
640-
// trigger-statement (InitListExpr in this case) passed down from CFG or
641-
// otherwise always available during construction.
642-
if (isa_and_nonnull<InitListExpr>(LCtx->getParentMap().getParent(E))) {
640+
// trigger-statement (InitListExpr or CXXParenListInitExpr in this case)
641+
// passed down from CFG or otherwise always available during construction.
642+
if (isa_and_nonnull<InitListExpr>(LCtx->getParentMap().getParent(E)) ||
643+
isa_and_nonnull<CXXParenListInitExpr>(
644+
LCtx->getParentMap().getParent(E))) {
643645
MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
644646
Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
645647
CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
@@ -1010,7 +1012,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
10101012
// values are properly placed inside the required region, however if an
10111013
// initializer list is used, this doesn't happen automatically.
10121014
auto *Init = CNE->getInitializer();
1013-
bool isInitList = isa_and_nonnull<InitListExpr>(Init);
1015+
bool isInitList = isa_and_nonnull<InitListExpr>(Init) ||
1016+
isa_and_nonnull<CXXParenListInitExpr>(Init);
10141017

10151018
QualType ObjTy =
10161019
isInitList ? Init->getType() : CNE->getType()->getPointeeType();

clang/test/Analysis/PR135665.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
2+
3+
template<typename... F>
4+
struct overload : public F...
5+
{
6+
using F::operator()...;
7+
};
8+
9+
template<typename... F>
10+
overload(F&&...) -> overload<F...>;
11+
12+
int main()
13+
{
14+
const auto l = overload([](const int* i) {});
15+
16+
return 0;
17+
}

0 commit comments

Comments
 (0)