================ @@ -607,6 +564,103 @@ class StreamChecker : public Checker<check::PreCall, eval::Call, CheckerContext &C); }; +struct StreamOperationEvaluator { + SValBuilder &SVB; + const ASTContext &ACtx; + + SymbolRef StreamSym; + const StreamState *SS = nullptr; + const CallExpr *CE = nullptr; + StreamErrorState NewES; + + StreamOperationEvaluator(CheckerContext &C) + : SVB(C.getSValBuilder()), ACtx(C.getASTContext()) { + ; + } + + bool Init(const FnDescription *Desc, const CallEvent &Call, CheckerContext &C, + ProgramStateRef State) { + StreamSym = getStreamArg(Desc, Call).getAsSymbol(); + if (!StreamSym) + return false; + SS = State->get<StreamMap>(StreamSym); + if (!SS) + return false; + NewES = SS->ErrorState; + CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()); + if (!CE) + return false; + + assertStreamStateOpened(SS); + + return true; + } + + bool isStreamEof() const { return SS->ErrorState == ErrorFEof; } + + NonLoc getZeroVal(const CallEvent &Call) { + return *SVB.makeZeroVal(Call.getResultType()).getAs<NonLoc>(); + } + + ProgramStateRef setStreamState(ProgramStateRef State, + const StreamState &NewSS) { + NewES = NewSS.ErrorState; + return State->set<StreamMap>(StreamSym, NewSS); + } + + ProgramStateRef makeAndBindRetVal(ProgramStateRef State, CheckerContext &C) { + NonLoc RetVal = makeRetVal(C, CE).castAs<NonLoc>(); + return State->BindExpr(CE, C.getLocationContext(), RetVal); + } + + ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C, + uint64_t Val) { + return State->BindExpr(CE, C.getLocationContext(), + SVB.makeIntVal(Val, CE->getCallReturnType(ACtx))); + } + + ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C, + SVal Val) { + return State->BindExpr(CE, C.getLocationContext(), Val); + } + + ProgramStateRef bindNullReturnValue(ProgramStateRef State, + CheckerContext &C) { + return State->BindExpr(CE, C.getLocationContext(), + C.getSValBuilder().makeNullWithType(CE->getType())); + } + + ProgramStateRef assumeBinOpNN(ProgramStateRef State, + BinaryOperator::Opcode Op, NonLoc LHS, + NonLoc RHS) { + auto Cond = SVB.evalBinOpNN(State, Op, LHS, RHS, SVB.getConditionType()) + .getAs<DefinedOrUnknownSVal>(); + if (!Cond) + return nullptr; + return State->assume(*Cond, true); + } + + ConstraintManager::ProgramStatePair + makeRetValAndAssumeDual(ProgramStateRef State, CheckerContext &C) { + DefinedSVal RetVal = makeRetVal(C, CE); + State = State->BindExpr(CE, C.getLocationContext(), RetVal); + return C.getConstraintManager().assumeDual(State, RetVal); + } + + const NoteTag *getStreamErrorNoteTag(const StreamChecker *Ch, ---------------- NagyDonat wrote:
It's a bit misleading that the name of this function refers to "Error" while it can place both the "Eof" and the "Error" note tags (depending on the situation). Try to find a more neutral name like `getStreamStateNoteTag` (or something better -- `State` is neutral between `Error` and `Eof`, but is an overused word). https://github.com/llvm/llvm-project/pull/83288 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits