[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
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
|
||||
51
clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
Normal file
51
clang/lib/Analysis/FlowSensitive/SourceLocationsLattice.cpp
Normal file
@@ -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
|
||||
@@ -9,6 +9,7 @@ add_clang_unittest(ClangAnalysisFlowSensitiveTests
|
||||
MapLatticeTest.cpp
|
||||
MultiVarConstantPropagationTest.cpp
|
||||
SingleVarConstantPropagationTest.cpp
|
||||
SourceLocationsLatticeTest.cpp
|
||||
TestingSupport.cpp
|
||||
TestingSupportTest.cpp
|
||||
TransferTest.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
|
||||
Reference in New Issue
Block a user