[clang] [clang][analyzer] Add function 'ungetc' to StreamChecker. (PR #77331)
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 9 01:08:12 PST 2024
================
@@ -916,6 +922,44 @@ 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.
+ // FIXME: Is it possible that StateFailed == StateNotFailed ?
+ ProgramStateRef StateFailed = bindInt(*EofVal, State, C, CE);
+ StreamState NewSS = StreamState::getOpened(Desc);
+ StateFailed = StateFailed->set<StreamMap>(StreamSym, NewSS);
----------------
balazske wrote:
`NewSS` is now removed.
https://github.com/llvm/llvm-project/pull/77331
More information about the cfe-commits
mailing list