1 //===---- ModernizeModuleTest.cpp - clang-tidy ----------------------------===//
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
7 //===----------------------------------------------------------------------===//
8 #include "ClangTidyTest.h"
9 #include "modernize/IntegralLiteralExpressionMatcher.h"
10 #include "clang/Lex/Lexer.h"
11 #include "gtest/gtest.h"
22 static std::vector
<Token
> tokenify(const char *Text
) {
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
;
32 End
= Lex
.LexFromRawLexer(Tok
);
33 Tokens
.push_back(Tok
);
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);
50 return Matcher
.largestLiteralSize();
51 return modernize::LiteralSize::Unknown
;
54 static const char *toString(modernize::LiteralSize Value
) {
56 case modernize::LiteralSize::Int
:
58 case modernize::LiteralSize::UnsignedInt
:
60 case modernize::LiteralSize::Long
:
62 case modernize::LiteralSize::UnsignedLong
:
63 return "UnsignedLong";
64 case modernize::LiteralSize::LongLong
:
66 case modernize::LiteralSize::UnsignedLongLong
:
67 return "UnsignedLongLong";
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
<< '\'';
88 modernize::LiteralSize Size
;
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
> {};
102 static const MatchParam MatchParams
[] = {
103 // Accept integral literals.
105 {true, true, "0177"},
106 {true, true, "0xdeadbeef"},
107 {true, true, "0b1011"},
109 // Reject non-integral literals.
110 {true, false, "1.23"},
111 {true, false, "0x1p3"},
112 {true, false, R
"("string
")"},
115 // Accept literals with these unary operators.
120 // Reject invalid unary operators.
126 // Accept valid binary operators.
132 {true, true, "1<<1"},
133 {true, true, "1>>1"},
134 {true, true, "1<=>1"},
137 {true, true, "1<=1"},
138 {true, true, "1>=1"},
139 {true, true, "1==1"},
140 {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.
156 {true, false, "1<<"},
157 {true, false, "1>>"},
158 {true, false, "1<=>"},
161 {true, false, "1<="},
162 {true, false, "1>="},
163 {true, false, "1=="},
164 {true, false, "1!="},
168 {true, false, "1&&"},
169 {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.
181 {true, false, "?:1"},
182 {true, false, "?1:"},
183 {true, false, "?1:1"},
185 {true, false, "1?1"},
186 {true, false, "1?:"},
187 {true, false, "1?1:"},
189 // Accept parenthesized expressions.
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
));