diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index ffc382fcf0..5746bfb724 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -171,18 +171,28 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, const Expr *Ex, const Expr *Result) { SVal V = State->getSVal(Ex, LC); - if (!Result && !V.getAs<NonLoc>()) - return State; + if (!Result) { + // If we don't have an explicit result expression, we're in "if needed" + // mode. Only create a region if the current value is a NonLoc. + if (!V.getAs<NonLoc>()) + return State; + Result = Ex; + } else { + // We need to create a region no matter what. For sanity, make sure we don't + // try to stuff a Loc into a non-pointer temporary region. + assert(!V.getAs<Loc>() || Loc::isLocType(Result->getType())); + } ProgramStateManager &StateMgr = State->getStateManager(); MemRegionManager &MRMgr = StateMgr.getRegionManager(); StoreManager &StoreMgr = StateMgr.getStoreManager(); // We need to be careful about treating a derived type's value as - // bindings for a base type. Start by stripping and recording base casts. + // bindings for a base type. Unless we're creating a temporary pointer region, + // start by stripping and recording base casts. SmallVector<const CastExpr *, 4> Casts; const Expr *Inner = Ex->IgnoreParens(); - if (V.getAs<NonLoc>()) { + if (!Loc::isLocType(Result->getType())) { while (const CastExpr *CE = dyn_cast<CastExpr>(Inner)) { if (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_UncheckedDerivedToBase) @@ -195,8 +205,13 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, } // Create a temporary object region for the inner expression (which may have - // a more derived type) and bind the NonLoc value into it. - SVal Reg = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(Inner, LC)); + // a more derived type) and bind the value into it. + const TypedValueRegion *TR = MRMgr.getCXXTempObjectRegion(Inner, LC); + SVal Reg = loc::MemRegionVal(TR); + + if (V.isUnknown()) + V = getSValBuilder().conjureSymbolVal(Result, LC, TR->getValueType(), + currBldrCtx->blockCount()); State = State->bindLoc(Reg, V); // Re-apply the casts (from innermost to outermost) for type sanity. @@ -206,7 +221,7 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, Reg = StoreMgr.evalDerivedToBase(Reg, *I); } - State = State->BindExpr(Result ? Result : Ex, LC, Reg); + State = State->BindExpr(Result, LC, Reg); return State; } @@ -515,18 +530,20 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - ProgramStateRef state = Pred->getState(); const VarDecl *varDecl = Dtor.getVarDecl(); - QualType varType = varDecl->getType(); - if (const ReferenceType *refType = varType->getAs<ReferenceType>()) - varType = refType->getPointeeType(); + ProgramStateRef state = Pred->getState(); + SVal dest = state->getLValue(varDecl, Pred->getLocationContext()); + const MemRegion *Region = dest.castAs<loc::MemRegionVal>().getRegion(); - Loc dest = state->getLValue(varDecl, Pred->getLocationContext()); + if (const ReferenceType *refType = varType->getAs<ReferenceType>()) { + varType = refType->getPointeeType(); + Region = state->getSVal(Region).getAsRegion(); + } - VisitCXXDestructor(varType, dest.castAs<loc::MemRegionVal>().getRegion(), - Dtor.getTriggerStmt(), /*IsBase=*/ false, Pred, Dst); + VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(), /*IsBase=*/ false, + Pred, Dst); } void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, |