[clang-format] Fix a bug in aligning comments above PPDirective (#72791)
[llvm-project.git] / clang / unittests / Analysis / FlowSensitive / MatchSwitchTest.cpp
blobeec1c704dbbb9544083728cbd14b120a12521dc0
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-exception
6 //
7 //===----------------------------------------------------------------------===//
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>
26 using namespace clang;
27 using namespace dataflow;
28 using namespace ast_matchers;
30 namespace {
32 TEST(MatchSwitchTest, Stmts) {
33 std::string Code = R"(
34 void Foo();
35 void Bar();
36 void f() {
37 int X = 1;
38 Foo();
39 Bar();
41 )";
42 auto Unit = tooling::buildASTFromCode(Code);
43 auto &Ctx = Unit->getASTContext();
45 llvm::StringRef XStr = "X";
46 llvm::StringRef FooStr = "Foo";
47 llvm::StringRef BarStr = "Bar";
49 auto XMatcher = declStmt(hasSingleDecl(varDecl(hasName(XStr))));
50 auto FooMatcher = callExpr(callee(functionDecl(hasName(FooStr))));
51 auto BarMatcher = callExpr(callee(functionDecl(hasName(BarStr))));
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;
65 // State modified from the first case of the switch
66 const auto *X = selectFirst<Stmt>(XStr, match(XMatcher.bind(XStr), Ctx));
67 MS(*X, Ctx, State);
68 EXPECT_EQ(State, XStr);
70 // State modified from the second case of the switch
71 const auto *Foo =
72 selectFirst<Stmt>(FooStr, match(FooMatcher.bind(FooStr), Ctx));
73 MS(*Foo, Ctx, State);
74 EXPECT_EQ(State, FooStr);
76 // State unmodified, no case defined for calling Bar
77 const auto *Bar =
78 selectFirst<Stmt>(BarStr, match(BarMatcher.bind(BarStr), Ctx));
79 MS(*Bar, Ctx, State);
80 EXPECT_EQ(State, FooStr);
83 TEST(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) {}
91 )";
92 auto Unit = tooling::buildASTFromCode(Code);
93 auto &Ctx = Unit->getASTContext();
95 llvm::StringRef IStr = "i";
96 llvm::StringRef JStr = "j";
97 llvm::StringRef ZStr = "z";
99 auto InitI = cxxCtorInitializer(forField(hasName(IStr)));
100 auto InitJ = cxxCtorInitializer(forField(hasName(JStr)));
101 auto InitZ = cxxCtorInitializer(forField(hasName(ZStr)));
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;
116 // State modified from the first case of the switch
117 const auto *I =
118 selectFirst<CXXCtorInitializer>(IStr, match(InitI.bind(IStr), Ctx));
119 MS(*I, Ctx, State);
120 EXPECT_EQ(State, IStr);
122 // State modified from the second case of the switch
123 const auto *J =
124 selectFirst<CXXCtorInitializer>(JStr, match(InitJ.bind(JStr), Ctx));
125 MS(*J, Ctx, State);
126 EXPECT_EQ(State, JStr);
128 // State unmodified, no case defined for the initializer of z
129 const auto *Z =
130 selectFirst<CXXCtorInitializer>(ZStr, match(InitZ.bind(ZStr), Ctx));
131 MS(*Z, Ctx, State);
132 EXPECT_EQ(State, JStr);
135 TEST(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();
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};
153 .Build();
154 std::vector<int> Actual = Switch(*S, Context, 7);
155 std::vector<int> Expected{1, 7, 3};
156 EXPECT_EQ(Actual, Expected);
159 } // namespace