JakeMerdichAMD created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The following revision follows https://reviews.llvm.org/D80115 since
@MyDeveloperDay and I apparently both had the same idea at the same
time, for https://bugs.llvm.org/show_bug.cgi?id=45816 and my efforts
on tooling support for AMDVLK, respectively.

This option aligns adjacent bitfield separators across lines, in a
manner similar to AlignConsecutiveAssignments and friends.

Example:

  struct RawFloat {
    uint32_t sign : 1;
    uint32_t exponent : 8;
    uint32_t mantissa : 23;
  };

would become

  struct RawFloat {
    uint32_t sign     : 1;
    uint32_t exponent : 8;
    uint32_t mantissa : 23;
  };

This also handles c++2a style bitfield-initializers with
AlignConsecutiveAssignments.

  struct RawFloat {
    uint32_t sign     : 1  = 0;
    uint32_t exponent : 8  = 127;
    uint32_t mantissa : 23 = 0;
  }; // defaults to 1.0f

Things this change does not do:

- Align multiple comma-chained bitfield variables. None of the other 
AlignConsecutive* options seem to implement that either.
- Detect bitfields that have a width specified with something other than a 
numeric literal (ie, 'int a : SOME_MACRO;'). That'd be fairly difficult to 
parse and is rare.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80176

Files:
  clang/docs/ClangFormatStyleOptions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/lib/Format/WhitespaceManager.cpp
  clang/lib/Format/WhitespaceManager.h
  clang/unittests/Format/FormatTest.cpp

Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -11955,6 +11955,48 @@
                Alignment);
 }
 
+TEST_F(FormatTest, AlignConsecutiveBitFields) {
+  FormatStyle Alignment = getLLVMStyle();
+  Alignment.AlignConsecutiveBitFields = true;
+  verifyFormat("int const a     : 5;\n"
+               "int oneTwoThree : 23;",
+               Alignment);
+
+  // Initializers are allowed starting with c++2a
+  verifyFormat("int const a     : 5 = 1;\n"
+               "int oneTwoThree : 23 = 0;",
+               Alignment);
+
+  Alignment.AlignConsecutiveDeclarations = true;
+  verifyFormat("int const a           : 5;\n"
+               "int       oneTwoThree : 23;",
+               Alignment);
+
+  verifyFormat("int const a           : 5;  // comment\n"
+               "int       oneTwoThree : 23; // comment",
+               Alignment);
+
+  verifyFormat("int const a           : 5 = 1;\n"
+               "int       oneTwoThree : 23 = 0;",
+               Alignment);
+
+  Alignment.AlignConsecutiveAssignments = true;
+  verifyFormat("int const a           : 5  = 1;\n"
+               "int       oneTwoThree : 23 = 0;",
+               Alignment);
+  verifyFormat("int const a           : 5  = {1};\n"
+               "int       oneTwoThree : 23 = 0;",
+               Alignment);
+
+  // Known limitations: ':' is only recognized as a bitfield colon when
+  // followed by a number.
+  /*
+  verifyFormat("int oneTwoThree : SOME_CONSTANT;\n"
+               "int a           : 5;",
+               Alignment);
+  */
+}
+
 TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   FormatStyle Alignment = getLLVMStyle();
   Alignment.AlignConsecutiveMacros = true;
@@ -13369,6 +13411,7 @@
   Style.Language = FormatStyle::LK_Cpp;
   CHECK_PARSE_BOOL(AlignTrailingComments);
   CHECK_PARSE_BOOL(AlignConsecutiveAssignments);
+  CHECK_PARSE_BOOL(AlignConsecutiveBitFields);
   CHECK_PARSE_BOOL(AlignConsecutiveDeclarations);
   CHECK_PARSE_BOOL(AlignConsecutiveMacros);
   CHECK_PARSE_BOOL(AllowAllArgumentsOnNextLine);
Index: clang/lib/Format/WhitespaceManager.h
===================================================================
--- clang/lib/Format/WhitespaceManager.h
+++ clang/lib/Format/WhitespaceManager.h
@@ -184,6 +184,9 @@
   /// Align consecutive assignments over all \c Changes.
   void alignConsecutiveAssignments();
 
