]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix crash when lambda captures a variable-length array.
authorDevin Coughlin <dcoughlin@apple.com>
Mon, 7 Dec 2015 23:01:53 +0000 (23:01 +0000)
committerDevin Coughlin <dcoughlin@apple.com>
Mon, 7 Dec 2015 23:01:53 +0000 (23:01 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@254962 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
test/Analysis/lambdas.cpp

index 1958d7bc4b1f9085743355134de3da6942298a8e..07ae41027d31ea2fefbb76ce432fa5c0022b71cf 100644 (file)
@@ -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
index ae4febbb42c437d03a299feccb253b427f4b8f8e..0b66e6b92fa66b8649ae70f3496b1204ac03b616 100644 (file)
@@ -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();