@@ -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,40 @@ 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+ // WARNING: As this function performs transitions between several different
679+ // states (perhaps in a branching structure) we must be careful to avoid
680+ // referencing obsolete or irrelevant states. In particular, 'CallEvent'
681+ // instances have an attached state (because this is is convenient within the
682+ // checker callbacks) and it is our responsibility to keep these up-to-date.
683+ // In fact, the parameter 'CallTemplate' is a "template" because its attached
684+ // state may be older than the state of 'Pred' (which will be further
685+ // transformed by the transitions within this method).
686+ // (Note that 'runCheckersFor*Call' and 'finishArgumentConstruction' are
687+ // prepared to take this template and and attach the proper state before
688+ // forwarding it to the checkers.)
680689
681690 // Run any pre-call checks using the generic call interface.
682691 ExplodedNodeSet dstPreVisit;
683- getCheckerManager ().runCheckersForPreCall (dstPreVisit, Pred,
684- Call, *this );
692+ getCheckerManager ().runCheckersForPreCall (dstPreVisit, Pred, CallTemplate,
693+ *this );
685694
686695 // Actually evaluate the function call. We try each of the checkers
687696 // to see if the can evaluate the function call, and get a callback at
688697 // defaultEvalCall if all of them fail.
689698 ExplodedNodeSet dstCallEvaluated;
690- getCheckerManager ().runCheckersForEvalCall (dstCallEvaluated, dstPreVisit,
691- Call , *this , EvalCallOptions ());
699+ getCheckerManager ().runCheckersForEvalCall (
700+ dstCallEvaluated, dstPreVisit, CallTemplate , *this , EvalCallOptions ());
692701
693702 // If there were other constructors called for object-type arguments
694703 // of this call, clean them up.
695704 ExplodedNodeSet dstArgumentCleanup;
696705 for (ExplodedNode *I : dstCallEvaluated)
697- finishArgumentConstruction (dstArgumentCleanup, I, Call );
706+ finishArgumentConstruction (dstArgumentCleanup, I, CallTemplate );
698707
699708 ExplodedNodeSet dstPostCall;
700709 getCheckerManager ().runCheckersForPostCall (dstPostCall, dstArgumentCleanup,
701- Call , *this );
710+ CallTemplate , *this );
702711
703712 // Escaping symbols conjured during invalidating the regions above.
704713 // Note that, for inlined calls the nodes were put back into the worklist,
@@ -708,12 +717,13 @@ void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
708717 // Run pointerEscape callback with the newly conjured symbols.
709718 SmallVector<std::pair<SVal, SVal>, 8 > Escaped;
710719 for (ExplodedNode *I : dstPostCall) {
711- NodeBuilder B (I, Dst, *currBldrCtx);
712720 ProgramStateRef State = I->getState ();
721+ CallEventRef<> Call = CallTemplate.cloneWithState (State);
722+ NodeBuilder B (I, Dst, *currBldrCtx);
713723 Escaped.clear ();
714724 {
715725 unsigned Arg = -1 ;
716- for (const ParmVarDecl *PVD : Call. parameters ()) {
726+ for (const ParmVarDecl *PVD : Call-> parameters ()) {
717727 ++Arg;
718728 QualType ParamTy = PVD->getType ();
719729 if (ParamTy.isNull () ||
@@ -722,13 +732,13 @@ void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
722732 QualType Pointee = ParamTy->getPointeeType ();
723733 if (Pointee.isConstQualified () || Pointee->isVoidType ())
724734 continue ;
725- if (const MemRegion *MR = Call. getArgSVal (Arg).getAsRegion ())
735+ if (const MemRegion *MR = Call-> getArgSVal (Arg).getAsRegion ())
726736 Escaped.emplace_back (loc::MemRegionVal (MR), State->getSVal (MR, Pointee));
727737 }
728738 }
729739
730740 State = processPointerEscapedOnBind (State, Escaped, I->getLocationContext (),
731- PSK_EscapeOutParameters, &Call);
741+ PSK_EscapeOutParameters, &* Call);
732742
733743 if (State == I->getState ())
734744 Dst.insert (I);
@@ -1212,59 +1222,58 @@ static bool isTrivialObjectAssignment(const CallEvent &Call) {
12121222}
12131223
12141224void ExprEngine::defaultEvalCall (NodeBuilder &Bldr, ExplodedNode *Pred,
1215- const CallEvent &CallTemplate ,
1225+ const CallEvent &Call ,
12161226 const EvalCallOptions &CallOpts) {
12171227 // Make sure we have the most recent state attached to the call.
12181228 ProgramStateRef State = Pred->getState ();
1219- CallEventRef<> Call = CallTemplate.cloneWithState (State);
12201229
12211230 // Special-case trivial assignment operators.
1222- if (isTrivialObjectAssignment (* Call)) {
1223- performTrivialCopy (Bldr, Pred, * Call);
1231+ if (isTrivialObjectAssignment (Call)) {
1232+ performTrivialCopy (Bldr, Pred, Call);
12241233 return ;
12251234 }
12261235
12271236 // Try to inline the call.
12281237 // The origin expression here is just used as a kind of checksum;
12291238 // this should still be safe even for CallEvents that don't come from exprs.
1230- const Expr *E = Call-> getOriginExpr ();
1239+ const Expr *E = Call. getOriginExpr ();
12311240
12321241 ProgramStateRef InlinedFailedState = getInlineFailedState (State, E);
12331242 if (InlinedFailedState) {
12341243 // If we already tried once and failed, make sure we don't retry later.
12351244 State = InlinedFailedState;
12361245 } else {
1237- RuntimeDefinition RD = Call-> getRuntimeDefinition ();
1238- Call-> setForeign (RD.isForeign ());
1246+ RuntimeDefinition RD = Call. getRuntimeDefinition ();
1247+ Call. setForeign (RD.isForeign ());
12391248 const Decl *D = RD.getDecl ();
1240- if (shouldInlineCall (* Call, D, Pred, CallOpts)) {
1249+ if (shouldInlineCall (Call, D, Pred, CallOpts)) {
12411250 if (RD.mayHaveOtherDefinitions ()) {
12421251 AnalyzerOptions &Options = getAnalysisManager ().options ;
12431252
12441253 // Explore with and without inlining the call.
12451254 if (Options.getIPAMode () == IPAK_DynamicDispatchBifurcate) {
1246- BifurcateCall (RD.getDispatchRegion (), * Call, D, Bldr, Pred);
1255+ BifurcateCall (RD.getDispatchRegion (), Call, D, Bldr, Pred);
12471256 return ;
12481257 }
12491258
12501259 // Don't inline if we're not in any dynamic dispatch mode.
12511260 if (Options.getIPAMode () != IPAK_DynamicDispatch) {
1252- conservativeEvalCall (* Call, Bldr, Pred, State);
1261+ conservativeEvalCall (Call, Bldr, Pred, State);
12531262 return ;
12541263 }
12551264 }
1256- ctuBifurcate (* Call, D, Bldr, Pred, State);
1265+ ctuBifurcate (Call, D, Bldr, Pred, State);
12571266 return ;
12581267 }
12591268 }
12601269
12611270 // If we can't inline it, clean up the state traits used only if the function
12621271 // is inlined.
12631272 State = removeStateTraitsUsedForArrayEvaluation (
1264- State, dyn_cast_or_null<CXXConstructExpr>(E), Call-> getLocationContext ());
1273+ State, dyn_cast_or_null<CXXConstructExpr>(E), Call. getLocationContext ());
12651274
12661275 // Also handle the return value and invalidate the regions.
1267- conservativeEvalCall (* Call, Bldr, Pred, State);
1276+ conservativeEvalCall (Call, Bldr, Pred, State);
12681277}
12691278
12701279void ExprEngine::BifurcateCall (const MemRegion *BifurReg,
0 commit comments