+  /// Align consecutive bitfields over all \c Changes.
+  void alignConsecutiveBitFields();
+
   /// Align consecutive declarations over all \c Changes.
   void alignConsecutiveDeclarations();
 
Index: clang/lib/Format/WhitespaceManager.cpp
===================================================================
--- clang/lib/Format/WhitespaceManager.cpp
+++ clang/lib/Format/WhitespaceManager.cpp
@@ -95,6 +95,7 @@
   calculateLineBreakInformation();
   alignConsecutiveMacros();
   alignConsecutiveDeclarations();
+  alignConsecutiveBitFields();
   alignConsecutiveAssignments();
   alignChainedConditionals();
   alignTrailingComments();
@@ -609,6 +610,25 @@
       Changes, /*StartAt=*/0);
 }
 
+void WhitespaceManager::alignConsecutiveBitFields() {
+  if (!Style.AlignConsecutiveBitFields)
+    return;
+
+  AlignTokens(Style,
+              [&](Change const &C) {
+                // Do not align on ':' that is first on a line.
+                if (C.NewlinesBefore > 0)
+                  return false;
+
+                // Do not align on ':' that is last on a line.
+                if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
+                  return false;
+
+                return C.Tok->is(TT_BitFieldColon);
+              },
+              Changes, /*StartAt=*/0);
+}
+
 void WhitespaceManager::alignConsecutiveDeclarations() {
   if (!Style.AlignConsecutiveDeclarations)
     return;
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -403,6 +403,8 @@
     IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
     IO.mapOptional("AlignConsecutiveAssignments",
                    Style.AlignConsecutiveAssignments);
+    IO.mapOptional("AlignConsecutiveBitFields",
+                   Style.AlignConsecutiveBitFields);
     IO.mapOptional("AlignConsecutiveDeclarations",
                    Style.AlignConsecutiveDeclarations);
     IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
@@ -766,6 +768,7 @@
   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
   LLVMStyle.AlignTrailingComments = true;
   LLVMStyle.AlignConsecutiveAssignments = false;
+  LLVMStyle.AlignConsecutiveBitFields = false;
   LLVMStyle.AlignConsecutiveDeclarations = false;
   LLVMStyle.AlignConsecutiveMacros = false;
   LLVMStyle.AllowAllArgumentsOnNextLine = true;
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -108,6 +108,17 @@
   /// \endcode
   bool AlignConsecutiveAssignments;
 
+  /// If ``true``, aligns consecutive bitfield members.
+  ///
+  /// This will align the bitfield separators of consecutive lines. This
+  /// will result in formattings like
+  /// \code
+  ///   int aaaa : 1;
+  ///   int b    : 12;
+  ///   int ccc  : 8;
+  /// \endcode
+  bool AlignConsecutiveBitFields;
+
   /// If ``true``, aligns consecutive declarations.
   ///
   /// This will align the declaration names of consecutive lines. This
@@ -2218,6 +2229,7 @@
     return AccessModifierOffset == R.AccessModifierOffset &&
            AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
            AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
+           AlignConsecutiveBitFields == R.AlignConsecutiveBitFields &&
            AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations &&
            AlignEscapedNewlines == R.AlignEscapedNewlines &&
            AlignOperands == R.AlignOperands &&
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -297,6 +297,21 @@
           bar();
         });
 
+- Option ``AlignConsecutiveBitFields`` has been added to align bit field
+  declarations across multiple adjacent lines
+
+  .. code-block:: c++
+
+      true:
+        bool aaa  : 1;
+        bool a    : 1;
+        bool bb   : 1;
+
+      false:
+        bool aaa : 1;
+        bool a : 1;
+        bool bb : 1;
+
 libclang
 --------
 
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -204,6 +204,18 @@
     int b    = 23;
     int ccc  = 23;
 
+**AlignConsecutiveBitFields** (``bool``)
+  If ``true``, aligns consecutive bitfield members.
+
+  This will align the bitfield separator of consecutive lines. This
+  will result in formattings like
+
+  .. code-block:: c++
+
+    int aaaa : 1;
+    int b    : 12;
+    int ccc  : 8;
+
 **AlignConsecutiveDeclarations** (``bool``)
   If ``true``, aligns consecutive declarations.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to