https://github.com/HazardyKnusperkeks updated https://github.com/llvm/llvm-project/pull/164286
From b013c91606aa3620caecbd4b6f6fca9d4efbeb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <[email protected]> Date: Mon, 20 Oct 2025 01:31:04 +0200 Subject: [PATCH] [clang-format] Add xxxMaxDigitsRemove to IntegerLiteralSeparator This basically adds a Leave option for a specific range of literals. --- clang/docs/ClangFormatStyleOptions.rst | 47 +++++++++++- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/Format/Format.h | 75 ++++++++++++++++--- clang/lib/Format/Format.cpp | 21 ++++-- .../Format/IntegerLiteralSeparatorFixer.cpp | 42 ++++++++--- clang/unittests/Format/ConfigParseTest.cpp | 30 ++++++++ .../Format/IntegerLiteralSeparatorTest.cpp | 26 +++++-- 7 files changed, 208 insertions(+), 36 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 94d6f0d27619f..eb586752a99e5 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -4767,7 +4767,12 @@ the configuration (without a prefix: ``Auto``). You can also specify a minimum number of digits (``BinaryMinDigits``, ``DecimalMinDigits``, and ``HexMinDigits``) the integer literal must - have in order for the separators to be inserted. + have in order for the separators to be inserted, and a maximum number of + digits (``BinaryMaxDigitsNoSeparator``, ``DecimalMaxDigitsNoSeparator``, + and ``HexMaxDigitsNoSeparator``) until the separators are removed. This + divides the literals in 3 regions, always without separator (up until + including ``xxxMaxDigitsNoSeparator``), maybe with, or without separators + (up until excluding ``xxxMinDigits``), and finally always with separators. * ``int8_t Binary`` Format separators in binary literals. @@ -4787,6 +4792,19 @@ the configuration (without a prefix: ``Auto``). b1 = 0b101101; b2 = 0b1'101'101; + * ``int8_t BinaryMaxDigitsNoSeparator`` Remove separators in binary literals with a maximum number of digits. + + .. code-block:: text + + // Binary: 3 + // BinaryMinDigits: 7 + // BinaryMaxDigitsNoSeparator: 4 + b0 = 0b1011; // Always removed. + b1 = 0b101101; // Not added. + b2 = 0b101'101; // Not removed. + b3 = 0b1'101'101; // Always added. + b4 = 0b10'1101; // Corrected to 0b101'101. + * ``int8_t Decimal`` Format separators in decimal literals. .. code-block:: text @@ -4804,6 +4822,19 @@ the configuration (without a prefix: ``Auto``). d1 = 2023; d2 = 10'000; + * ``int8_t DecimalMaxDigitsNoSeparator`` Remove separators in decimal literals with a maximum number of digits. + + .. code-block:: text + + // Decimal: 3 + // DecimalMinDigits: 7 + // DecimalMaxDigitsNoSeparator: 4 + d0 = 2023; // Always removed. + d1 = 123456; // Not added. + d2 = 123'456; // Not removed. + d3 = 5'000'000; // Always added. + d4 = 1'23'45; // Corrected to 12'345. + * ``int8_t Hex`` Format separators in hexadecimal literals. .. code-block:: text @@ -4822,6 +4853,20 @@ the configuration (without a prefix: ``Auto``). h1 = 0xABCDE; h2 = 0xAB'CD'EF; + * ``int8_t HexMaxDigitsNoSeparator`` Remove separators in hexadecimal literals with a maximum number of + digits. + + .. code-block:: text + + // Hex: 2 + // HexMinDigits: 6 + // HexMaxDigitsNoSeparator: 4 + h0 = 0xAFFE; // Always removed. + h1 = 0xABCDE; // Not added. + h2 = 0xA'BC'DE; // Not removed. + h3 = 0xAB'CD'EF; // Always added. + h4 = 0xABCD'E; // Corrected to 0xA'BC'DE. + .. _JavaImportGroups: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f8a8fc3c0f450..17c633a9a481c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -687,6 +687,9 @@ clang-format ``AlignAfterOpenBracket`` option, and make ``AlignAfterOpenBracket`` a ``bool`` type. - Add ``AlignPPAndNotPP`` suboption to ``AlignTrailingComments``. +- Rename ``(Binary|Decimal|Hex)MinDigits`` to ``...MinDigitsInsert`` and add + ``(Binary|Decimal|Hex)MaxDigitsSeparator`` suboptions to + ``IntegerLiteralSeparator``. libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index b6f124f948b59..45584a0da90dc 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -3275,9 +3275,15 @@ struct FormatStyle { /// Hex: -1 /// \endcode /// - /// You can also specify a minimum number of digits (``BinaryMinDigits``, - /// ``DecimalMinDigits``, and ``HexMinDigits``) the integer literal must - /// have in order for the separators to be inserted. + /// You can also specify a minimum number of digits + /// (``BinaryMinDigitsInsert``, ``DecimalMinDigitsInsert``, and + /// ``HexMinDigitsInsert``) the integer literal must have in order for the + /// separators to be inserted, and a maximum number of digits + /// (``BinaryMaxDigitsRemove``, ``DecimalMaxDigitsRemove``, and + /// ``HexMaxDigitsRemove``) until the separators are removed. This divides the + /// literals in 3 regions, always without separator (up until including + /// ``xxxMaxDigitsRemove``), maybe with, or without separators (up until + /// excluding ``xxxMinDigitsInsert``), and finally always with separators. struct IntegerLiteralSeparatorStyle { /// Format separators in binary literals. /// \code{.text} @@ -3290,11 +3296,23 @@ struct FormatStyle { /// Format separators in binary literals with a minimum number of digits. /// \code{.text} /// // Binary: 3 - /// // BinaryMinDigits: 7 + /// // BinaryMinDigitsInsert: 7 /// b1 = 0b101101; /// b2 = 0b1'101'101; /// \endcode - int8_t BinaryMinDigits; + int8_t BinaryMinDigitsInsert; + /// Remove separators in binary literals with a maximum number of digits. + /// \code{.text} + /// // Binary: 3 + /// // BinaryMinDigitsInsert: 7 + /// // BinaryMaxDigitsRemove: 4 + /// b0 = 0b1011; // Always removed. + /// b1 = 0b101101; // Not added. + /// b2 = 0b1'01'101; // Not removed, not corrected. + /// b3 = 0b1'101'101; // Always added. + /// b4 = 0b10'1101; // Corrected to 0b101'101. + /// \endcode + int8_t BinaryMaxDigitsRemove; /// Format separators in decimal literals. /// \code{.text} /// /* -1: */ d = 18446744073709550592ull; @@ -3305,11 +3323,23 @@ struct FormatStyle { /// Format separators in decimal literals with a minimum number of digits. /// \code{.text} /// // Decimal: 3 - /// // DecimalMinDigits: 5 + /// // DecimalMinDigitsInsert: 5 /// d1 = 2023; /// d2 = 10'000; /// \endcode - int8_t DecimalMinDigits; + int8_t DecimalMinDigitsInsert; + /// Remove separators in decimal literals with a maximum number of digits. + /// \code{.text} + /// // Decimal: 3 + /// // DecimalMinDigitsInsert: 7 + /// // DecimalMaxDigitsRemove: 4 + /// d0 = 2023; // Always removed. + /// d1 = 123456; // Not added. + /// d2 = 1'23'456; // Not removed, not corrected. + /// d3 = 5'000'000; // Always added. + /// d4 = 1'23'45; // Corrected to 12'345. + /// \endcode + int8_t DecimalMaxDigitsRemove; /// Format separators in hexadecimal literals. /// \code{.text} /// /* -1: */ h = 0xDEADBEEFDEADBEEFuz; @@ -3321,15 +3351,36 @@ struct FormatStyle { /// digits. /// \code{.text} /// // Hex: 2 - /// // HexMinDigits: 6 + /// // HexMinDigitsInsert: 6 /// h1 = 0xABCDE; /// h2 = 0xAB'CD'EF; /// \endcode - int8_t HexMinDigits; + int8_t HexMinDigitsInsert; + /// Remove separators in hexadecimal literals with a maximum number of + /// digits. + /// \code{.text} + /// // Hex: 2 + /// // HexMinDigitsInsert: 6 + /// // HexMaxDigitsRemove: 4 + /// h0 = 0xAFFE; // Always removed. + /// h1 = 0xABCDE; // Not added. + /// h2 = 0xABC'DE; // Not removed, not corrected. + /// h3 = 0xAB'CD'EF; // Always added. + /// h4 = 0xABCD'E; // Corrected to 0xA'BC'DE. + /// \endcode + int8_t HexMaxDigitsRemove; bool operator==(const IntegerLiteralSeparatorStyle &R) const { - return Binary == R.Binary && BinaryMinDigits == R.BinaryMinDigits && - Decimal == R.Decimal && DecimalMinDigits == R.DecimalMinDigits && - Hex == R.Hex && HexMinDigits == R.HexMinDigits; + return Binary == R.Binary && + BinaryMinDigitsInsert == R.BinaryMinDigitsInsert && + BinaryMaxDigitsRemove == R.BinaryMaxDigitsRemove && + Decimal == R.Decimal && + DecimalMinDigitsInsert == R.DecimalMinDigitsInsert && + DecimalMaxDigitsRemove == R.DecimalMaxDigitsRemove && + Hex == R.Hex && HexMinDigitsInsert == R.HexMinDigitsInsert && + HexMaxDigitsRemove == R.HexMaxDigitsRemove; + } + bool operator!=(const IntegerLiteralSeparatorStyle &R) const { + return !operator==(R); } }; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 9bbb33cb14502..f0e9aff2fd21a 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -405,11 +405,19 @@ struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> { template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> { static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) { IO.mapOptional("Binary", Base.Binary); - IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits); + IO.mapOptional("BinaryMinDigitsInsert", Base.BinaryMinDigitsInsert); + IO.mapOptional("BinaryMaxDigitsRemove", Base.BinaryMaxDigitsRemove); IO.mapOptional("Decimal", Base.Decimal); - IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits); + IO.mapOptional("DecimalMinDigitsInsert", Base.DecimalMinDigitsInsert); + IO.mapOptional("DecimalMaxDigitsRemove", Base.DecimalMaxDigitsRemove); IO.mapOptional("Hex", Base.Hex); - IO.mapOptional("HexMinDigits", Base.HexMinDigits); + IO.mapOptional("HexMinDigitsInsert", Base.HexMinDigitsInsert); + IO.mapOptional("HexMaxDigitsRemove", Base.HexMaxDigitsRemove); + + // For backward compatibility. + IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigitsInsert); + IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigitsInsert); + IO.mapOptional("HexMinDigits", Base.HexMinDigitsInsert); } }; @@ -1758,10 +1766,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.InsertBraces = false; LLVMStyle.InsertNewlineAtEOF = false; LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; - LLVMStyle.IntegerLiteralSeparator = { - /*Binary=*/0, /*BinaryMinDigits=*/0, - /*Decimal=*/0, /*DecimalMinDigits=*/0, - /*Hex=*/0, /*HexMinDigits=*/0}; + LLVMStyle.IntegerLiteralSeparator = {}; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; LLVMStyle.JavaScriptWrapImports = true; LLVMStyle.KeepEmptyLines = { @@ -2183,7 +2188,7 @@ FormatStyle getClangFormatStyle() { Style.InsertBraces = true; Style.InsertNewlineAtEOF = true; Style.IntegerLiteralSeparator.Decimal = 3; - Style.IntegerLiteralSeparator.DecimalMinDigits = 5; + Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5; Style.LineEnding = FormatStyle::LE_LF; Style.RemoveBracesLLVM = true; Style.RemoveEmptyLinesInUnwrappedLines = true; diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp index b51991bfeff4b..0cc22853ea5db 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp @@ -72,11 +72,25 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env, if (SkipBinary && SkipDecimal && SkipHex) return {}; - const auto BinaryMinDigits = - std::max((int)Option.BinaryMinDigits, Binary + 1); - const auto DecimalMinDigits = - std::max((int)Option.DecimalMinDigits, Decimal + 1); - const auto HexMinDigits = std::max((int)Option.HexMinDigits, Hex + 1); + auto CalcMinAndMax = [](int Digits, int MinDigitsInsert, + int MaxDigitsRemove) { + std::pair<int, int> Ret; + Ret.first = std::max(MinDigitsInsert, Digits + 1); + if (Ret.first == 0) + Ret.second = 0; + else if (MaxDigitsRemove <= 0) + Ret.second = Ret.first - 1; + else + Ret.second = std::min(MaxDigitsRemove, Ret.first - 1); + return Ret; + }; + + const auto [BinaryMinDigitsInsert, BinaryMaxDigitsRemove] = CalcMinAndMax( + Binary, Option.BinaryMinDigitsInsert, Option.BinaryMaxDigitsRemove); + const auto [DecimalMinDigitsInsert, DecimalMaxDigitsRemove] = CalcMinAndMax( + Decimal, Option.DecimalMinDigitsInsert, Option.DecimalMaxDigitsRemove); + const auto [HexMinDigitsInsert, HexMaxDigitsRemove] = + CalcMinAndMax(Hex, Option.HexMinDigitsInsert, Option.HexMaxDigitsRemove); const auto &SourceMgr = Env.getSourceManager(); AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges()); @@ -138,20 +152,28 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env, Text = Text.substr(Start, Length); } auto DigitsPerGroup = Decimal; - auto MinDigits = DecimalMinDigits; + auto MinDigitsInsert = DecimalMinDigitsInsert; + auto MaxDigitsRemove = DecimalMaxDigitsRemove; if (IsBase2) { DigitsPerGroup = Binary; - MinDigits = BinaryMinDigits; + MinDigitsInsert = BinaryMinDigitsInsert; + MaxDigitsRemove = BinaryMaxDigitsRemove; } else if (IsBase16) { DigitsPerGroup = Hex; - MinDigits = HexMinDigits; + MinDigitsInsert = HexMinDigitsInsert; + MaxDigitsRemove = HexMaxDigitsRemove; } const auto SeparatorCount = Text.count(Separator); const int DigitCount = Length - SeparatorCount; - const bool RemoveSeparator = DigitsPerGroup < 0 || DigitCount < MinDigits; + const bool RemoveSeparator = + DigitsPerGroup < 0 || DigitCount <= MaxDigitsRemove; + const bool AddSeparator = + DigitsPerGroup > 0 && DigitCount >= MinDigitsInsert; + if (!RemoveSeparator && !AddSeparator) + continue; if (RemoveSeparator && SeparatorCount == 0) continue; - if (!RemoveSeparator && SeparatorCount > 0 && + if (AddSeparator && SeparatorCount > 0 && checkSeparator(Text, DigitsPerGroup)) { continue; } diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index d578fa7a1a1e8..fec1c48c448d2 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -1164,6 +1164,36 @@ TEST(ConfigParseTest, ParsesConfiguration) { FormatStyle::BLS_Block); CHECK_PARSE("Cpp11BracedListStyle: true", Cpp11BracedListStyle, FormatStyle::BLS_AlignFirstComment); + + constexpr FormatStyle::IntegerLiteralSeparatorStyle + ExpectedIntegerLiteralSeparatorStyle{/*Binary=*/2, + /*BinaryMinDigitInsert=*/5, + /*BinaryMaxDigitRemove=*/2, + /*Decimal=*/6, + /*DecimalMinDigitInsert=*/6, + /*DecimalMaxDigitRemove=*/3, + /*Hex=*/4, + /*HexMinDigitInsert=*/2, + /*HexMaxDigitRemove=*/1}; + CHECK_PARSE("IntegerLiteralSeparator:\n" + " Binary: 2\n" + " BinaryMinDigitsInsert: 5\n" + " BinaryMaxDigitsRemove: 2\n" + " Decimal: 6\n" + " DecimalMinDigitsInsert: 6\n" + " DecimalMaxDigitsRemove: 3\n" + " Hex: 4\n" + " HexMinDigitsInsert: 2\n" + " HexMaxDigitsRemove: 1", + IntegerLiteralSeparator, ExpectedIntegerLiteralSeparatorStyle); + + // Backward compatibility: + CHECK_PARSE_NESTED_VALUE("BinaryMinDigits: 6", IntegerLiteralSeparator, + BinaryMinDigitsInsert, 6); + CHECK_PARSE_NESTED_VALUE("DecimalMinDigits: 5", IntegerLiteralSeparator, + DecimalMinDigitsInsert, 5); + CHECK_PARSE_NESTED_VALUE("HexMinDigits: 5", IntegerLiteralSeparator, + HexMinDigitsInsert, 5); } TEST(ConfigParseTest, ParsesConfigurationWithLanguages) { diff --git a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp index 53b6dd8efadff..fdcdda909b8da 100644 --- a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp +++ b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp @@ -137,34 +137,34 @@ TEST_F(IntegerLiteralSeparatorTest, UnderscoreAsSeparator) { verifyFormat("o = 0o400000000000000003n;", Style); } -TEST_F(IntegerLiteralSeparatorTest, MinDigits) { +TEST_F(IntegerLiteralSeparatorTest, MinDigitsInsert) { FormatStyle Style = getLLVMStyle(); Style.IntegerLiteralSeparator.Binary = 3; Style.IntegerLiteralSeparator.Decimal = 3; Style.IntegerLiteralSeparator.Hex = 2; - Style.IntegerLiteralSeparator.BinaryMinDigits = 7; + Style.IntegerLiteralSeparator.BinaryMinDigitsInsert = 7; verifyFormat("b1 = 0b101101;\n" "b2 = 0b1'101'101;", "b1 = 0b101'101;\n" "b2 = 0b1101101;", Style); - Style.IntegerLiteralSeparator.DecimalMinDigits = 5; + Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5; verifyFormat("d1 = 2023;\n" "d2 = 10'000;", "d1 = 2'023;\n" "d2 = 100'00;", Style); - Style.IntegerLiteralSeparator.DecimalMinDigits = 3; + Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 3; verifyFormat("d1 = 123;\n" "d2 = 1'234;", "d1 = 12'3;\n" "d2 = 12'34;", Style); - Style.IntegerLiteralSeparator.HexMinDigits = 6; + Style.IntegerLiteralSeparator.HexMinDigitsInsert = 6; verifyFormat("h1 = 0xABCDE;\n" "h2 = 0xAB'CD'EF;", "h1 = 0xA'BC'DE;\n" @@ -243,6 +243,22 @@ TEST_F(IntegerLiteralSeparatorTest, FloatingPoint) { Style); } +TEST_F(IntegerLiteralSeparatorTest, MaxDigitsRemove) { + auto Style = getLLVMStyle(); + Style.IntegerLiteralSeparator.Decimal = 3; + Style.IntegerLiteralSeparator.DecimalMaxDigitsRemove = 4; + Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 7; + verifyFormat("d0 = 2023;\n" + "d1 = 123456;\n" + "d2 = 1234'56;\n" + "d3 = 5'000'000;", + "d0 = 20'2'3;\n" + "d1 = 123456;\n" + "d2 = 1234'56;\n" + "d3 = 5000000;", + Style); +} + } // namespace } // namespace test } // namespace format _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
