[clang] 6e2aecd - [clang][dataflow] Add base types for building dataflow analyses

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 30 06:45:00 PST 2021


Author: Stanislav Gatev
Date: 2021-11-30T14:44:40Z
New Revision: 6e2aecd759dc3f8bf664323388365ac234271e9b

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

LOG: [clang][dataflow] Add base types for building dataflow analyses

This is part of the implementation of the dataflow analysis framework.
See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev.

Reviewed By: ymandel, xazax.hun, gribozavr2

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

Added: 
    clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
    clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
    clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h
    clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
    clang/lib/Analysis/FlowSensitive/CMakeLists.txt
    clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp

Modified: 
    clang/lib/Analysis/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
new file mode 100644
index 0000000000000..975d618e99edc
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -0,0 +1,134 @@
+//===- DataflowAnalysis.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines base types and functions for building dataflow analyses
+//  that run over Control-Flow Graphs (CFGs).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
+#include "llvm/ADT/Any.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+namespace dataflow {
+
+/// Base class template for dataflow analyses built on a single lattice type.
+///
+/// Requirements:
+///
+///  `Derived` must be derived from a specialization of this class template and
+///  must provide the following public members:
+///   * `LatticeT initialElement()` - returns a lattice element that models the
+///     initial state of a basic block;
+///   * `LatticeT transfer(const Stmt *, const LatticeT &, Environment &)` -
+///     applies the analysis transfer function for a given statement and lattice
+///     element.
+///
+///  `LatticeT` is a bounded join-semilattice that is used by `Derived` and must
+///  provide the following public members:
+///   * `LatticeJoinEffect join(const LatticeT &)` - joins the object and the
+///     argument by computing their least upper bound, modifies the object if
+///     necessary, and returns an effect indicating whether any changes were
+///     made to it;
+///   * `bool operator==(const LatticeT &) const` - returns true if and only if
+///     the object is equal to the argument.
+template <typename Derived, typename LatticeT>
+class DataflowAnalysis : public TypeErasedDataflowAnalysis {
+public:
+  /// Bounded join-semilattice that is used in the analysis.
+  using Lattice = LatticeT;
+
+  explicit DataflowAnalysis(ASTContext &Context) : Context(Context) {}
+
+  ASTContext &getASTContext() final { return Context; }
+
+  AnyLatticeElement typeErasedInitialElement() final {
+    return {static_cast<Derived *>(this)->initialElement()};
+  }
+
+  LatticeJoinEffect joinTypeErased(TypeErasedLattice &E1,
+                                   const TypeErasedLattice &E2) final {
+    Lattice &L1 = llvm::any_cast<Lattice &>(E1.Value);
+    const Lattice &L2 = llvm::any_cast<const Lattice &>(E2.Value);
+    return L1.join(L2);
+  }
+
+  bool isEqualTypeErased(const TypeErasedLattice &E1,
+                         const TypeErasedLattice &E2) final {
+    const Lattice &L1 = llvm::any_cast<const Lattice &>(E1.Value);
+    const Lattice &L2 = llvm::any_cast<const Lattice &>(E2.Value);
+    return L1 == L2;
+  }
+
+  AnyLatticeElement transferTypeErased(const Stmt *Stmt,
+                                       const AnyLatticeElement &E,
+                                       Environment &Env) final {
+    const Lattice &L = llvm::any_cast<const Lattice &>(E.Value);
+    return {static_cast<Derived *>(this)->transfer(Stmt, L, Env)};
+  }
+
+private:
+  ASTContext &Context;
+};
+
+// Model of the program at a given program point.
+template <typename LatticeT> struct DataflowAnalysisState {
+  // Model of a program property.
+  LatticeT Lattice;
+
+  // Model of the state of the program (store and heap).
+  Environment Env;
+};
+
+/// Performs dataflow analysis and returns a mapping from basic block IDs to
+/// dataflow analysis states that model the respective basic blocks. Indices
+/// of the returned vector correspond to basic block IDs.
+///
+/// Requirements:
+///
+///  `Cfg` must have been built with `CFG::BuildOptions::setAllAlwaysAdd()` to
+///  ensure that all sub-expressions in a basic block are evaluated.
+template <typename AnalysisT>
+std::vector<llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
+runDataflowAnalysis(const CFG &Cfg, AnalysisT &Analysis,
+                    const Environment &InitEnv) {
+  auto TypeErasedBlockStates =
+      runTypeErasedDataflowAnalysis(Cfg, Analysis, InitEnv);
+  std::vector<
+      llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
+      BlockStates;
+  BlockStates.reserve(TypeErasedBlockStates.size());
+  llvm::transform(std::move(TypeErasedBlockStates),
+                  std::back_inserter(BlockStates), [](auto &OptState) {
+                    return std::move(OptState).map([](auto &&State) {
+                      return DataflowAnalysisState<typename AnalysisT::Lattice>{
+                          llvm::any_cast<typename AnalysisT::Lattice>(
+                              std::move(State.Lattice.Value)),
+                          std::move(State.Env)};
+                    });
+                  });
+  return BlockStates;
+}
+
+} // namespace dataflow
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H

diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
new file mode 100644
index 0000000000000..69a5c2e47b66d
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -0,0 +1,27 @@
+//===-- DataflowEnvironment.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines an Environment class that is used by dataflow analyses
+//  that run over Control-Flow Graphs (CFGs) to keep track of the state of the
+//  program at given program points.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
+
+namespace clang {
+namespace dataflow {
+
+/// Holds the state of the program (store and heap) at a given program point.
+class Environment {};
+
+} // namespace dataflow
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H

diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h b/clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h
new file mode 100644
index 0000000000000..37d2e02004106
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowLattice.h
@@ -0,0 +1,29 @@
+//===- DataflowLattice.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines base types for building lattices to be used in dataflow
+//  analyses that run over Control-Flow Graphs (CFGs).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWLATTICE_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWLATTICE_H
+
+namespace clang {
+namespace dataflow {
+
+/// Effect indicating whether a lattice join operation resulted in a new value.
+enum class LatticeJoinEffect {
+  Unchanged,
+  Changed,
+};
+
+} // namespace dataflow
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWLATTICE_H

diff  --git a/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
new file mode 100644
index 0000000000000..21647411ef5bd
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -0,0 +1,93 @@
+//===- TypeErasedDataflowAnalysis.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines type-erased base types and functions for building dataflow
+//  analyses that run over Control-Flow Graphs (CFGs).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
+
+#include <vector>
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "llvm/ADT/Any.h"
+#include "llvm/ADT/Optional.h"
+
+namespace clang {
+namespace dataflow {
+
+/// Type-erased lattice element container.
+///
+/// Requirements:
+///
+///  The type of the object stored in the container must be a bounded
+///  join-semilattice.
+struct TypeErasedLattice {
+  llvm::Any Value;
+};
+
+/// Type-erased base class for dataflow analyses built on a single lattice type.
+class TypeErasedDataflowAnalysis {
+public:
+  /// Returns the `ASTContext` that is used by the analysis.
+  virtual ASTContext &getASTContext() = 0;
+
+  /// Returns a type-erased lattice element that models the initial state of a
+  /// basic block.
+  virtual TypeErasedLattice typeErasedInitialElement() = 0;
+
+  /// Joins two type-erased lattice elements by computing their least upper
+  /// bound. Places the join result in the left element and returns an effect
+  /// indicating whether any changes were made to it.
+  virtual LatticeJoinEffect joinTypeErased(TypeErasedLattice &,
+                                           const TypeErasedLattice &) = 0;
+
+  /// Returns true if and only if the two given type-erased lattice elements are
+  /// equal.
+  virtual bool isEqualTypeErased(const TypeErasedLattice &,
+                                 const TypeErasedLattice &) = 0;
+
+  /// Applies the analysis transfer function for a given statement and
+  /// type-erased lattice element.
+  virtual TypeErasedLattice transferTypeErased(const Stmt *,
+                                               const TypeErasedLattice &,
+                                               Environment &) = 0;
+};
+
+/// Type-erased model of the program at a given program point.
+struct TypeErasedDataflowAnalysisState {
+  /// Type-erased model of a program property.
+  TypeErasedLattice Lattice;
+
+  /// Model of the state of the program (store and heap).
+  Environment Env;
+};
+
+/// Performs dataflow analysis and returns a mapping from basic block IDs to
+/// dataflow analysis states that model the respective basic blocks. Indices
+/// of the returned vector correspond to basic block IDs.
+///
+/// Requirements:
+///
+///  `Cfg` must have been built with `CFG::BuildOptions::setAllAlwaysAdd()` to
+///  ensure that all sub-expressions in a basic block are evaluated.
+std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>
+runTypeErasedDataflowAnalysis(const CFG &Cfg,
+                              TypeErasedDataflowAnalysis &Analysis,
+                              const Environment &InitEnv);
+
+} // namespace dataflow
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H

diff  --git a/clang/lib/Analysis/CMakeLists.txt b/clang/lib/Analysis/CMakeLists.txt
index 00c8d67561779..16e3f474060cb 100644
--- a/clang/lib/Analysis/CMakeLists.txt
+++ b/clang/lib/Analysis/CMakeLists.txt
@@ -44,3 +44,4 @@ add_clang_library(clangAnalysis
   )
 
 add_subdirectory(plugins)
+add_subdirectory(FlowSensitive)

diff  --git a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt
new file mode 100644
index 0000000000000..34e97df2182e4
--- /dev/null
+++ b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_clang_library(clangAnalysisFlowSensitive
+  TypeErasedDataflowAnalysis.cpp
+
+  LINK_LIBS
+  clangAnalysis
+  clangAST
+  )

diff  --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
new file mode 100644
index 0000000000000..bb7eb99710681
--- /dev/null
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -0,0 +1,35 @@
+//===- TypeErasedDataflowAnalysis.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines type-erased base types and functions for building dataflow
+//  analyses that run over Control-Flow Graphs (CFGs).
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
+#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
+#include "llvm/ADT/Optional.h"
+
+using namespace clang;
+using namespace dataflow;
+
+std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>
+runTypeErasedDataflowAnalysis(const CFG &Cfg,
+                              TypeErasedDataflowAnalysis &Analysis,
+                              const Environment &InitEnv) {
+  // FIXME: Consider enforcing that `Cfg` meets the requirements that
+  // are specified in the header. This could be done by remembering
+  // what options were used to build `Cfg` and asserting on them here.
+
+  // FIXME: Implement work list-based algorithm to compute the fixed
+  // point of `Analysis::transform` for every basic block in `Cfg`.
+  return {};
+}


        


More information about the cfe-commits mailing list