1*7c636728Smartinboehme //===- unittests/Analysis/FlowSensitive/SimplifyConstraintsTest.cpp -------===//
2*7c636728Smartinboehme //
3*7c636728Smartinboehme // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*7c636728Smartinboehme // See https://llvm.org/LICENSE.txt for license information.
5*7c636728Smartinboehme // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*7c636728Smartinboehme //
7*7c636728Smartinboehme //===----------------------------------------------------------------------===//
8*7c636728Smartinboehme
9*7c636728Smartinboehme #include "clang/Analysis/FlowSensitive/SimplifyConstraints.h"
10*7c636728Smartinboehme #include "TestingSupport.h"
11*7c636728Smartinboehme #include "clang/Analysis/FlowSensitive/Arena.h"
12*7c636728Smartinboehme #include "gmock/gmock.h"
13*7c636728Smartinboehme #include "gtest/gtest.h"
14*7c636728Smartinboehme
15*7c636728Smartinboehme namespace {
16*7c636728Smartinboehme
17*7c636728Smartinboehme using namespace clang;
18*7c636728Smartinboehme using namespace dataflow;
19*7c636728Smartinboehme
20*7c636728Smartinboehme using ::testing::ElementsAre;
21*7c636728Smartinboehme using ::testing::IsEmpty;
22*7c636728Smartinboehme
23*7c636728Smartinboehme class SimplifyConstraintsTest : public ::testing::Test {
24*7c636728Smartinboehme protected:
parse(StringRef Lines)25*7c636728Smartinboehme llvm::SetVector<const Formula *> parse(StringRef Lines) {
26*7c636728Smartinboehme std::vector<const Formula *> formulas = test::parseFormulas(A, Lines);
27*7c636728Smartinboehme llvm::SetVector<const Formula *> Constraints(formulas.begin(),
28*7c636728Smartinboehme formulas.end());
29*7c636728Smartinboehme return Constraints;
30*7c636728Smartinboehme }
31*7c636728Smartinboehme
simplify(StringRef Lines,SimplifyConstraintsInfo & Info)32*7c636728Smartinboehme llvm::SetVector<const Formula *> simplify(StringRef Lines,
33*7c636728Smartinboehme SimplifyConstraintsInfo &Info) {
34*7c636728Smartinboehme llvm::SetVector<const Formula *> Constraints = parse(Lines);
35*7c636728Smartinboehme simplifyConstraints(Constraints, A, &Info);
36*7c636728Smartinboehme return Constraints;
37*7c636728Smartinboehme }
38*7c636728Smartinboehme
39*7c636728Smartinboehme Arena A;
40*7c636728Smartinboehme };
41*7c636728Smartinboehme
printConstraints(const llvm::SetVector<const Formula * > & Constraints,raw_ostream & OS)42*7c636728Smartinboehme void printConstraints(const llvm::SetVector<const Formula *> &Constraints,
43*7c636728Smartinboehme raw_ostream &OS) {
44*7c636728Smartinboehme if (Constraints.empty()) {
45*7c636728Smartinboehme OS << "empty";
46*7c636728Smartinboehme return;
47*7c636728Smartinboehme }
48*7c636728Smartinboehme for (const auto *Constraint : Constraints) {
49*7c636728Smartinboehme Constraint->print(OS);
50*7c636728Smartinboehme OS << "\n";
51*7c636728Smartinboehme }
52*7c636728Smartinboehme }
53*7c636728Smartinboehme
54*7c636728Smartinboehme std::string
constraintsToString(const llvm::SetVector<const Formula * > & Constraints)55*7c636728Smartinboehme constraintsToString(const llvm::SetVector<const Formula *> &Constraints) {
56*7c636728Smartinboehme std::string Str;
57*7c636728Smartinboehme llvm::raw_string_ostream OS(Str);
58*7c636728Smartinboehme printConstraints(Constraints, OS);
59*7c636728Smartinboehme return Str;
60*7c636728Smartinboehme }
61*7c636728Smartinboehme
62*7c636728Smartinboehme MATCHER_P(EqualsConstraints, Constraints,
63*7c636728Smartinboehme "constraints are: " + constraintsToString(Constraints)) {
64*7c636728Smartinboehme if (arg == Constraints)
65*7c636728Smartinboehme return true;
66*7c636728Smartinboehme
67*7c636728Smartinboehme if (result_listener->stream()) {
68*7c636728Smartinboehme llvm::raw_os_ostream OS(*result_listener->stream());
69*7c636728Smartinboehme OS << "constraints are: ";
70*7c636728Smartinboehme printConstraints(arg, OS);
71*7c636728Smartinboehme }
72*7c636728Smartinboehme return false;
73*7c636728Smartinboehme }
74*7c636728Smartinboehme
TEST_F(SimplifyConstraintsTest,TriviallySatisfiable)75*7c636728Smartinboehme TEST_F(SimplifyConstraintsTest, TriviallySatisfiable) {
76*7c636728Smartinboehme SimplifyConstraintsInfo Info;
77*7c636728Smartinboehme EXPECT_THAT(simplify(R"(
78*7c636728Smartinboehme V0
79*7c636728Smartinboehme )",
80*7c636728Smartinboehme Info),
81*7c636728Smartinboehme EqualsConstraints(parse("")));
82*7c636728Smartinboehme EXPECT_THAT(Info.EquivalentAtoms, IsEmpty());
83*7c636728Smartinboehme EXPECT_THAT(Info.TrueAtoms, ElementsAre(Atom(0)));
84*7c636728Smartinboehme EXPECT_THAT(Info.FalseAtoms, IsEmpty());
85*7c636728Smartinboehme }
86*7c636728Smartinboehme
TEST_F(SimplifyConstraintsTest,SimpleContradiction)87*7c636728Smartinboehme TEST_F(SimplifyConstraintsTest, SimpleContradiction) {
88*7c636728Smartinboehme SimplifyConstraintsInfo Info;
89*7c636728Smartinboehme EXPECT_THAT(simplify(R"(
90*7c636728Smartinboehme V0
91*7c636728Smartinboehme !V0
92*7c636728Smartinboehme )",
93*7c636728Smartinboehme Info),
94*7c636728Smartinboehme EqualsConstraints(parse("false")));
95*7c636728Smartinboehme EXPECT_THAT(Info.EquivalentAtoms, IsEmpty());
96*7c636728Smartinboehme EXPECT_THAT(Info.TrueAtoms, IsEmpty());
97*7c636728Smartinboehme EXPECT_THAT(Info.FalseAtoms, IsEmpty());
98*7c636728Smartinboehme }
99*7c636728Smartinboehme
TEST_F(SimplifyConstraintsTest,ContradictionThroughEquivalence)100*7c636728Smartinboehme TEST_F(SimplifyConstraintsTest, ContradictionThroughEquivalence) {
101*7c636728Smartinboehme SimplifyConstraintsInfo Info;
102*7c636728Smartinboehme EXPECT_THAT(simplify(R"(
103*7c636728Smartinboehme (V0 = V1)
104*7c636728Smartinboehme V0
105*7c636728Smartinboehme !V1
106*7c636728Smartinboehme )",
107*7c636728Smartinboehme Info),
108*7c636728Smartinboehme EqualsConstraints(parse("false")));
109*7c636728Smartinboehme EXPECT_THAT(Info.EquivalentAtoms, IsEmpty());
110*7c636728Smartinboehme EXPECT_THAT(Info.TrueAtoms, IsEmpty());
111*7c636728Smartinboehme EXPECT_THAT(Info.FalseAtoms, IsEmpty());
112*7c636728Smartinboehme }
113*7c636728Smartinboehme
TEST_F(SimplifyConstraintsTest,EquivalenceChain)114*7c636728Smartinboehme TEST_F(SimplifyConstraintsTest, EquivalenceChain) {
115*7c636728Smartinboehme SimplifyConstraintsInfo Info;
116*7c636728Smartinboehme EXPECT_THAT(simplify(R"(
117*7c636728Smartinboehme (V0 | V3)
118*7c636728Smartinboehme (V1 = V2)
119*7c636728Smartinboehme (V2 = V3)
120*7c636728Smartinboehme )",
121*7c636728Smartinboehme Info),
122*7c636728Smartinboehme EqualsConstraints(parse("(V0 | V1)")));
123*7c636728Smartinboehme EXPECT_THAT(Info.EquivalentAtoms,
124*7c636728Smartinboehme ElementsAre(ElementsAre(Atom(1), Atom(2), Atom(3))));
125*7c636728Smartinboehme EXPECT_THAT(Info.TrueAtoms, IsEmpty());
126*7c636728Smartinboehme EXPECT_THAT(Info.FalseAtoms, IsEmpty());
127*7c636728Smartinboehme }
128*7c636728Smartinboehme
TEST_F(SimplifyConstraintsTest,TrueAndFalseAtomsSimplifyOtherExpressions)129*7c636728Smartinboehme TEST_F(SimplifyConstraintsTest, TrueAndFalseAtomsSimplifyOtherExpressions) {
130*7c636728Smartinboehme SimplifyConstraintsInfo Info;
131*7c636728Smartinboehme EXPECT_THAT(simplify(R"(
132*7c636728Smartinboehme V0
133*7c636728Smartinboehme !V1
134*7c636728Smartinboehme (V0 & (V2 => V3))
135*7c636728Smartinboehme (V1 | (V4 => V5))
136*7c636728Smartinboehme )",
137*7c636728Smartinboehme Info),
138*7c636728Smartinboehme EqualsConstraints(parse(R"(
139*7c636728Smartinboehme (V2 => V3)
140*7c636728Smartinboehme (V4 => V5)
141*7c636728Smartinboehme )")));
142*7c636728Smartinboehme EXPECT_THAT(Info.EquivalentAtoms, IsEmpty());
143*7c636728Smartinboehme EXPECT_THAT(Info.TrueAtoms, ElementsAre(Atom(0)));
144*7c636728Smartinboehme EXPECT_THAT(Info.FalseAtoms, ElementsAre(Atom(1)));
145*7c636728Smartinboehme }
146*7c636728Smartinboehme
TEST_F(SimplifyConstraintsTest,TrueAtomUnlocksEquivalenceChain)147*7c636728Smartinboehme TEST_F(SimplifyConstraintsTest, TrueAtomUnlocksEquivalenceChain) {
148*7c636728Smartinboehme SimplifyConstraintsInfo Info;
149*7c636728Smartinboehme EXPECT_THAT(simplify(R"(
150*7c636728Smartinboehme V0
151*7c636728Smartinboehme (V0 & (V1 = V2))
152*7c636728Smartinboehme (V0 & (V2 = V3))
153*7c636728Smartinboehme )",
154*7c636728Smartinboehme Info),
155*7c636728Smartinboehme EqualsConstraints(parse("")));
156*7c636728Smartinboehme EXPECT_THAT(Info.EquivalentAtoms,
157*7c636728Smartinboehme ElementsAre(ElementsAre(Atom(1), Atom(2), Atom(3))));
158*7c636728Smartinboehme EXPECT_THAT(Info.TrueAtoms, ElementsAre(Atom(0)));
159*7c636728Smartinboehme EXPECT_THAT(Info.FalseAtoms, IsEmpty());
160*7c636728Smartinboehme }
161*7c636728Smartinboehme
TEST_F(SimplifyConstraintsTest,TopLevelAndSplitIntoMultipleConstraints)162*7c636728Smartinboehme TEST_F(SimplifyConstraintsTest, TopLevelAndSplitIntoMultipleConstraints) {
163*7c636728Smartinboehme SimplifyConstraintsInfo Info;
164*7c636728Smartinboehme EXPECT_THAT(simplify(R"(
165*7c636728Smartinboehme ((V0 => V1) & (V2 => V3))
166*7c636728Smartinboehme )",
167*7c636728Smartinboehme Info),
168*7c636728Smartinboehme EqualsConstraints(parse(R"(
169*7c636728Smartinboehme (V0 => V1)
170*7c636728Smartinboehme (V2 => V3)
171*7c636728Smartinboehme )")));
172*7c636728Smartinboehme EXPECT_THAT(Info.EquivalentAtoms, IsEmpty());
173*7c636728Smartinboehme EXPECT_THAT(Info.TrueAtoms, IsEmpty());
174*7c636728Smartinboehme EXPECT_THAT(Info.FalseAtoms, IsEmpty());
175*7c636728Smartinboehme }
176*7c636728Smartinboehme
177*7c636728Smartinboehme } // namespace
178