[analyzer] Fix a crash on copy elided initialized lambda captures

Inside `ExprEngine::VisitLambdaExpr()` we wasn't prepared for a
copy elided initialized capture's `InitExpr`. This patch teaches
the analyzer how to handle such situation.

Differential Revision: https://reviews.llvm.org/D131784
This commit is contained in:
isuckatcs 2022-08-12 17:12:50 +02:00
parent e17cae076c
commit b4e3e3a3eb
2 changed files with 25 additions and 2 deletions

View File

@ -1143,7 +1143,9 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
SVal InitVal;
if (!FieldForCapture->hasCapturedVLAType()) {
Expr *InitExpr = *i;
const Expr *InitExpr = *i;
assert(InitExpr && "Capture missing initialization expression");
if (const auto AILE = dyn_cast<ArrayInitLoopExpr>(InitExpr)) {
// If the AILE initializes a POD array, we need to keep it as the
@ -1152,7 +1154,12 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
InitExpr = AILE->getSubExpr();
}
assert(InitExpr && "Capture missing initialization expression");
// With C++17 copy elision this can happen.
if (const auto *FC = dyn_cast<CXXFunctionalCastExpr>(InitExpr))
InitExpr = FC->getSubExpr();
assert(InitExpr &&
"Extracted capture initialization expression is missing");
if (dyn_cast<CXXConstructExpr>(InitExpr)) {
InitVal = *getObjectUnderConstruction(State, {LE, Idx}, LocCtxt);

View File

@ -203,6 +203,22 @@ void testVariableLengthArrayCaptured() {
clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
}
#if __cplusplus >= 201402L
// Capture copy elided object.
struct Elided{
int x = 0;
Elided(int) {}
};
void testCopyElidedObjectCaptured(int x) {
[e = Elided(x)] {
clang_analyzer_eval(e.x == 0); // expected-warning{{TRUE}}
}();
}
#endif
// Test inline defensive checks
int getNum();