[clang] 6e6a26b - [analyzer] Extract InlinedFunctionCallHandler

Valeriy Savchenko via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 15 01:38:00 PDT 2021


Author: Valeriy Savchenko
Date: 2021-06-15T11:37:36+03:00
New Revision: 6e6a26b8f0ea8300d5a814e4150e225c33ec25de

URL: https://github.com/llvm/llvm-project/commit/6e6a26b8f0ea8300d5a814e4150e225c33ec25de
DIFF: https://github.com/llvm/llvm-project/commit/6e6a26b8f0ea8300d5a814e4150e225c33ec25de.diff

LOG: [analyzer] Extract InlinedFunctionCallHandler

Differential Revision: https://reviews.llvm.org/D103961

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 835c54ef5f68..dab1ba0a9d50 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -937,91 +937,6 @@ class ReturnVisitor : public TrackingBugReporterVisitor {
     ID.AddBoolean(EnableNullFPSuppression);
   }
 
-  /// Adds a ReturnVisitor if the given statement represents a call that was
-  /// inlined.
-  ///
-  /// This will search back through the ExplodedGraph, starting from the given
-  /// node, looking for when the given statement was processed. If it turns out
-  /// the statement is a call that was inlined, we add the visitor to the
-  /// bug report, so it can print a note later.
-  static void addVisitorIfNecessary(TrackerRef ParentTracker,
-                                    const ExplodedNode *Node, const Stmt *S,
-                                    PathSensitiveBugReport &BR,
-                                    bool InEnableNullFPSuppression,
-                                    bugreporter::TrackingKind TKind) {
-    if (!CallEvent::isCallStmt(S))
-      return;
-
-    // First, find when we processed the statement.
-    // If we work with a 'CXXNewExpr' that is going to be purged away before
-    // its call take place. We would catch that purge in the last condition
-    // as a 'StmtPoint' so we have to bypass it.
-    const bool BypassCXXNewExprEval = isa<CXXNewExpr>(S);
-
-    // This is moving forward when we enter into another context.
-    const StackFrameContext *CurrentSFC = Node->getStackFrame();
-
-    do {
-      // If that is satisfied we found our statement as an inlined call.
-      if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>())
-        if (CEE->getCalleeContext()->getCallSite() == S)
-          break;
-
-      // Try to move forward to the end of the call-chain.
-      Node = Node->getFirstPred();
-      if (!Node)
-        break;
-
-      const StackFrameContext *PredSFC = Node->getStackFrame();
-
-      // If that is satisfied we found our statement.
-      // FIXME: This code currently bypasses the call site for the
-      //        conservatively evaluated allocator.
-      if (!BypassCXXNewExprEval)
-        if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>())
-          // See if we do not enter into another context.
-          if (SP->getStmt() == S && CurrentSFC == PredSFC)
-            break;
-
-      CurrentSFC = PredSFC;
-    } while (Node->getStackFrame() == CurrentSFC);
-
-    // Next, step over any post-statement checks.
-    while (Node && Node->getLocation().getAs<PostStmt>())
-      Node = Node->getFirstPred();
-    if (!Node)
-      return;
-
-    // Finally, see if we inlined the call.
-    Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>();
-    if (!CEE)
-      return;
-
-    const StackFrameContext *CalleeContext = CEE->getCalleeContext();
-    if (CalleeContext->getCallSite() != S)
-      return;
-
-    // Check the return value.
-    ProgramStateRef State = Node->getState();
-    SVal RetVal = Node->getSVal(S);
-
-    // Handle cases where a reference is returned and then immediately used.
-    if (cast<Expr>(S)->isGLValue())
-      if (Optional<Loc> LValue = RetVal.getAs<Loc>())
-        RetVal = State->getSVal(*LValue);
-
-    // See if the return value is NULL. If so, suppress the report.
-    AnalyzerOptions &Options = State->getAnalysisManager().options;
-
-    bool EnableNullFPSuppression = false;
-    if (InEnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths)
-      if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
-        EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
-
-    BR.addVisitor<ReturnVisitor>(ParentTracker, CalleeContext,
-                                 EnableNullFPSuppression, Options, TKind);
-  }
-
   PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N,
                                           BugReporterContext &BRC,
                                           PathSensitiveBugReport &BR) {
@@ -2228,6 +2143,96 @@ class InterestingLValueHandler final : public ExpressionHandler {
   }
 };
 
