[clang] 7ee97c2 - [clang][dataflow] Add a lattice to track source locations.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 4 09:13:39 PST 2022


Author: Yitzhak Mandelbaum
Date: 2022-03-04T17:13:24Z
New Revision: 7ee97c24efab4b2617da7f188760b0ad2dcc2125

URL: https://github.com/llvm/llvm-project/commit/7ee97c24efab4b2617da7f188760b0ad2dcc2125
DIFF: https://github.com/llvm/llvm-project/commit/7ee97c24efab4b2617da7f188760b0ad2dcc2125.diff

LOG: [clang][dataflow] Add a lattice to track source locations.

This patch adds a simpe lattice used to collect source loctions. An intended application is to track errors found in code during an analysis.

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

Added: 
    clang/include/clang/Analysis/FlowSensitive/SourceLocationsLattice.h
    clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
    clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp

Modified: 
    clang/lib/Analysis/FlowSensitive/CMakeLists.txt
    clang/unittests/Analysis/FlowSensitive/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/FlowSensitive/SourceLocationsLattice.h b/clang/include/clang/Analysis/FlowSensitive/SourceLocationsLattice.h
new file mode 100644
index 0000000000000..d294f9768cdc5
--- /dev/null
+++ b/clang/include/clang/Analysis/FlowSensitive/SourceLocationsLattice.h
@@ -0,0 +1,65 @@
+//===-- SourceLocationsLattice.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 a lattice that collects source locations of interest.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOURCELOCATIONS_LATTICE_H
+#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOURCELOCATIONS_LATTICE_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseSet.h"
+#include <string>
+#include <utility>
+
+namespace clang {
+namespace dataflow {
+
+/// Lattice for dataflow analysis that keeps track of a set of source locations.
+///
+/// Bottom is the empty set, join is set union, and equality is set equality.
+///
+/// FIXME: Generalize into a (templated) PowerSetLattice.
+class SourceLocationsLattice {
+public:
+  SourceLocationsLattice() = default;
+
+  explicit SourceLocationsLattice(llvm::DenseSet<SourceLocation> Locs)
+      : Locs(std::move(Locs)) {}
+
+  bool operator==(const SourceLocationsLattice &Other) const {
+    return Locs == Other.Locs;
+  }
+
+  bool operator!=(const SourceLocationsLattice &Other) const {
+    return !(*this == Other);
+  }
+
+  LatticeJoinEffect join(const SourceLocationsLattice &Other);
+
+  llvm::DenseSet<SourceLocation> &getSourceLocations() { return Locs; }
+
+  const llvm::DenseSet<SourceLocation> &getSourceLocations() const {
+    return Locs;
+  }
+
+private:
+  llvm::DenseSet<SourceLocation> Locs;
+};
+
+/// Returns a string that represents the source locations of the lattice.
+std::string DebugString(const SourceLocationsLattice &Lattice,
+                        const ASTContext &Context);
+
+} // namespace dataflow
+} // namespace clang
+
+#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOURCELOCATIONS_LATTICE_H

diff  --git a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt
index 933792d569799..cfe3c8e77b4fd 100644
--- a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt
+++ b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt
@@ -2,6 +2,7 @@ add_clang_library(clangAnalysisFlowSensitive
   ControlFlowContext.cpp
   DataflowAnalysisContext.cpp
   DataflowEnvironment.cpp
+  SourceLocationsLattice.cpp
   Transfer.cpp
   TypeErasedDataflowAnalysis.cpp
   WatchedLiteralsSolver.cpp
@@ -9,4 +10,5 @@ add_clang_library(clangAnalysisFlowSensitive
   LINK_LIBS
   clangAnalysis
   clangAST
+  clangBasic
   )

diff  --git a/clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp b/clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
new file mode 100644
index 0000000000000..9e280f4e634a1
--- /dev/null
+++ b/clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
@@ -0,0 +1,51 @@
+//===- SourceLocationsLattice.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 implements a lattice that collects source locations of interest.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace dataflow {
+
+LatticeJoinEffect
+SourceLocationsLattice::join(const SourceLocationsLattice &Other) {
+  auto SizeBefore = Locs.size();
+  Locs.insert(Other.Locs.begin(), Other.Locs.end());
+  return SizeBefore == Locs.size() ? LatticeJoinEffect::Unchanged
+                                   : LatticeJoinEffect::Changed;
+}
+
+std::string DebugString(const SourceLocationsLattice &Lattice,
+                        const ASTContext &Context) {
+  if (Lattice.getSourceLocations().empty())
+    return "";
+
+  std::vector<std::string> Locations;
+  Locations.reserve(Lattice.getSourceLocations().size());
+  for (const clang::SourceLocation &Loc : Lattice.getSourceLocations()) {
+    Locations.push_back(Loc.printToString(Context.getSourceManager()));
+  }
+  std::sort(Locations.begin(), Locations.end());
+  std::string result;
+  llvm::raw_string_ostream OS(result);
+  llvm::interleaveComma(Locations, OS);
+  return result;
+}
+
+} // namespace dataflow
+} // namespace clang

