[PATCH] D75682: [Analyzer][StreamChecker] Introduction of stream error handling.

Balázs Kéri via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 16 02:10:29 PDT 2020


balazske marked 6 inline comments as done.
balazske added inline comments.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:88
 struct FnDescription;
 using FnCheck = std::function<void(const StreamChecker *, const FnDescription *,
                                    const CallEvent &, CheckerContext &)>;
----------------
NoQ wrote:
> `llvm::function_ref`?
`function_ref`'s documentation says:
> This class does not own the callable, so it is not in general safe to store a function_ref.
The `FnDescription` stores these functions so it is not safe to use `llvm::function_ref`?





================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:366
+
+  State = State->set<StreamMap>(StreamSym, StreamState::getOpened());
+  C.addTransition(State);
----------------
NoQ wrote:
> So what exactly happens when you're calling `clearerr` on a closed stream? Does it actually become opened? Also what happens when you're calling it on an open-failed stream?
The stream gets always in opened and error-free state. The `preDefault` checks that the stream is opened (not closed and not open-failed) and creates error node if not. If this create fails that is a problem case, the stream will be opened after `clearerr`. Should check in the eval functions for closed stream even if the pre-functions (in `preCall` callback) have normally checked this?


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:379-381
+  const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
+  if (!CE)
+    return;
----------------
NoQ wrote:
> Maybe we should add a helper function for this, `CallEvent::getOriginCallExpr()`. That's an otherwise ugly function given that `CallEvent ` is a class hierarchy and the superclass doesn't need to know about subclasses, but most users do in fact only care about call-expressions and concise checker API is important. Same with `dyn_cast_or_null<FunctionDecl>(Call.getDecl())` that could be written as `Call.getFunctionDecl()`.
Can be done in another revision together with changing every use of `dyn_cast_or_null<CallExpr>(Call.getOriginExpr())` to the new function.


================
Comment at: clang/test/Analysis/stream-error.c:33-34
+  int ch = fputc('a', F);
+  if (ch == EOF) {
+    // FIXME: fputc not handled by checker yet, should expect TRUE
+    clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
----------------
NoQ wrote:
> Szelethus wrote:
> > Sure, we don't, but the bigger issue here is that we wouldn't mark `F` to be in EOF even if we did handle it, we would also need to understand that `ch == EOF` is the telling sign. But that also ins't in the scope of this patch :)
> Yeah, that's gonna be fun.
If there is a `fputc` call (for example) that is recognized (has recognized stream and no functions "fail") there is already an error and non-error branch created for it. On the error branch the return value of `fputc` would be **EOF** and the stream state is set to error. (The `fputc` should be later modeled by this checker, not done yet.)

If the `ch == EOF` is found then to figure out if this `ch` comes from an `fputc` that is called on a stream that is not recognized (it may be function parameter) and then make a "tracked" stream with error state for it, this is another thing.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75682/new/

https://reviews.llvm.org/D75682





More information about the cfe-commits mailing list