[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