================ @@ -916,6 +922,45 @@ void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call, C.addTransition(StateFailed); } +void StreamChecker::evalUngetc(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + SymbolRef StreamSym = getStreamArg(Desc, Call).getAsSymbol(); + if (!StreamSym) + return; + + const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()); + if (!CE) + return; + + const StreamState *OldSS = State->get<StreamMap>(StreamSym); + if (!OldSS) + return; + + assertStreamStateOpened(OldSS); + + // Generate a transition for the success state. + std::optional<NonLoc> PutVal = Call.getArgSVal(0).getAs<NonLoc>(); + if (!PutVal) + return; + ProgramStateRef StateNotFailed = + State->BindExpr(CE, C.getLocationContext(), *PutVal); + StateNotFailed = + StateNotFailed->set<StreamMap>(StreamSym, StreamState::getOpened(Desc)); + C.addTransition(StateNotFailed); + + // Add transition for the failed state. + // Failure of 'ungetc' does not result in feof or ferror state. + // If the PutVal has value of EofVal the function should "fail", but this is + // the same transition as the success state. + // In this case only one state transition is added by the analyzer (the two + // new states may be similar). + ProgramStateRef StateFailed = bindInt(*EofVal, State, C, CE); + StateFailed = + StateFailed->set<StreamMap>(StreamSym, StreamState::getOpened(Desc)); + C.addTransition(StateFailed); ---------------- balazs-benics-sonarsource wrote:
Why did we not set `ErrorFError | ErrorFEof` errors for the failure state? https://github.com/llvm/llvm-project/pull/77331 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits