baloghadamsoftware added inline comments.

================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:33-45
+  enum KindTy {
+    Opened, /// Stream is opened.
+    Closed, /// Closed stream (an invalid stream pointer after it was closed).
+    OpenFailed /// The last open operation has failed.
+  } State;
+
+  /// The error state of a stream.
----------------
xazax.hun wrote:
> Szelethus wrote:
> > balazske wrote:
> > > Szelethus wrote:
> > > > Hmm, now that I think of it, could we just merge these 2 enums? Also, I 
> > > > fear that indexers would accidentally assign the comment to the enum 
> > > > after the comma:
> > > > 
> > > > ```lang=cpp
> > > >     Opened, /// Stream is opened.
> > > >     Closed, /// Closed stream (an invalid stream pointer after it was 
> > > > closed).
> > > >     OpenFailed /// The last open operation has failed.
> > > > ```
> > > > ` /// Stream is opened` might be assigned to `Closed`. How about this:
> > > > ```lang=cpp
> > > >     /// Stream is opened.
> > > >     Opened,
> > > >     /// Closed stream (an invalid stream pointer after it was closed).
> > > >     Closed,
> > > >     /// The last open operation has failed.
> > > >     OpenFailed
> > > > ```
> > > Probably these can be merged, it is used for a stream that is in an 
> > > indeterminate state after failed `freopen`, but practically it is handled 
> > > the same way as a closed stream. But this change would be done in another 
> > > revision.
> > I meant to merge the two enums (`StreamState` and `ErrorKindTy`) and the 
> > fields associated with them (`State` and `ErrorState`). We could however 
> > merge `Closed` and `OpenFailed`, granted that we put a `NoteTag` to 
> > `evalFreopen`. But I agree, that should be another revision's topic :)
> Since you mentioned that ErrorState is only applicable to Open streams, I am 
> also +1 on merging the enums. These two states are not orthogonal, no reason 
> for them to be separate.
Not orthogonal, but rather hiearchical. That is a reason for not merging. I am 
completely against it.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:43
+    EofError,   /// EOF condition (`feof` is true).
+    OtherError, /// Other (non-EOF) error (`ferror` is true).
+    AnyError    /// EofError or OtherError, used if exact error is unknown.
----------------
balazske wrote:
> Szelethus wrote:
> > Shouldn't we call this `FError` instead, if this is set precisely when 
> > `ferror()` is true? Despite the comments, I still managed to get myself 
> > confused with it :)
> Plan is to rename to `NoError`, `FEofError`, `FErrorError`, 
> `FEofOrFErrorError`.
If would suggest  `NoError`, `FEoF`, `FError`, `FEoFOrFError`. Too many `Error` 
suffixes reduce the readability.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:51
+
+  bool isNoError() const { return ErrorState == NoError; }
+  bool isEofError() const { return ErrorState == EofError; }
----------------
balazske wrote:
> Szelethus wrote:
> > If a stream's opening failed, its still an error, yet this getter would 
> > return true for it. I think this is yet another reason to just merge the 2 
> > enums :)
> But as the comment says, the error state is applicable only in the opened 
> state. If not opened, we may not call the "error" functions at all (assertion 
> can be added). Anyway it is possible to merge the enums, then the `isOpened` 
> will be a bit difficult (true if state is one of `OpenedNoError`, 
> `OpenedFErrorError`, `OpenedFEofError`, `OpenedFEofOrFErrorError`). Logically 
> it is better to see that the state is an aggregation of two states, an 
> "openedness" and an error state. Probably this does not matter much here 
> because it is unlikely that new states will appear that make the code more 
> complex.
I would not merge the two enums: this way they are hierarchical. When only 
checking the openness we do not need to check for 4 different states. I 
completely agree with @balazske here.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:54
+  bool isOtherError() const { return ErrorState == OtherError; }
+  bool isAnyError() const { return ErrorState == AnyError; }
+
----------------
Szelethus wrote:
> balazske wrote:
> > Szelethus wrote:
> > > This is confusing -- I would expect a method called `isAnyError()` to 
> > > return true when `isNoError()` is false.
> > The error state kinds are not mutually exclusive. The "any error" means we 
> > know that there is some error but we do not know what the error is (it is 
> > not relevant because nothing was done that depends on it). If a function is 
> > called that needs to know if "ferror" or "feof" is the error, the state 
> > will be split to `FErrorError` and `FEofError`.
> How about we change the name of it to `isUnknownError`? My main issue is that 
> to me, the name `isAnyError()` answeres the question whether the stream is in 
> any form of erroneous state.
Yes, "Any" usually means //any// of the possible kinds. But instead of 
`UnknownError` use `FEoFOrFerror`.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:383
+
+  if (SS->isAnyError()) {
+    // We do not know yet what kind of error is set.
----------------
Szelethus wrote:
> Does this ever run? We never actually set the stream state to `AnyError`.
I suggest to move codes that are only executed after a new functionality is 
added in a subsequent patch to that patch.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:394
+        StreamSym, StreamState::getOpenedWithOtherError());
+    C.addTransition(StateEof);
+    C.addTransition(StateOther);
----------------
xazax.hun wrote:
> As you probably know we are splitting the execution paths here. This will 
> potentially result in doubling the analysis tome for a function for each 
> `feof` call. Since state splits can be really bad for performance we need 
> good justification for each of them.
> So the questions are:
> * Is it really important to differentiate between eof and other error or is 
> it possible to just have an any error state?
> * Do we find more bugs in real world code that justifies these state splits?
I agree here. Do not introduce such forks without specific reason.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:404-405
+
+void StreamChecker::evalFerror(const FnDescription *Desc, const CallEvent 
&Call,
+                               CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
----------------
balazske wrote:
> Szelethus wrote:
> > This function is practically the same as `evalFeof`, can we merge them?
> It is not the same code ("EOF" and "other error" are interchanged), but can 
> be merged somehow.
Maybe using a template with a functor parameter and pass a lambda in the two 
instantiations? (See `DebugContainerModeling` and `DebugIteratorModeling`) and 
also some example is `Iterator.cpp`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D75682



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to