brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · eec1c70 Raw
160 lines · cpp
1//===- unittests/Analysis/FlowSensitive/MatchSwitchTest.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/MatchSwitch.h"10#include "clang/AST/ASTContext.h"11#include "clang/AST/Decl.h"12#include "clang/AST/DeclCXX.h"13#include "clang/AST/Expr.h"14#include "clang/AST/Stmt.h"15#include "clang/ASTMatchers/ASTMatchFinder.h"16#include "clang/ASTMatchers/ASTMatchers.h"17#include "clang/Tooling/Tooling.h"18#include "llvm/ADT/StringRef.h"19#include "gtest/gtest.h"20#include <cstdint>21#include <memory>22#include <ostream>23#include <string>24#include <utility>25 26using namespace clang;27using namespace dataflow;28using namespace ast_matchers;29 30namespace {31 32TEST(MatchSwitchTest, Stmts) {33  std::string Code = R"(34    void Foo();35    void Bar();36    void f() {37      int X = 1;38      Foo();39      Bar();40    }41  )";42  auto Unit = tooling::buildASTFromCode(Code);43  auto &Ctx = Unit->getASTContext();44 45  llvm::StringRef XStr = "X";46  llvm::StringRef FooStr = "Foo";47  llvm::StringRef BarStr = "Bar";48 49  auto XMatcher = declStmt(hasSingleDecl(varDecl(hasName(XStr))));50  auto FooMatcher = callExpr(callee(functionDecl(hasName(FooStr))));51  auto BarMatcher = callExpr(callee(functionDecl(hasName(BarStr))));52 53  ASTMatchSwitch<Stmt, llvm::StringRef> MS =54      ASTMatchSwitchBuilder<Stmt, llvm::StringRef>()55          .CaseOf<Stmt>(XMatcher,56                        [&XStr](const Stmt *, const MatchFinder::MatchResult &,57                                llvm::StringRef &State) { State = XStr; })58          .CaseOf<Stmt>(FooMatcher,59                        [&FooStr](const Stmt *,60                                  const MatchFinder::MatchResult &,61                                  llvm::StringRef &State) { State = FooStr; })62          .Build();63  llvm::StringRef State;64 65  // State modified from the first case of the switch66  const auto *X = selectFirst<Stmt>(XStr, match(XMatcher.bind(XStr), Ctx));67  MS(*X, Ctx, State);68  EXPECT_EQ(State, XStr);69 70  // State modified from the second case of the switch71  const auto *Foo =72      selectFirst<Stmt>(FooStr, match(FooMatcher.bind(FooStr), Ctx));73  MS(*Foo, Ctx, State);74  EXPECT_EQ(State, FooStr);75 76  // State unmodified, no case defined for calling Bar77  const auto *Bar =78      selectFirst<Stmt>(BarStr, match(BarMatcher.bind(BarStr), Ctx));79  MS(*Bar, Ctx, State);80  EXPECT_EQ(State, FooStr);81}82 83TEST(MatchSwitchTest, CtorInitializers) {84  std::string Code = R"(85    struct f {86      int i;87      int j;88      int z;89      f(): i(1), j(1), z(1) {}90    };91  )";92  auto Unit = tooling::buildASTFromCode(Code);93  auto &Ctx = Unit->getASTContext();94 95  llvm::StringRef IStr = "i";96  llvm::StringRef JStr = "j";97  llvm::StringRef ZStr = "z";98 99  auto InitI = cxxCtorInitializer(forField(hasName(IStr)));100  auto InitJ = cxxCtorInitializer(forField(hasName(JStr)));101  auto InitZ = cxxCtorInitializer(forField(hasName(ZStr)));102 103  ASTMatchSwitch<CXXCtorInitializer, llvm::StringRef> MS =104      ASTMatchSwitchBuilder<CXXCtorInitializer, llvm::StringRef>()105          .CaseOf<CXXCtorInitializer>(106              InitI, [&IStr](const CXXCtorInitializer *,107                             const MatchFinder::MatchResult &,108                             llvm::StringRef &State) { State = IStr; })109          .CaseOf<CXXCtorInitializer>(110              InitJ, [&JStr](const CXXCtorInitializer *,111                             const MatchFinder::MatchResult &,112                             llvm::StringRef &State) { State = JStr; })113          .Build();114  llvm::StringRef State;115 116  // State modified from the first case of the switch117  const auto *I =118      selectFirst<CXXCtorInitializer>(IStr, match(InitI.bind(IStr), Ctx));119  MS(*I, Ctx, State);120  EXPECT_EQ(State, IStr);121 122  // State modified from the second case of the switch123  const auto *J =124      selectFirst<CXXCtorInitializer>(JStr, match(InitJ.bind(JStr), Ctx));125  MS(*J, Ctx, State);126  EXPECT_EQ(State, JStr);127 128  // State unmodified, no case defined for the initializer of z129  const auto *Z =130      selectFirst<CXXCtorInitializer>(ZStr, match(InitZ.bind(ZStr), Ctx));131  MS(*Z, Ctx, State);132  EXPECT_EQ(State, JStr);133}134 135TEST(MatchSwitchTest, ReturnNonVoid) {136  auto Unit =137      tooling::buildASTFromCode("void f() { int x = 42; }", "input.cc",138                                std::make_shared<PCHContainerOperations>());139  auto &Context = Unit->getASTContext();140  const auto *S =141      selectFirst<FunctionDecl>(142          "f",143          match(functionDecl(isDefinition(), hasName("f")).bind("f"), Context))144          ->getBody();145 146  ASTMatchSwitch<Stmt, const int, std::vector<int>> Switch =147      ASTMatchSwitchBuilder<Stmt, const int, std::vector<int>>()148          .CaseOf<Stmt>(stmt(),149                        [](const Stmt *, const MatchFinder::MatchResult &,150                           const int &State) -> std::vector<int> {151                          return {1, State, 3};152                        })153          .Build();154  std::vector<int> Actual = Switch(*S, Context, 7);155  std::vector<int> Expected{1, 7, 3};156  EXPECT_EQ(Actual, Expected);157}158 159} // namespace160