summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Pan <owenpiano@gmail.com>2023-03-28 21:59:05 -0700
committerTom Stellard <tstellar@redhat.com>2023-04-04 10:40:57 -0700
commit356cb7e0d01681ed4f1e7cdd494267c5b3b81ab1 (patch)
tree5e667cc8e74752be37e22e8bc88c105e70eaf522
parent6bf663061947954d54fe66cd25da2615c0cfd9cb (diff)
downloadllvm-356cb7e0d01681ed4f1e7cdd494267c5b3b81ab1.tar.gz
[clang-format] Add MinDigits suboptions to IntegerLiteralSeparator
Closes #61209. Differential Revision: https://reviews.llvm.org/D147111 (cherry picked from commit 253985d58caf95db8a84632d5a761b96fb7cd7d6)
-rw-r--r--clang/docs/ClangFormatStyleOptions.rst32
-rw-r--r--clang/include/clang/Format/Format.h39
-rw-r--r--clang/lib/Format/Format.cpp8
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.cpp42
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.h3
-rw-r--r--clang/unittests/Format/IntegerLiteralSeparatorTest.cpp35
6 files changed, 137 insertions, 22 deletions
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index da5af2645f18..3316b5d3cda2 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -3373,6 +3373,10 @@ the configuration (without a prefix: ``Auto``).
Decimal: 3
Hex: -1
+ 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.
+
* ``int8_t Binary`` Format separators in binary literals.
.. code-block:: text
@@ -3382,6 +3386,15 @@ the configuration (without a prefix: ``Auto``).
/* 3: */ b = 0b100'111'101'101;
/* 4: */ b = 0b1001'1110'1101;
+ * ``int8_t BinaryMinDigits`` Format separators in binary literals with a minimum number of digits.
+
+ .. code-block:: text
+
+ // Binary: 3
+ // BinaryMinDigits: 7
+ b1 = 0b101101;
+ b2 = 0b1'101'101;
+
* ``int8_t Decimal`` Format separators in decimal literals.
.. code-block:: text
@@ -3390,6 +3403,15 @@ the configuration (without a prefix: ``Auto``).
/* 0: */ d = 184467'440737'0'95505'92ull;
/* 3: */ d = 18'446'744'073'709'550'592ull;
+ * ``int8_t DecimalMinDigits`` Format separators in decimal literals with a minimum number of digits.
+
+ .. code-block:: text
+
+ // Decimal: 3
+ // DecimalMinDigits: 5
+ d1 = 2023;
+ d2 = 10'000;
+
* ``int8_t Hex`` Format separators in hexadecimal literals.
.. code-block:: text
@@ -3398,6 +3420,16 @@ the configuration (without a prefix: ``Auto``).
/* 0: */ h = 0xDEAD'BEEF'DE'AD'BEE'Fuz;
/* 2: */ h = 0xDE'AD'BE'EF'DE'AD'BE'EFuz;
+ * ``int8_t HexMinDigits`` Format separators in hexadecimal literals with a minimum number of
+ digits.
+
+ .. code-block:: text
+
+ // Hex: 2
+ // HexMinDigits: 6
+ h1 = 0xABCDE;
+ h2 = 0xAB'CD'EF;
+
.. _JavaImportGroups:
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 72efd3be1cc7..7a313460d888 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2500,6 +2500,10 @@ struct FormatStyle {
/// Decimal: 3
/// 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.
struct IntegerLiteralSeparatorStyle {
/// Format separators in binary literals.
/// \code{.text}
@@ -2509,6 +2513,14 @@ struct FormatStyle {
/// /* 4: */ b = 0b1001'1110'1101;
/// \endcode
int8_t Binary;
+ /// Format separators in binary literals with a minimum number of digits.
+ /// \code{.text}
+ /// // Binary: 3
+ /// // BinaryMinDigits: 7
+ /// b1 = 0b101101;
+ /// b2 = 0b1'101'101;
+ /// \endcode
+ int8_t BinaryMinDigits;
/// Format separators in decimal literals.
/// \code{.text}
/// /* -1: */ d = 18446744073709550592ull;
@@ -2516,6 +2528,14 @@ struct FormatStyle {
/// /* 3: */ d = 18'446'744'073'709'550'592ull;
/// \endcode
int8_t Decimal;
+ /// Format separators in decimal literals with a minimum number of digits.
+ /// \code{.text}
+ /// // Decimal: 3
+ /// // DecimalMinDigits: 5
+ /// d1 = 2023;
+ /// d2 = 10'000;
+ /// \endcode
+ int8_t DecimalMinDigits;
/// Format separators in hexadecimal literals.
/// \code{.text}
/// /* -1: */ h = 0xDEADBEEFDEADBEEFuz;
@@ -2523,6 +2543,20 @@ struct FormatStyle {
/// /* 2: */ h = 0xDE'AD'BE'EF'DE'AD'BE'EFuz;
/// \endcode
int8_t Hex;
+ /// Format separators in hexadecimal literals with a minimum number of
+ /// digits.
+ /// \code{.text}
+ /// // Hex: 2
+ /// // HexMinDigits: 6
+ /// h1 = 0xABCDE;
+ /// h2 = 0xAB'CD'EF;
+ /// \endcode
+ int8_t HexMinDigits;
+ 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;
+ }
};
/// Format integer literal separators (``'`` for C++ and ``_`` for C#, Java,
@@ -4212,10 +4246,7 @@ struct FormatStyle {
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
InsertBraces == R.InsertBraces &&
InsertNewlineAtEOF == R.InsertNewlineAtEOF &&
- IntegerLiteralSeparator.Binary == R.IntegerLiteralSeparator.Binary &&
- IntegerLiteralSeparator.Decimal ==
- R.IntegerLiteralSeparator.Decimal &&
- IntegerLiteralSeparator.Hex == R.IntegerLiteralSeparator.Hex &&
+ IntegerLiteralSeparator == R.IntegerLiteralSeparator &&
JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index f37c3f983635..0d3fde90ab38 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -348,8 +348,11 @@ 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("Decimal", Base.Decimal);
+ IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);
IO.mapOptional("Hex", Base.Hex);
+ IO.mapOptional("HexMinDigits", Base.HexMinDigits);
}
};
@@ -1392,7 +1395,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.InsertBraces = false;
LLVMStyle.InsertNewlineAtEOF = false;
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
- LLVMStyle.IntegerLiteralSeparator = {/*Binary=*/0, /*Decimal=*/0, /*Hex=*/0};
+ LLVMStyle.IntegerLiteralSeparator = {
+ /*Binary=*/0, /*BinaryMinDigits=*/0,
+ /*Decimal=*/0, /*DecimalMinDigits=*/0,
+ /*Hex=*/0, /*HexMinDigits=*/0};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
index 063951976458..44034e44adec 100644
--- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
@@ -69,6 +69,12 @@ 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);
+
const auto &SourceMgr = Env.getSourceManager();
AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges());
@@ -116,11 +122,6 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
(IsBase16 && Text.find_last_of(".pP") != StringRef::npos)) {
continue;
}
- if (((IsBase2 && Binary < 0) || (IsBase10 && Decimal < 0) ||
- (IsBase16 && Hex < 0)) &&
- Text.find(Separator) == StringRef::npos) {
- continue;
- }
const auto Start = Text[0] == '0' ? 2 : 0;
auto End = Text.find_first_of("uUlLzZn", Start);
if (End == StringRef::npos)
@@ -130,13 +131,25 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
Text = Text.substr(Start, Length);
}
auto DigitsPerGroup = Decimal;
- if (IsBase2)
+ auto MinDigits = DecimalMinDigits;
+ if (IsBase2) {
DigitsPerGroup = Binary;
- else if (IsBase16)
+ MinDigits = BinaryMinDigits;
+ } else if (IsBase16) {
DigitsPerGroup = Hex;
- if (DigitsPerGroup > 0 && checkSeparator(Text, DigitsPerGroup))
+ MinDigits = HexMinDigits;
+ }
+ const auto SeparatorCount = Text.count(Separator);
+ const int DigitCount = Length - SeparatorCount;
+ const bool RemoveSeparator = DigitsPerGroup < 0 || DigitCount < MinDigits;
+ if (RemoveSeparator && SeparatorCount == 0)
continue;
- const auto &Formatted = format(Text, DigitsPerGroup);
+ if (!RemoveSeparator && SeparatorCount > 0 &&
+ checkSeparator(Text, DigitsPerGroup)) {
+ continue;
+ }
+ const auto &Formatted =
+ format(Text, DigitsPerGroup, DigitCount, RemoveSeparator);
assert(Formatted != Text);
if (Start > 0)
Location = Location.getLocWithOffset(Start);
@@ -168,23 +181,20 @@ bool IntegerLiteralSeparatorFixer::checkSeparator(
}
std::string IntegerLiteralSeparatorFixer::format(const StringRef IntegerLiteral,
- int DigitsPerGroup) const {
+ int DigitsPerGroup,
+ int DigitCount,
+ bool RemoveSeparator) const {
assert(DigitsPerGroup != 0);
std::string Formatted;
- if (DigitsPerGroup < 0) {
+ if (RemoveSeparator) {
for (auto C : IntegerLiteral)
if (C != Separator)
Formatted.push_back(C);
return Formatted;
}
- int DigitCount = 0;
- for (auto C : IntegerLiteral)
- if (C != Separator)
- ++DigitCount;
-
int Remainder = DigitCount % DigitsPerGroup;
int I = 0;
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.h b/clang/lib/Format/IntegerLiteralSeparatorFixer.h
index 156bf5c14fca..2c158e4473bf 100644
--- a/clang/lib/Format/IntegerLiteralSeparatorFixer.h
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.h
@@ -27,7 +27,8 @@ public:
private:
bool checkSeparator(const StringRef IntegerLiteral, int DigitsPerGroup) const;
- std::string format(const StringRef IntegerLiteral, int DigitsPerGroup) const;
+ std::string format(const StringRef IntegerLiteral, int DigitsPerGroup,
+ int DigitCount, bool RemoveSeparator) const;
char Separator;
};
diff --git a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp
index d16c321badc3..f3bcacbf0254 100644
--- a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp
+++ b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp
@@ -166,6 +166,41 @@ TEST_F(IntegerLiteralSeparatorTest, UnderscoreAsSeparator) {
verifyFormat("o = 0o400000000000000003n;", Style);
}
+TEST_F(IntegerLiteralSeparatorTest, MinDigits) {
+ FormatStyle Style = getLLVMStyle();
+ Style.IntegerLiteralSeparator.Binary = 3;
+ Style.IntegerLiteralSeparator.Decimal = 3;
+ Style.IntegerLiteralSeparator.Hex = 2;
+
+ Style.IntegerLiteralSeparator.BinaryMinDigits = 7;
+ verifyFormat("b1 = 0b101101;\n"
+ "b2 = 0b1'101'101;",
+ "b1 = 0b101'101;\n"
+ "b2 = 0b1101101;",
+ Style);
+
+ Style.IntegerLiteralSeparator.DecimalMinDigits = 5;
+ verifyFormat("d1 = 2023;\n"
+ "d2 = 10'000;",
+ "d1 = 2'023;\n"
+ "d2 = 100'00;",
+ Style);
+
+ Style.IntegerLiteralSeparator.DecimalMinDigits = 3;
+ verifyFormat("d1 = 123;\n"
+ "d2 = 1'234;",
+ "d1 = 12'3;\n"
+ "d2 = 12'34;",
+ Style);
+
+ Style.IntegerLiteralSeparator.HexMinDigits = 6;
+ verifyFormat("h1 = 0xABCDE;\n"
+ "h2 = 0xAB'CD'EF;",
+ "h1 = 0xA'BC'DE;\n"
+ "h2 = 0xABC'DEF;",
+ Style);
+}
+
TEST_F(IntegerLiteralSeparatorTest, FixRanges) {
FormatStyle Style = getLLVMStyle();
Style.IntegerLiteralSeparator.Decimal = 3;