diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 1958d7bc4b1f..07ae41027d31 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -531,9 +531,23 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, for (LambdaExpr::const_capture_init_iterator i = LE->capture_init_begin(), e = LE->capture_init_end(); i != e; ++i, ++CurField) { - SVal Field = State->getLValue(*CurField, V); - SVal InitExpr = State->getSVal(*i, LocCtxt); - State = State->bindLoc(Field, InitExpr); + FieldDecl *FieldForCapture = *CurField; + SVal FieldLoc = State->getLValue(FieldForCapture, V); + + SVal InitVal; + if (!FieldForCapture->hasCapturedVLAType()) { + Expr *InitExpr = *i; + assert(InitExpr && "Capture missing initialization expression"); + InitVal = State->getSVal(InitExpr, LocCtxt); + } else { + // The field stores the length of a captured variable-length array. + // These captures don't have initialization expressions; instead we + // get the length from the VLAType size expression. + Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr(); + InitVal = State->getSVal(SizeExpr, LocCtxt); + } + + State = State->bindLoc(FieldLoc, InitVal); } // Decay the Loc into an RValue, because there might be a diff --git a/clang/test/Analysis/lambdas.cpp b/clang/test/Analysis/lambdas.cpp index ae4febbb42c4..0b66e6b92fa6 100644 --- a/clang/test/Analysis/lambdas.cpp +++ b/clang/test/Analysis/lambdas.cpp @@ -173,6 +173,19 @@ void testFunctionPointerCapture() { clang_analyzer_eval(i == 6); // expected-warning{{TRUE}} } +// Captured variable-length array. + +void testVariableLengthArrayCaptured() { + int n = 2; + int array[n]; + array[0] = 7; + + int i = [&]{ + return array[0]; + }(); + + clang_analyzer_eval(i == 7); // expected-warning{{TRUE}} +} // Test inline defensive checks int getNum();