brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · 826b84c Raw
125 lines · cpp
1//===- unittests/Analysis/FlowSensitive/CFGMatchSwitchTest.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#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"10#include "clang/AST/ASTContext.h"11#include "clang/AST/Decl.h"12#include "clang/AST/Stmt.h"13#include "clang/Analysis/CFG.h"14#include "clang/Tooling/Tooling.h"15#include "llvm/ADT/StringRef.h"16#include "gtest/gtest.h"17 18using namespace clang;19using namespace dataflow;20using namespace ast_matchers;21 22namespace {23// State for tracking the number of matches on each kind of CFGElement by the24// CFGMatchSwitch. Currently only tracks CFGStmt and CFGInitializer.25struct CFGElementMatches {26  unsigned StmtMatches = 0;27  unsigned InitializerMatches = 0;28};29 30// Returns a match switch that counts the number of local variables31// (singly-declared) and fields initialized to the integer literal 42.32auto buildCFGMatchSwitch() {33  return CFGMatchSwitchBuilder<CFGElementMatches>()34      .CaseOfCFGStmt<DeclStmt>(35          declStmt(hasSingleDecl(36              varDecl(hasInitializer(integerLiteral(equals(42)))))),37          [](const DeclStmt *, const MatchFinder::MatchResult &,38             CFGElementMatches &Counter) { Counter.StmtMatches++; })39      .CaseOfCFGInit<CXXCtorInitializer>(40          cxxCtorInitializer(withInitializer(integerLiteral(equals(42)))),41          [](const CXXCtorInitializer *, const MatchFinder::MatchResult &,42             CFGElementMatches &Counter) { Counter.InitializerMatches++; })43      .Build();44}45 46// Runs the match switch `MS` on the control flow graph generated from `Code`,47// tracking information in state `S`. For simplicity, this test utility is48// restricted to CFGs with a single control flow block (excluding entry and49// exit blocks) - generated by `Code` with sequential flow (i.e. no branching).50//51// Requirements:52//53//  `Code` must contain a function named `f`, the body of this function will be54//  used to generate the CFG.55template <typename State>56void applySwitchToCode(CFGMatchSwitch<State> &MS, State &S,57                       llvm::StringRef Code) {58  auto Unit = tooling::buildASTFromCodeWithArgs(Code, {"-Wno-unused-value"});59  auto &Ctx = Unit->getASTContext();60  const auto *F = selectFirst<FunctionDecl>(61      "f", match(functionDecl(isDefinition(), hasName("f")).bind("f"), Ctx));62 63  CFG::BuildOptions BO;64  BO.AddInitializers = true;65 66  auto CFG = CFG::buildCFG(F, F->getBody(), &Ctx, BO);67  auto CFGBlock = *CFG->getEntry().succ_begin();68  for (auto &Elt : CFGBlock->Elements) {69    MS(Elt, Ctx, S);70  }71}72 73TEST(CFGMatchSwitchTest, NoInitializationTo42) {74  CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();75  CFGElementMatches Counter;76  applySwitchToCode(Switch, Counter, R"(77    void f() {78      42;79    }80  )");81  EXPECT_EQ(Counter.StmtMatches, 0u);82  EXPECT_EQ(Counter.InitializerMatches, 0u);83}84 85TEST(CFGMatchSwitchTest, SingleLocalVarInitializationTo42) {86  CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();87  CFGElementMatches Counter;88  applySwitchToCode(Switch, Counter, R"(89    void f() {90      int i = 42;91    }92  )");93  EXPECT_EQ(Counter.StmtMatches, 1u);94  EXPECT_EQ(Counter.InitializerMatches, 0u);95}96 97TEST(CFGMatchSwitchTest, SingleFieldInitializationTo42) {98  CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();99  CFGElementMatches Counter;100  applySwitchToCode(Switch, Counter, R"(101    struct f {102      int i;103      f(): i(42) {}104    };105  )");106  EXPECT_EQ(Counter.StmtMatches, 0u);107  EXPECT_EQ(Counter.InitializerMatches, 1u);108}109 110TEST(CFGMatchSwitchTest, LocalVarAndFieldInitializationTo42) {111  CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();112  CFGElementMatches Counter;113  applySwitchToCode(Switch, Counter, R"(114    struct f {115      int i;116      f(): i(42) {117        int j = 42;118      }119    };120  )");121  EXPECT_EQ(Counter.StmtMatches, 1u);122  EXPECT_EQ(Counter.InitializerMatches, 1u);123}124} // namespace125