Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -589,6 +589,24 @@ unsigned Idx = 0; if (CE->getType()->isArrayType() || AILE) { + + // No element construction will happen in a 0 size array. + auto Size = 1; + + if (auto *CAT = dyn_cast(CE->getType())) + Size = getContext().getConstantArrayElementCount(CAT); + + if (AILE) + Size = AILE->getArraySize().getLimitedValue(); + + if (Size == 0) { + StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); + static SimpleProgramPointTag T{"ExprEngine", + "Skipping 0 sized array construction"}; + Bldr.generateNode(CE, Pred, State, &T); + return; + } + Idx = getIndexOfElementToConstruct(State, CE, LCtx).value_or(0u); State = setIndexOfElementToConstruct(State, CE, LCtx, Idx + 1); } @@ -1141,7 +1159,7 @@ FieldDecl *FieldForCapture = *CurField; SVal FieldLoc = State->getLValue(FieldForCapture, V); - SVal InitVal; + SVal InitVal = UnknownVal{}; if (!FieldForCapture->hasCapturedVLAType()) { Expr *InitExpr = *i; @@ -1155,10 +1173,15 @@ assert(InitExpr && "Capture missing initialization expression"); if (dyn_cast(InitExpr)) { - InitVal = *getObjectUnderConstruction(State, {LE, Idx}, LocCtxt); - InitVal = State->getSVal(InitVal.getAsRegion()); - - State = finishObjectConstruction(State, {LE, Idx}, LocCtxt); + // The condition is false if we capture a 0 size array. We do nothing in + // that case. + if (auto ObjVal = + getObjectUnderConstruction(State, {LE, Idx}, LocCtxt)) { + InitVal = *ObjVal; + InitVal = State->getSVal(InitVal.getAsRegion()); + + State = finishObjectConstruction(State, {LE, Idx}, LocCtxt); + } } else InitVal = State->getSVal(InitExpr, LocCtxt); Index: clang/test/Analysis/array-init-loop.cpp =================================================================== --- clang/test/Analysis/array-init-loop.cpp +++ clang/test/Analysis/array-init-loop.cpp @@ -223,3 +223,27 @@ clang_analyzer_eval(moved.arr[2].i == 5); // expected-warning{{TRUE}} clang_analyzer_eval(moved.arr[3].i == 6); // expected-warning{{TRUE}} } + +// This snippet used to crash +namespace crash { + +struct S +{ + int x; + S() { x = 1; } +}; + +void no_crash() { + S arr[0]; + int n = 1; + + auto l = [arr, n] { return n; }; + + int x = l(); + clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} + + // FIXME: This should be 'Undefined'. + clang_analyzer_eval(arr[0].x); // expected-warning{{UNKNOWN}} +} + +}