115 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines a test for the transferBranch function of the10// 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 TestPropagationAnalysis42 : 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 [](const llvm::StringMap<DataflowAnalysisState<TestLattice>> &Results,101 const AnalysisOutputs &) {102 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p", "q"));103 104 const TestLattice &LP = getLatticeAtAnnotation(Results, "p");105 EXPECT_THAT(LP.Branch, std::make_optional(true));106 107 const TestLattice &LQ = getLatticeAtAnnotation(Results, "q");108 EXPECT_THAT(LQ.Branch, std::make_optional(false));109 },110 LangStandard::lang_cxx17);111}112 113} // namespace114} // namespace clang::dataflow::test115