balazske created this revision. Herald added subscribers: cfe-commits, martong, Charusso, gamesh411, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun. Herald added a reviewer: Szelethus. Herald added a project: clang.
Have a description object for the stream functions that can store different aspects of a single stream operation. I plan to extend the structure with other members, for example pre-callback and index of the stream argument. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D75158 Files: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp Index: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -49,6 +49,15 @@ } }; +class StreamChecker; + +using FnCheck = std::function<void(const StreamChecker *, const CallEvent &, + CheckerContext &)>; + +struct FnDescription { + FnCheck EvalFn; +}; + class StreamChecker : public Checker<eval::Call, check::DeadSymbols > { mutable std::unique_ptr<BuiltinBug> BT_nullfp, BT_illegalwhence, @@ -59,35 +68,33 @@ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; private: - using FnCheck = std::function<void(const StreamChecker *, const CallEvent &, - CheckerContext &)>; - - CallDescriptionMap<FnCheck> Callbacks = { - {{"fopen"}, &StreamChecker::evalFopen}, - {{"freopen", 3}, &StreamChecker::evalFreopen}, - {{"tmpfile"}, &StreamChecker::evalFopen}, - {{"fclose", 1}, &StreamChecker::evalFclose}, + + CallDescriptionMap<FnDescription> FnDescriptions = { + {{"fopen"}, {&StreamChecker::evalFopen}}, + {{"freopen", 3}, {&StreamChecker::evalFreopen}}, + {{"tmpfile"}, {&StreamChecker::evalFopen}}, + {{"fclose", 1}, {&StreamChecker::evalFclose}}, {{"fread", 4}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}}, {{"fwrite", 4}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}, - {{"fseek", 3}, &StreamChecker::evalFseek}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}}, + {{"fseek", 3}, {&StreamChecker::evalFseek}}, {{"ftell", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"rewind", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"fgetpos", 2}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"fsetpos", 2}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"clearerr", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"feof", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"ferror", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"fileno", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, }; void evalFopen(const CallEvent &Call, CheckerContext &C) const; @@ -125,11 +132,11 @@ return false; } - const FnCheck *Callback = Callbacks.lookup(Call); - if (!Callback) + const FnDescription *Description = FnDescriptions.lookup(Call); + if (!Description) return false; - (*Callback)(this, Call, C); + (Description->EvalFn)(this, Call, C); return C.isDifferent(); }
Index: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -49,6 +49,15 @@ } }; +class StreamChecker; + +using FnCheck = std::function<void(const StreamChecker *, const CallEvent &, + CheckerContext &)>; + +struct FnDescription { + FnCheck EvalFn; +}; + class StreamChecker : public Checker<eval::Call, check::DeadSymbols > { mutable std::unique_ptr<BuiltinBug> BT_nullfp, BT_illegalwhence, @@ -59,35 +68,33 @@ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; private: - using FnCheck = std::function<void(const StreamChecker *, const CallEvent &, - CheckerContext &)>; - - CallDescriptionMap<FnCheck> Callbacks = { - {{"fopen"}, &StreamChecker::evalFopen}, - {{"freopen", 3}, &StreamChecker::evalFreopen}, - {{"tmpfile"}, &StreamChecker::evalFopen}, - {{"fclose", 1}, &StreamChecker::evalFclose}, + + CallDescriptionMap<FnDescription> FnDescriptions = { + {{"fopen"}, {&StreamChecker::evalFopen}}, + {{"freopen", 3}, {&StreamChecker::evalFreopen}}, + {{"tmpfile"}, {&StreamChecker::evalFopen}}, + {{"fclose", 1}, {&StreamChecker::evalFclose}}, {{"fread", 4}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}}, {{"fwrite", 4}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}, - {{"fseek", 3}, &StreamChecker::evalFseek}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 3)}}, + {{"fseek", 3}, {&StreamChecker::evalFseek}}, {{"ftell", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"rewind", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"fgetpos", 2}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"fsetpos", 2}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"clearerr", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"feof", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"ferror", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, {{"fileno", 1}, - std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}, + {std::bind(&StreamChecker::checkArgNullStream, _1, _2, _3, 0)}}, }; void evalFopen(const CallEvent &Call, CheckerContext &C) const; @@ -125,11 +132,11 @@ return false; } - const FnCheck *Callback = Callbacks.lookup(Call); - if (!Callback) + const FnDescription *Description = FnDescriptions.lookup(Call); + if (!Description) return false; - (*Callback)(this, Call, C); + (Description->EvalFn)(this, Call, C); return C.isDifferent(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits