[clang] [clang][analyzer] Support `fgetc` in StreamChecker (PR #72627)
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 22 08:42:35 PST 2023
================
@@ -768,26 +772,56 @@ void StreamChecker::evalFputc(const FnDescription *Desc, const CallEvent &Call,
assertStreamStateOpened(OldSS);
+ // `fgetc` returns the read character on success, otherwise returns EOF.
// `fputc` returns the written character on success, otherwise returns EOF.
- // 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);
+ // Generate a transition for the success state of fputc.
+ if (!IsRead) {
+ 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);
+ }
+ // Generate a transition for the success state of fgetc.
+ // If we know the state to be FEOF at fgetc, do not add a success state.
+ else if (OldSS->ErrorState != ErrorFEof) {
+ NonLoc RetVal = makeRetVal(C, CE).castAs<NonLoc>();
+ ProgramStateRef StateNotFailed =
+ State->BindExpr(CE, C.getLocationContext(), RetVal);
+ SValBuilder &SVB = C.getSValBuilder();
+ auto Cond = SVB.evalBinOp(State, BO_GE, RetVal,
+ SVB.makeZeroVal(C.getASTContext().IntTy),
+ SVB.getConditionType())
+ .getAs<DefinedOrUnknownSVal>();
+ if (!Cond)
+ return;
----------------
balazske wrote:
The function returns an `unsigned char` value converted to `int`, another condition should be added for the upper limit.
https://github.com/llvm/llvm-project/pull/72627
More information about the cfe-commits
mailing list