RedDocMD updated this revision to Diff 349295.
RedDocMD added a comment.

trackExpressionValue recieving callback, passing it to ReturnVisitor


Repository:
  rG LLVM Github Monorepo

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

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.
 //===----------------------------------------------------------------------===//
@@ -883,7 +899,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 +911,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)
+      : CalleeSFC(Frame), EnableNullFPSuppression(Suppressed), Options(Options),
+        TKind(TKind), Callback(Callback) {}
 
   static void *getTag() {
     static int Tag = 0;
@@ -913,6 +931,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.
   ///
@@ -923,7 +948,8 @@
   static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
                                     PathSensitiveBugReport &BR,
                                     bool InEnableNullFPSuppression,
-                                    bugreporter::TrackingKind TKind) {
+                                    bugreporter::TrackingKind TKind,
+                                    VisitorCallback Callback) {
     if (!CallEvent::isCallStmt(S))
       return;
 
@@ -994,9 +1020,9 @@
       if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
         EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
 
-    BR.addVisitor(std::make_unique<ReturnVisitor>(CalleeContext,
-                                                   EnableNullFPSuppression,
-                                                   Options, TKind));
+    BR.addVisitor(
+        std::make_unique<ReturnVisitor>(CalleeContext, EnableNullFPSuppression,
+                                        Options, TKind, std::move(Callback)));
   }
 
   PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N,
@@ -1123,6 +1149,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;
   }
 
@@ -1966,7 +1996,8 @@
                                        const Expr *E,
                                        PathSensitiveBugReport &report,
                                        bugreporter::TrackingKind TKind,
-                                       bool EnableNullFPSuppression) {
+                                       bool EnableNullFPSuppression,
+                                       VisitorCallback Callback) {
 
   if (!E || !InputNode)
     return false;
@@ -2067,7 +2098,7 @@
   SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
 
   ReturnVisitor::addVisitorIfNecessary(
-    LVNode, Inner, report, EnableNullFPSuppression, TKind);
+      LVNode, Inner, report, EnableNullFPSuppression, TKind, Callback);
 
   // Is it a symbolic value?
   if (auto L = V.getAs<loc::MemRegionVal>()) {
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,30 @@
                     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);
+};
+
+// Callback type for trackExpressionValue
+using VisitorCallback = llvm::function_ref<void(
+    const ExplodedNode *, BugReporterContext &, PathSensitiveBugReport &)>;
+
 namespace bugreporter {
 
 /// Specifies the type of tracking for an expression.
@@ -114,7 +138,8 @@
 bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
                           PathSensitiveBugReport &R,
                           TrackingKind TKind = TrackingKind::Thorough,
-                          bool EnableNullFPSuppression = true);
+                          bool EnableNullFPSuppression = true,
+                          VisitorCallback Callback = nullptr);
 
 const Expr *getDerefExpr(const Stmt *S);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to