[clang] 88210b8 - [clang][dataflow] Refactor `clang/Analysis/FlowSensitive/MatchSwitchTest.cpp`.

Wei Yi Tee via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 19 12:10:58 PDT 2022


Author: Wei Yi Tee
Date: 2022-09-19T19:10:41Z
New Revision: 88210b81eed803598afeeaa2a60eb26ddbb65435

URL: https://github.com/llvm/llvm-project/commit/88210b81eed803598afeeaa2a60eb26ddbb65435
DIFF: https://github.com/llvm/llvm-project/commit/88210b81eed803598afeeaa2a60eb26ddbb65435.diff

LOG: [clang][dataflow] Refactor `clang/Analysis/FlowSensitive/MatchSwitchTest.cpp`.

- Remove use of `runDataflowAnalysis` to keep test isolated.
- Add test for `ASTMatchSwitch<CXXCtorInitializer, ...>`.

Reviewed By: gribozavr2, sgatev

Differential Revision: https://reviews.llvm.org/D133935

Added: 
    

Modified: 
    clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp b/clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
index 42bf5ddec508..eec1c704dbbb 100644
--- a/clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
@@ -7,24 +7,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Analysis/FlowSensitive/MatchSwitch.h"
-#include "TestingSupport.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/Stmt.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
-#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include "clang/Analysis/FlowSensitive/MapLattice.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.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"
 #include <cstdint>
 #include <memory>
@@ -34,172 +25,114 @@
 
 using namespace clang;
 using namespace dataflow;
+using namespace ast_matchers;
 
 namespace {
-using ::llvm::IsStringMapEntry;
-using ::testing::UnorderedElementsAre;
 
-class BooleanLattice {
-public:
-  BooleanLattice() : Value(false) {}
-  explicit BooleanLattice(bool B) : Value(B) {}
-
-  static BooleanLattice bottom() { return BooleanLattice(false); }
-
-  static BooleanLattice top() { return BooleanLattice(true); }
-
-  LatticeJoinEffect join(BooleanLattice Other) {
-    auto Prev = Value;
-    Value = Value || Other.Value;
-    return Prev == Value ? LatticeJoinEffect::Unchanged
-                         : LatticeJoinEffect::Changed;
-  }
-
-  friend bool operator==(BooleanLattice LHS, BooleanLattice RHS) {
-    return LHS.Value == RHS.Value;
-  }
-
-  friend std::ostream &operator<<(std::ostream &Os, const BooleanLattice &B) {
-    Os << B.Value;
-    return Os;
-  }
-
-  bool value() const { return Value; }
-
-private:
-  bool Value;
-};
-} // namespace
-
-MATCHER_P(Holds, m,
-          ((negation ? "doesn't hold" : "holds") +
-           llvm::StringRef(" a lattice element that ") +
-           ::testing::DescribeMatcher<BooleanLattice>(m, negation))
-              .str()) {
-  return ExplainMatchResult(m, arg.Lattice, result_listener);
-}
-
-void TransferSetTrue(const DeclRefExpr *,
-                     const ast_matchers::MatchFinder::MatchResult &,
-                     TransferState<BooleanLattice> &State) {
-  State.Lattice = BooleanLattice(true);
-}
-
-void TransferSetFalse(const Stmt *,
-                      const ast_matchers::MatchFinder::MatchResult &,
-                      TransferState<BooleanLattice> &State) {
-  State.Lattice = BooleanLattice(false);
-}
-
-class TestAnalysis : public DataflowAnalysis<TestAnalysis, BooleanLattice> {
-  MatchSwitch<TransferState<BooleanLattice>> TransferSwitch;
-
-public:
-  explicit TestAnalysis(ASTContext &Context)
-      : DataflowAnalysis<TestAnalysis, BooleanLattice>(Context) {
-    using namespace ast_matchers;
-    TransferSwitch =
-        MatchSwitchBuilder<TransferState<BooleanLattice>>()
-            .CaseOf<DeclRefExpr>(declRefExpr(to(varDecl(hasName("X")))),
-                                 TransferSetTrue)
-            .CaseOf<Stmt>(callExpr(callee(functionDecl(hasName("Foo")))),
-                          TransferSetFalse)
-            .Build();
-  }
-
-  static BooleanLattice initialElement() { return BooleanLattice::bottom(); }
-
-  void transfer(const Stmt *S, BooleanLattice &L, Environment &Env) {
-    TransferState<BooleanLattice> State(L, Env);
-    TransferSwitch(*S, getASTContext(), State);
-  }
-};
-
-template <typename Matcher>
-void RunDataflow(llvm::StringRef Code, Matcher Expectations) {
-  using namespace ast_matchers;
-  using namespace test;
-  ASSERT_THAT_ERROR(
-      checkDataflow<TestAnalysis>(
-          AnalysisInputs<TestAnalysis>(
-              Code, hasName("fun"),
-              [](ASTContext &C, Environment &) { return TestAnalysis(C); })
-              .withASTBuildArgs({"-fsyntax-only", "-std=c++17"}),
-          /*VerifyResults=*/
-          [&Expectations](
-              const llvm::StringMap<
-                  DataflowAnalysisState<TestAnalysis::Lattice>> &Results,
-              const AnalysisOutputs &) { EXPECT_THAT(Results, Expectations); }),
-      llvm::Succeeded());
-}
-
-TEST(MatchSwitchTest, JustX) {
-  std::string Code = R"(
-    void fun() {
-      int X = 1;
-      (void)X;
-      // [[p]]
-    }
-  )";
-  RunDataflow(Code, UnorderedElementsAre(
-                        IsStringMapEntry("p", Holds(BooleanLattice(true)))));
-}
-
-TEST(MatchSwitchTest, JustFoo) {
-  std::string Code = R"(
-    void Foo();
-    void fun() {
-      Foo();
-      // [[p]]
-    }
-  )";
-  RunDataflow(Code, UnorderedElementsAre(
-                        IsStringMapEntry("p", Holds(BooleanLattice(false)))));
-}
-
-TEST(MatchSwitchTest, XThenFoo) {
+TEST(MatchSwitchTest, Stmts) {
   std::string Code = R"(
     void Foo();
-    void fun() {
+    void Bar();
+    void f() {
       int X = 1;
-      (void)X;
-      Foo();
-      // [[p]]
-    }
-  )";
-  RunDataflow(Code, UnorderedElementsAre(
-                        IsStringMapEntry("p", Holds(BooleanLattice(false)))));
-}
-
-TEST(MatchSwitchTest, FooThenX) {
-  std::string Code = R"(
-    void Foo();
-    void fun() {
       Foo();
-      int X = 1;
-      (void)X;
-      // [[p]]
+      Bar();
     }
   )";
-  RunDataflow(Code, UnorderedElementsAre(
-                        IsStringMapEntry("p", Holds(BooleanLattice(true)))));
+  auto Unit = tooling::buildASTFromCode(Code);
+  auto &Ctx = Unit->getASTContext();
+
+  llvm::StringRef XStr = "X";
+  llvm::StringRef FooStr = "Foo";
+  llvm::StringRef BarStr = "Bar";
+
+  auto XMatcher = declStmt(hasSingleDecl(varDecl(hasName(XStr))));
+  auto FooMatcher = callExpr(callee(functionDecl(hasName(FooStr))));
+  auto BarMatcher = callExpr(callee(functionDecl(hasName(BarStr))));
+
+  ASTMatchSwitch<Stmt, llvm::StringRef> MS =
+      ASTMatchSwitchBuilder<Stmt, llvm::StringRef>()
+          .CaseOf<Stmt>(XMatcher,
+                        [&XStr](const Stmt *, const MatchFinder::MatchResult &,
+                                llvm::StringRef &State) { State = XStr; })
+          .CaseOf<Stmt>(FooMatcher,
+                        [&FooStr](const Stmt *,
+                                  const MatchFinder::MatchResult &,
+                                  llvm::StringRef &State) { State = FooStr; })
+          .Build();
+  llvm::StringRef State;
+
+  // State modified from the first case of the switch
+  const auto *X = selectFirst<Stmt>(XStr, match(XMatcher.bind(XStr), Ctx));
+  MS(*X, Ctx, State);
+  EXPECT_EQ(State, XStr);
+
+  // State modified from the second case of the switch
+  const auto *Foo =
+      selectFirst<Stmt>(FooStr, match(FooMatcher.bind(FooStr), Ctx));
+  MS(*Foo, Ctx, State);
+  EXPECT_EQ(State, FooStr);
+
+  // State unmodified, no case defined for calling Bar
+  const auto *Bar =
+      selectFirst<Stmt>(BarStr, match(BarMatcher.bind(BarStr), Ctx));
+  MS(*Bar, Ctx, State);
+  EXPECT_EQ(State, FooStr);
 }
 
