diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -794,6 +794,43 @@ int aaaaaaaaaaaaaaaaaaaa, int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} +**BitFieldColonSpacing** (``BitFieldColonSpacingStyle``) + The BitFieldColonSpacingStyle to use for bitfields. + + Possible values: + + * ``BFCS_Both`` (in configuration: ``Both``) + Add one space on each side of the ``:`` + + .. code-block:: c++ + + unsigned bf : 2; + + * ``BFCS_None`` (in configuration: ``None``) + Add no space around the ``:`` (except when needed for + ``AlignConsecutiveBitFields``). + + .. code-block:: c++ + + unsigned bf:2; + + * ``BFCS_Before`` (in configuration: ``Before``) + Add space before the ``:`` only + + .. code-block:: c++ + + unsigned bf :2; + + * ``BFCS_After`` (in configuration: ``After``) + Add space after the ``:`` only (space may be added before if + needed for ``AlignConsecutiveBitFields``). + + .. code-block:: c++ + + unsigned bf: 2; + + + **BraceWrapping** (``BraceWrappingFlags``) Control of individual brace wrapping cases. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -149,7 +149,33 @@ clang-format ------------ -- ... +- Option ``BitFieldColonSpacing`` has been added that decides how + space should be added around identifier, colon and bit-width in + bitfield definitions. + + .. code-block:: c++ + + // Both (default) + struct F { + unsigned dscp : 6; + unsigned ecn : 2; // AlignConsecutiveBitFields=true + }; + // None + struct F { + unsigned dscp:6; + unsigned ecn :2; + }; + // Before + struct F { + unsigned dscp :6; + unsigned ecn :2; + }; + // After + struct F { + unsigned dscp: 6; + unsigned ecn : 2; + }; + libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h old mode 100755 new mode 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2233,6 +2233,34 @@ /// \endcode bool SpaceBeforeSquareBrackets; + /// Styles for adding spacing around ``:`` in bitfield definitions. + enum BitFieldColonSpacingStyle { + /// Add one space on each side of the ``:`` + /// \code + /// unsigned bf : 2; + /// \endcode + BFCS_Both, + /// Add no space around the ``:`` (except when needed for + /// ``AlignConsecutiveBitFields``). + /// \code + /// unsigned bf:2; + /// \endcode + BFCS_None, + /// Add space before the ``:`` only + /// \code + /// unsigned bf :2; + /// \endcode + BFCS_Before, + /// Add space after the ``:`` only (space may be added before if + /// needed for ``AlignConsecutiveBitFields``). + /// \code + /// unsigned bf: 2; + /// \endcode + BFCS_After + }; + /// The BitFieldColonSpacingStyle to use for bitfields. + BitFieldColonSpacingStyle BitFieldColonSpacing; + /// Supported language standards for parsing and formatting C++ constructs. /// \code /// Latest: vector> @@ -2409,6 +2437,7 @@ SpacesInParentheses == R.SpacesInParentheses && SpacesInSquareBrackets == R.SpacesInSquareBrackets && SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets && + BitFieldColonSpacing == R.BitFieldColonSpacing && Standard == R.Standard && TabWidth == R.TabWidth && StatementMacros == R.StatementMacros && UseTab == R.UseTab && UseCRLF == R.UseCRLF && TypenameMacros == R.TypenameMacros; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -366,6 +366,17 @@ } }; +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, + FormatStyle::BitFieldColonSpacingStyle &Value) { + IO.enumCase(Value, "Both", FormatStyle::BFCS_Both); + IO.enumCase(Value, "None", FormatStyle::BFCS_None); + IO.enumCase(Value, "Before", FormatStyle::BFCS_Before); + IO.enumCase(Value, "After", FormatStyle::BFCS_After); + } +}; + template <> struct MappingTraits { static void mapping(IO &IO, FormatStyle &Style) { // When reading, read the language first, we need it for getPredefinedStyle. @@ -593,6 +604,7 @@ IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); IO.mapOptional("SpaceBeforeSquareBrackets", Style.SpaceBeforeSquareBrackets); + IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing); IO.mapOptional("Standard", Style.Standard); IO.mapOptional("StatementMacros", Style.StatementMacros); IO.mapOptional("TabWidth", Style.TabWidth); @@ -918,6 +930,7 @@ LLVMStyle.SpaceBeforeAssignmentOperators = true; LLVMStyle.SpaceBeforeCpp11BracedList = false; LLVMStyle.SpaceBeforeSquareBrackets = false; + LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; LLVMStyle.SpacesInAngles = false; LLVMStyle.SpacesInConditionalStatement = false; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3251,6 +3251,9 @@ if (Right.is(TT_RangeBasedForLoopColon) && !Style.SpaceBeforeRangeBasedForLoopColon) return false; + if (Left.is(TT_BitFieldColon)) + return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both || + Style.BitFieldColonSpacing == FormatStyle::BFCS_After; if (Right.is(tok::colon)) { if (Line.First->isOneOf(tok::kw_case, tok::kw_default) || !Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi)) @@ -3267,6 +3270,9 @@ return false; if (Right.is(TT_CSharpNamedArgumentColon)) return false; + if (Right.is(TT_BitFieldColon)) + return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both || + Style.BitFieldColonSpacing == FormatStyle::BFCS_Before; return true; } if (Left.is(TT_UnaryOperator)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -2165,6 +2165,33 @@ " uchar : 8;\n" " uchar other;\n" "};"); + FormatStyle Style = getLLVMStyle(); + Style.BitFieldColonSpacing = FormatStyle::BFCS_None; + verifyFormat("struct Bitfields {\n" + " unsigned sClass:8;\n" + " unsigned ValueKind:2;\n" + " uchar other;\n" + "};", + Style); + verifyFormat("struct A {\n" + " int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:1,\n" + " bbbbbbbbbbbbbbbbbbbbbbbbb:2;\n" + "};", + Style); + Style.BitFieldColonSpacing = FormatStyle::BFCS_Before; + verifyFormat("struct Bitfields {\n" + " unsigned sClass :8;\n" + " unsigned ValueKind :2;\n" + " uchar other;\n" + "};", + Style); + Style.BitFieldColonSpacing = FormatStyle::BFCS_After; + verifyFormat("struct Bitfields {\n" + " unsigned sClass: 8;\n" + " unsigned ValueKind: 2;\n" + " uchar other;\n" + "};", + Style); } TEST_F(FormatTest, FormatsNamespaces) { @@ -12156,6 +12183,21 @@ "int oneTwoThree : 23 = 0;", Alignment); + Alignment.BitFieldColonSpacing = FormatStyle::BFCS_None; + verifyFormat("int const a :5;\n" + "int oneTwoThree:23;", + Alignment); + + Alignment.BitFieldColonSpacing = FormatStyle::BFCS_Before; + verifyFormat("int const a :5;\n" + "int oneTwoThree :23;", + Alignment); + + Alignment.BitFieldColonSpacing = FormatStyle::BFCS_After; + verifyFormat("int const a : 5;\n" + "int oneTwoThree: 23;", + Alignment); + // Known limitations: ':' is only recognized as a bitfield colon when // followed by a number. /* @@ -14004,6 +14046,16 @@ CHECK_PARSE("IndentExternBlock: false", IndentExternBlock, FormatStyle::IEBS_NoIndent); + Style.BitFieldColonSpacing = FormatStyle::BFCS_None; + CHECK_PARSE("BitFieldColonSpacing: Both", BitFieldColonSpacing, + FormatStyle::BFCS_Both); + CHECK_PARSE("BitFieldColonSpacing: None", BitFieldColonSpacing, + FormatStyle::BFCS_None); + CHECK_PARSE("BitFieldColonSpacing: Before", BitFieldColonSpacing, + FormatStyle::BFCS_Before); + CHECK_PARSE("BitFieldColonSpacing: After", BitFieldColonSpacing, + FormatStyle::BFCS_After); + // FIXME: This is required because parsing a configuration simply overwrites // the first N elements of the list instead of resetting it. Style.ForEachMacros.clear();