OSDN Git Service

[clang-format][PR45816] Add AlignConsecutiveBitFields
authormydeveloperday <mydeveloperday@gmail.com>
Wed, 20 May 2020 06:42:07 +0000 (07:42 +0100)
committermydeveloperday <mydeveloperday@gmail.com>
Wed, 20 May 2020 06:42:58 +0000 (07:42 +0100)
Summary:
The following revision follows 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.

Patch By:  JakeMerdichAMD

Reviewed By: MyDeveloperDay

Subscribers: cfe-commits, MyDeveloperDay

Tags: #clang, #clang-format

Differential Revision: https://reviews.llvm.org/D80176

clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Format/Format.h [changed mode: 0644->0755]
clang/lib/Format/Format.cpp
clang/lib/Format/WhitespaceManager.cpp
clang/lib/Format/WhitespaceManager.h
clang/unittests/Format/FormatTest.cpp

index e367c36..c4d6c1d 100644 (file)
@@ -204,6 +204,18 @@ the configuration (without a prefix: ``Auto``).
     int b    = 23;
     int ccc  = 23;
 
+**AlignConsecutiveBitFields** (``bool``)
+  If ``true``, aligns consecutive bitfield members.
+
+  This will align the bitfield separators 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.
 
index 8dd2288..06b0142 100644 (file)
@@ -297,6 +297,21 @@ clang-format
           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
 --------
 
old mode 100644 (file)
new mode 100755 (executable)
index 9bc08a7..7083a46
@@ -108,6 +108,17 @@ struct FormatStyle {
   /// \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
@@ -2011,8 +2022,8 @@ struct FormatStyle {
     /// \endcode
     SBPO_ControlStatements,
     /// Same as ``SBPO_ControlStatements`` except this option doesn't apply to
-    /// ForEach macros. This is useful in projects where ForEach macros are 
-    /// treated as function calls instead of control statements. 
+    /// ForEach macros. This is useful in projects where ForEach macros are
+    /// treated as function calls instead of control statements.
     /// \code
     ///    void f() {
     ///      Q_FOREACH(...) {
@@ -2218,6 +2229,7 @@ struct FormatStyle {
     return AccessModifierOffset == R.AccessModifierOffset &&
            AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
            AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
+           AlignConsecutiveBitFields == R.AlignConsecutiveBitFields &&
            AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations &&
            AlignEscapedNewlines == R.AlignEscapedNewlines &&
            AlignOperands == R.AlignOperands &&
index cda4baf..418ace7 100644 (file)
@@ -403,6 +403,8 @@ template <> struct MappingTraits<FormatStyle> {
     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 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
   LLVMStyle.AlignTrailingComments = true;
   LLVMStyle.AlignConsecutiveAssignments = false;
+  LLVMStyle.AlignConsecutiveBitFields = false;
   LLVMStyle.AlignConsecutiveDeclarations = false;
   LLVMStyle.AlignConsecutiveMacros = false;
   LLVMStyle.AllowAllArgumentsOnNextLine = true;
index fd1d749..32e0b68 100644 (file)
@@ -95,6 +95,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
   calculateLineBreakInformation();
   alignConsecutiveMacros();
   alignConsecutiveDeclarations();
+  alignConsecutiveBitFields();
   alignConsecutiveAssignments();
   alignChainedConditionals();
   alignTrailingComments();
@@ -617,6 +618,26 @@ void WhitespaceManager::alignConsecutiveAssignments() {
       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 87f24e9..1398a3a 100644 (file)
@@ -184,6 +184,9 @@ private:
   /// 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 5eefe99..9f1b88b 100644 (file)
@@ -12022,6 +12022,48 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
                    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;
@@ -13436,6 +13478,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
   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);