diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 6445b9df5a58..1cbd09ea5793 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -1,9 +1,8 @@ //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -197,6 +196,12 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction( // able to find construction context at all. break; } + if (isa<BlockInvocationContext>(CallerLCtx)) { + // Unwrap block invocation contexts. They're mostly part of + // the current stack frame. + CallerLCtx = CallerLCtx->getParent(); + assert(!isa<BlockInvocationContext>(CallerLCtx)); + } return prepareForObjectConstruction( cast<Expr>(SFC->getCallSite()), State, CallerLCtx, RTC->getConstructionContext(), CallOpts); @@ -423,25 +428,20 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, prepareForObjectConstruction(CE, State, LCtx, CC, CallOpts); break; } - case CXXConstructExpr::CK_VirtualBase: + case CXXConstructExpr::CK_VirtualBase: { // Make sure we are not calling virtual base class initializers twice. // Only the most-derived object should initialize virtual base classes. - if (const Stmt *Outer = LCtx->getStackFrame()->getCallSite()) { - const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer); - if (OuterCtor) { - switch (OuterCtor->getConstructionKind()) { - case CXXConstructExpr::CK_NonVirtualBase: - case CXXConstructExpr::CK_VirtualBase: - // Bail out! - destNodes.Add(Pred); - return; - case CXXConstructExpr::CK_Complete: - case CXXConstructExpr::CK_Delegating: - break; - } - } - } + const auto *OuterCtor = dyn_cast_or_null<CXXConstructExpr>( + LCtx->getStackFrame()->getCallSite()); + assert( + (!OuterCtor || + OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete || + OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) && + ("This virtual base should have already been initialized by " + "the most derived class!")); + (void)OuterCtor; LLVM_FALLTHROUGH; + } case CXXConstructExpr::CK_NonVirtualBase: // In C++17, classes with non-virtual bases may be aggregates, so they would // be initialized as aggregates without a constructor call, so we may have @@ -604,6 +604,7 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType, ExplodedNode *Pred, ExplodedNodeSet &Dst, const EvalCallOptions &CallOpts) { + assert(S && "A destructor without a trigger!"); const LocationContext *LCtx = Pred->getLocationContext(); ProgramStateRef State = Pred->getState(); @@ -611,6 +612,19 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType, assert(RecordDecl && "Only CXXRecordDecls should have destructors"); const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); + // FIXME: There should always be a Decl, otherwise the destructor call + // shouldn't have been added to the CFG in the first place. + if (!DtorDecl) { + // Skip the invalid destructor. We cannot simply return because + // it would interrupt the analysis instead. + static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor"); + // FIXME: PostImplicitCall with a null decl may crash elsewhere anyway. + PostImplicitCall PP(/*Decl=*/nullptr, S->getEndLoc(), LCtx, &T); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); + Bldr.generateNode(PP, Pred->getState(), Pred); + return; + } + CallEventManager &CEMgr = getStateManager().getCallEventManager(); CallEventRef<CXXDestructorCall> Call = CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); @@ -629,7 +643,6 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType, I != E; ++I) defaultEvalCall(Bldr, *I, *Call, CallOpts); - ExplodedNodeSet DstPostCall; getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, *Call, *this); } |