[clang] 82d50fe - [clang][dataflow] Change the diagnoser API to receive a correctly typed lattice element

Dmitri Gribenko via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 13 05:49:13 PST 2022


Author: Dani Ferreira Franco Moura
Date: 2022-12-13T14:49:07+01:00
New Revision: 82d50fef9b7c1dfdff7f9265340fde40a34870cf

URL: https://github.com/llvm/llvm-project/commit/82d50fef9b7c1dfdff7f9265340fde40a34870cf
DIFF: https://github.com/llvm/llvm-project/commit/82d50fef9b7c1dfdff7f9265340fde40a34870cf.diff

LOG: [clang][dataflow] Change the diagnoser API to receive a correctly typed lattice element

Previously, the diagnoser could only receive the Environment at a given program point. Now, it receives the complete dataflow state: the environment and lattice element.

This change does not contain any tests because we modify the checkDataflow function to rely on the newly introduced lattice element in PostVisitCFG, and existing tests that verify lattice elements depend on this overload of checkDataflow.

Reviewed By: gribozavr2, ymandel

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

Added: 
    

Modified: 
    clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
    clang/unittests/Analysis/FlowSensitive/TestingSupport.h
    clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h b/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
index 76d18c1d24463..37894ab37dd8d 100644
--- a/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
+++ b/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
@@ -48,6 +48,16 @@ template <typename LatticeT> struct TransferState {
   Environment &Env;
 };
 
+/// A read-only version of TransferState.
+template <typename LatticeT> struct TransferStateForDiagnostics {
+  TransferStateForDiagnostics(const LatticeT &Lattice, const Environment &Env)
+      : Lattice(Lattice), Env(Env) {}
+
+  /// Current lattice element.
+  const LatticeT &Lattice;
+  const Environment &Env;
+};
+
 template <typename T>
 using MatchSwitchMatcher = ast_matchers::internal::Matcher<T>;
 

diff  --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index 511ff71ed1d43..d20e1ed0d34fd 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -30,6 +30,7 @@
 #include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
 #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Serialization/PCHContainerOperations.h"
@@ -116,11 +117,26 @@ template <typename AnalysisT> struct AnalysisInputs {
     SetupTest = std::move(Arg);
     return std::move(*this);
   }
