[clang] 8dd14c4 - [clang][dataflow] Use `StringMap` for storing analysis states at annotated points instead of `vector<pair<string, StateT>>`.
Wei Yi Tee via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 1 07:10:31 PDT 2022
Author: Wei Yi Tee
Date: 2022-09-01T14:09:43Z
New Revision: 8dd14c427ae5c86cc2af4b8cac05b41bc4a49e86
URL: https://github.com/llvm/llvm-project/commit/8dd14c427ae5c86cc2af4b8cac05b41bc4a49e86
DIFF: https://github.com/llvm/llvm-project/commit/8dd14c427ae5c86cc2af4b8cac05b41bc4a49e86.diff
LOG: [clang][dataflow] Use `StringMap` for storing analysis states at annotated points instead of `vector<pair<string, StateT>>`.
Reviewed By: gribozavr2, sgatev, ymandel
Differential Revision: https://reviews.llvm.org/D132763
Added:
Modified:
clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
clang/unittests/Analysis/FlowSensitive/TestingSupport.h
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
Removed:
################################################################################
diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
index c0c05b0efdbb..dbb06c85814f 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Error.h"
#include "llvm/Testing/Support/Annotations.h"
#include <cassert>
@@ -72,6 +73,7 @@ llvm::Expected<llvm::DenseMap<const Stmt *, std::string>>
test::buildStatementToAnnotationMapping(const FunctionDecl *Func,
llvm::Annotations AnnotatedCode) {
llvm::DenseMap<const Stmt *, std::string> Result;
+ llvm::StringSet<> ExistingAnnotations;
auto StmtMatcher =
findAll(stmt(unless(anyOf(hasParent(expr()), hasParent(returnStmt()))))
@@ -113,7 +115,14 @@ test::buildStatementToAnnotationMapping(const FunctionDecl *Func,
.data());
}
- Result[Stmt] = Code.slice(Range.Begin, Range.End).str();
+ auto Annotation = Code.slice(Range.Begin, Range.End).str();
+ if (!ExistingAnnotations.insert(Annotation).second) {
+ return llvm::createStringError(
+ std::make_error_code(std::errc::invalid_argument),
+ "Repeated use of annotation: %s", Annotation.data());
+ }
+ Result[Stmt] = std::move(Annotation);
+
I++;
if (I < Annotations.size() && Annotations[I].Begin >= Offset) {
diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index 285c0c991d23..e3b68ca2976d 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -37,6 +37,7 @@
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
@@ -284,13 +285,12 @@ checkDataflow(AnalysisInputs<AnalysisT> AI,
///
/// Annotations must not be repeated.
template <typename AnalysisT>
-llvm::Error checkDataflow(
- AnalysisInputs<AnalysisT> AI,
- std::function<void(
- llvm::ArrayRef<std::pair<
- std::string, DataflowAnalysisState<typename AnalysisT::Lattice>>>,
- const AnalysisOutputs &)>
- VerifyResults) {
+llvm::Error
+checkDataflow(AnalysisInputs<AnalysisT> AI,
+ std::function<void(const llvm::StringMap<DataflowAnalysisState<
+ typename AnalysisT::Lattice>> &,
+ const AnalysisOutputs &)>
+ VerifyResults) {
// Compute mapping from nodes of annotated statements to the content in the
// annotation.
llvm::DenseMap<const Stmt *, std::string> StmtToAnnotations;
@@ -308,11 +308,9 @@ llvm::Error checkDataflow(
using StateT = DataflowAnalysisState<typename AnalysisT::Lattice>;
- // FIXME: Use a string map instead of a vector of pairs.
- //
// Save the states computed for program points immediately following annotated
// statements. The saved states are keyed by the content of the annotation.
- std::vector<std::pair<std::string, StateT>> AnnotationStates;
+ llvm::StringMap<StateT> AnnotationStates;
auto PostVisitCFG = [&StmtToAnnotations, &AnnotationStates,
PrevPostVisitCFG = std::move(AI.PostVisitCFG)](
ASTContext &Ctx, const CFGElement &Elt,
@@ -329,7 +327,10 @@ llvm::Error checkDataflow(
return;
auto *Lattice =
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
- AnnotationStates.emplace_back(It->second, StateT{*Lattice, State.Env});
+ auto [_, InsertSuccess] =
+ AnnotationStates.insert({It->second, StateT{*Lattice, State.Env}});
+ (void)InsertSuccess;
+ assert(InsertSuccess);
};
return checkDataflow<AnalysisT>(
std::move(AI)
@@ -378,12 +379,20 @@ llvm::Error checkDataflow(
std::move(MakeAnalysis))
.withASTBuildArgs(std::move(Args))
.withASTBuildVirtualMappedFiles(std::move(VirtualMappedFiles)),
- [&VerifyResults](
- llvm::ArrayRef<std::pair<
- std::string, DataflowAnalysisState<typename AnalysisT::Lattice>>>
- AnnotationStates,
- const AnalysisOutputs &AO) {
- VerifyResults(AnnotationStates, AO.ASTCtx);
+ [&VerifyResults](const llvm::StringMap<DataflowAnalysisState<
+ typename AnalysisT::Lattice>> &AnnotationStates,
+ const AnalysisOutputs &AO) {
+ std::vector<std::pair<
+ std::string, DataflowAnalysisState<typename AnalysisT::Lattice>>>
+ AnnotationStatesAsVector;
+ for (const auto &P : AnnotationStates) {
+ AnnotationStatesAsVector.push_back(
+ std::make_pair(P.first().str(), std::move(P.second)));
+ }
+ llvm::sort(AnnotationStatesAsVector,
+ [](auto a, auto b) { return a.first < b.first; });
+
+ VerifyResults(AnnotationStatesAsVector, AO.ASTCtx);
});
}
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 7f055f3ad8b7..d08afd096bc3 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -649,8 +649,8 @@ TEST(TransferTest, JoinVarDecl) {
std::string, DataflowAnalysisState<NoopLattice>>>
Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
- Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _),
+ Pair("p3", _), Pair("p4", _)));
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
@@ -660,24 +660,24 @@ TEST(TransferTest, JoinVarDecl) {
const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
ASSERT_THAT(BazDecl, NotNull());
- const Environment &Env1 = Results[3].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
const StorageLocation *FooLoc =
Env1.getStorageLocation(*FooDecl, SkipPast::None);
EXPECT_THAT(FooLoc, NotNull());
EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
- const Environment &Env2 = Results[2].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull());
EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
- const Environment &Env3 = Results[1].second.Env;
+ const Environment &Env3 = Results[2].second.Env;
EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull());
- const Environment &Env4 = Results[0].second.Env;
+ const Environment &Env4 = Results[3].second.Env;
EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
@@ -3305,8 +3305,8 @@ TEST(TransferTest, CorrelatedBranches) {
ASSERT_THAT(CDecl, NotNull());
{
- ASSERT_THAT(Results[2], Pair("p0", _));
- const Environment &Env = Results[2].second.Env;
+ ASSERT_THAT(Results[0], Pair("p0", _));
+ const Environment &Env = Results[0].second.Env;
const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
ASSERT_THAT(BDecl, NotNull());
auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
@@ -3322,8 +3322,8 @@ TEST(TransferTest, CorrelatedBranches) {
}
{
- ASSERT_THAT(Results[0], Pair("p2", _));
- const Environment &Env = Results[0].second.Env;
+ ASSERT_THAT(Results[2], Pair("p2", _));
+ const Environment &Env = Results[2].second.Env;
auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
EXPECT_TRUE(Env.flowConditionImplies(CVal));
}
@@ -3422,9 +3422,9 @@ TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results,
- ElementsAre(Pair("p-outer", _), Pair("p-inner", _)));
- const Environment &OuterEnv = Results[0].second.Env;
- const Environment &InnerEnv = Results[1].second.Env;
+ ElementsAre(Pair("p-inner", _), Pair("p-outer", _)));
+ const Environment &InnerEnv = Results[0].second.Env;
+ const Environment &OuterEnv = Results[1].second.Env;
const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
ASSERT_THAT(ValDecl, NotNull());
diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
index d308011047a0..0a87a7f02fa5 100644
--- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -426,12 +426,12 @@ TEST_F(JoinFlowConditionsTest, JoinDistinctButProvablyEquivalentValues) {
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
- Pair("p2", _), Pair("p1", _)));
- const Environment &Env1 = Results[3].second.Env;
- const Environment &Env2 = Results[2].second.Env;
- const Environment &Env3 = Results[1].second.Env;
- const Environment &Env4 = Results[0].second.Env;
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _),
+ Pair("p3", _), Pair("p4", _)));
+ const Environment &Env1 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
+ const Environment &Env3 = Results[2].second.Env;
+ const Environment &Env4 = Results[3].second.Env;
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
@@ -579,10 +579,10 @@ TEST_F(WideningTest, JoinDistinctValuesWithDistinctProperties) {
Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results,
- ElementsAre(Pair("p3", _), Pair("p2", _), Pair("p1", _)));
- const Environment &Env1 = Results[2].second.Env;
+ ElementsAre(Pair("p1", _), Pair("p2", _), Pair("p3", _)));
+ const Environment &Env1 = Results[0].second.Env;
const Environment &Env2 = Results[1].second.Env;
- const Environment &Env3 = Results[0].second.Env;
+ const Environment &Env3 = Results[2].second.Env;
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
@@ -622,12 +622,12 @@ TEST_F(WideningTest, JoinDistinctValuesWithSameProperties) {
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
- Pair("p2", _), Pair("p1", _)));
- const Environment &Env1 = Results[3].second.Env;
- const Environment &Env2 = Results[2].second.Env;
- const Environment &Env3 = Results[1].second.Env;
- const Environment &Env4 = Results[0].second.Env;
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _),
+ Pair("p3", _), Pair("p4", _)));
+ const Environment &Env1 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
+ const Environment &Env3 = Results[2].second.Env;
+ const Environment &Env4 = Results[3].second.Env;
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
@@ -751,14 +751,14 @@ TEST_F(FlowConditionTest, IfStmtSingleVar) {
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
- ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
- const Environment &Env1 = Results[1].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
auto *FooVal1 =
cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
- const Environment &Env2 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
auto *FooVal2 =
cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
@@ -785,14 +785,14 @@ TEST_F(FlowConditionTest, IfStmtSingleNegatedVar) {
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
- ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
- const Environment &Env1 = Results[1].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
auto *FooVal1 =
cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
- const Environment &Env2 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
auto *FooVal2 =
cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
EXPECT_TRUE(Env2.flowConditionImplies(*FooVal2));
@@ -847,9 +847,9 @@ TEST_F(FlowConditionTest, Conjunction) {
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
- ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
- const Environment &Env1 = Results[1].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
auto *FooVal1 =
cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
auto *BarVal1 =
@@ -857,7 +857,7 @@ TEST_F(FlowConditionTest, Conjunction) {
EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
- const Environment &Env2 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
auto *FooVal2 =
cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
auto *BarVal2 =
@@ -890,9 +890,9 @@ TEST_F(FlowConditionTest, Disjunction) {
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
- ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
- const Environment &Env1 = Results[1].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
auto *FooVal1 =
cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
auto *BarVal1 =
@@ -900,7 +900,7 @@ TEST_F(FlowConditionTest, Disjunction) {
EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
- const Environment &Env2 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
auto *FooVal2 =
cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
auto *BarVal2 =
@@ -933,9 +933,9 @@ TEST_F(FlowConditionTest, NegatedConjunction) {
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
- ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
- const Environment &Env1 = Results[1].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
auto *FooVal1 =
cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
auto *BarVal1 =
@@ -943,7 +943,7 @@ TEST_F(FlowConditionTest, NegatedConjunction) {
EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
- const Environment &Env2 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
auto *FooVal2 =
cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
auto *BarVal2 =
@@ -976,9 +976,9 @@ TEST_F(FlowConditionTest, DeMorgan) {
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
- ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
- const Environment &Env1 = Results[1].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
auto *FooVal1 =
cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
auto *BarVal1 =
@@ -986,7 +986,7 @@ TEST_F(FlowConditionTest, DeMorgan) {
EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
- const Environment &Env2 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
auto *FooVal2 =
cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
auto *BarVal2 =
@@ -1159,16 +1159,16 @@ TEST_F(FlowConditionTest, PointerToBoolImplicitCast) {
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p2", _), Pair("p1", _)));
+ ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
- const Environment &Env1 = Results[1].second.Env;
+ const Environment &Env1 = Results[0].second.Env;
auto &FooVal1 =
*cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::Reference));
EXPECT_TRUE(Env1.flowConditionImplies(FooVal1));
- const Environment &Env2 = Results[0].second.Env;
+ const Environment &Env2 = Results[1].second.Env;
auto &FooVal2 =
*cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::Reference));
EXPECT_FALSE(Env2.flowConditionImplies(FooVal2));
More information about the cfe-commits
mailing list