@@ -628,6 +628,8 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
628628
629629ProgramStateRef ExprEngine::finishArgumentConstruction (ProgramStateRef State,
630630 const CallEvent &Call) {
631+ // WARNING: The state attached to 'Call' may be obsolete, do not call any
632+ // methods that rely on it!
631633 const Expr *E = Call.getOriginExpr ();
632634 // FIXME: Constructors to placement arguments of operator new
633635 // are not supported yet.
@@ -653,6 +655,8 @@ ProgramStateRef ExprEngine::finishArgumentConstruction(ProgramStateRef State,
653655void ExprEngine::finishArgumentConstruction (ExplodedNodeSet &Dst,
654656 ExplodedNode *Pred,
655657 const CallEvent &Call) {
658+ // WARNING: The state attached to 'Call' may be obsolete, do not call any
659+ // methods that rely on it!
656660 ProgramStateRef State = Pred->getState ();
657661 ProgramStateRef CleanedState = finishArgumentConstruction (State, Call);
658662 if (CleanedState == State) {
@@ -670,35 +674,33 @@ void ExprEngine::finishArgumentConstruction(ExplodedNodeSet &Dst,
670674}
671675
672676void ExprEngine::evalCall (ExplodedNodeSet &Dst, ExplodedNode *Pred,
673- const CallEvent &Call) {
674- // WARNING: At this time, the state attached to 'Call' may be older than the
675- // state in 'Pred'. This is a minor optimization since CheckerManager will
676- // use an updated CallEvent instance when calling checkers, but if 'Call' is
677- // ever used directly in this function all callers should be updated to pass
678- // the most recent state. (It is probably not worth doing the work here since
679- // for some callers this will not be necessary.)
677+ const CallEvent &CallTemplate) {
678+ // NOTE: CallTemplate is called a "template" because its attached state may
679+ // be obsolete (compared to the state of Pred). The state-dependent methods
680+ // of CallEvent should be used only after a `cloneWithState` call that
681+ // attaches the up-to-date state to this template object.
680682
681683 // Run any pre-call checks using the generic call interface.
682684 ExplodedNodeSet dstPreVisit;
683- getCheckerManager ().runCheckersForPreCall (dstPreVisit, Pred,
684- Call, *this );
685+ getCheckerManager ().runCheckersForPreCall (dstPreVisit, Pred, CallTemplate,
686+ *this );
685687
686688 // Actually evaluate the function call. We try each of the checkers
687689 // to see if the can evaluate the function call, and get a callback at
688690 // defaultEvalCall if all of them fail.
689691 ExplodedNodeSet dstCallEvaluated;
690- getCheckerManager ().runCheckersForEvalCall (dstCallEvaluated, dstPreVisit,
691- Call , *this , EvalCallOptions ());
692+ getCheckerManager ().runCheckersForEvalCall (
693+ dstCallEvaluated, dstPreVisit, CallTemplate , *this , EvalCallOptions ());
692694
693695 // If there were other constructors called for object-type arguments
694696 // of this call, clean them up.
695697 ExplodedNodeSet dstArgumentCleanup;
696698 for (ExplodedNode *I : dstCallEvaluated)
697- finishArgumentConstruction (dstArgumentCleanup, I, Call );
699+ finishArgumentConstruction (dstArgumentCleanup, I, CallTemplate );
698700
699701 ExplodedNodeSet dstPostCall;
700702 getCheckerManager ().runCheckersForPostCall (dstPostCall, dstArgumentCleanup,
701- Call , *this );
703+ CallTemplate , *this );
702704
703705 // Escaping symbols conjured during invalidating the regions above.
704706 // Note that, for inlined calls the nodes were put back into the worklist,
@@ -708,12 +710,13 @@ void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
708710 // Run pointerEscape callback with the newly conjured symbols.
709711 SmallVector<std::pair<SVal, SVal>, 8 > Escaped;
710712 for (ExplodedNode *I : dstPostCall) {
711- NodeBuilder B (I, Dst, *currBldrCtx);
712713 ProgramStateRef State = I->getState ();
714+ CallEventRef<> Call = CallTemplate.cloneWithState (State);
715+ NodeBuilder B (I, Dst, *currBldrCtx);
713716 Escaped.clear ();
714717 {
715718 unsigned Arg = -1 ;
716- for (const ParmVarDecl *PVD : Call. parameters ()) {
719+ for (const ParmVarDecl *PVD : Call-> parameters ()) {
717720 ++Arg;
718721 QualType ParamTy = PVD->getType ();
719722 if (ParamTy.isNull () ||
@@ -722,13 +725,13 @@ void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
722725 QualType Pointee = ParamTy->getPointeeType ();
723726 if (Pointee.isConstQualified () || Pointee->isVoidType ())
724727 continue ;
725- if (const MemRegion *MR = Call. getArgSVal (Arg).getAsRegion ())
728+ if (const MemRegion *MR = Call-> getArgSVal (Arg).getAsRegion ())
726729 Escaped.emplace_back (loc::MemRegionVal (MR), State->getSVal (MR, Pointee));
727730 }
728731 }
729732
730733 State = processPointerEscapedOnBind (State, Escaped, I->getLocationContext (),
731- PSK_EscapeOutParameters, &Call);
734+ PSK_EscapeOutParameters, &* Call);
732735
733736 if (State == I->getState ())
734737 Dst.insert (I);
@@ -1212,59 +1215,58 @@ static bool isTrivialObjectAssignment(const CallEvent &Call) {
12121215}
12131216
12141217void ExprEngine::defaultEvalCall (NodeBuilder &Bldr, ExplodedNode *Pred,
1215- const CallEvent &CallTemplate ,
1218+ const CallEvent &Call ,
12161219 const EvalCallOptions &CallOpts) {
12171220 // Make sure we have the most recent state attached to the call.
12181221 ProgramStateRef State = Pred->getState ();
1219- CallEventRef<> Call = CallTemplate.cloneWithState (State);
12201222
12211223 // Special-case trivial assignment operators.
1222- if (isTrivialObjectAssignment (* Call)) {
1223- performTrivialCopy (Bldr, Pred, * Call);
1224+ if (isTrivialObjectAssignment (Call)) {
1225+ performTrivialCopy (Bldr, Pred, Call);
12241226 return ;
12251227 }
12261228
12271229 // Try to inline the call.
12281230 // The origin expression here is just used as a kind of checksum;
12291231 // this should still be safe even for CallEvents that don't come from exprs.
1230- const Expr *E = Call-> getOriginExpr ();
1232+ const Expr *E = Call. getOriginExpr ();
12311233
12321234 ProgramStateRef InlinedFailedState = getInlineFailedState (State, E);
12331235 if (InlinedFailedState) {
12341236 // If we already tried once and failed, make sure we don't retry later.
12351237 State = InlinedFailedState;
12361238 } else {
1237- RuntimeDefinition RD = Call-> getRuntimeDefinition ();
1238- Call-> setForeign (RD.isForeign ());
1239+ RuntimeDefinition RD = Call. getRuntimeDefinition ();
1240+ Call. setForeign (RD.isForeign ());
12391241 const Decl *D = RD.getDecl ();
1240- if (shouldInlineCall (* Call, D, Pred, CallOpts)) {
1242+ if (shouldInlineCall (Call, D, Pred, CallOpts)) {
12411243 if (RD.mayHaveOtherDefinitions ()) {
12421244 AnalyzerOptions &Options = getAnalysisManager ().options ;
12431245
12441246 // Explore with and without inlining the call.
12451247 if (Options.getIPAMode () == IPAK_DynamicDispatchBifurcate) {
1246- BifurcateCall (RD.getDispatchRegion (), * Call, D, Bldr, Pred);
1248+ BifurcateCall (RD.getDispatchRegion (), Call, D, Bldr, Pred);
12471249 return ;
12481250 }
12491251
12501252 // Don't inline if we're not in any dynamic dispatch mode.
12511253 if (Options.getIPAMode () != IPAK_DynamicDispatch) {
1252- conservativeEvalCall (* Call, Bldr, Pred, State);
1254+ conservativeEvalCall (Call, Bldr, Pred, State);
12531255 return ;
12541256 }
12551257 }
1256- ctuBifurcate (* Call, D, Bldr, Pred, State);
1258+ ctuBifurcate (Call, D, Bldr, Pred, State);
12571259 return ;
12581260 }
12591261 }
12601262
12611263 // If we can't inline it, clean up the state traits used only if the function
12621264 // is inlined.
12631265 State = removeStateTraitsUsedForArrayEvaluation (
1264- State, dyn_cast_or_null<CXXConstructExpr>(E), Call-> getLocationContext ());
1266+ State, dyn_cast_or_null<CXXConstructExpr>(E), Call. getLocationContext ());
12651267
12661268 // Also handle the return value and invalidate the regions.
1267- conservativeEvalCall (* Call, Bldr, Pred, State);
1269+ conservativeEvalCall (Call, Bldr, Pred, State);
12681270}
12691271
12701272void ExprEngine::BifurcateCall (const MemRegion *BifurReg,
0 commit comments