[clang] [clang][analyzer] Support `fflush` in the StreamChecker (PR #74296)
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 6 08:58:55 PST 2023
================
@@ -1191,6 +1199,49 @@ void StreamChecker::evalSetFeofFerror(const FnDescription *Desc,
C.addTransition(State);
}
+void StreamChecker::preFflush(const FnDescription *Desc, const CallEvent &Call,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ SVal StreamVal = getStreamArg(Desc, Call);
+ std::optional<DefinedSVal> Stream = StreamVal.getAs<DefinedSVal>();
+ if (!Stream)
+ return;
+
+ ConstraintManager::ProgramStatePair SP =
+ C.getConstraintManager().assumeDual(State, *Stream);
+ if (State = SP.first)
+ if (State = ensureStreamOpened(StreamVal, C, State))
+ C.addTransition(State);
+}
+
+void StreamChecker::evalFflush(const FnDescription *Desc, const CallEvent &Call,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+
+ // We will check the result even if the input is `NULL`,
+ // but do nothing if the input state is unknown.
+ SymbolRef StreamSym = getStreamArg(Desc, Call).getAsSymbol();
+ if (StreamSym) {
+ const StreamState *OldSS = State->get<StreamMap>(StreamSym);
+ if (!OldSS)
+ return;
+ assertStreamStateOpened(OldSS);
+ }
+
+ const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
+ if (!CE)
+ return;
+
+ // `fflush` returns 0 on success, otherwise returns EOF.
+ ProgramStateRef StateNotFailed = bindInt(0, State, C, CE);
+ ProgramStateRef StateFailed = bindInt(*EofVal, State, C, CE);
+
+ // This function does not affect the stream state.
+ // Still we add success and failure state with the appropriate return value.
----------------
balazske wrote:
The stream state can be affected in some way, if the stream was in failed (`ferror`) state or the position is indeterminate, probably the `fflush` can be allowed but the error (and indeterminate position) should be reset to non-error. If the argument is null we can do this reset for all of the known streams. It is somewhat questionable what should happen at a failing `fflush`, but probably it is OK to leave the error flags as it was before.
https://github.com/llvm/llvm-project/pull/74296
More information about the cfe-commits
mailing list