| //===---- ModernizeModuleTest.cpp - clang-tidy ----------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| #include "ClangTidyTest.h" |
| #include "modernize/IntegralLiteralExpressionMatcher.h" |
| #include "clang/Lex/Lexer.h" |
| #include "gtest/gtest.h" |
| |
| #include <cstring> |
| #include <iterator> |
| #include <string> |
| #include <vector> |
| |
| namespace clang { |
| namespace tidy { |
| namespace test { |
| |
| static std::vector<Token> tokenify(const char *Text) { |
| LangOptions LangOpts; |
| std::vector<std::string> Includes; |
| LangOptions::setLangDefaults(LangOpts, Language::CXX, llvm::Triple(), |
| Includes, LangStandard::lang_cxx20); |
| Lexer Lex(SourceLocation{}, LangOpts, Text, Text, Text + std::strlen(Text)); |
| std::vector<Token> Tokens; |
| bool End = false; |
| while (!End) { |
| Token Tok; |
| End = Lex.LexFromRawLexer(Tok); |
| Tokens.push_back(Tok); |
| } |
| |
| return Tokens; |
| } |
| |
| static bool matchText(const char *Text, bool AllowComma) { |
| std::vector<Token> Tokens{tokenify(Text)}; |
| modernize::IntegralLiteralExpressionMatcher Matcher(Tokens, AllowComma); |
| |
| return Matcher.match(); |
| } |
| |
| static modernize::LiteralSize sizeText(const char *Text) { |
| std::vector<Token> Tokens{tokenify(Text)}; |
| modernize::IntegralLiteralExpressionMatcher Matcher(Tokens, true); |
| if (Matcher.match()) |
| return Matcher.largestLiteralSize(); |
| return modernize::LiteralSize::Unknown; |
| } |
| |
| static const char *toString(modernize::LiteralSize Value) { |
| switch (Value) { |
| case modernize::LiteralSize::Int: |
| return "Int"; |
| case modernize::LiteralSize::UnsignedInt: |
| return "UnsignedInt"; |
| case modernize::LiteralSize::Long: |
| return "Long"; |
| case modernize::LiteralSize::UnsignedLong: |
| return "UnsignedLong"; |
| case modernize::LiteralSize::LongLong: |
| return "LongLong"; |
| case modernize::LiteralSize::UnsignedLongLong: |
| return "UnsignedLongLong"; |
| default: |
| return "Unknown"; |
| } |
| } |
| |
| namespace { |
| |
| struct MatchParam { |
| bool AllowComma; |
| bool Matched; |
| const char *Text; |
| |
| friend std::ostream &operator<<(std::ostream &Str, const MatchParam &Value) { |
| return Str << "Allow operator,: " << std::boolalpha << Value.AllowComma |
| << ", Matched: " << std::boolalpha << Value.Matched |
| << ", Text: '" << Value.Text << '\''; |
| } |
| }; |
| |
| struct SizeParam { |
| modernize::LiteralSize Size; |
| const char *Text; |
| |
| friend std::ostream &operator<<(std::ostream &Str, const SizeParam &Value) { |
| return Str << "Size: " << toString(Value.Size) << ", Text: '" << Value.Text << '\''; |
| } |
| }; |
| |
| class MatcherTest : public ::testing::TestWithParam<MatchParam> {}; |
| |
| class SizeTest : public ::testing::TestWithParam<SizeParam> {}; |
| |
| } // namespace |
| |
| static const MatchParam MatchParams[] = { |
| // Accept integral literals. |
| {true, true, "1"}, |
| {true, true, "0177"}, |
| {true, true, "0xdeadbeef"}, |
| {true, true, "0b1011"}, |
| {true, true, "'c'"}, |
| // Reject non-integral literals. |
| {true, false, "1.23"}, |
| {true, false, "0x1p3"}, |
| {true, false, R"("string")"}, |
| {true, false, "1i"}, |
| |
| // Accept literals with these unary operators. |
| {true, true, "-1"}, |
| {true, true, "+1"}, |
| {true, true, "~1"}, |
| {true, true, "!1"}, |
| // Reject invalid unary operators. |
| {true, false, "1-"}, |
| {true, false, "1+"}, |
| {true, false, "1~"}, |
| {true, false, "1!"}, |
| |
| // Accept valid binary operators. |
| {true, true, "1+1"}, |
| {true, true, "1-1"}, |
| {true, true, "1*1"}, |
| {true, true, "1/1"}, |
| {true, true, "1%2"}, |
| {true, true, "1<<1"}, |
| {true, true, "1>>1"}, |
| {true, true, "1<=>1"}, |
| {true, true, "1<1"}, |
| {true, true, "1>1"}, |
| {true, true, "1<=1"}, |
| {true, true, "1>=1"}, |
| {true, true, "1==1"}, |
| {true, true, "1!=1"}, |
| {true, true, "1&1"}, |
| {true, true, "1^1"}, |
| {true, true, "1|1"}, |
| {true, true, "1&&1"}, |
| {true, true, "1||1"}, |
| {true, true, "1+ +1"}, // A space is needed to avoid being tokenized as ++ or --. |
| {true, true, "1- -1"}, |
| // Comma is only valid when inside parentheses. |
| {true, true, "(1,1)"}, |
| // Reject invalid binary operators. |
| {true, false, "1+"}, |
| {true, false, "1-"}, |
| {true, false, "1*"}, |
| {true, false, "1/"}, |
| {true, false, "1%"}, |
| {true, false, "1<<"}, |
| {true, false, "1>>"}, |
| {true, false, "1<=>"}, |
| {true, false, "1<"}, |
| {true, false, "1>"}, |
| {true, false, "1<="}, |
| {true, false, "1>="}, |
| {true, false, "1=="}, |
| {true, false, "1!="}, |
| {true, false, "1&"}, |
| {true, false, "1^"}, |
| {true, false, "1|"}, |
| {true, false, "1&&"}, |
| {true, false, "1||"}, |
| {true, false, "1,"}, |
| {true, false, ",1"}, |
| {true, false, "1,1"}, |
| |
| // Accept valid ternary operators. |
| {true, true, "1?1:1"}, |
| {true, true, "1?:1"}, // A gcc extension treats x ? : y as x ? x : y. |
| // Reject invalid ternary operators. |
| {true, false, "?"}, |
| {true, false, "?1"}, |
| {true, false, "?:"}, |
| {true, false, "?:1"}, |
| {true, false, "?1:"}, |
| {true, false, "?1:1"}, |
| {true, false, "1?"}, |
| {true, false, "1?1"}, |
| {true, false, "1?:"}, |
| {true, false, "1?1:"}, |
| |
| // Accept parenthesized expressions. |
| {true, true, "(1)"}, |
| {true, true, "((+1))"}, |
| {true, true, "((+(1)))"}, |
| {true, true, "(-1)"}, |
| {true, true, "-(1)"}, |
| {true, true, "(+1)"}, |
| {true, true, "((+1))"}, |
| {true, true, "+(1)"}, |
| {true, true, "(~1)"}, |
| {true, true, "~(1)"}, |
| {true, true, "(!1)"}, |
| {true, true, "!(1)"}, |
| {true, true, "(1+1)"}, |
| {true, true, "(1-1)"}, |
| {true, true, "(1*1)"}, |
| {true, true, "(1/1)"}, |
| {true, true, "(1%2)"}, |
| {true, true, "(1<<1)"}, |
| {true, true, "(1>>1)"}, |
| {true, true, "(1<=>1)"}, |
| {true, true, "(1<1)"}, |
| {true, true, "(1>1)"}, |
| {true, true, "(1<=1)"}, |
| {true, true, "(1>=1)"}, |
| {true, true, "(1==1)"}, |
| {true, true, "(1!=1)"}, |
| {true, true, "(1&1)"}, |
| {true, true, "(1^1)"}, |
| {true, true, "(1|1)"}, |
| {true, true, "(1&&1)"}, |
| {true, true, "(1||1)"}, |
| {true, true, "(1?1:1)"}, |
| |
| // Accept more complicated "chained" expressions. |
| {true, true, "1+1+1"}, |
| {true, true, "1+1+1+1"}, |
| {true, true, "1+1+1+1+1"}, |
| {true, true, "1*1*1"}, |
| {true, true, "1*1*1*1"}, |
| {true, true, "1*1*1*1*1"}, |
| {true, true, "1<<1<<1"}, |
| {true, true, "4U>>1>>1"}, |
| {true, true, "1<1<1"}, |
| {true, true, "1>1>1"}, |
| {true, true, "1<=1<=1"}, |
| {true, true, "1>=1>=1"}, |
| {true, true, "1==1==1"}, |
| {true, true, "1!=1!=1"}, |
| {true, true, "1&1&1"}, |
| {true, true, "1^1^1"}, |
| {true, true, "1|1|1"}, |
| {true, true, "1&&1&&1"}, |
| {true, true, "1||1||1"}, |
| {true, true, "(1,1,1)"}, |
| |
| // Optionally reject comma operator |
| {false, false, "1,1"} |
| }; |
| |
| TEST_P(MatcherTest, MatchResult) { |
| const MatchParam &Param = GetParam(); |
| |
| EXPECT_TRUE(matchText(Param.Text, Param.AllowComma) == Param.Matched); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(IntegralLiteralExpressionMatcherTests, MatcherTest, |
| ::testing::ValuesIn(MatchParams)); |
| |
| static const SizeParam SizeParams[] = { |
| {modernize::LiteralSize::Int, "1"}, |
| {modernize::LiteralSize::UnsignedInt, "1U"}, |
| {modernize::LiteralSize::Long, "1L"}, |
| {modernize::LiteralSize::UnsignedLong, "1UL"}, |
| {modernize::LiteralSize::UnsignedLong, "1LU"}, |
| {modernize::LiteralSize::LongLong, "1LL"}, |
| {modernize::LiteralSize::UnsignedLongLong, "1ULL"}, |
| {modernize::LiteralSize::UnsignedLongLong, "1LLU"}}; |
| |
| TEST_P(SizeTest, TokenSize) { |
| EXPECT_EQ(sizeText(GetParam().Text), GetParam().Size); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(IntegralLiteralExpressionMatcherTests, SizeTest, |
| ::testing::ValuesIn(SizeParams)); |
| |
| } // namespace test |
| } // namespace tidy |
| } // namespace clang |