diff  --git a/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt b/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
index da162abf6113e..4dc442ba61722 100644
--- a/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
+++ b/clang/unittests/Analysis/FlowSensitive/CMakeLists.txt
@@ -9,6 +9,7 @@ add_clang_unittest(ClangAnalysisFlowSensitiveTests
   MapLatticeTest.cpp
   MultiVarConstantPropagationTest.cpp
   SingleVarConstantPropagationTest.cpp
+  SourceLocationsLatticeTest.cpp
   TestingSupport.cpp
   TestingSupportTest.cpp
   TransferTest.cpp

diff  --git a/clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp b/clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
new file mode 100644
index 0000000000000..4c7b1ce60fb52
--- /dev/null
+++ b/clang/unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.cpp
@@ -0,0 +1,68 @@
+//===- unittests/Analysis/FlowSensitive/SourceLocationsLatticeTest.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/FlowSensitive/SourceLocationsLattice.h"
+
+#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
+#include "clang/Basic/SourceLocation.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace dataflow {
+namespace {
+
+TEST(SourceLocationsLatticeTest, Comparison) {
+  const SourceLocationsLattice Bottom;
+  const SourceLocationsLattice NonBottom(
+      {SourceLocation::getFromRawEncoding(0)});
+
+  EXPECT_TRUE(Bottom == Bottom);
+  EXPECT_FALSE(Bottom == NonBottom);
+  EXPECT_FALSE(NonBottom == Bottom);
+  EXPECT_TRUE(NonBottom == NonBottom);
+
+  EXPECT_FALSE(Bottom != Bottom);
+  EXPECT_TRUE(Bottom != NonBottom);
+  EXPECT_TRUE(NonBottom != Bottom);
+  EXPECT_FALSE(NonBottom != NonBottom);
+}
+
+TEST(SourceLocationsLatticeTest, Join) {
+  const SourceLocationsLattice Bottom;
+  const SourceLocationsLattice NonBottom(
+      {SourceLocation::getFromRawEncoding(0)});
+  {
+    SourceLocationsLattice LHS = Bottom;
+    const SourceLocationsLattice RHS = Bottom;
+    EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
+    EXPECT_EQ(LHS, Bottom);
+  }
+  {
+    SourceLocationsLattice LHS = NonBottom;
+    const SourceLocationsLattice RHS = Bottom;
+    EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
+    EXPECT_EQ(LHS, NonBottom);
+  }
+  {
+    SourceLocationsLattice LHS = Bottom;
+    const SourceLocationsLattice RHS = NonBottom;
+    EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Changed);
+    EXPECT_EQ(LHS, NonBottom);
+  }
+  {
+    SourceLocationsLattice LHS = NonBottom;
+    const SourceLocationsLattice RHS = NonBottom;
+    EXPECT_EQ(LHS.join(RHS), LatticeJoinEffect::Unchanged);
+    EXPECT_EQ(LHS, NonBottom);
+  }
+}
+
+} // namespace
+} // namespace dataflow
+} // namespace clang


        


More information about the cfe-commits mailing list