1//===- unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a test for the transferBranch function of the
10// TypeErasedDataflowAnalysis.
11//
12//===----------------------------------------------------------------------===//
13
14#include "TestingSupport.h"
15#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
16#include "clang/Tooling/Tooling.h"
17#include "llvm/Support/Error.h"
18#include "llvm/Testing/Annotations/Annotations.h"
19#include "llvm/Testing/Support/Error.h"
20#include "gtest/gtest.h"
21#include <optional>
22
23namespace clang::dataflow::test {
24namespace {
25
26using namespace ast_matchers;
27
28struct TestLattice {
29 std::optional<bool> Branch;
30 static TestLattice bottom() { return {}; }
31
32 // Does not matter for this test, but we must provide some definition of join.
33 LatticeJoinEffect join(const TestLattice &Other) {
34 return LatticeJoinEffect::Unchanged;
35 }
36 friend bool operator==(const TestLattice &Lhs, const TestLattice &Rhs) {
37 return Lhs.Branch == Rhs.Branch;
38 }
39};
40
41class TestPropagationAnalysis
42 : public DataflowAnalysis<TestPropagationAnalysis, TestLattice> {
43public:
44 explicit TestPropagationAnalysis(ASTContext &Context)
45 : DataflowAnalysis<TestPropagationAnalysis, TestLattice>(Context) {}
46 static TestLattice initialElement() { return TestLattice::bottom(); }
47 void transfer(const CFGElement &, TestLattice &, Environment &) {}
48 void transferBranch(bool Branch, const Stmt *S, TestLattice &L,
49 Environment &Env) {
50 L.Branch = Branch;
51 }
52};
53
54using ::testing::UnorderedElementsAre;
55
56template <typename Matcher>
57void runDataflow(llvm::StringRef Code, Matcher VerifyResults,
58 LangStandard::Kind Std = LangStandard::lang_cxx17,
59 llvm::StringRef TargetFun = "fun") {
60 using ast_matchers::hasName;
61 ASSERT_THAT_ERROR(
62 checkDataflow<TestPropagationAnalysis>(
63 AnalysisInputs<TestPropagationAnalysis>(
64 Code, hasName(TargetFun),
65 [](ASTContext &C, Environment &) {
66 return TestPropagationAnalysis(C);
67 })
68 .withASTBuildArgs(
69 {"-fsyntax-only", "-fno-delayed-template-parsing",
70 "-std=" +
71 std::string(LangStandard::getLangStandardForKind(Std)
72 .getName())}),
73 VerifyResults),
74 llvm::Succeeded());
75}
76
77template <typename LatticeT>
78const LatticeT &getLatticeAtAnnotation(
79 const llvm::StringMap<DataflowAnalysisState<LatticeT>> &AnnotationStates,
80 llvm::StringRef Annotation) {
81 auto It = AnnotationStates.find(Annotation);
82 assert(It != AnnotationStates.end());
83 return It->getValue().Lattice;
84}
85
86TEST(TransferBranchTest, IfElse) {
87 std::string Code = R"(
88 void fun(int a) {
89 if (a > 0) {
90 (void)1;
91 // [[p]]
92 } else {
93 (void)0;
94 // [[q]]
95 }
96 }
97 )";
98 runDataflow(
99 Code,
100 VerifyResults: [](const llvm::StringMap<DataflowAnalysisState<TestLattice>> &Results,
101 const AnalysisOutputs &) {
102 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p", "q"));
103
104 const TestLattice &LP = getLatticeAtAnnotation(AnnotationStates: Results, Annotation: "p");
105 EXPECT_THAT(LP.Branch, std::make_optional(true));
106
107 const TestLattice &LQ = getLatticeAtAnnotation(AnnotationStates: Results, Annotation: "q");
108 EXPECT_THAT(LQ.Branch, std::make_optional(false));
109 },
110 Std: LangStandard::lang_cxx17);
111}
112
113} // namespace
114} // namespace clang::dataflow::test
115

source code of clang/unittests/Analysis/FlowSensitive/TransferBranchTest.cpp