Bump version to 19.1.0 (final)
[llvm-project.git] / clang-tools-extra / unittests / clang-tidy / ModernizeModuleTest.cpp
blob4a8c1c3e5f3126ae394b83b30a97e6ffa8b6babd
1 //===---- ModernizeModuleTest.cpp - clang-tidy ----------------------------===//
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 #include "ClangTidyTest.h"
9 #include "modernize/IntegralLiteralExpressionMatcher.h"
10 #include "clang/Lex/Lexer.h"
11 #include "gtest/gtest.h"
13 #include <cstring>
14 #include <iterator>
15 #include <string>
16 #include <vector>
18 namespace clang {
19 namespace tidy {
20 namespace test {
22 static std::vector<Token> tokenify(const char *Text) {
23 LangOptions LangOpts;
24 std::vector<std::string> Includes;
25 LangOptions::setLangDefaults(LangOpts, Language::CXX, llvm::Triple(),
26 Includes, LangStandard::lang_cxx20);
27 Lexer Lex(SourceLocation{}, LangOpts, Text, Text, Text + std::strlen(Text));
28 std::vector<Token> Tokens;
29 bool End = false;
30 while (!End) {
31 Token Tok;
32 End = Lex.LexFromRawLexer(Tok);
33 Tokens.push_back(Tok);
36 return Tokens;
39 static bool matchText(const char *Text, bool AllowComma) {
40 std::vector<Token> Tokens{tokenify(Text)};
41 modernize::IntegralLiteralExpressionMatcher Matcher(Tokens, AllowComma);
43 return Matcher.match();
46 static modernize::LiteralSize sizeText(const char *Text) {
47 std::vector<Token> Tokens{tokenify(Text)};
48 modernize::IntegralLiteralExpressionMatcher Matcher(Tokens, true);
49 if (Matcher.match())
50 return Matcher.largestLiteralSize();
51 return modernize::LiteralSize::Unknown;
54 static const char *toString(modernize::LiteralSize Value) {
55 switch (Value) {
56 case modernize::LiteralSize::Int:
57 return "Int";
58 case modernize::LiteralSize::UnsignedInt:
59 return "UnsignedInt";
60 case modernize::LiteralSize::Long:
61 return "Long";
62 case modernize::LiteralSize::UnsignedLong:
63 return "UnsignedLong";
64 case modernize::LiteralSize::LongLong:
65 return "LongLong";
66 case modernize::LiteralSize::UnsignedLongLong:
67 return "UnsignedLongLong";
68 default:
69 return "Unknown";
73 namespace {
75 struct MatchParam {
76 bool AllowComma;
77 bool Matched;
78 const char *Text;
80 friend std::ostream &operator<<(std::ostream &Str, const MatchParam &Value) {
81 return Str << "Allow operator,: " << std::boolalpha << Value.AllowComma
82 << ", Matched: " << std::boolalpha << Value.Matched
83 << ", Text: '" << Value.Text << '\'';
87 struct SizeParam {
88 modernize::LiteralSize Size;
89 const char *Text;
91 friend std::ostream &operator<<(std::ostream &Str, const SizeParam &Value) {
92 return Str << "Size: " << toString(Value.Size) << ", Text: '" << Value.Text << '\'';
96 class MatcherTest : public ::testing::TestWithParam<MatchParam> {};
98 class SizeTest : public ::testing::TestWithParam<SizeParam> {};
100 } // namespace
102 static const MatchParam MatchParams[] = {
103 // Accept integral literals.
104 {true, true, "1"},
105 {true, true, "0177"},
106 {true, true, "0xdeadbeef"},
107 {true, true, "0b1011"},
108 {true, true, "'c'"},
109 // Reject non-integral literals.
110 {true, false, "1.23"},
111 {true, false, "0x1p3"},
112 {true, false, R"("string")"},
113 {true, false, "1i"},
115 // Accept literals with these unary operators.
116 {true, true, "-1"},
117 {true, true, "+1"},
118 {true, true, "~1"},
119 {true, true, "!1"},
120 // Reject invalid unary operators.
121 {true, false, "1-"},
122 {true, false, "1+"},
123 {true, false, "1~"},
124 {true, false, "1!"},
126 // Accept valid binary operators.
127 {true, true, "1+1"},
128 {true, true, "1-1"},
129 {true, true, "1*1"},
130 {true, true, "1/1"},
131 {true, true, "1%2"},
132 {true, true, "1<<1"},
133 {true, true, "1>>1"},
134 {true, true, "1<=>1"},
135 {true, true, "1<1"},
136 {true, true, "1>1"},
137 {true, true, "1<=1"},
138 {true, true, "1>=1"},
139 {true, true, "1==1"},
140 {true, true, "1!=1"},
141 {true, true, "1&1"},
142 {true, true, "1^1"},
143 {true, true, "1|1"},
144 {true, true, "1&&1"},
145 {true, true, "1||1"},
146 {true, true, "1+ +1"}, // A space is needed to avoid being tokenized as ++ or --.
147 {true, true, "1- -1"},
148 // Comma is only valid when inside parentheses.
149 {true, true, "(1,1)"},
150 // Reject invalid binary operators.
151 {true, false, "1+"},
152 {true, false, "1-"},
153 {true, false, "1*"},
154 {true, false, "1/"},
155 {true, false, "1%"},
156 {true, false, "1<<"},
157 {true, false, "1>>"},
158 {true, false, "1<=>"},
159 {true, false, "1<"},
160 {true, false, "1>"},
161 {true, false, "1<="},
162 {true, false, "1>="},
163 {true, false, "1=="},
164 {true, false, "1!="},
165 {true, false, "1&"},
166 {true, false, "1^"},
167 {true, false, "1|"},
168 {true, false, "1&&"},
169 {true, false, "1||"},
170 {true, false, "1,"},
171 {true, false, ",1"},
172 {true, false, "1,1"},
174 // Accept valid ternary operators.
175 {true, true, "1?1:1"},
176 {true, true, "1?:1"}, // A gcc extension treats x ? : y as x ? x : y.
177 // Reject invalid ternary operators.
178 {true, false, "?"},
179 {true, false, "?1"},
180 {true, false, "?:"},
181 {true, false, "?:1"},
182 {true, false, "?1:"},
183 {true, false, "?1:1"},
184 {true, false, "1?"},
185 {true, false, "1?1"},
186 {true, false, "1?:"},
187 {true, false, "1?1:"},
189 // Accept parenthesized expressions.
190 {true, true, "(1)"},
191 {true, true, "((+1))"},
192 {true, true, "((+(1)))"},
193 {true, true, "(-1)"},
194 {true, true, "-(1)"},
195 {true, true, "(+1)"},
196 {true, true, "((+1))"},
197 {true, true, "+(1)"},
198 {true, true, "(~1)"},
199 {true, true, "~(1)"},
200 {true, true, "(!1)"},
201 {true, true, "!(1)"},
202 {true, true, "(1+1)"},
203 {true, true, "(1-1)"},
204 {true, true, "(1*1)"},
205 {true, true, "(1/1)"},
206 {true, true, "(1%2)"},
207 {true, true, "(1<<1)"},
208 {true, true, "(1>>1)"},
209 {true, true, "(1<=>1)"},
210 {true, true, "(1<1)"},
211 {true, true, "(1>1)"},
212 {true, true, "(1<=1)"},
213 {true, true, "(1>=1)"},
214 {true, true, "(1==1)"},
215 {true, true, "(1!=1)"},
216 {true, true, "(1&1)"},
217 {true, true, "(1^1)"},
218 {true, true, "(1|1)"},
219 {true, true, "(1&&1)"},
220 {true, true, "(1||1)"},
221 {true, true, "(1?1:1)"},
223 // Accept more complicated "chained" expressions.
224 {true, true, "1+1+1"},
225 {true, true, "1+1+1+1"},
226 {true, true, "1+1+1+1+1"},
227 {true, true, "1*1*1"},
228 {true, true, "1*1*1*1"},
229 {true, true, "1*1*1*1*1"},
230 {true, true, "1<<1<<1"},
231 {true, true, "4U>>1>>1"},
232 {true, true, "1<1<1"},
233 {true, true, "1>1>1"},
234 {true, true, "1<=1<=1"},
235 {true, true, "1>=1>=1"},
236 {true, true, "1==1==1"},
237 {true, true, "1!=1!=1"},
238 {true, true, "1&1&1"},
239 {true, true, "1^1^1"},
240 {true, true, "1|1|1"},
241 {true, true, "1&&1&&1"},
242 {true, true, "1||1||1"},
243 {true, true, "(1,1,1)"},
245 // Optionally reject comma operator
246 {false, false, "1,1"}
249 TEST_P(MatcherTest, MatchResult) {
250 const MatchParam &Param = GetParam();
252 EXPECT_TRUE(matchText(Param.Text, Param.AllowComma) == Param.Matched);
255 INSTANTIATE_TEST_SUITE_P(IntegralLiteralExpressionMatcherTests, MatcherTest,
256 ::testing::ValuesIn(MatchParams));
258 static const SizeParam SizeParams[] = {
259 {modernize::LiteralSize::Int, "1"},
260 {modernize::LiteralSize::UnsignedInt, "1U"},
261 {modernize::LiteralSize::Long, "1L"},
262 {modernize::LiteralSize::UnsignedLong, "1UL"},
263 {modernize::LiteralSize::UnsignedLong, "1LU"},
264 {modernize::LiteralSize::LongLong, "1LL"},
265 {modernize::LiteralSize::UnsignedLongLong, "1ULL"},
266 {modernize::LiteralSize::UnsignedLongLong, "1LLU"}};
268 TEST_P(SizeTest, TokenSize) {
269 EXPECT_EQ(sizeText(GetParam().Text), GetParam().Size);
272 INSTANTIATE_TEST_SUITE_P(IntegralLiteralExpressionMatcherTests, SizeTest,
273 ::testing::ValuesIn(SizeParams));
275 } // namespace test
276 } // namespace tidy
277 } // namespace clang