From 7bdca8b24f2d0b4379f1a6424a6dab409925377b Mon Sep 17 00:00:00 2001 From: Devin Coughlin Date: Mon, 7 Dec 2015 23:01:53 +0000 Subject: [PATCH] [analyzer] Fix crash when lambda captures a variable-length array. When a C++ lambda captures a variable-length array, it creates a capture field to store the size of the array. The initialization expression for this capture is null, which led the analyzer to crash when initializing the field. To avoid this, use the size expression from the VLA type to determine the initialization value. rdar://problem/23748072 llvm-svn: 254962 --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 20 +++++++++++++++++--- clang/test/Analysis/lambdas.cpp | 13 +++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 1958d7b..07ae410 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 ae4febb..0b66e6b 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(); -- 2.7.4