#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
+#include "llvm/Testing/ADT/StringMapEntry.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace dataflow;
using namespace test;
using namespace ast_matchers;
-using ::testing::_;
-using ::testing::ElementsAre;
+using llvm::IsStringMapEntry;
+using ::testing::DescribeMatcher;
using ::testing::IsEmpty;
-using ::testing::IsNull;
using ::testing::NotNull;
-using ::testing::Pair;
using ::testing::Test;
using ::testing::UnorderedElementsAre;
}
struct FunctionCallLattice {
- llvm::SmallSet<std::string, 8> CalledFunctions;
+ using FunctionSet = llvm::SmallSet<std::string, 8>;
+ FunctionSet CalledFunctions;
bool operator==(const FunctionCallLattice &Other) const {
return CalledFunctions == Other.CalledFunctions;
ASSERT_THAT_ERROR(
test::checkDataflow<FunctionCallAnalysis>(
- Code, "target",
- [](ASTContext &C, Environment &) {
- return FunctionCallAnalysis(C);
- },
+ AnalysisInputs<FunctionCallAnalysis>(
+ Code, ast_matchers::hasName("target"),
+ [](ASTContext &C, Environment &) {
+ return FunctionCallAnalysis(C);
+ })
+ .withASTBuildArgs({"-fsyntax-only", "-std=c++17"})
+ .withASTBuildVirtualMappedFiles(std::move(FilesContents)),
+ /*VerifyResults=*/
[&Expectations](
- llvm::ArrayRef<std::pair<
- std::string, DataflowAnalysisState<FunctionCallLattice>>>
- Results,
- ASTContext &) { EXPECT_THAT(Results, Expectations); },
- {"-fsyntax-only", "-std=c++17"}, FilesContents),
+ const llvm::StringMap<
+ DataflowAnalysisState<FunctionCallLattice>> &Results,
+ const AnalysisOutputs &) {
+ EXPECT_THAT(Results, Expectations);
+ }),
llvm::Succeeded());
}
};
MATCHER_P(HoldsFunctionCallLattice, m,
((negation ? "doesn't hold" : "holds") +
llvm::StringRef(" a lattice element that ") +
- ::testing::DescribeMatcher<FunctionCallLattice>(m, negation))
+ DescribeMatcher<FunctionCallLattice>(m))
.str()) {
return ExplainMatchResult(m, arg.Lattice, result_listener);
}
-MATCHER_P(HasCalledFunctions, m, "") {
+MATCHER_P(HasCalledFunctions, m,
+ ((negation ? "doesn't hold" : "holds") +
+ llvm::StringRef(" a set of called functions that ") +
+ DescribeMatcher<FunctionCallLattice::FunctionSet>(m))
+ .str()) {
return ExplainMatchResult(m, arg.CalledFunctions, result_listener);
}
// [[p]]
}
)";
- runDataflow(Code, UnorderedElementsAre(
- Pair("p", HoldsFunctionCallLattice(HasCalledFunctions(
- UnorderedElementsAre("foo", "bar"))))));
+ runDataflow(Code, UnorderedElementsAre(IsStringMapEntry(
+ "p", HoldsFunctionCallLattice(HasCalledFunctions(
+ UnorderedElementsAre("foo", "bar"))))));
}
TEST_F(NoreturnDestructorTest, ConditionalOperatorLeftBranchReturns) {
// [[p]]
}
)";
- runDataflow(Code, UnorderedElementsAre(
- Pair("p", HoldsFunctionCallLattice(HasCalledFunctions(
- UnorderedElementsAre("foo"))))));
+ runDataflow(Code, UnorderedElementsAre(IsStringMapEntry(
+ "p", HoldsFunctionCallLattice(HasCalledFunctions(
+ UnorderedElementsAre("foo"))))));
}
TEST_F(NoreturnDestructorTest, ConditionalOperatorRightBranchReturns) {
// [[p]]
}
)";
- runDataflow(Code, UnorderedElementsAre(
- Pair("p", HoldsFunctionCallLattice(HasCalledFunctions(
- UnorderedElementsAre("foo"))))));
+ runDataflow(Code, UnorderedElementsAre(IsStringMapEntry(
+ "p", HoldsFunctionCallLattice(HasCalledFunctions(
+ UnorderedElementsAre("foo"))))));
}
TEST_F(NoreturnDestructorTest, ConditionalOperatorNestedBranchesDoNotReturn) {
// [[p]]
}
)";
- runDataflow(Code, UnorderedElementsAre(
- Pair("p", HoldsFunctionCallLattice(HasCalledFunctions(
- UnorderedElementsAre("baz", "foo"))))));
+ runDataflow(Code, UnorderedElementsAre(IsStringMapEntry(
+ "p", HoldsFunctionCallLattice(HasCalledFunctions(
+ UnorderedElementsAre("baz", "foo"))))));
// FIXME: Called functions at point `p` should contain only "foo".
}
void runDataflow(llvm::StringRef Code, Matcher Match) {
ASSERT_THAT_ERROR(
test::checkDataflow<SpecialBoolAnalysis>(
- Code, "target",
- [](ASTContext &Context, Environment &Env) {
- return SpecialBoolAnalysis(Context);
- },
- [&Match](
- llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) { Match(Results, ASTCtx); },
- {"-fsyntax-only", "-std=c++17"}),
+ AnalysisInputs<SpecialBoolAnalysis>(
+ Code, ast_matchers::hasName("target"),
+ [](ASTContext &Context, Environment &Env) {
+ return SpecialBoolAnalysis(Context);
+ })
+ .withASTBuildArgs({"-fsyntax-only", "-std=c++17"}),
+ /*VerifyResults=*/[&Match](const llvm::StringMap<
+ DataflowAnalysisState<NoopLattice>>
+ &Results,
+ const AnalysisOutputs
+ &AO) { Match(Results, AO.ASTCtx); }),
llvm::Succeeded());
}
};
}
)";
runDataflow(
- Code, [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- 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;
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(),
+ UnorderedElementsAre("p1", "p2", "p3", "p4"));
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
+ const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4");
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
};
)"));
ASSERT_THAT_ERROR(
- test::checkDataflow<OptionalIntAnalysis>(
- Code, "target",
- [this](ASTContext &Context, Environment &Env) {
- assert(HasValueTop == nullptr);
- HasValueTop =
- &Env.takeOwnership(std::make_unique<AtomicBoolValue>());
- return OptionalIntAnalysis(Context, *HasValueTop);
- },
- [&Match](
- llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) { Match(Results, ASTCtx); },
- {"-fsyntax-only", "-std=c++17"}, FilesContents),
+ checkDataflow<OptionalIntAnalysis>(
+ AnalysisInputs<OptionalIntAnalysis>(
+ Code, ast_matchers::hasName("target"),
+ [this](ASTContext &Context, Environment &Env) {
+ assert(HasValueTop == nullptr);
+ HasValueTop =
+ &Env.takeOwnership(std::make_unique<AtomicBoolValue>());
+ return OptionalIntAnalysis(Context, *HasValueTop);
+ })
+ .withASTBuildArgs({"-fsyntax-only", "-std=c++17"})
+ .withASTBuildVirtualMappedFiles(std::move(FilesContents)),
+ /*VerifyResults=*/[&Match](const llvm::StringMap<
+ DataflowAnalysisState<NoopLattice>>
+ &Results,
+ const AnalysisOutputs
+ &AO) { Match(Results, AO.ASTCtx); }),
llvm::Succeeded());
}
)";
runDataflow(
Code,
- [this](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
+ [this](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
- ASSERT_THAT(Results,
- 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[2].second.Env;
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3"));
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
/*[[p4]]*/
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- 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());
-
- auto GetFooValue = [FooDecl](const Environment &Env) {
- return Env.getValue(*FooDecl, SkipPast::None);
- };
-
- EXPECT_EQ(GetFooValue(Env1)->getProperty("has_value"),
- &Env1.getBoolLiteralValue(false));
- EXPECT_EQ(GetFooValue(Env2)->getProperty("has_value"),
- &Env2.getBoolLiteralValue(true));
- EXPECT_EQ(GetFooValue(Env3)->getProperty("has_value"),
- &Env3.getBoolLiteralValue(true));
- EXPECT_EQ(GetFooValue(Env4)->getProperty("has_value"),
- &Env4.getBoolLiteralValue(true));
- });
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(),
+ UnorderedElementsAre("p1", "p2", "p3", "p4"));
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
+ const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4");
+
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ auto GetFooValue = [FooDecl](const Environment &Env) {
+ return Env.getValue(*FooDecl, SkipPast::None);
+ };
+
+ EXPECT_EQ(GetFooValue(Env1)->getProperty("has_value"),
+ &Env1.getBoolLiteralValue(false));
+ EXPECT_EQ(GetFooValue(Env2)->getProperty("has_value"),
+ &Env2.getBoolLiteralValue(true));
+ EXPECT_EQ(GetFooValue(Env3)->getProperty("has_value"),
+ &Env3.getBoolLiteralValue(true));
+ EXPECT_EQ(GetFooValue(Env4)->getProperty("has_value"),
+ &Env4.getBoolLiteralValue(true));
+ });
}
TEST_F(WideningTest, DistinctPointersToTheSameLocationAreEquivalent) {
// [[p]]
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
- const Environment &Env = Results[0].second.Env;
-
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
- ASSERT_THAT(BarDecl, NotNull());
-
- const auto *FooLoc = cast<ScalarStorageLocation>(
- Env.getStorageLocation(*FooDecl, SkipPast::None));
- const auto *BarVal =
- cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
- EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
- });
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ ASSERT_THAT(BarDecl, NotNull());
+
+ const auto *FooLoc = cast<ScalarStorageLocation>(
+ Env.getStorageLocation(*FooDecl, SkipPast::None));
+ const auto *BarVal =
+ cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
+ EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
+ });
}
TEST_F(WideningTest, DistinctValuesWithSamePropertiesAreEquivalent) {
/*[[p]]*/
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
- const Environment &Env = Results[0].second.Env;
-
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
- EXPECT_EQ(FooVal->getProperty("has_value"),
- &Env.getBoolLiteralValue(true));
- });
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
+ EXPECT_EQ(FooVal->getProperty("has_value"),
+ &Env.getBoolLiteralValue(true));
+ });
}
class FlowConditionTest : public Test {
template <typename Matcher>
void runDataflow(llvm::StringRef Code, Matcher Match) {
ASSERT_THAT_ERROR(
- test::checkDataflow<NoopAnalysis>(
- Code, "target",
- [](ASTContext &Context, Environment &Env) {
- return NoopAnalysis(Context, true);
- },
- [&Match](
- llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) { Match(Results, ASTCtx); },
- {"-fsyntax-only", "-std=c++17"}),
+ checkDataflow<NoopAnalysis>(
+ AnalysisInputs<NoopAnalysis>(
+ Code, ast_matchers::hasName("target"),
+ [](ASTContext &Context, Environment &Env) {
+ return NoopAnalysis(Context, true);
+ })
+ .withASTBuildArgs({"-fsyntax-only", "-std=c++17"}),
+ /*VerifyResults=*/[&Match](const llvm::StringMap<
+ DataflowAnalysisState<NoopLattice>>
+ &Results,
+ const AnalysisOutputs
+ &AO) { Match(Results, AO.ASTCtx); }),
llvm::Succeeded());
}
};
}
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
-
- 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[1].second.Env;
- auto *FooVal2 =
- cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
- EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
- });
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
+
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ auto *FooVal1 =
+ cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
+ EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
+
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ auto *FooVal2 =
+ cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
+ EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
+ });
}
TEST_F(FlowConditionTest, IfStmtSingleNegatedVar) {
}
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
-
- 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[1].second.Env;
- auto *FooVal2 =
- cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
- EXPECT_TRUE(Env2.flowConditionImplies(*FooVal2));
- });
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
+
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ auto *FooVal1 =
+ cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
+ EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
+
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ auto *FooVal2 =
+ cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
+ EXPECT_TRUE(Env2.flowConditionImplies(*FooVal2));
+ });
}
TEST_F(FlowConditionTest, WhileStmt) {
}
)";
runDataflow(
- Code, [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
- ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
- const Environment &Env = Results[0].second.Env;
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
auto *FooVal = cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
EXPECT_TRUE(Env.flowConditionImplies(*FooVal));
}
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
- ASSERT_THAT(BarDecl, NotNull());
-
- ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
-
- const Environment &Env1 = Results[0].second.Env;
- auto *FooVal1 =
- cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
- auto *BarVal1 =
- cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
- EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
- EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
-
- const Environment &Env2 = Results[1].second.Env;
- auto *FooVal2 =
- cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
- auto *BarVal2 =
- cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
- EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
- EXPECT_FALSE(Env2.flowConditionImplies(*BarVal2));
- });
+ runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
+ &Results,
+ ASTContext &ASTCtx) {
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ ASSERT_THAT(BarDecl, NotNull());
+
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
+
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ auto *FooVal1 = cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal1 = cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
+ EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
+ EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
+
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ auto *FooVal2 = cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal2 = cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
+ EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
+ EXPECT_FALSE(Env2.flowConditionImplies(*BarVal2));
+ });
}
TEST_F(FlowConditionTest, Disjunction) {
}
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
- ASSERT_THAT(BarDecl, NotNull());
-
- ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
-
- const Environment &Env1 = Results[0].second.Env;
- auto *FooVal1 =
- cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
- auto *BarVal1 =
- cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
- EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
- EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
-
- const Environment &Env2 = Results[1].second.Env;
- auto *FooVal2 =
- cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
- auto *BarVal2 =
- cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
- EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
- EXPECT_FALSE(Env2.flowConditionImplies(*BarVal2));
- });
+ runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
+ &Results,
+ ASTContext &ASTCtx) {
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ ASSERT_THAT(BarDecl, NotNull());
+
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
+
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ auto *FooVal1 = cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal1 = cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
+ EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
+ EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
+
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ auto *FooVal2 = cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal2 = cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
+ EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
+ EXPECT_FALSE(Env2.flowConditionImplies(*BarVal2));
+ });
}
TEST_F(FlowConditionTest, NegatedConjunction) {
}
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
- ASSERT_THAT(BarDecl, NotNull());
-
- ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
-
- const Environment &Env1 = Results[0].second.Env;
- auto *FooVal1 =
- cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
- auto *BarVal1 =
- cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
- EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
- EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
-
- const Environment &Env2 = Results[1].second.Env;
- auto *FooVal2 =
- cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
- auto *BarVal2 =
- cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
- EXPECT_TRUE(Env2.flowConditionImplies(*FooVal2));
- EXPECT_TRUE(Env2.flowConditionImplies(*BarVal2));
- });
+ runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
+ &Results,
+ ASTContext &ASTCtx) {
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ ASSERT_THAT(BarDecl, NotNull());
+
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
+
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ auto *FooVal1 = cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal1 = cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
+ EXPECT_FALSE(Env1.flowConditionImplies(*FooVal1));
+ EXPECT_FALSE(Env1.flowConditionImplies(*BarVal1));
+
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ auto *FooVal2 = cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal2 = cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
+ EXPECT_TRUE(Env2.flowConditionImplies(*FooVal2));
+ EXPECT_TRUE(Env2.flowConditionImplies(*BarVal2));
+ });
}
TEST_F(FlowConditionTest, DeMorgan) {
}
}
)";
- runDataflow(Code,
- [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
- ASSERT_THAT(FooDecl, NotNull());
-
- const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
- ASSERT_THAT(BarDecl, NotNull());
-
- ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
-
- const Environment &Env1 = Results[0].second.Env;
- auto *FooVal1 =
- cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
- auto *BarVal1 =
- cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
- EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
- EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
-
- const Environment &Env2 = Results[1].second.Env;
- auto *FooVal2 =
- cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
- auto *BarVal2 =
- cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
- EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
- EXPECT_FALSE(Env2.flowConditionImplies(*BarVal2));
- });
+ runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
+ &Results,
+ ASTContext &ASTCtx) {
+ const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
+ ASSERT_THAT(FooDecl, NotNull());
+
+ const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
+ ASSERT_THAT(BarDecl, NotNull());
+
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
+
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
+ auto *FooVal1 = cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal1 = cast<BoolValue>(Env1.getValue(*BarDecl, SkipPast::None));
+ EXPECT_TRUE(Env1.flowConditionImplies(*FooVal1));
+ EXPECT_TRUE(Env1.flowConditionImplies(*BarVal1));
+
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
+ auto *FooVal2 = cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::None));
+ auto *BarVal2 = cast<BoolValue>(Env2.getValue(*BarDecl, SkipPast::None));
+ EXPECT_FALSE(Env2.flowConditionImplies(*FooVal2));
+ EXPECT_FALSE(Env2.flowConditionImplies(*BarVal2));
+ });
}
TEST_F(FlowConditionTest, Join) {
}
)";
runDataflow(
- Code, [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
- const Environment &Env = Results[0].second.Env;
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
auto *FooVal = cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
EXPECT_TRUE(Env.flowConditionImplies(*FooVal));
});
}
)";
runDataflow(
- Code, [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
- const Environment &Env = Results[0].second.Env;
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
}
)";
runDataflow(
- Code, [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
- const Environment &Env = Results[0].second.Env;
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
}
)";
runDataflow(
- Code, [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
- const Environment &Env = Results[0].second.Env;
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
}
)";
runDataflow(
- Code, [](llvm::ArrayRef<
- std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
- Results,
- ASTContext &ASTCtx) {
- ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
+
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());
- const Environment &Env1 = Results[0].second.Env;
+ const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
auto &FooVal1 =
*cast<BoolValue>(Env1.getValue(*FooDecl, SkipPast::Reference));
EXPECT_TRUE(Env1.flowConditionImplies(FooVal1));
- const Environment &Env2 = Results[1].second.Env;
+ const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
auto &FooVal2 =
*cast<BoolValue>(Env2.getValue(*FooDecl, SkipPast::Reference));
EXPECT_FALSE(Env2.flowConditionImplies(FooVal2));