diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -231,8 +231,6 @@ /// If true, evaluate special testing stream functions. bool TestMode = false; - const BugType *getBT_StreamEof() const { return &BT_StreamEof; } - private: CallDescriptionMap FnDescriptions = { {{"fopen"}, {nullptr, &StreamChecker::evalFopen, ArgNone}}, @@ -376,37 +374,29 @@ return FnDescriptions.lookup(Call); } - /// Generate a message for BugReporterVisitor if the stored symbol is - /// marked as interesting by the actual bug report. - // FIXME: Use lambda instead. - struct NoteFn { - const BugType *BT_ResourceLeak; - SymbolRef StreamSym; - std::string Message; - - std::string operator()(PathSensitiveBugReport &BR) const { - if (BR.isInteresting(StreamSym) && &BR.getBugType() == BT_ResourceLeak) - return Message; - - return ""; - } - }; - const NoteTag *constructNoteTag(CheckerContext &C, SymbolRef StreamSym, - const std::string &Message) const { - return C.getNoteTag(NoteFn{&BT_ResourceLeak, StreamSym, Message}); - } - - const NoteTag *constructSetEofNoteTag(CheckerContext &C, - SymbolRef StreamSym) const { - return C.getNoteTag([this, StreamSym](PathSensitiveBugReport &BR) { - if (!BR.isInteresting(StreamSym) || - &BR.getBugType() != this->getBT_StreamEof()) + const BugType *BT) const { + const char *Message; + if (BT == &BT_UseAfterClose) + Message = "Stream closed here"; + else if (BT == &BT_UseAfterOpenFailed) + Message = "Assuming opening the stream fails here"; + else if (BT == &BT_IndeterminatePosition) + Message = "Assuming this stream operation fails"; + else if (BT == &BT_StreamEof) + Message = "Assuming stream reaches end-of-file here"; + else if (BT == &BT_ResourceLeak) + Message = "Stream opened here"; + else + llvm_unreachable("Invalid bug type for note tag"); + + return C.getNoteTag([StreamSym, BT, Message](PathSensitiveBugReport &BR) { + if (!BR.isInteresting(StreamSym) || &BR.getBugType() != BT) return ""; BR.markNotInteresting(StreamSym); - return "Assuming stream reaches end-of-file here"; + return Message; }); } @@ -499,8 +489,7 @@ StateNull = StateNull->set(RetSym, StreamState::getOpenFailed(Desc)); - C.addTransition(StateNotNull, - constructNoteTag(C, RetSym, "Stream opened here")); + C.addTransition(StateNotNull, constructNoteTag(C, RetSym, &BT_ResourceLeak)); C.addTransition(StateNull); } @@ -557,7 +546,7 @@ StateRetNull->set(StreamSym, StreamState::getOpenFailed(Desc)); C.addTransition(StateRetNotNull, - constructNoteTag(C, StreamSym, "Stream reopened here")); + constructNoteTag(C, StreamSym, &BT_ResourceLeak)); C.addTransition(StateRetNull); } @@ -705,7 +694,7 @@ StreamState NewSS = StreamState::getOpened(Desc, NewES, !NewES.isFEof()); StateFailed = StateFailed->set(StreamSym, NewSS); if (IsFread && OldSS->ErrorState != ErrorFEof) - C.addTransition(StateFailed, constructSetEofNoteTag(C, StreamSym)); + C.addTransition(StateFailed, constructNoteTag(C, StreamSym, &BT_StreamEof)); else C.addTransition(StateFailed); } @@ -766,7 +755,7 @@ StreamState::getOpened(Desc, ErrorNone | ErrorFEof | ErrorFError, true)); C.addTransition(StateNotFailed); - C.addTransition(StateFailed, constructSetEofNoteTag(C, StreamSym)); + C.addTransition(StateFailed, constructNoteTag(C, StreamSym, &BT_StreamEof)); } void StreamChecker::evalClearerr(const FnDescription *Desc, diff --git a/clang/test/Analysis/stream-note.c b/clang/test/Analysis/stream-note.c --- a/clang/test/Analysis/stream-note.c +++ b/clang/test/Analysis/stream-note.c @@ -33,12 +33,12 @@ // expected-note@-2 {{Opened stream never closed. Potential resource leak}} void check_note_freopen() { - FILE *F = fopen("file", "r"); // expected-note {{Stream opened here}} + FILE *F = fopen("file", "r"); if (!F) // expected-note@-1 {{'F' is non-null}} // expected-note@-2 {{Taking false branch}} return; - F = freopen(0, "w", F); // expected-note {{Stream reopened here}} + F = freopen(0, "w", F); // expected-note {{Stream opened here}} if (!F) // expected-note@-1 {{'F' is non-null}} // expected-note@-2 {{Taking false branch}}