-TEST(MatchSwitchTest, Neither) {
+TEST(MatchSwitchTest, CtorInitializers) {
   std::string Code = R"(
-    void Bar();
-    void fun(bool b) {
-      Bar();
-      // [[p]]
-    }
+    struct f {
+      int i;
+      int j;
+      int z;
+      f(): i(1), j(1), z(1) {}
+    };
   )";
-  RunDataflow(Code, UnorderedElementsAre(
-                        IsStringMapEntry("p", Holds(BooleanLattice(false)))));
+  auto Unit = tooling::buildASTFromCode(Code);
+  auto &Ctx = Unit->getASTContext();
+
+  llvm::StringRef IStr = "i";
+  llvm::StringRef JStr = "j";
+  llvm::StringRef ZStr = "z";
+
+  auto InitI = cxxCtorInitializer(forField(hasName(IStr)));
+  auto InitJ = cxxCtorInitializer(forField(hasName(JStr)));
+  auto InitZ = cxxCtorInitializer(forField(hasName(ZStr)));
+
+  ASTMatchSwitch<CXXCtorInitializer, llvm::StringRef> MS =
+      ASTMatchSwitchBuilder<CXXCtorInitializer, llvm::StringRef>()
+          .CaseOf<CXXCtorInitializer>(
+              InitI, [&IStr](const CXXCtorInitializer *,
+                             const MatchFinder::MatchResult &,
+                             llvm::StringRef &State) { State = IStr; })
+          .CaseOf<CXXCtorInitializer>(
+              InitJ, [&JStr](const CXXCtorInitializer *,
+                             const MatchFinder::MatchResult &,
+                             llvm::StringRef &State) { State = JStr; })
+          .Build();
+  llvm::StringRef State;
+
+  // State modified from the first case of the switch
+  const auto *I =
+      selectFirst<CXXCtorInitializer>(IStr, match(InitI.bind(IStr), Ctx));
+  MS(*I, Ctx, State);
+  EXPECT_EQ(State, IStr);
+
+  // State modified from the second case of the switch
+  const auto *J =
+      selectFirst<CXXCtorInitializer>(JStr, match(InitJ.bind(JStr), Ctx));
+  MS(*J, Ctx, State);
+  EXPECT_EQ(State, JStr);
+
+  // State unmodified, no case defined for the initializer of z
+  const auto *Z =
+      selectFirst<CXXCtorInitializer>(ZStr, match(InitZ.bind(ZStr), Ctx));
+  MS(*Z, Ctx, State);
+  EXPECT_EQ(State, JStr);
 }
 
 TEST(MatchSwitchTest, ReturnNonVoid) {
-  using namespace ast_matchers;
-
   auto Unit =
       tooling::buildASTFromCode("void f() { int x = 42; }", "input.cc",
                                 std::make_shared<PCHContainerOperations>());
@@ -210,8 +143,8 @@ TEST(MatchSwitchTest, ReturnNonVoid) {
           match(functionDecl(isDefinition(), hasName("f")).bind("f"), Context))
           ->getBody();
 
-  MatchSwitch<const int, std::vector<int>> Switch =
-      MatchSwitchBuilder<const int, std::vector<int>>()
+  ASTMatchSwitch<Stmt, const int, std::vector<int>> Switch =
+      ASTMatchSwitchBuilder<Stmt, const int, std::vector<int>>()
           .CaseOf<Stmt>(stmt(),
                         [](const Stmt *, const MatchFinder::MatchResult &,
                            const int &State) -> std::vector<int> {
@@ -222,3 +155,5 @@ TEST(MatchSwitchTest, ReturnNonVoid) {
   std::vector<int> Expected{1, 7, 3};
   EXPECT_EQ(Actual, Expected);
 }
+
+} // namespace


        


More information about the cfe-commits mailing list