+/// Adds a ReturnVisitor if the given statement represents a call that was
+/// inlined.
+///
+/// This will search back through the ExplodedGraph, starting from the given
+/// node, looking for when the given statement was processed. If it turns out
+/// the statement is a call that was inlined, we add the visitor to the
+/// bug report, so it can print a note later.
+class InlinedFunctionCallHandler final : public ExpressionHandler {
+  using ExpressionHandler::ExpressionHandler;
+
+  Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
+                         const ExplodedNode *ExprNode,
+                         TrackingOptions Opts) override {
+    if (!CallEvent::isCallStmt(E))
+      return {};
+
+    // First, find when we processed the statement.
+    // If we work with a 'CXXNewExpr' that is going to be purged away before
+    // its call take place. We would catch that purge in the last condition
+    // as a 'StmtPoint' so we have to bypass it.
+    const bool BypassCXXNewExprEval = isa<CXXNewExpr>(E);
+
+    // This is moving forward when we enter into another context.
+    const StackFrameContext *CurrentSFC = ExprNode->getStackFrame();
+
+    do {
+      // If that is satisfied we found our statement as an inlined call.
+      if (Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>())
+        if (CEE->getCalleeContext()->getCallSite() == E)
+          break;
+
+      // Try to move forward to the end of the call-chain.
+      ExprNode = ExprNode->getFirstPred();
+      if (!ExprNode)
+        break;
+
+      const StackFrameContext *PredSFC = ExprNode->getStackFrame();
+
+      // If that is satisfied we found our statement.
+      // FIXME: This code currently bypasses the call site for the
+      //        conservatively evaluated allocator.
+      if (!BypassCXXNewExprEval)
+        if (Optional<StmtPoint> SP = ExprNode->getLocationAs<StmtPoint>())
+          // See if we do not enter into another context.
+          if (SP->getStmt() == E && CurrentSFC == PredSFC)
+            break;
+
+      CurrentSFC = PredSFC;
+    } while (ExprNode->getStackFrame() == CurrentSFC);
+
+    // Next, step over any post-statement checks.
+    while (ExprNode && ExprNode->getLocation().getAs<PostStmt>())
+      ExprNode = ExprNode->getFirstPred();
+    if (!ExprNode)
+      return {};
+
+    // Finally, see if we inlined the call.
+    Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>();
+    if (!CEE)
+      return {};
+
+    const StackFrameContext *CalleeContext = CEE->getCalleeContext();
+    if (CalleeContext->getCallSite() != E)
+      return {};
+
+    // Check the return value.
+    ProgramStateRef State = ExprNode->getState();
+    SVal RetVal = ExprNode->getSVal(E);
+
+    // Handle cases where a reference is returned and then immediately used.
+    if (cast<Expr>(E)->isGLValue())
+      if (Optional<Loc> LValue = RetVal.getAs<Loc>())
+        RetVal = State->getSVal(*LValue);
+
+    // See if the return value is NULL. If so, suppress the report.
+    AnalyzerOptions &Options = State->getAnalysisManager().options;
+
+    bool EnableNullFPSuppression = false;
+    if (Opts.EnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths)
+      if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
+        EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
+
+    PathSensitiveBugReport &Report = getParentTracker().getReport();
+    Report.addVisitor<ReturnVisitor>(&getParentTracker(), CalleeContext,
+                                     EnableNullFPSuppression, Options,
+                                     Opts.Kind);
+    return {true};
+  }
+};
+
 class DefaultExpressionHandler final : public ExpressionHandler {
 public:
   using ExpressionHandler::ExpressionHandler;
@@ -2244,10 +2249,6 @@ class DefaultExpressionHandler final : public ExpressionHandler {
     // track the constraints on its contents.
     SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
 
-    ReturnVisitor::addVisitorIfNecessary(&getParentTracker(), LVNode, Inner,
-                                         Report, Opts.EnableNullFPSuppression,
-                                         Opts.Kind);
-
     // Is it a symbolic value?
     if (auto L = V.getAs<loc::MemRegionVal>()) {
       // FIXME: this is a hack for fixing a later crash when attempting to
@@ -2347,6 +2348,7 @@ Tracker::Tracker(PathSensitiveBugReport &Report) : Report(Report) {
   addLowPriorityHandler<NilReceiverHandler>();
   addLowPriorityHandler<ArrayIndexHandler>();
   addLowPriorityHandler<InterestingLValueHandler>();
+  addLowPriorityHandler<InlinedFunctionCallHandler>();
   addLowPriorityHandler<DefaultExpressionHandler>();
   addLowPriorityHandler<PRValueHandler>();
   // Default store handlers.


        


More information about the cfe-commits mailing list