[clang] [analyzer] Avoid use of `CallEvent`s with obsolete state (PR #160707)

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 29 09:57:20 PDT 2025


================
@@ -731,33 +731,36 @@ void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
     ExplodedNodeSet checkDst;
     NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
 
+    ProgramStateRef State = Pred->getState();
+    CallEventRef<> UpdatedCall = Call.cloneWithState(State);
+
     // Check if any of the EvalCall callbacks can evaluate the call.
     for (const auto &EvalCallChecker : EvalCallCheckers) {
       // TODO: Support the situation when the call doesn't correspond
       // to any Expr.
       ProgramPoint L = ProgramPoint::getProgramPoint(
-          Call.getOriginExpr(), ProgramPoint::PostStmtKind,
+          UpdatedCall->getOriginExpr(), ProgramPoint::PostStmtKind,
           Pred->getLocationContext(), EvalCallChecker.Checker);
       bool evaluated = false;
       { // CheckerContext generates transitions(populates checkDest) on
         // destruction, so introduce the scope to make sure it gets properly
         // populated.
         CheckerContext C(B, Eng, Pred, L);
-        evaluated = EvalCallChecker(Call, C);
+        evaluated = EvalCallChecker(*UpdatedCall, C);
       }
 #ifndef NDEBUG
       if (evaluated && evaluatorChecker) {
-        const auto toString = [](const CallEvent &Call) -> std::string {
+        const auto toString = [](CallEventRef<> Call) -> std::string {
           std::string Buf;
           llvm::raw_string_ostream OS(Buf);
-          Call.dump(OS);
+          Call->dump(OS);
----------------
haoNoQ wrote:

The dump probably doesn't change after the clone.

But generally, in the checker loop, the updated call event indicates that the call was evaluated by multiple checkers. Which should be impossible in practice but it looks like we've decided to act gracefully when assertions are turned off.

That said, we aren't doing a great job at that, given that we're using `llvm_unreachable()` that translates to pure undefined behavior (aka `__builtin_unreachable()`) when assertions are turned off. (See also [LLVM_UNREACHABLE_OPTIMIZE](https://llvm.org/docs/CMake.html). These UBs are sometimes incredibly fun to debug.)

https://github.com/llvm/llvm-project/pull/160707


More information about the cfe-commits mailing list