1dcb4950dSSam Estep //===- unittests/Analysis/FlowSensitive/SingleVarConstantPropagation.cpp --===//
28179e1fdSYitzhak Mandelbaum //
38179e1fdSYitzhak Mandelbaum // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48179e1fdSYitzhak Mandelbaum // See https://llvm.org/LICENSE.txt for license information.
58179e1fdSYitzhak Mandelbaum // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68179e1fdSYitzhak Mandelbaum //
78179e1fdSYitzhak Mandelbaum //===----------------------------------------------------------------------===//
88179e1fdSYitzhak Mandelbaum //
98179e1fdSYitzhak Mandelbaum // This file defines a simplistic version of Constant Propagation as an example
108179e1fdSYitzhak Mandelbaum // of a forward, monotonic dataflow analysis. The analysis only tracks one
118179e1fdSYitzhak Mandelbaum // variable at a time -- the one with the most recent declaration encountered.
128179e1fdSYitzhak Mandelbaum //
138179e1fdSYitzhak Mandelbaum //===----------------------------------------------------------------------===//
148179e1fdSYitzhak Mandelbaum
153dd7877bSStanislav Gatev #include "TestingSupport.h"
168179e1fdSYitzhak Mandelbaum #include "clang/AST/ASTContext.h"
178179e1fdSYitzhak Mandelbaum #include "clang/AST/Decl.h"
188179e1fdSYitzhak Mandelbaum #include "clang/AST/Expr.h"
198179e1fdSYitzhak Mandelbaum #include "clang/AST/Stmt.h"
208179e1fdSYitzhak Mandelbaum #include "clang/ASTMatchers/ASTMatchFinder.h"
218179e1fdSYitzhak Mandelbaum #include "clang/ASTMatchers/ASTMatchers.h"
22cf94c52eSWei Yi Tee #include "clang/Analysis/CFG.h"
238179e1fdSYitzhak Mandelbaum #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
248179e1fdSYitzhak Mandelbaum #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
258179e1fdSYitzhak Mandelbaum #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
268179e1fdSYitzhak Mandelbaum #include "llvm/ADT/StringRef.h"
278179e1fdSYitzhak Mandelbaum #include "llvm/ADT/Twine.h"
288179e1fdSYitzhak Mandelbaum #include "llvm/Support/Error.h"
299cbdef61SWei Yi Tee #include "llvm/Testing/ADT/StringMapEntry.h"
303432f4bfSJordan Rupprecht #include "llvm/Testing/Annotations/Annotations.h"
31875117aeSYitzhak Mandelbaum #include "llvm/Testing/Support/Error.h"
328179e1fdSYitzhak Mandelbaum #include "gmock/gmock.h"
338179e1fdSYitzhak Mandelbaum #include "gtest/gtest.h"
348179e1fdSYitzhak Mandelbaum #include <cstdint>
358179e1fdSYitzhak Mandelbaum #include <memory>
36a1580d7bSKazu Hirata #include <optional>
378179e1fdSYitzhak Mandelbaum #include <ostream>
388179e1fdSYitzhak Mandelbaum #include <string>
398179e1fdSYitzhak Mandelbaum #include <utility>
408179e1fdSYitzhak Mandelbaum
418179e1fdSYitzhak Mandelbaum namespace clang {
428179e1fdSYitzhak Mandelbaum namespace dataflow {
438179e1fdSYitzhak Mandelbaum namespace {
448179e1fdSYitzhak Mandelbaum using namespace ast_matchers;
458179e1fdSYitzhak Mandelbaum
468179e1fdSYitzhak Mandelbaum // A semi-lattice for dataflow analysis that tracks the value of a single
478179e1fdSYitzhak Mandelbaum // integer variable. If it can be identified with a single (constant) value,
488179e1fdSYitzhak Mandelbaum // then that value is stored.
498179e1fdSYitzhak Mandelbaum struct ConstantPropagationLattice {
508179e1fdSYitzhak Mandelbaum // A null `Var` represents "top": either more than one value is possible or
518179e1fdSYitzhak Mandelbaum // more than one variable was encountered. Otherwise, `Data` indicates that
528179e1fdSYitzhak Mandelbaum // `Var` has the given `Value` at the program point with which this lattice
538179e1fdSYitzhak Mandelbaum // element is associated, for all paths through the program.
548179e1fdSYitzhak Mandelbaum struct VarValue {
558179e1fdSYitzhak Mandelbaum const VarDecl *Var;
568179e1fdSYitzhak Mandelbaum int64_t Value;
578179e1fdSYitzhak Mandelbaum
operator ==clang::dataflow::__anone21bec560111::ConstantPropagationLattice588179e1fdSYitzhak Mandelbaum friend bool operator==(VarValue Lhs, VarValue Rhs) {
598179e1fdSYitzhak Mandelbaum return Lhs.Var == Rhs.Var && Lhs.Value == Rhs.Value;
608179e1fdSYitzhak Mandelbaum }
618179e1fdSYitzhak Mandelbaum };
62*e955e4fbSKazu Hirata // `std::nullopt` is "bottom".
636ad0788cSKazu Hirata std::optional<VarValue> Data;
648179e1fdSYitzhak Mandelbaum
bottomclang::dataflow::__anone21bec560111::ConstantPropagationLattice65a41fbb1fSKazu Hirata static constexpr ConstantPropagationLattice bottom() {
66a41fbb1fSKazu Hirata return {std::nullopt};
67a41fbb1fSKazu Hirata }
topclang::dataflow::__anone21bec560111::ConstantPropagationLattice688179e1fdSYitzhak Mandelbaum static constexpr ConstantPropagationLattice top() {
698179e1fdSYitzhak Mandelbaum return {VarValue{nullptr, 0}};
708179e1fdSYitzhak Mandelbaum }
718179e1fdSYitzhak Mandelbaum
operator ==(const ConstantPropagationLattice & Lhs,const ConstantPropagationLattice & Rhs)728179e1fdSYitzhak Mandelbaum friend bool operator==(const ConstantPropagationLattice &Lhs,
738179e1fdSYitzhak Mandelbaum const ConstantPropagationLattice &Rhs) {
748179e1fdSYitzhak Mandelbaum return Lhs.Data == Rhs.Data;
758179e1fdSYitzhak Mandelbaum }
768179e1fdSYitzhak Mandelbaum
joinclang::dataflow::__anone21bec560111::ConstantPropagationLattice778179e1fdSYitzhak Mandelbaum LatticeJoinEffect join(const ConstantPropagationLattice &Other) {
788179e1fdSYitzhak Mandelbaum if (*this == Other || Other == bottom() || *this == top())
798179e1fdSYitzhak Mandelbaum return LatticeJoinEffect::Unchanged;
808179e1fdSYitzhak Mandelbaum
818179e1fdSYitzhak Mandelbaum if (*this == bottom()) {
828179e1fdSYitzhak Mandelbaum *this = Other;
838179e1fdSYitzhak Mandelbaum return LatticeJoinEffect::Changed;
848179e1fdSYitzhak Mandelbaum }
858179e1fdSYitzhak Mandelbaum
868179e1fdSYitzhak Mandelbaum *this = top();
878179e1fdSYitzhak Mandelbaum return LatticeJoinEffect::Changed;
888179e1fdSYitzhak Mandelbaum }
898179e1fdSYitzhak Mandelbaum };
908179e1fdSYitzhak Mandelbaum
operator <<(std::ostream & OS,const ConstantPropagationLattice & L)918179e1fdSYitzhak Mandelbaum std::ostream &operator<<(std::ostream &OS,
928179e1fdSYitzhak Mandelbaum const ConstantPropagationLattice &L) {
938179e1fdSYitzhak Mandelbaum if (L == L.bottom())
948179e1fdSYitzhak Mandelbaum return OS << "None";
958179e1fdSYitzhak Mandelbaum if (L == L.top())
968179e1fdSYitzhak Mandelbaum return OS << "Any";
978179e1fdSYitzhak Mandelbaum return OS << L.Data->Var->getName().str() << " = " << L.Data->Value;
988179e1fdSYitzhak Mandelbaum }
998179e1fdSYitzhak Mandelbaum
1008179e1fdSYitzhak Mandelbaum } // namespace
1018179e1fdSYitzhak Mandelbaum
1028179e1fdSYitzhak Mandelbaum static constexpr char kVar[] = "var";
1038179e1fdSYitzhak Mandelbaum static constexpr char kInit[] = "init";
1048179e1fdSYitzhak Mandelbaum static constexpr char kJustAssignment[] = "just-assignment";
1058179e1fdSYitzhak Mandelbaum static constexpr char kAssignment[] = "assignment";
1068179e1fdSYitzhak Mandelbaum static constexpr char kRHS[] = "rhs";
1078179e1fdSYitzhak Mandelbaum
refToVar()1088179e1fdSYitzhak Mandelbaum static auto refToVar() { return declRefExpr(to(varDecl().bind(kVar))); }
1098179e1fdSYitzhak Mandelbaum
1108179e1fdSYitzhak Mandelbaum namespace {
1118179e1fdSYitzhak Mandelbaum // N.B. This analysis is deliberately simplistic, leaving out many important
1128179e1fdSYitzhak Mandelbaum // details needed for a real analysis in production. Most notably, the transfer
1138179e1fdSYitzhak Mandelbaum // function does not account for the variable's address possibly escaping, which
1148179e1fdSYitzhak Mandelbaum // would invalidate the analysis.
1158179e1fdSYitzhak Mandelbaum class ConstantPropagationAnalysis
1168179e1fdSYitzhak Mandelbaum : public DataflowAnalysis<ConstantPropagationAnalysis,
1178179e1fdSYitzhak Mandelbaum ConstantPropagationLattice> {
1188179e1fdSYitzhak Mandelbaum public:
ConstantPropagationAnalysis(ASTContext & Context)1198179e1fdSYitzhak Mandelbaum explicit ConstantPropagationAnalysis(ASTContext &Context)
1208179e1fdSYitzhak Mandelbaum : DataflowAnalysis<ConstantPropagationAnalysis,
1218179e1fdSYitzhak Mandelbaum ConstantPropagationLattice>(Context) {}
1228179e1fdSYitzhak Mandelbaum
initialElement()1238179e1fdSYitzhak Mandelbaum static ConstantPropagationLattice initialElement() {
1248179e1fdSYitzhak Mandelbaum return ConstantPropagationLattice::bottom();
1258179e1fdSYitzhak Mandelbaum }
1268179e1fdSYitzhak Mandelbaum
transfer(const CFGElement & E,ConstantPropagationLattice & Element,Environment & Env)1276b991ba4SYitzhak Mandelbaum void transfer(const CFGElement &E, ConstantPropagationLattice &Element,
1288179e1fdSYitzhak Mandelbaum Environment &Env) {
1296b991ba4SYitzhak Mandelbaum auto CS = E.getAs<CFGStmt>();
130cf94c52eSWei Yi Tee if (!CS)
131cf94c52eSWei Yi Tee return;
132cf94c52eSWei Yi Tee auto S = CS->getStmt();
1338179e1fdSYitzhak Mandelbaum auto matcher = stmt(
1348179e1fdSYitzhak Mandelbaum anyOf(declStmt(hasSingleDecl(varDecl(hasType(isInteger()),
1358179e1fdSYitzhak Mandelbaum hasInitializer(expr().bind(kInit)))
1368179e1fdSYitzhak Mandelbaum .bind(kVar))),
1378179e1fdSYitzhak Mandelbaum binaryOperator(hasOperatorName("="), hasLHS(refToVar()),
1388179e1fdSYitzhak Mandelbaum hasRHS(expr().bind(kRHS)))
1398179e1fdSYitzhak Mandelbaum .bind(kJustAssignment),
1408179e1fdSYitzhak Mandelbaum binaryOperator(isAssignmentOperator(), hasLHS(refToVar()))
1418179e1fdSYitzhak Mandelbaum .bind(kAssignment)));
1428179e1fdSYitzhak Mandelbaum
1438179e1fdSYitzhak Mandelbaum ASTContext &Context = getASTContext();
1448179e1fdSYitzhak Mandelbaum auto Results = match(matcher, *S, Context);
1458179e1fdSYitzhak Mandelbaum if (Results.empty())
14664f7b2d4SYitzhak Mandelbaum return;
1478179e1fdSYitzhak Mandelbaum const BoundNodes &Nodes = Results[0];
1488179e1fdSYitzhak Mandelbaum
1498179e1fdSYitzhak Mandelbaum const auto *Var = Nodes.getNodeAs<clang::VarDecl>(kVar);
1508179e1fdSYitzhak Mandelbaum assert(Var != nullptr);
1518179e1fdSYitzhak Mandelbaum
1528179e1fdSYitzhak Mandelbaum if (const auto *E = Nodes.getNodeAs<clang::Expr>(kInit)) {
1538179e1fdSYitzhak Mandelbaum Expr::EvalResult R;
15464f7b2d4SYitzhak Mandelbaum Element =
15564f7b2d4SYitzhak Mandelbaum (E->EvaluateAsInt(R, Context) && R.Val.isInt())
15664f7b2d4SYitzhak Mandelbaum ? ConstantPropagationLattice{{{Var,
15764f7b2d4SYitzhak Mandelbaum R.Val.getInt().getExtValue()}}}
15864f7b2d4SYitzhak Mandelbaum : ConstantPropagationLattice::top();
15964f7b2d4SYitzhak Mandelbaum } else if (Nodes.getNodeAs<clang::Expr>(kJustAssignment)) {
1608179e1fdSYitzhak Mandelbaum const auto *RHS = Nodes.getNodeAs<clang::Expr>(kRHS);
1618179e1fdSYitzhak Mandelbaum assert(RHS != nullptr);
1628179e1fdSYitzhak Mandelbaum
1638179e1fdSYitzhak Mandelbaum Expr::EvalResult R;
16464f7b2d4SYitzhak Mandelbaum Element =
16564f7b2d4SYitzhak Mandelbaum (RHS->EvaluateAsInt(R, Context) && R.Val.isInt())
16664f7b2d4SYitzhak Mandelbaum ? ConstantPropagationLattice{{{Var,
16764f7b2d4SYitzhak Mandelbaum R.Val.getInt().getExtValue()}}}
16864f7b2d4SYitzhak Mandelbaum : ConstantPropagationLattice::top();
16964f7b2d4SYitzhak Mandelbaum } else if (Nodes.getNodeAs<clang::Expr>(kAssignment))
1708179e1fdSYitzhak Mandelbaum // Any assignment involving the expression itself resets the variable to
1718179e1fdSYitzhak Mandelbaum // "unknown". A more advanced analysis could try to evaluate the compound
1728179e1fdSYitzhak Mandelbaum // assignment. For example, `x += 0` need not invalidate `x`.
17364f7b2d4SYitzhak Mandelbaum Element = ConstantPropagationLattice::top();
1748179e1fdSYitzhak Mandelbaum }
1758179e1fdSYitzhak Mandelbaum };
1768179e1fdSYitzhak Mandelbaum
1779cbdef61SWei Yi Tee using ::clang::dataflow::test::AnalysisInputs;
1789cbdef61SWei Yi Tee using ::clang::dataflow::test::AnalysisOutputs;
1799cbdef61SWei Yi Tee using ::clang::dataflow::test::checkDataflow;
1809cbdef61SWei Yi Tee using ::llvm::IsStringMapEntry;
1818179e1fdSYitzhak Mandelbaum using ::testing::UnorderedElementsAre;
1828179e1fdSYitzhak Mandelbaum
183b8df4093SKazu Hirata MATCHER_P(HasConstantVal, v, "") { return arg.Data && arg.Data->Value == v; }
1848179e1fdSYitzhak Mandelbaum
1858179e1fdSYitzhak Mandelbaum MATCHER(IsUnknown, "") { return arg == arg.bottom(); }
1868179e1fdSYitzhak Mandelbaum MATCHER(Varies, "") { return arg == arg.top(); }
1878179e1fdSYitzhak Mandelbaum
1888179e1fdSYitzhak Mandelbaum MATCHER_P(HoldsCPLattice, m,
1898179e1fdSYitzhak Mandelbaum ((negation ? "doesn't hold" : "holds") +
1908179e1fdSYitzhak Mandelbaum llvm::StringRef(" a lattice element that ") +
1918179e1fdSYitzhak Mandelbaum ::testing::DescribeMatcher<ConstantPropagationLattice>(m, negation))
1928179e1fdSYitzhak Mandelbaum .str()) {
1938179e1fdSYitzhak Mandelbaum return ExplainMatchResult(m, arg.Lattice, result_listener);
1948179e1fdSYitzhak Mandelbaum }
1958179e1fdSYitzhak Mandelbaum
1968179e1fdSYitzhak Mandelbaum template <typename Matcher>
RunDataflow(llvm::StringRef Code,Matcher Expectations)1978179e1fdSYitzhak Mandelbaum void RunDataflow(llvm::StringRef Code, Matcher Expectations) {
198875117aeSYitzhak Mandelbaum ASSERT_THAT_ERROR(
1999cbdef61SWei Yi Tee checkDataflow<ConstantPropagationAnalysis>(
2009cbdef61SWei Yi Tee AnalysisInputs<ConstantPropagationAnalysis>(
2019cbdef61SWei Yi Tee Code, hasName("fun"),
2028179e1fdSYitzhak Mandelbaum [](ASTContext &C, Environment &) {
2038179e1fdSYitzhak Mandelbaum return ConstantPropagationAnalysis(C);
2049cbdef61SWei Yi Tee })
2059cbdef61SWei Yi Tee .withASTBuildArgs({"-fsyntax-only", "-std=c++17"}),
2069cbdef61SWei Yi Tee /*VerifyResults=*/
2079cbdef61SWei Yi Tee [&Expectations](const llvm::StringMap<DataflowAnalysisState<
2089cbdef61SWei Yi Tee ConstantPropagationAnalysis::Lattice>> &Results,
2099cbdef61SWei Yi Tee const AnalysisOutputs &) {
2109cbdef61SWei Yi Tee EXPECT_THAT(Results, Expectations);
2119cbdef61SWei Yi Tee }),
212875117aeSYitzhak Mandelbaum llvm::Succeeded());
2138179e1fdSYitzhak Mandelbaum }
2148179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,JustInit)2151d83a16bSSam Estep TEST(ConstantPropagationTest, JustInit) {
2168179e1fdSYitzhak Mandelbaum std::string Code = R"(
2178179e1fdSYitzhak Mandelbaum void fun() {
2188179e1fdSYitzhak Mandelbaum int target = 1;
2198179e1fdSYitzhak Mandelbaum // [[p]]
2208179e1fdSYitzhak Mandelbaum }
2218179e1fdSYitzhak Mandelbaum )";
2229cbdef61SWei Yi Tee RunDataflow(Code, UnorderedElementsAre(IsStringMapEntry(
2239cbdef61SWei Yi Tee "p", HoldsCPLattice(HasConstantVal(1)))));
2248179e1fdSYitzhak Mandelbaum }
2258179e1fdSYitzhak Mandelbaum
2268179e1fdSYitzhak Mandelbaum // Verifies that the analysis tracks the last variable seen.
TEST(ConstantPropagationTest,TwoVariables)2271d83a16bSSam Estep TEST(ConstantPropagationTest, TwoVariables) {
2288179e1fdSYitzhak Mandelbaum std::string Code = R"(
2298179e1fdSYitzhak Mandelbaum void fun() {
2308179e1fdSYitzhak Mandelbaum int target = 1;
2318179e1fdSYitzhak Mandelbaum // [[p1]]
2328179e1fdSYitzhak Mandelbaum int other = 2;
2338179e1fdSYitzhak Mandelbaum // [[p2]]
2348179e1fdSYitzhak Mandelbaum target = 3;
2358179e1fdSYitzhak Mandelbaum // [[p3]]
2368179e1fdSYitzhak Mandelbaum }
2378179e1fdSYitzhak Mandelbaum )";
2389cbdef61SWei Yi Tee RunDataflow(Code,
2399cbdef61SWei Yi Tee UnorderedElementsAre(
2409cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(HasConstantVal(1))),
2419cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(HasConstantVal(2))),
2429cbdef61SWei Yi Tee IsStringMapEntry("p3", HoldsCPLattice(HasConstantVal(3)))));
2438179e1fdSYitzhak Mandelbaum }
2448179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,Assignment)2451d83a16bSSam Estep TEST(ConstantPropagationTest, Assignment) {
2468179e1fdSYitzhak Mandelbaum std::string Code = R"(
2478179e1fdSYitzhak Mandelbaum void fun() {
2488179e1fdSYitzhak Mandelbaum int target = 1;
2498179e1fdSYitzhak Mandelbaum // [[p1]]
2508179e1fdSYitzhak Mandelbaum target = 2;
2518179e1fdSYitzhak Mandelbaum // [[p2]]
2528179e1fdSYitzhak Mandelbaum }
2538179e1fdSYitzhak Mandelbaum )";
2549cbdef61SWei Yi Tee RunDataflow(Code,
2559cbdef61SWei Yi Tee UnorderedElementsAre(
2569cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(HasConstantVal(1))),
2579cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(HasConstantVal(2)))));
2588179e1fdSYitzhak Mandelbaum }
2598179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,AssignmentCall)2601d83a16bSSam Estep TEST(ConstantPropagationTest, AssignmentCall) {
2618179e1fdSYitzhak Mandelbaum std::string Code = R"(
2628179e1fdSYitzhak Mandelbaum int g();
2638179e1fdSYitzhak Mandelbaum void fun() {
2648179e1fdSYitzhak Mandelbaum int target;
2658179e1fdSYitzhak Mandelbaum target = g();
2668179e1fdSYitzhak Mandelbaum // [[p]]
2678179e1fdSYitzhak Mandelbaum }
2688179e1fdSYitzhak Mandelbaum )";
2699cbdef61SWei Yi Tee RunDataflow(Code, UnorderedElementsAre(
2709cbdef61SWei Yi Tee IsStringMapEntry("p", HoldsCPLattice(Varies()))));
2718179e1fdSYitzhak Mandelbaum }
2728179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,AssignmentBinOp)2731d83a16bSSam Estep TEST(ConstantPropagationTest, AssignmentBinOp) {
2748179e1fdSYitzhak Mandelbaum std::string Code = R"(
2758179e1fdSYitzhak Mandelbaum void fun() {
2768179e1fdSYitzhak Mandelbaum int target;
2778179e1fdSYitzhak Mandelbaum target = 2 + 3;
2788179e1fdSYitzhak Mandelbaum // [[p]]
2798179e1fdSYitzhak Mandelbaum }
2808179e1fdSYitzhak Mandelbaum )";
2819cbdef61SWei Yi Tee RunDataflow(Code, UnorderedElementsAre(IsStringMapEntry(
2829cbdef61SWei Yi Tee "p", HoldsCPLattice(HasConstantVal(5)))));
2838179e1fdSYitzhak Mandelbaum }
2848179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,PlusAssignment)2851d83a16bSSam Estep TEST(ConstantPropagationTest, PlusAssignment) {
2868179e1fdSYitzhak Mandelbaum std::string Code = R"(
2878179e1fdSYitzhak Mandelbaum void fun() {
2888179e1fdSYitzhak Mandelbaum int target = 1;
2898179e1fdSYitzhak Mandelbaum // [[p1]]
2908179e1fdSYitzhak Mandelbaum target += 2;
2918179e1fdSYitzhak Mandelbaum // [[p2]]
2928179e1fdSYitzhak Mandelbaum }
2938179e1fdSYitzhak Mandelbaum )";
2949cbdef61SWei Yi Tee RunDataflow(Code,
2959cbdef61SWei Yi Tee UnorderedElementsAre(
2969cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(HasConstantVal(1))),
2979cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(Varies()))));
2988179e1fdSYitzhak Mandelbaum }
2998179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,SameAssignmentInBranches)3001d83a16bSSam Estep TEST(ConstantPropagationTest, SameAssignmentInBranches) {
3018179e1fdSYitzhak Mandelbaum std::string Code = R"cc(
3028179e1fdSYitzhak Mandelbaum void fun(bool b) {
3038179e1fdSYitzhak Mandelbaum int target;
3048179e1fdSYitzhak Mandelbaum // [[p1]]
3058179e1fdSYitzhak Mandelbaum if (b) {
3068179e1fdSYitzhak Mandelbaum target = 2;
3078179e1fdSYitzhak Mandelbaum // [[pT]]
3088179e1fdSYitzhak Mandelbaum } else {
3098179e1fdSYitzhak Mandelbaum target = 2;
3108179e1fdSYitzhak Mandelbaum // [[pF]]
3118179e1fdSYitzhak Mandelbaum }
3128179e1fdSYitzhak Mandelbaum (void)0;
3138179e1fdSYitzhak Mandelbaum // [[p2]]
3148179e1fdSYitzhak Mandelbaum }
3158179e1fdSYitzhak Mandelbaum )cc";
3169cbdef61SWei Yi Tee RunDataflow(Code,
3179cbdef61SWei Yi Tee UnorderedElementsAre(
3189cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(IsUnknown())),
3199cbdef61SWei Yi Tee IsStringMapEntry("pT", HoldsCPLattice(HasConstantVal(2))),
3209cbdef61SWei Yi Tee IsStringMapEntry("pF", HoldsCPLattice(HasConstantVal(2))),
3219cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(HasConstantVal(2)))));
3228179e1fdSYitzhak Mandelbaum }
3238179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,SameAssignmentInBranch)3241d83a16bSSam Estep TEST(ConstantPropagationTest, SameAssignmentInBranch) {
3258179e1fdSYitzhak Mandelbaum std::string Code = R"cc(
3268179e1fdSYitzhak Mandelbaum void fun(bool b) {
3278179e1fdSYitzhak Mandelbaum int target = 1;
3288179e1fdSYitzhak Mandelbaum // [[p1]]
3298179e1fdSYitzhak Mandelbaum if (b) {
3308179e1fdSYitzhak Mandelbaum target = 1;
3318179e1fdSYitzhak Mandelbaum }
3328179e1fdSYitzhak Mandelbaum (void)0;
3338179e1fdSYitzhak Mandelbaum // [[p2]]
3348179e1fdSYitzhak Mandelbaum }
3358179e1fdSYitzhak Mandelbaum )cc";
3369cbdef61SWei Yi Tee RunDataflow(Code,
3379cbdef61SWei Yi Tee UnorderedElementsAre(
3389cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(HasConstantVal(1))),
3399cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(HasConstantVal(1)))));
3408179e1fdSYitzhak Mandelbaum }
3418179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,NewVarInBranch)3421d83a16bSSam Estep TEST(ConstantPropagationTest, NewVarInBranch) {
3438179e1fdSYitzhak Mandelbaum std::string Code = R"cc(
3448179e1fdSYitzhak Mandelbaum void fun(bool b) {
3458179e1fdSYitzhak Mandelbaum if (b) {
3468179e1fdSYitzhak Mandelbaum int target;
3478179e1fdSYitzhak Mandelbaum // [[p1]]
3488179e1fdSYitzhak Mandelbaum target = 1;
3498179e1fdSYitzhak Mandelbaum // [[p2]]
3508179e1fdSYitzhak Mandelbaum } else {
3518179e1fdSYitzhak Mandelbaum int target;
3528179e1fdSYitzhak Mandelbaum // [[p3]]
3538179e1fdSYitzhak Mandelbaum target = 1;
3548179e1fdSYitzhak Mandelbaum // [[p4]]
3558179e1fdSYitzhak Mandelbaum }
3568179e1fdSYitzhak Mandelbaum }
3578179e1fdSYitzhak Mandelbaum )cc";
3589cbdef61SWei Yi Tee RunDataflow(Code,
3599cbdef61SWei Yi Tee UnorderedElementsAre(
3609cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(IsUnknown())),
3619cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(HasConstantVal(1))),
3629cbdef61SWei Yi Tee IsStringMapEntry("p3", HoldsCPLattice(IsUnknown())),
3639cbdef61SWei Yi Tee IsStringMapEntry("p4", HoldsCPLattice(HasConstantVal(1)))));
3648179e1fdSYitzhak Mandelbaum }
3658179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,DifferentAssignmentInBranches)3661d83a16bSSam Estep TEST(ConstantPropagationTest, DifferentAssignmentInBranches) {
3678179e1fdSYitzhak Mandelbaum std::string Code = R"cc(
3688179e1fdSYitzhak Mandelbaum void fun(bool b) {
3698179e1fdSYitzhak Mandelbaum int target;
3708179e1fdSYitzhak Mandelbaum // [[p1]]
3718179e1fdSYitzhak Mandelbaum if (b) {
3728179e1fdSYitzhak Mandelbaum target = 1;
3738179e1fdSYitzhak Mandelbaum // [[pT]]
3748179e1fdSYitzhak Mandelbaum } else {
3758179e1fdSYitzhak Mandelbaum target = 2;
3768179e1fdSYitzhak Mandelbaum // [[pF]]
3778179e1fdSYitzhak Mandelbaum }
3788179e1fdSYitzhak Mandelbaum (void)0;
3798179e1fdSYitzhak Mandelbaum // [[p2]]
3808179e1fdSYitzhak Mandelbaum }
3818179e1fdSYitzhak Mandelbaum )cc";
3829cbdef61SWei Yi Tee RunDataflow(Code,
3839cbdef61SWei Yi Tee UnorderedElementsAre(
3849cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(IsUnknown())),
3859cbdef61SWei Yi Tee IsStringMapEntry("pT", HoldsCPLattice(HasConstantVal(1))),
3869cbdef61SWei Yi Tee IsStringMapEntry("pF", HoldsCPLattice(HasConstantVal(2))),
3879cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(Varies()))));
3888179e1fdSYitzhak Mandelbaum }
3898179e1fdSYitzhak Mandelbaum
TEST(ConstantPropagationTest,DifferentAssignmentInBranch)3901d83a16bSSam Estep TEST(ConstantPropagationTest, DifferentAssignmentInBranch) {
3918179e1fdSYitzhak Mandelbaum std::string Code = R"cc(
3928179e1fdSYitzhak Mandelbaum void fun(bool b) {
3938179e1fdSYitzhak Mandelbaum int target = 1;
3948179e1fdSYitzhak Mandelbaum // [[p1]]
3958179e1fdSYitzhak Mandelbaum if (b) {
3968179e1fdSYitzhak Mandelbaum target = 3;
3978179e1fdSYitzhak Mandelbaum }
3988179e1fdSYitzhak Mandelbaum (void)0;
3998179e1fdSYitzhak Mandelbaum // [[p2]]
4008179e1fdSYitzhak Mandelbaum }
4018179e1fdSYitzhak Mandelbaum )cc";
4029cbdef61SWei Yi Tee RunDataflow(Code,
4039cbdef61SWei Yi Tee UnorderedElementsAre(
4049cbdef61SWei Yi Tee IsStringMapEntry("p1", HoldsCPLattice(HasConstantVal(1))),
4059cbdef61SWei Yi Tee IsStringMapEntry("p2", HoldsCPLattice(Varies()))));
4068179e1fdSYitzhak Mandelbaum }
4078179e1fdSYitzhak Mandelbaum
4088179e1fdSYitzhak Mandelbaum } // namespace
4098179e1fdSYitzhak Mandelbaum } // namespace dataflow
4108179e1fdSYitzhak Mandelbaum } // namespace clang
411