RedDocMD created this revision. RedDocMD added reviewers: NoQ, vsavchenko, xazax.hun, teemperor. Herald added subscribers: manas, steakhal, ASDenysPetrov, martong, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware. RedDocMD requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This patch introduces the concept of *Stoppable* visitors, ie, a visitor that must perform some task when it runs out of nodes on which it has work to do. Initially, the `ReturnVisitor` is being made *stoppable*, thus allowing it to run callbacks on completion. These callbacks are meant to be supplied from `trackExpressionValue`. Thus, this patch will also allow `trackExpressionValue` to recieve a callback to run when it is done tracking. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D103434 Files: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -320,6 +320,22 @@ return P; } +//===----------------------------------------------------------------------===// +// Implementation of StoppableBugReporterVisitor +//===----------------------------------------------------------------------===// + +StoppableBugReporterVisitor::~StoppableBugReporterVisitor() { + assert(Stopped && "Stoppable visitor not stopped in its lifetime"); +} + +void StoppableBugReporterVisitor::Stop(const ExplodedNode *Curr, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { + assert(!Stopped && "Stop() can be called only once in visitor's lifetime"); + Stopped = true; + OnStop(Curr, BRC, BR); +} + //===----------------------------------------------------------------------===// // Implementation of NoStoreFuncVisitor. //===----------------------------------------------------------------------===// @@ -876,6 +892,9 @@ namespace { +using VisitorCallback = llvm::function_ref<void( + const ExplodedNode *, BugReporterContext &, PathSensitiveBugReport &)>; + /// Emits an extra note at the return statement of an interesting stack frame. /// /// The returned value is marked as an interesting value, and if it's null, @@ -883,7 +902,7 @@ /// /// This visitor is intended to be used when another visitor discovers that an /// interesting value comes from an inlined function call. -class ReturnVisitor : public BugReporterVisitor { +class ReturnVisitor : public StoppableBugReporterVisitor { const StackFrameContext *CalleeSFC; enum { Initial, @@ -895,12 +914,14 @@ bool ShouldInvalidate = true; AnalyzerOptions& Options; bugreporter::TrackingKind TKind; + VisitorCallback Callback; public: ReturnVisitor(const StackFrameContext *Frame, bool Suppressed, - AnalyzerOptions &Options, bugreporter::TrackingKind TKind) - : CalleeSFC(Frame), EnableNullFPSuppression(Suppressed), - Options(Options), TKind(TKind) {} + AnalyzerOptions &Options, bugreporter::TrackingKind TKind, + VisitorCallback &&Callback = nullptr) + : CalleeSFC(Frame), EnableNullFPSuppression(Suppressed), Options(Options), + TKind(TKind), Callback(Callback) {} static void *getTag() { static int Tag = 0; @@ -913,6 +934,13 @@ ID.AddBoolean(EnableNullFPSuppression); } + void OnStop(const ExplodedNode *Curr, BugReporterContext &BRC, + PathSensitiveBugReport &BR) const override { + if (Callback) { + Callback(Curr, BRC, BR); + } + } + /// Adds a ReturnVisitor if the given statement represents a call that was /// inlined. /// @@ -1123,6 +1151,10 @@ else BR.markInteresting(CalleeSFC); + // Since we know that no other notes will be emitted subsequently by this + // visitor. + Stop(N, BRC, BR); + return EventPiece; } Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -85,6 +85,26 @@ const PathSensitiveBugReport &BR); }; +/// StoppableBugReporterVisitor is a special type of visitor that is known to +/// not have any useful work to do after it reaches a certain node in its +/// traversal. When it does reach that node, the \ref Stop method must be +/// called. This in turn calls the \ref OnStop method (which must be overriden +/// in the sub-class). Note that such visitors *must* be stopped exactly once. +class StoppableBugReporterVisitor : public BugReporterVisitor { + /// This method is run once the \ref Stop method is called. + virtual void OnStop(const ExplodedNode *Curr, BugReporterContext &BRC, + PathSensitiveBugReport &BR) const = 0; + bool Stopped; + +public: + StoppableBugReporterVisitor() : Stopped{false} {} + virtual ~StoppableBugReporterVisitor(); + + /// Call this method once the visitor runs out of useful nodes to process. + void Stop(const ExplodedNode *Curr, BugReporterContext &BRC, + PathSensitiveBugReport &BR); +}; + namespace bugreporter { /// Specifies the type of tracking for an expression.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits