diff --git a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp --- a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp +++ b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp @@ -44,6 +44,7 @@ const MemRegion *MR, SValBuilder &SVB, QualType ElementTy) { + assert(MR != nullptr && "Not-null region expected"); MR = MR->StripCasts(); DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1241,6 +1241,7 @@ const QualType &ElementTy, const LocationContext *LCtx, SVal *ElementCountVal) { + assert(Region != nullptr && "Not-null region expected"); QualType Ty = ElementTy.getDesugaredType(getContext()); while (const auto *NTy = dyn_cast(Ty)) @@ -1420,31 +1421,32 @@ const MemRegion *ArgR = ArgVal.getAsRegion(); if (DE->isArrayForm()) { - SVal ElementCount; - std::tie(State, Idx) = - prepareStateForArrayDestruction(State, ArgR, DTy, LCtx, &ElementCount); - CallOpts.IsArrayCtorOrDtor = true; // Yes, it may even be a multi-dimensional array. while (const auto *AT = getContext().getAsArrayType(DTy)) DTy = AT->getElementType(); - // If we're about to destruct a 0 length array, don't run any of the - // destructors. - if (ElementCount.isConstant() && - ElementCount.getAsInteger()->getLimitedValue() == 0) { + if (ArgR) { + SVal ElementCount; + std::tie(State, Idx) = prepareStateForArrayDestruction( + State, ArgR, DTy, LCtx, &ElementCount); - static SimpleProgramPointTag PT( - "ExprEngine", "Skipping 0 length array delete destruction"); - PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT); - NodeBuilder Bldr(Pred, Dst, *currBldrCtx); - Bldr.generateNode(PP, Pred->getState(), Pred); - return; - } + // If we're about to destruct a 0 length array, don't run any of the + // destructors. + if (ElementCount.isConstant() && + ElementCount.getAsInteger()->getLimitedValue() == 0) { + + static SimpleProgramPointTag PT( + "ExprEngine", "Skipping 0 length array delete destruction"); + PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); + Bldr.generateNode(PP, Pred->getState(), Pred); + return; + } - if (ArgR) ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal) .getAsRegion(); + } } NodeBuilder Bldr(Pred, Dst, getBuilderContext()); diff --git a/clang/test/Analysis/dtor-array.cpp b/clang/test/Analysis/dtor-array.cpp --- a/clang/test/Analysis/dtor-array.cpp +++ b/clang/test/Analysis/dtor-array.cpp @@ -344,3 +344,36 @@ // region to a conjured symbol. clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}} expected-warning {{FALSE}} } + +namespace crash6 { + +struct NonTrivialItem { + ~NonTrivialItem(); +}; + +struct WeirdVec { + void clear() { + delete[] data; + size = 0; + } + NonTrivialItem *data; + unsigned size; +}; + +void top(int j) { + WeirdVec *p = new WeirdVec; + + p[j].size = 0; + delete[] p->data; // no-crash +} + +template +T make_unknown() { + return reinterpret_cast(static_cast(0.404)); +} + +void directUnknownSymbol() { + delete[] make_unknown(); // no-crash +} + +}