Szelethus added a comment. Thanks for sticking this out! It just takes me a while to get to the mental space regarding this patch you are already in, sometimes through saying incorrect statements or stupid suggestions! :) If others could chip in in this discussion, it would be most appreciated, because I fear that otherwise this patch is a bit too exposed to my own wrongs.
In D75682#1918839 <https://reviews.llvm.org/D75682#1918839>, @balazske wrote: > In D75682#1917257 <https://reviews.llvm.org/D75682#1917257>, @Szelethus wrote: > > > Could you please add the warning we discussed? That would be a great > > demonstration of this patch's capabilities, and wouldn't deserve its own > > patch. > > > Was it this warning? > > if (feof(F)) { // note: Assuming the condition is true > // note: Stream 'F' has the EOF flag set > fgets(F); // warning: Illegal stream operation on a stream that has EOF > set > } > > > The warning above should be get even if the `feof` call is missing because it > is still possible that the previous operation resulted in EOF state. What I meant to demonstrate (but failed to describe) is that if the condition of the `if` statement is `!feof(F)`, we **shouldn't** get the warning. > The checker does not work by "assuming feof is true" (this can be a later > feature, if the `F` is not tracked and a feof call is encountered). Value of > `feof` (more precisely: if any error happened) is fixed when the file > operation is called that causes the error. [...] And still that warning would > not be testable because `FEof` error state is never set in this patch. I suspect that at this point you are 2 steps ahead of me, but this is how I would imagine such a patch to look like: we //evaluate// `feof()` by splitting the state (this should be worth the cost, because why would we ever call `feof` if the state couldn't be EOF or non-EOF?), associate the state where its return value is true with the argument being marked as EOF, and the other as non-EOF. This obviously wouldn't be sufficient -- values retrieved from stream reading operations may be EOF themselves, which should make us set the appropriate state for the originating stream, but that should indeed be the topic of a followup patch. What is the goal here if not this? I have a suspicion I'm just not seeing the obvious here, but I don't get it just yet. > By the way, a file read is not invalid if any error is there, it simply fails > again. Oh, yea, silly me. You're totally right :) > Probably it would be better to make a full working prototype first, because > the design decisions made now can turn out to be wrong later when the new > functionality would be added and we do "not see the full picture" now. If you try to implement a warning just to see how this would turn out long term, that would indeed be a good idea. Feel free to upload them, if you prefer, as a WIP patch! ================ Comment at: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp:393-394 + + // Make the return value accordingly to the error. + State = State->assume(RetVal, (SS->*IsOfError)()); + assert(State && "Return value should not be constrained already."); ---------------- Is this correct? We set the `feof()` return value whether we know the state of the stream to be EOF, but in this case we would incorrectly mark it as non-EOF: ```lang=bash $ cat a.txt # contains a single newline $ cat test.cpp ``` ```lang=cpp #include <cstdio> void tryRead(FILE *F) { char C = fgetc(F); if (feof(F)) printf("The stream is EOF!\n"); else printf("The stream is good! Read '%c'\n", C); } int main() { FILE *F = fopen("a.txt", "r"); tryRead(F); tryRead(F); // Incorrectly mark F to be non-EOF } ``` ```lang=bash $ clang test.cpp -fsanitize=address && ./a.out The stream is good! Read ' ' The stream is EOF! ``` Wouldn't it be safer to assume it to be `true` if we **know** its EOF and do nothing otherwise? How about a state split? (I know this functions also handler FError, but you see what my point is.) ================ 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}} ---------------- 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 :) 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