+  AnalysisInputs<AnalysisT> &&withPostVisitCFG(
+      std::function<void(
+          ASTContext &, const CFGElement &,
+          const TransferStateForDiagnostics<typename AnalysisT::Lattice> &)>
+          Arg) && {
+    PostVisitCFG = std::move(Arg);
+    return std::move(*this);
+  }
+
   AnalysisInputs<AnalysisT> &&
   withPostVisitCFG(std::function<void(ASTContext &, const CFGElement &,
                                       const TypeErasedDataflowAnalysisState &)>
                        Arg) && {
-    PostVisitCFG = std::move(Arg);
+    PostVisitCFG =
+        [Arg = std::move(Arg)](ASTContext &Context, const CFGElement &Element,
+            const TransferStateForDiagnostics<typename AnalysisT::Lattice>
+                &State) {
+          Arg(Context, Element,
+              TypeErasedDataflowAnalysisState({State.Lattice}, State.Env));
+        };
     return std::move(*this);
   }
   AnalysisInputs<AnalysisT> &&withASTBuildArgs(ArrayRef<std::string> Arg) && {
@@ -148,8 +164,9 @@ template <typename AnalysisT> struct AnalysisInputs {
   std::function<llvm::Error(AnalysisOutputs &)> SetupTest = nullptr;
   /// Optional. If provided, this function is applied on each CFG element after
   /// the analysis has been run.
-  std::function<void(ASTContext &, const CFGElement &,
-                     const TypeErasedDataflowAnalysisState &)>
+  std::function<void(
+      ASTContext &, const CFGElement &,
+      const TransferStateForDiagnostics<typename AnalysisT::Lattice> &)>
       PostVisitCFG = nullptr;
 
   /// Optional. Options for building the AST context.
@@ -226,11 +243,15 @@ checkDataflow(AnalysisInputs<AnalysisT> AI,
                      const TypeErasedDataflowAnalysisState &)>
       PostVisitCFGClosure = nullptr;
   if (AI.PostVisitCFG) {
-    PostVisitCFGClosure =
-        [&AI, &Context](const CFGElement &Element,
-                        const TypeErasedDataflowAnalysisState &State) {
-          AI.PostVisitCFG(Context, Element, State);
-        };
+    PostVisitCFGClosure = [&AI, &Context](
+                              const CFGElement &Element,
+                              const TypeErasedDataflowAnalysisState &State) {
+      AI.PostVisitCFG(Context, Element,
+                      TransferStateForDiagnostics<typename AnalysisT::Lattice>(
+                          llvm::any_cast<const typename AnalysisT::Lattice &>(
+                              State.Lattice.Value),
+                          State.Env));
+    };
   }
 
   // Additional test setup.
@@ -326,28 +347,28 @@ checkDataflow(AnalysisInputs<AnalysisT> AI,
   // Save the states computed for program points immediately following annotated
   // statements. The saved states are keyed by the content of the annotation.
   llvm::StringMap<StateT> AnnotationStates;
-  auto PostVisitCFG = [&StmtToAnnotations, &AnnotationStates,
-                       PrevPostVisitCFG = std::move(AI.PostVisitCFG)](
-                          ASTContext &Ctx, const CFGElement &Elt,
-                          const TypeErasedDataflowAnalysisState &State) {
-    if (PrevPostVisitCFG) {
-      PrevPostVisitCFG(Ctx, Elt, State);
-    }
-    // FIXME: Extend retrieval of state for non statement constructs.
-    auto Stmt = Elt.getAs<CFGStmt>();
-    if (!Stmt)
-      return;
-    auto It = StmtToAnnotations.find(Stmt->getStmt());
-    if (It == StmtToAnnotations.end())
-      return;
-    auto *Lattice =
-        llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
-    auto [_, InsertSuccess] =
-        AnnotationStates.insert({It->second, StateT{*Lattice, State.Env}});
-    (void)_;
-    (void)InsertSuccess;
-    assert(InsertSuccess);
-  };
+  auto PostVisitCFG =
+      [&StmtToAnnotations, &AnnotationStates,
+       PrevPostVisitCFG = std::move(AI.PostVisitCFG)](
+          ASTContext &Ctx, const CFGElement &Elt,
+          const TransferStateForDiagnostics<typename AnalysisT::Lattice>
+              &State) {
+        if (PrevPostVisitCFG) {
+          PrevPostVisitCFG(Ctx, Elt, State);
+        }
+        // FIXME: Extend retrieval of state for non statement constructs.
+        auto Stmt = Elt.getAs<CFGStmt>();
+        if (!Stmt)
+          return;
+        auto It = StmtToAnnotations.find(Stmt->getStmt());
+        if (It == StmtToAnnotations.end())
+          return;
+        auto [_, InsertSuccess] = AnnotationStates.insert(
+            {It->second, StateT{State.Lattice, State.Env}});
+        (void)_;
+        (void)InsertSuccess;
+        assert(InsertSuccess);
+      };
   return checkDataflow<AnalysisT>(
       std::move(AI)
           .withSetupTest(std::move(SetupTest))

diff  --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index 74fb73804a1f9..17ec08bffef25 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -1314,7 +1314,8 @@ class UncheckedOptionalAccessTest
                 [&Diagnostics,
                  Diagnoser = UncheckedOptionalAccessDiagnoser(Options)](
                     ASTContext &Ctx, const CFGElement &Elt,
-                    const TypeErasedDataflowAnalysisState &State) mutable {
+                    const TransferStateForDiagnostics<NoopLattice>
+                        &State) mutable {
                   auto EltDiagnostics =
                       Diagnoser.diagnose(Ctx, &Elt, State.Env);
                   llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));


        


More information about the cfe-commits mailing list