Author: sstwcw
Date: 2022-03-14T04:41:40Z
New Revision: c24b3db45c7d0f08b423308723cd2e678a0cb7f1

URL: 
https://github.com/llvm/llvm-project/commit/c24b3db45c7d0f08b423308723cd2e678a0cb7f1
DIFF: 
https://github.com/llvm/llvm-project/commit/c24b3db45c7d0f08b423308723cd2e678a0cb7f1.diff

LOG: [clang-format] Add option to align compound assignments like `+=`

Reviewed By: curdeius, HazardyKnusperkeks, MyDeveloperDay

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

Added: 
    

Modified: 
    clang/docs/ClangFormatStyleOptions.rst
    clang/include/clang/Format/Format.h
    clang/lib/Format/Format.cpp
    clang/lib/Format/WhitespaceManager.cpp
    clang/unittests/Format/FormatTest.cpp
    clang/unittests/Format/FormatTestJS.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index c1af14466dd0e..a9e35fdceb810 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -281,70 +281,120 @@ the configuration (without a prefix: ``Auto``).
     int somelongname = 2;
     double c         = 3;
 
-  Possible values:
+  Nested configuration flags:
+
+  Alignment options.
+
+  They can also be read as a whole for compatibility. The choices are:
+  - None
+  - Consecutive
+  - AcrossEmptyLines
+  - AcrossComments
+  - AcrossEmptyLinesAndComments
+
+  For example, to align across empty lines and not across comments, either
+  of these work.
+
+  .. code-block:: c++
+
+    AlignConsecutiveMacros: AcrossEmptyLines
 
-  * ``ACS_None`` (in configuration: ``None``)
-     Do not align assignments on consecutive lines.
+    AlignConsecutiveMacros:
+      Enabled: true
+      AcrossEmptyLines: true
+      AcrossComments: false
 
-  * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-     Align assignments on consecutive lines. This will result in
-     formattings like:
+  * ``bool Enabled`` Whether aligning is enabled.
 
-     .. code-block:: c++
+    .. code-block:: c++
+
+      #define SHORT_NAME       42
+      #define LONGER_NAME      0x007f
+      #define EVEN_LONGER_NAME (2)
+      #define foo(x)           (x * x)
+      #define bar(y, z)        (y + z)
 
-       int a            = 1;
-       int somelongname = 2;
-       double c         = 3;
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       int d = 3;
-       /* A comment. */
-       double e = 4;
+      int aaaa : 1;
+      int b    : 12;
+      int ccc  : 8;
 
-  * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-     Same as ACS_Consecutive, but also spans over empty lines, e.g.
+      int         aaaa = 12;
+      float       b = 23;
+      std::string ccc;
 
-     .. code-block:: c++
+  * ``bool AcrossEmptyLines`` Whether to align across empty lines.
 
-       int a            = 1;
-       int somelongname = 2;
-       double c         = 3;
+    .. code-block:: c++
 
-       int d            = 3;
-       /* A comment. */
-       double e = 4;
+      true:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-  * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments, e.g.
+      int d            = 3;
 
-     .. code-block:: c++
+      false:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       int a            = 1;
-       int somelongname = 2;
-       double c         = 3;
+      int d = 3;
 
-       int d    = 3;
-       /* A comment. */
-       double e = 4;
+  * ``bool AcrossComments`` Whether to align across comments.
 
-  * ``ACS_AcrossEmptyLinesAndComments``
-    (in configuration: ``AcrossEmptyLinesAndComments``)
+    .. code-block:: c++
 
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments and empty lines, e.g.
+      true:
+      int d    = 3;
+      /* A comment. */
+      double e = 4;
 
-     .. code-block:: c++
+      false:
+      int d = 3;
+      /* A comment. */
+      double e = 4;
+
+  * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``.  Whether 
compound
+    assignments like ``+=`` are aligned along with ``=``.
+
+    .. code-block:: c++
+
+      true:
+      a   &= 2;
+      bbb  = 2;
+
+      false:
+      a &= 2;
+      bbb = 2;
+
+  * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``.  Whether 
short
+    assignment operators are left-padded to the same length as long
+    ones in order to put all assignment operators to the right of
+    the left hand side.
+
+    .. code-block:: c++
+
+      true:
+      a   >>= 2;
+      bbb   = 2;
+
+      a     = 2;
+      bbb >>= 2;
+
+      false:
+      a >>= 2;
+      bbb = 2;
 
-       int a            = 1;
-       int somelongname = 2;
-       double c         = 3;
+      a     = 2;
+      bbb >>= 2;
 
-       int d            = 3;
-       /* A comment. */
-       double e         = 4;
 
 **AlignConsecutiveBitFields** (``AlignConsecutiveStyle``) 
:versionbadge:`clang-format 11`
-  Style of aligning consecutive bit field.
+  Style of aligning consecutive bit fields.
 
   ``Consecutive`` will align the bitfield separators of consecutive lines.
   This will result in formattings like:
@@ -355,67 +405,117 @@ the configuration (without a prefix: ``Auto``).
     int b    : 12;
     int ccc  : 8;
 
-  Possible values:
+  Nested configuration flags:
+
+  Alignment options.
+
+  They can also be read as a whole for compatibility. The choices are:
+  - None
+  - Consecutive
+  - AcrossEmptyLines
+  - AcrossComments
+  - AcrossEmptyLinesAndComments
+
+  For example, to align across empty lines and not across comments, either
+  of these work.
+
+  .. code-block:: c++
+
+    AlignConsecutiveMacros: AcrossEmptyLines
 
-  * ``ACS_None`` (in configuration: ``None``)
-     Do not align bit fields on consecutive lines.
+    AlignConsecutiveMacros:
+      Enabled: true
+      AcrossEmptyLines: true
+      AcrossComments: false
 
-  * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-     Align bit fields on consecutive lines. This will result in
-     formattings like:
+  * ``bool Enabled`` Whether aligning is enabled.
 
-     .. code-block:: c++
+    .. code-block:: c++
+
+      #define SHORT_NAME       42
+      #define LONGER_NAME      0x007f
+      #define EVEN_LONGER_NAME (2)
+      #define foo(x)           (x * x)
+      #define bar(y, z)        (y + z)
 
-       int aaaa : 1;
-       int b    : 12;
-       int ccc  : 8;
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       int d : 2;
-       /* A comment. */
-       int ee : 3;
+      int aaaa : 1;
+      int b    : 12;
+      int ccc  : 8;
 
-  * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-     Same as ACS_Consecutive, but also spans over empty lines, e.g.
+      int         aaaa = 12;
+      float       b = 23;
+      std::string ccc;
 
-     .. code-block:: c++
+  * ``bool AcrossEmptyLines`` Whether to align across empty lines.
 
-       int aaaa : 1;
-       int b    : 12;
-       int ccc  : 8;
+    .. code-block:: c++
 
-       int d    : 2;
-       /* A comment. */
-       int ee : 3;
+      true:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-  * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments, e.g.
+      int d            = 3;
 
-     .. code-block:: c++
+      false:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       int aaaa : 1;
-       int b    : 12;
-       int ccc  : 8;
+      int d = 3;
 
-       int d  : 2;
-       /* A comment. */
-       int ee : 3;
+  * ``bool AcrossComments`` Whether to align across comments.
 
-  * ``ACS_AcrossEmptyLinesAndComments``
-    (in configuration: ``AcrossEmptyLinesAndComments``)
+    .. code-block:: c++
 
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments and empty lines, e.g.
+      true:
+      int d    = 3;
+      /* A comment. */
+      double e = 4;
 
-     .. code-block:: c++
+      false:
+      int d = 3;
+      /* A comment. */
+      double e = 4;
+
+  * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``.  Whether 
compound
+    assignments like ``+=`` are aligned along with ``=``.
+
+    .. code-block:: c++
+
+      true:
+      a   &= 2;
+      bbb  = 2;
+
+      false:
+      a &= 2;
+      bbb = 2;
+
+  * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``.  Whether 
short
+    assignment operators are left-padded to the same length as long
+    ones in order to put all assignment operators to the right of
+    the left hand side.
+
+    .. code-block:: c++
+
+      true:
+      a   >>= 2;
+      bbb   = 2;
+
+      a     = 2;
+      bbb >>= 2;
+
+      false:
+      a >>= 2;
+      bbb = 2;
 
-       int aaaa : 1;
-       int b    : 12;
-       int ccc  : 8;
+      a     = 2;
+      bbb >>= 2;
 
-       int d    : 2;
-       /* A comment. */
-       int ee   : 3;
 
 **AlignConsecutiveDeclarations** (``AlignConsecutiveStyle``) 
:versionbadge:`clang-format 3.8`
   Style of aligning consecutive declarations.
@@ -429,67 +529,117 @@ the configuration (without a prefix: ``Auto``).
     float       b = 23;
     std::string ccc;
 
-  Possible values:
+  Nested configuration flags:
+
+  Alignment options.
+
+  They can also be read as a whole for compatibility. The choices are:
+  - None
+  - Consecutive
+  - AcrossEmptyLines
+  - AcrossComments
+  - AcrossEmptyLinesAndComments
+
+  For example, to align across empty lines and not across comments, either
+  of these work.
+
+  .. code-block:: c++
+
+    AlignConsecutiveMacros: AcrossEmptyLines
 
-  * ``ACS_None`` (in configuration: ``None``)
-     Do not align bit declarations on consecutive lines.
+    AlignConsecutiveMacros:
+      Enabled: true
+      AcrossEmptyLines: true
+      AcrossComments: false
 
-  * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-     Align declarations on consecutive lines. This will result in
-     formattings like:
+  * ``bool Enabled`` Whether aligning is enabled.
 
-     .. code-block:: c++
+    .. code-block:: c++
+
+      #define SHORT_NAME       42
+      #define LONGER_NAME      0x007f
+      #define EVEN_LONGER_NAME (2)
+      #define foo(x)           (x * x)
+      #define bar(y, z)        (y + z)
 
-       int         aaaa = 12;
-       float       b = 23;
-       std::string ccc;
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       int a = 42;
-       /* A comment. */
-       bool c = false;
+      int aaaa : 1;
+      int b    : 12;
+      int ccc  : 8;
 
-  * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-     Same as ACS_Consecutive, but also spans over empty lines, e.g.
+      int         aaaa = 12;
+      float       b = 23;
+      std::string ccc;
 
-     .. code-block:: c++
+  * ``bool AcrossEmptyLines`` Whether to align across empty lines.
 
-       int         aaaa = 12;
-       float       b = 23;
-       std::string ccc;
+    .. code-block:: c++
 
-       int         a = 42;
-       /* A comment. */
-       bool c = false;
+      true:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-  * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments, e.g.
+      int d            = 3;
 
-     .. code-block:: c++
+      false:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       int         aaaa = 12;
-       float       b = 23;
-       std::string ccc;
+      int d = 3;
 
-       int  a = 42;
-       /* A comment. */
-       bool c = false;
+  * ``bool AcrossComments`` Whether to align across comments.
 
-  * ``ACS_AcrossEmptyLinesAndComments``
-    (in configuration: ``AcrossEmptyLinesAndComments``)
+    .. code-block:: c++
 
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments and empty lines, e.g.
+      true:
+      int d    = 3;
+      /* A comment. */
+      double e = 4;
 
-     .. code-block:: c++
+      false:
+      int d = 3;
+      /* A comment. */
+      double e = 4;
+
+  * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``.  Whether 
compound
+    assignments like ``+=`` are aligned along with ``=``.
+
+    .. code-block:: c++
+
+      true:
+      a   &= 2;
+      bbb  = 2;
+
+      false:
+      a &= 2;
+      bbb = 2;
+
+  * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``.  Whether 
short
+    assignment operators are left-padded to the same length as long
+    ones in order to put all assignment operators to the right of
+    the left hand side.
+
+    .. code-block:: c++
+
+      true:
+      a   >>= 2;
+      bbb   = 2;
+
+      a     = 2;
+      bbb >>= 2;
+
+      false:
+      a >>= 2;
+      bbb = 2;
 
-       int         aaaa = 12;
-       float       b = 23;
-       std::string ccc;
+      a     = 2;
+      bbb >>= 2;
 
-       int         a = 42;
-       /* A comment. */
-       bool        c = false;
 
 **AlignConsecutiveMacros** (``AlignConsecutiveStyle``) 
:versionbadge:`clang-format 9`
   Style of aligning consecutive macro definitions.
@@ -504,67 +654,117 @@ the configuration (without a prefix: ``Auto``).
     #define foo(x)           (x * x)
     #define bar(y, z)        (y + z)
 
-  Possible values:
+  Nested configuration flags:
+
+  Alignment options.
+
+  They can also be read as a whole for compatibility. The choices are:
+  - None
+  - Consecutive
+  - AcrossEmptyLines
+  - AcrossComments
+  - AcrossEmptyLinesAndComments
+
+  For example, to align across empty lines and not across comments, either
+  of these work.
+
+  .. code-block:: c++
+
+    AlignConsecutiveMacros: AcrossEmptyLines
 
-  * ``ACS_None`` (in configuration: ``None``)
-     Do not align macro definitions on consecutive lines.
+    AlignConsecutiveMacros:
+      Enabled: true
+      AcrossEmptyLines: true
+      AcrossComments: false
 
-  * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-     Align macro definitions on consecutive lines. This will result in
-     formattings like:
+  * ``bool Enabled`` Whether aligning is enabled.
 
-     .. code-block:: c++
+    .. code-block:: c++
+
+      #define SHORT_NAME       42
+      #define LONGER_NAME      0x007f
+      #define EVEN_LONGER_NAME (2)
+      #define foo(x)           (x * x)
+      #define bar(y, z)        (y + z)
 
-       #define SHORT_NAME       42
-       #define LONGER_NAME      0x007f
-       #define EVEN_LONGER_NAME (2)
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       #define foo(x) (x * x)
-       /* some comment */
-       #define bar(y, z) (y + z)
+      int aaaa : 1;
+      int b    : 12;
+      int ccc  : 8;
 
-  * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-     Same as ACS_Consecutive, but also spans over empty lines, e.g.
+      int         aaaa = 12;
+      float       b = 23;
+      std::string ccc;
 
-     .. code-block:: c++
+  * ``bool AcrossEmptyLines`` Whether to align across empty lines.
 
-       #define SHORT_NAME       42
-       #define LONGER_NAME      0x007f
-       #define EVEN_LONGER_NAME (2)
+    .. code-block:: c++
 
-       #define foo(x)           (x * x)
-       /* some comment */
-       #define bar(y, z) (y + z)
+      true:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-  * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments, e.g.
+      int d            = 3;
 
-     .. code-block:: c++
+      false:
+      int a            = 1;
+      int somelongname = 2;
+      double c         = 3;
 
-       #define SHORT_NAME       42
-       #define LONGER_NAME      0x007f
-       #define EVEN_LONGER_NAME (2)
+      int d = 3;
 
-       #define foo(x)    (x * x)
-       /* some comment */
-       #define bar(y, z) (y + z)
+  * ``bool AcrossComments`` Whether to align across comments.
 
-  * ``ACS_AcrossEmptyLinesAndComments``
-    (in configuration: ``AcrossEmptyLinesAndComments``)
+    .. code-block:: c++
 
-     Same as ACS_Consecutive, but also spans over lines only containing
-     comments and empty lines, e.g.
+      true:
+      int d    = 3;
+      /* A comment. */
+      double e = 4;
 
-     .. code-block:: c++
+      false:
+      int d = 3;
+      /* A comment. */
+      double e = 4;
+
+  * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``.  Whether 
compound
+    assignments like ``+=`` are aligned along with ``=``.
+
+    .. code-block:: c++
+
+      true:
+      a   &= 2;
+      bbb  = 2;
+
+      false:
+      a &= 2;
+      bbb = 2;
+
+  * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``.  Whether 
short
+    assignment operators are left-padded to the same length as long
+    ones in order to put all assignment operators to the right of
+    the left hand side.
+
+    .. code-block:: c++
+
+      true:
+      a   >>= 2;
+      bbb   = 2;
+
+      a     = 2;
+      bbb >>= 2;
+
+      false:
+      a >>= 2;
+      bbb = 2;
 
-       #define SHORT_NAME       42
-       #define LONGER_NAME      0x007f
-       #define EVEN_LONGER_NAME (2)
+      a     = 2;
+      bbb >>= 2;
 
-       #define foo(x)           (x * x)
-       /* some comment */
-       #define bar(y, z)        (y + z)
 
 **AlignEscapedNewlines** (``EscapedNewlineAlignmentStyle``) 
:versionbadge:`clang-format 5`
   Options for aligning backslashes in escaped newlines.

diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 70af9b19085ee..eb53d7987dbd2 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -138,18 +138,116 @@ struct FormatStyle {
   /// \version 13
   ArrayInitializerAlignmentStyle AlignArrayOfStructures;
 
-  /// Styles for alignment of consecutive tokens. Tokens can be assignment 
signs
-  /// (see
-  /// ``AlignConsecutiveAssignments``), bitfield member separators (see
-  /// ``AlignConsecutiveBitFields``), names in declarations (see
-  /// ``AlignConsecutiveDeclarations``) or macro definitions (see
-  /// ``AlignConsecutiveMacros``).
-  enum AlignConsecutiveStyle {
-    ACS_None,
-    ACS_Consecutive,
-    ACS_AcrossEmptyLines,
-    ACS_AcrossComments,
-    ACS_AcrossEmptyLinesAndComments
+  /// Alignment options.
+  ///
+  /// They can also be read as a whole for compatibility. The choices are:
+  /// - None
+  /// - Consecutive
+  /// - AcrossEmptyLines
+  /// - AcrossComments
+  /// - AcrossEmptyLinesAndComments
+  ///
+  /// For example, to align across empty lines and not across comments, either
+  /// of these work.
+  /// \code
+  ///   AlignConsecutiveMacros: AcrossEmptyLines
+  ///
+  ///   AlignConsecutiveMacros:
+  ///     Enabled: true
+  ///     AcrossEmptyLines: true
+  ///     AcrossComments: false
+  /// \endcode
+  struct AlignConsecutiveStyle {
+    /// Whether aligning is enabled.
+    /// \code
+    ///   #define SHORT_NAME       42
+    ///   #define LONGER_NAME      0x007f
+    ///   #define EVEN_LONGER_NAME (2)
+    ///   #define foo(x)           (x * x)
+    ///   #define bar(y, z)        (y + z)
+    ///
+    ///   int a            = 1;
+    ///   int somelongname = 2;
+    ///   double c         = 3;
+    ///
+    ///   int aaaa : 1;
+    ///   int b    : 12;
+    ///   int ccc  : 8;
+    ///
+    ///   int         aaaa = 12;
+    ///   float       b = 23;
+    ///   std::string ccc;
+    /// \endcode
+    bool Enabled;
+    /// Whether to align across empty lines.
+    /// \code
+    ///   true:
+    ///   int a            = 1;
+    ///   int somelongname = 2;
+    ///   double c         = 3;
+    ///
+    ///   int d            = 3;
+    ///
+    ///   false:
+    ///   int a            = 1;
+    ///   int somelongname = 2;
+    ///   double c         = 3;
+    ///
+    ///   int d = 3;
+    /// \endcode
+    bool AcrossEmptyLines;
+    /// Whether to align across comments.
+    /// \code
+    ///   true:
+    ///   int d    = 3;
+    ///   /* A comment. */
+    ///   double e = 4;
+    ///
+    ///   false:
+    ///   int d = 3;
+    ///   /* A comment. */
+    ///   double e = 4;
+    /// \endcode
+    bool AcrossComments;
+    /// Only for ``AlignConsecutiveAssignments``.  Whether compound assignments
+    /// like ``+=`` are aligned along with ``=``.
+    /// \code
+    ///   true:
+    ///   a   &= 2;
+    ///   bbb  = 2;
+    ///
+    ///   false:
+    ///   a &= 2;
+    ///   bbb = 2;
+    /// \endcode
+    bool AlignCompound;
+    /// Only for ``AlignConsecutiveAssignments``.  Whether short assignment
+    /// operators are left-padded to the same length as long ones in order to
+    /// put all assignment operators to the right of the left hand side.
+    /// \code
+    ///   true:
+    ///   a   >>= 2;
+    ///   bbb   = 2;
+    ///
+    ///   a     = 2;
+    ///   bbb >>= 2;
+    ///
+    ///   false:
+    ///   a >>= 2;
+    ///   bbb = 2;
+    ///
+    ///   a     = 2;
+    ///   bbb >>= 2;
+    /// \endcode
+    bool PadOperators;
+    bool operator==(const AlignConsecutiveStyle &R) const {
+      return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
+             AcrossComments == R.AcrossComments &&
+             AlignCompound == R.AlignCompound && PadOperators == 
R.PadOperators;
+    }
+    bool operator!=(const AlignConsecutiveStyle &R) const {
+      return !(*this == R);
+    }
   };
 
   /// Style of aligning consecutive macro definitions.
@@ -162,67 +260,8 @@ struct FormatStyle {
   ///   #define foo(x)           (x * x)
   ///   #define bar(y, z)        (y + z)
   /// \endcode
-  ///
-  /// Possible values:
-  ///
-  /// * ``ACS_None`` (in configuration: ``None``)
-  ///    Do not align macro definitions on consecutive lines.
-  ///
-  /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-  ///    Align macro definitions on consecutive lines. This will result in
-  ///    formattings like:
-  ///    \code
-  ///      #define SHORT_NAME       42
-  ///      #define LONGER_NAME      0x007f
-  ///      #define EVEN_LONGER_NAME (2)
-  ///
-  ///      #define foo(x) (x * x)
-  ///      /* some comment */
-  ///      #define bar(y, z) (y + z)
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-  ///    Same as ACS_Consecutive, but also spans over empty lines, e.g.
-  ///    \code
-  ///      #define SHORT_NAME       42
-  ///      #define LONGER_NAME      0x007f
-  ///      #define EVEN_LONGER_NAME (2)
-  ///
-  ///      #define foo(x)           (x * x)
-  ///      /* some comment */
-  ///      #define bar(y, z) (y + z)
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments, e.g.
-  ///    \code
-  ///      #define SHORT_NAME       42
-  ///      #define LONGER_NAME      0x007f
-  ///      #define EVEN_LONGER_NAME (2)
-  ///
-  ///      #define foo(x)    (x * x)
-  ///      /* some comment */
-  ///      #define bar(y, z) (y + z)
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLinesAndComments``
-  ///   (in configuration: ``AcrossEmptyLinesAndComments``)
-  ///
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments and empty lines, e.g.
-  ///    \code
-  ///      #define SHORT_NAME       42
-  ///      #define LONGER_NAME      0x007f
-  ///      #define EVEN_LONGER_NAME (2)
-  ///
-  ///      #define foo(x)           (x * x)
-  ///      /* some comment */
-  ///      #define bar(y, z)        (y + z)
-  ///    \endcode
   /// \version 9
   AlignConsecutiveStyle AlignConsecutiveMacros;
-
   /// Style of aligning consecutive assignments.
   ///
   /// ``Consecutive`` will result in formattings like:
@@ -231,68 +270,9 @@ struct FormatStyle {
   ///   int somelongname = 2;
   ///   double c         = 3;
   /// \endcode
-  ///
-  /// Possible values:
-  ///
-  /// * ``ACS_None`` (in configuration: ``None``)
-  ///    Do not align assignments on consecutive lines.
-  ///
-  /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-  ///    Align assignments on consecutive lines. This will result in
-  ///    formattings like:
-  ///    \code
-  ///      int a            = 1;
-  ///      int somelongname = 2;
-  ///      double c         = 3;
-  ///
-  ///      int d = 3;
-  ///      /* A comment. */
-  ///      double e = 4;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-  ///    Same as ACS_Consecutive, but also spans over empty lines, e.g.
-  ///    \code
-  ///      int a            = 1;
-  ///      int somelongname = 2;
-  ///      double c         = 3;
-  ///
-  ///      int d            = 3;
-  ///      /* A comment. */
-  ///      double e = 4;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments, e.g.
-  ///    \code
-  ///      int a            = 1;
-  ///      int somelongname = 2;
-  ///      double c         = 3;
-  ///
-  ///      int d    = 3;
-  ///      /* A comment. */
-  ///      double e = 4;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLinesAndComments``
-  ///   (in configuration: ``AcrossEmptyLinesAndComments``)
-  ///
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments and empty lines, e.g.
-  ///    \code
-  ///      int a            = 1;
-  ///      int somelongname = 2;
-  ///      double c         = 3;
-  ///
-  ///      int d            = 3;
-  ///      /* A comment. */
-  ///      double e         = 4;
-  ///    \endcode
   /// \version 3.8
   AlignConsecutiveStyle AlignConsecutiveAssignments;
-
-  /// Style of aligning consecutive bit field.
+  /// Style of aligning consecutive bit fields.
   ///
   /// ``Consecutive`` will align the bitfield separators of consecutive lines.
   /// This will result in formattings like:
@@ -301,67 +281,8 @@ struct FormatStyle {
   ///   int b    : 12;
   ///   int ccc  : 8;
   /// \endcode
-  ///
-  /// Possible values:
-  ///
-  /// * ``ACS_None`` (in configuration: ``None``)
-  ///    Do not align bit fields on consecutive lines.
-  ///
-  /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-  ///    Align bit fields on consecutive lines. This will result in
-  ///    formattings like:
-  ///    \code
-  ///      int aaaa : 1;
-  ///      int b    : 12;
-  ///      int ccc  : 8;
-  ///
-  ///      int d : 2;
-  ///      /* A comment. */
-  ///      int ee : 3;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-  ///    Same as ACS_Consecutive, but also spans over empty lines, e.g.
-  ///    \code
-  ///      int aaaa : 1;
-  ///      int b    : 12;
-  ///      int ccc  : 8;
-  ///
-  ///      int d    : 2;
-  ///      /* A comment. */
-  ///      int ee : 3;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments, e.g.
-  ///    \code
-  ///      int aaaa : 1;
-  ///      int b    : 12;
-  ///      int ccc  : 8;
-  ///
-  ///      int d  : 2;
-  ///      /* A comment. */
-  ///      int ee : 3;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLinesAndComments``
-  ///   (in configuration: ``AcrossEmptyLinesAndComments``)
-  ///
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments and empty lines, e.g.
-  ///    \code
-  ///      int aaaa : 1;
-  ///      int b    : 12;
-  ///      int ccc  : 8;
-  ///
-  ///      int d    : 2;
-  ///      /* A comment. */
-  ///      int ee   : 3;
-  ///    \endcode
   /// \version 11
   AlignConsecutiveStyle AlignConsecutiveBitFields;
-
   /// Style of aligning consecutive declarations.
   ///
   /// ``Consecutive`` will align the declaration names of consecutive lines.
@@ -371,64 +292,6 @@ struct FormatStyle {
   ///   float       b = 23;
   ///   std::string ccc;
   /// \endcode
-  ///
-  /// Possible values:
-  ///
-  /// * ``ACS_None`` (in configuration: ``None``)
-  ///    Do not align bit declarations on consecutive lines.
-  ///
-  /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``)
-  ///    Align declarations on consecutive lines. This will result in
-  ///    formattings like:
-  ///    \code
-  ///      int         aaaa = 12;
-  ///      float       b = 23;
-  ///      std::string ccc;
-  ///
-  ///      int a = 42;
-  ///      /* A comment. */
-  ///      bool c = false;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``)
-  ///    Same as ACS_Consecutive, but also spans over empty lines, e.g.
-  ///    \code
-  ///      int         aaaa = 12;
-  ///      float       b = 23;
-  ///      std::string ccc;
-  ///
-  ///      int         a = 42;
-  ///      /* A comment. */
-  ///      bool c = false;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``)
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments, e.g.
-  ///    \code
-  ///      int         aaaa = 12;
-  ///      float       b = 23;
-  ///      std::string ccc;
-  ///
-  ///      int  a = 42;
-  ///      /* A comment. */
-  ///      bool c = false;
-  ///    \endcode
-  ///
-  /// * ``ACS_AcrossEmptyLinesAndComments``
-  ///   (in configuration: ``AcrossEmptyLinesAndComments``)
-  ///
-  ///    Same as ACS_Consecutive, but also spans over lines only containing
-  ///    comments and empty lines, e.g.
-  ///    \code
-  ///      int         aaaa = 12;
-  ///      float       b = 23;
-  ///      std::string ccc;
-  ///
-  ///      int         a = 42;
-  ///      /* A comment. */
-  ///      bool        c = false;
-  ///    \endcode
   /// \version 3.8
   AlignConsecutiveStyle AlignConsecutiveDeclarations;
 

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 4f9320f2b34e5..0bbd54353d7b8 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -152,18 +152,55 @@ template <> struct 
ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
   }
 };
 
-template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> 
{
-  static void enumeration(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
-    IO.enumCase(Value, "None", FormatStyle::ACS_None);
-    IO.enumCase(Value, "Consecutive", FormatStyle::ACS_Consecutive);
-    IO.enumCase(Value, "AcrossEmptyLines", FormatStyle::ACS_AcrossEmptyLines);
-    IO.enumCase(Value, "AcrossComments", FormatStyle::ACS_AcrossComments);
+template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
+  static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
+    IO.enumCase(Value, "None",
+                FormatStyle::AlignConsecutiveStyle(
+                    {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,
+                     /*PadOperators=*/true}));
+    IO.enumCase(Value, "Consecutive",
+                FormatStyle::AlignConsecutiveStyle(
+                    {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,
+                     /*PadOperators=*/true}));
+    IO.enumCase(Value, "AcrossEmptyLines",
+                FormatStyle::AlignConsecutiveStyle(
+                    {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,
+                     /*PadOperators=*/true}));
+    IO.enumCase(Value, "AcrossComments",
+                FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true,
+                                                    /*AcrossEmptyLines=*/false,
+                                                    /*AcrossComments=*/true,
+                                                    /*AlignCompound=*/false,
+                                                    /*PadOperators=*/true}));
     IO.enumCase(Value, "AcrossEmptyLinesAndComments",
-                FormatStyle::ACS_AcrossEmptyLinesAndComments);
+                FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true,
+                                                    /*AcrossEmptyLines=*/true,
+                                                    /*AcrossComments=*/true,
+                                                    /*AlignCompound=*/false,
+                                                    /*PadOperators=*/true}));
 
     // For backward compatibility.
-    IO.enumCase(Value, "true", FormatStyle::ACS_Consecutive);
-    IO.enumCase(Value, "false", FormatStyle::ACS_None);
+    IO.enumCase(Value, "true",
+                FormatStyle::AlignConsecutiveStyle(
+                    {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,
+                     /*PadOperators=*/true}));
+    IO.enumCase(Value, "false",
+                FormatStyle::AlignConsecutiveStyle(
+                    {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,
+                     /*PadOperators=*/true}));
+  }
+
+  static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
+    IO.mapOptional("Enabled", Value.Enabled);
+    IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
+    IO.mapOptional("AcrossComments", Value.AcrossComments);
+    IO.mapOptional("AlignCompound", Value.AlignCompound);
+    IO.mapOptional("PadOperators", Value.PadOperators);
   }
 };
 
@@ -600,13 +637,13 @@ template <> struct MappingTraits<FormatStyle> {
     IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
     IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
     IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
-    IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
     IO.mapOptional("AlignConsecutiveAssignments",
                    Style.AlignConsecutiveAssignments);
     IO.mapOptional("AlignConsecutiveBitFields",
                    Style.AlignConsecutiveBitFields);
     IO.mapOptional("AlignConsecutiveDeclarations",
                    Style.AlignConsecutiveDeclarations);
+    IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
     IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
     IO.mapOptional("AlignOperands", Style.AlignOperands);
     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
@@ -1141,10 +1178,15 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
   LLVMStyle.AlignTrailingComments = true;
-  LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
-  LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None;
-  LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
-  LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None;
+  LLVMStyle.AlignConsecutiveAssignments = {};
+  LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
+  LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
+  LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
+  LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
+  LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
+  LLVMStyle.AlignConsecutiveBitFields = {};
+  LLVMStyle.AlignConsecutiveDeclarations = {};
+  LLVMStyle.AlignConsecutiveMacros = {};
   LLVMStyle.AllowAllArgumentsOnNextLine = true;
   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
   LLVMStyle.AllowShortEnumsOnASingleLine = true;

diff  --git a/clang/lib/Format/WhitespaceManager.cpp 
b/clang/lib/Format/WhitespaceManager.cpp
index b62fdb33722a3..6a46d850c3d5e 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -267,10 +267,13 @@ void WhitespaceManager::calculateLineBreakInformation() {
 }
 
 // Align a single sequence of tokens, see AlignTokens below.
+// Column - The token for which Matches returns true is moved to this column.
+// RightJustify - Whether it is the token's right end or left end that gets
+// moved to that column.
 template <typename F>
 static void
 AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
-                   unsigned Column, F &&Matches,
+                   unsigned Column, bool RightJustify, F &&Matches,
                    SmallVector<WhitespaceManager::Change, 16> &Changes) {
   bool FoundMatchOnLine = false;
   int Shift = 0;
@@ -329,7 +332,8 @@ AlignTokenSequence(const FormatStyle &Style, unsigned 
Start, unsigned End,
     // shifted by the same amount
     if (!FoundMatchOnLine && !SkipMatchCheck && Matches(Changes[i])) {
       FoundMatchOnLine = true;
-      Shift = Column - Changes[i].StartOfTokenColumn;
+      Shift = Column - (RightJustify ? Changes[i].TokenLength : 0) -
+              Changes[i].StartOfTokenColumn;
       Changes[i].Spaces += Shift;
       // FIXME: This is a workaround that should be removed when we fix
       // http://llvm.org/PR53699. An assertion later below verifies this.
@@ -456,13 +460,31 @@ AlignTokenSequence(const FormatStyle &Style, unsigned 
Start, unsigned End,
 // However, the special exception is that we do NOT skip function parameters
 // that are split across multiple lines. See the test case in FormatTest.cpp
 // that mentions "split function parameter alignment" for an example of this.
+// When the parameter RightJustify is true, the operator will be
+// right-justified. It is used to align compound assignments like `+=` and `=`.
+// When RightJustify and ACS.PadOperators are true, operators in each block to
+// be aligned will be padded on the left to the same length before aligning.
 template <typename F>
-static unsigned AlignTokens(
-    const FormatStyle &Style, F &&Matches,
-    SmallVector<WhitespaceManager::Change, 16> &Changes, unsigned StartAt,
-    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
-  unsigned MinColumn = 0;
-  unsigned MaxColumn = UINT_MAX;
+static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
+                            SmallVector<WhitespaceManager::Change, 16> 
&Changes,
+                            unsigned StartAt,
+                            const FormatStyle::AlignConsecutiveStyle &ACS = {},
+                            bool RightJustify = false) {
+  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
+  // and text to its left and right. In the aligned text the width of each part
+  // will be the maximum of that over the block that has been aligned. Maximum
+  // widths of each part so far. When RightJustify is true and ACS.PadOperators
+  // is false, the part from start of line to the right end of the anchor.
+  // Otherwise, only the part to the left of the anchor. Including the space
+  // that exists on its left from the start. Not including the padding added on
+  // the left to right-justify the anchor.
+  unsigned WidthLeft = 0;
+  // The operator to be aligned when RightJustify is true and ACS.PadOperators
+  // is false. 0 otherwise.
+  unsigned WidthAnchor = 0;
+  // Width to the right of the anchor. Plus width of the anchor when
+  // RightJustify is false.
+  unsigned WidthRight = 0;
 
   // Line number of the start and the end of the current token sequence.
   unsigned StartOfSequence = 0;
@@ -495,10 +517,12 @@ static unsigned AlignTokens(
   // containing any matching token to be aligned and located after such token.
   auto AlignCurrentSequence = [&] {
     if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
-      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
-                         Matches, Changes);
-    MinColumn = 0;
-    MaxColumn = UINT_MAX;
+      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
+                         WidthLeft + WidthAnchor, RightJustify, Matches,
+                         Changes);
+    WidthLeft = 0;
+    WidthAnchor = 0;
+    WidthRight = 0;
     StartOfSequence = 0;
     EndOfSequence = 0;
   };
@@ -514,17 +538,12 @@ static unsigned AlignTokens(
 
       // Whether to break the alignment sequence because of an empty line.
       bool EmptyLineBreak =
-          (Changes[i].NewlinesBefore > 1) &&
-          (ACS != FormatStyle::ACS_AcrossEmptyLines) &&
-          (ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments);
+          (Changes[i].NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
 
       // Whether to break the alignment sequence because of a line without a
       // match.
       bool NoMatchBreak =
-          !FoundMatchOnLine &&
-          !(LineIsComment &&
-            ((ACS == FormatStyle::ACS_AcrossComments) ||
-             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
+          !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
 
       if (EmptyLineBreak || NoMatchBreak)
         AlignCurrentSequence();
@@ -563,29 +582,44 @@ static unsigned AlignTokens(
     if (StartOfSequence == 0)
       StartOfSequence = i;
 
-    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
-    int LineLengthAfter = Changes[i].TokenLength;
+    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
+    unsigned ChangeWidthAnchor = 0;
+    unsigned ChangeWidthRight = 0;
+    if (RightJustify) {
+      if (ACS.PadOperators)
+        ChangeWidthAnchor = Changes[i].TokenLength;
+      else
+        ChangeWidthLeft += Changes[i].TokenLength;
+    } else
+      ChangeWidthRight = Changes[i].TokenLength;
     for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
-      LineLengthAfter += Changes[j].Spaces;
+      ChangeWidthRight += Changes[j].Spaces;
       // Changes are generally 1:1 with the tokens, but a change could also be
       // inside of a token, in which case it's counted more than once: once for
       // the whitespace surrounding the token (!IsInsideToken) and once for
       // each whitespace change within it (IsInsideToken).
       // Therefore, changes inside of a token should only count the space.
       if (!Changes[j].IsInsideToken)
-        LineLengthAfter += Changes[j].TokenLength;
+        ChangeWidthRight += Changes[j].TokenLength;
     }
-    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
 
     // If we are restricted by the maximum column width, end the sequence.
-    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
-        CommasBeforeLastMatch != CommasBeforeMatch) {
+    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
+    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
+    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
+    // `ColumnLimit == 0` means there is no column limit.
+    if (Style.ColumnLimit != 0 &&
+        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
       AlignCurrentSequence();
       StartOfSequence = i;
+      WidthLeft = ChangeWidthLeft;
+      WidthAnchor = ChangeWidthAnchor;
+      WidthRight = ChangeWidthRight;
+    } else {
+      WidthLeft = NewLeft;
+      WidthAnchor = NewAnchor;
+      WidthRight = NewRight;
     }
-
-    MinColumn = std::max(MinColumn, ChangeMinColumn);
-    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
   }
 
   EndOfSequence = i;
@@ -639,7 +673,7 @@ static void AlignMacroSequence(
 }
 
 void WhitespaceManager::alignConsecutiveMacros() {
-  if (Style.AlignConsecutiveMacros == FormatStyle::ACS_None)
+  if (!Style.AlignConsecutiveMacros.Enabled)
     return;
 
   auto AlignMacrosMatches = [](const Change &C) {
@@ -690,20 +724,14 @@ void WhitespaceManager::alignConsecutiveMacros() {
       EndOfSequence = I;
 
       // Whether to break the alignment sequence because of an empty line.
-      bool EmptyLineBreak =
-          (Changes[I].NewlinesBefore > 1) &&
-          (Style.AlignConsecutiveMacros != FormatStyle::ACS_AcrossEmptyLines) 
&&
-          (Style.AlignConsecutiveMacros !=
-           FormatStyle::ACS_AcrossEmptyLinesAndComments);
+      bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
+                            !Style.AlignConsecutiveMacros.AcrossEmptyLines;
 
       // Whether to break the alignment sequence because of a line without a
       // match.
       bool NoMatchBreak =
           !FoundMatchOnLine &&
-          !(LineIsComment && ((Style.AlignConsecutiveMacros ==
-                               FormatStyle::ACS_AcrossComments) ||
-                              (Style.AlignConsecutiveMacros ==
-                               FormatStyle::ACS_AcrossEmptyLinesAndComments)));
+          !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
 
       if (EmptyLineBreak || NoMatchBreak)
         AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, 
MaxColumn,
@@ -741,7 +769,7 @@ void WhitespaceManager::alignConsecutiveMacros() {
 }
 
 void WhitespaceManager::alignConsecutiveAssignments() {
-  if (Style.AlignConsecutiveAssignments == FormatStyle::ACS_None)
+  if (!Style.AlignConsecutiveAssignments.Enabled)
     return;
 
   AlignTokens(
@@ -760,13 +788,16 @@ void WhitespaceManager::alignConsecutiveAssignments() {
         if (Previous && Previous->is(tok::kw_operator))
           return false;
 
-        return C.Tok->is(tok::equal);
+        return Style.AlignConsecutiveAssignments.AlignCompound
+                   ? C.Tok->getPrecedence() == prec::Assignment
+                   : C.Tok->is(tok::equal);
       },
-      Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments);
+      Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments,
+      /*RightJustify=*/true);
 }
 
 void WhitespaceManager::alignConsecutiveBitFields() {
-  if (Style.AlignConsecutiveBitFields == FormatStyle::ACS_None)
+  if (!Style.AlignConsecutiveBitFields.Enabled)
     return;
 
   AlignTokens(
@@ -786,7 +817,7 @@ void WhitespaceManager::alignConsecutiveBitFields() {
 }
 
 void WhitespaceManager::alignConsecutiveDeclarations() {
-  if (Style.AlignConsecutiveDeclarations == FormatStyle::ACS_None)
+  if (!Style.AlignConsecutiveDeclarations.Enabled)
     return;
 
   AlignTokens(

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index baa3993805bcb..5ca6f6244c40c 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2083,7 +2083,7 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
       "                     res2 = [](int &a) { return 0000000000000; };",
       Style);
 
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("Const unsigned int *c;\n"
                "const unsigned int *d;\n"
                "Const unsigned int &e;\n"
@@ -2124,7 +2124,7 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
       "                    res2 = [](int& a) { return 0000000000000; };",
       Style);
 
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("Const unsigned int* c;\n"
                "const unsigned int* d;\n"
                "Const unsigned int& e;\n"
@@ -2145,7 +2145,7 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
   verifyFormat("for (int a = 0, b = 0; const Foo *c : {1, 2, 3})", Style);
   verifyFormat("for (int a = 0, b++; const Foo *c : {1, 2, 3})", Style);
 
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("Const unsigned int *c;\n"
                "const unsigned int *d;\n"
                "Const unsigned int& e;\n"
@@ -2181,7 +2181,7 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
       "                     res2 = [](int & a) { return 0000000000000; };",
       Style);
 
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("Const unsigned int*  c;\n"
                "const unsigned int*  d;\n"
                "Const unsigned int & e;\n"
@@ -14515,8 +14515,8 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
                    "*/\n"
                    "}",
                    Tab));
-  Tab.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
-  Tab.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Tab.AlignConsecutiveAssignments.Enabled = true;
+  Tab.AlignConsecutiveDeclarations.Enabled = true;
   Tab.TabWidth = 4;
   Tab.IndentWidth = 4;
   verifyFormat("class Assign {\n"
@@ -14754,8 +14754,8 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
                    "*/\n"
                    "}",
                    Tab));
-  Tab.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
-  Tab.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Tab.AlignConsecutiveAssignments.Enabled = true;
+  Tab.AlignConsecutiveDeclarations.Enabled = true;
   Tab.TabWidth = 4;
   Tab.IndentWidth = 4;
   verifyFormat("class Assign {\n"
@@ -15925,9 +15925,8 @@ TEST_F(FormatTest, 
ConfigurableSpaceAroundPointerQualifiers) {
 
 TEST_F(FormatTest, AlignConsecutiveMacros) {
   FormatStyle Style = getLLVMStyle();
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_None;
+  Style.AlignConsecutiveAssignments.Enabled = true;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
 
   verifyFormat("#define a 3\n"
                "#define bbbb 4\n"
@@ -15951,7 +15950,7 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
                "#define ffff(x, y) (x - y)",
                Style);
 
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveMacros.Enabled = true;
   verifyFormat("#define a    3\n"
                "#define bbbb 4\n"
                "#define ccc  (5)",
@@ -15991,7 +15990,7 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
                "};",
                Style);
 
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_None;
+  Style.AlignConsecutiveMacros.Enabled = false;
   Style.ColumnLimit = 20;
 
   verifyFormat("#define a          \\\n"
@@ -16005,7 +16004,7 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
                "  \"LLLLLLLL\"\n",
                Style);
 
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveMacros.Enabled = true;
   verifyFormat("#define a          \\\n"
                "  \"aabbbbbbbbbbbb\"\n"
                "#define D          \\\n"
@@ -16020,7 +16019,7 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
   // Test across comments
   Style.MaxEmptyLinesToKeep = 10;
   Style.ReflowComments = false;
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_AcrossComments;
+  Style.AlignConsecutiveMacros.AcrossComments = true;
   EXPECT_EQ("#define a    3\n"
             "// line comment\n"
             "#define bbbb 4\n"
@@ -16078,7 +16077,8 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
                    Style));
 
   // Test across empty lines
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_AcrossEmptyLines;
+  Style.AlignConsecutiveMacros.AcrossComments = false;
+  Style.AlignConsecutiveMacros.AcrossEmptyLines = true;
   EXPECT_EQ("#define a    3\n"
             "\n"
             "#define bbbb 4\n"
@@ -16116,7 +16116,7 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
                    Style));
 
   // Test across empty lines and comments
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_AcrossEmptyLinesAndComments;
+  Style.AlignConsecutiveMacros.AcrossComments = true;
   verifyFormat("#define a    3\n"
                "\n"
                "// line comment\n"
@@ -16167,8 +16167,9 @@ TEST_F(FormatTest, AlignConsecutiveMacros) {
 
 TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossEmptyLines) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_AcrossEmptyLines;
+  Alignment.AlignConsecutiveMacros.Enabled = true;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
+  Alignment.AlignConsecutiveAssignments.AcrossEmptyLines = true;
 
   Alignment.MaxEmptyLinesToKeep = 10;
   /* Test alignment across empty lines */
@@ -16241,9 +16242,9 @@ TEST_F(FormatTest, 
AlignConsecutiveAssignmentsAcrossEmptyLines) {
 
 TEST_F(FormatTest, AlignConsecutiveDeclarationsAcrossEmptyLinesAndComments) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveDeclarations =
-      FormatStyle::ACS_AcrossEmptyLinesAndComments;
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+  Alignment.AlignConsecutiveDeclarations.Enabled = true;
+  Alignment.AlignConsecutiveDeclarations.AcrossEmptyLines = true;
+  Alignment.AlignConsecutiveDeclarations.AcrossComments = true;
 
   Alignment.MaxEmptyLinesToKeep = 10;
   /* Test alignment across empty lines */
@@ -16305,8 +16306,9 @@ TEST_F(FormatTest, 
AlignConsecutiveDeclarationsAcrossEmptyLinesAndComments) {
 
 TEST_F(FormatTest, AlignConsecutiveBitFieldsAcrossEmptyLinesAndComments) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveBitFields =
-      FormatStyle::ACS_AcrossEmptyLinesAndComments;
+  Alignment.AlignConsecutiveBitFields.Enabled = true;
+  Alignment.AlignConsecutiveBitFields.AcrossEmptyLines = true;
+  Alignment.AlignConsecutiveBitFields.AcrossComments = true;
 
   Alignment.MaxEmptyLinesToKeep = 10;
   /* Test alignment across empty lines */
@@ -16372,8 +16374,9 @@ TEST_F(FormatTest, 
AlignConsecutiveBitFieldsAcrossEmptyLinesAndComments) {
 
 TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossComments) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_AcrossComments;
+  Alignment.AlignConsecutiveMacros.Enabled = true;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
+  Alignment.AlignConsecutiveAssignments.AcrossComments = true;
 
   Alignment.MaxEmptyLinesToKeep = 10;
   /* Test alignment across empty lines */
@@ -16459,9 +16462,10 @@ TEST_F(FormatTest, 
AlignConsecutiveAssignmentsAcrossComments) {
 
 TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossEmptyLinesAndComments) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
-  Alignment.AlignConsecutiveAssignments =
-      FormatStyle::ACS_AcrossEmptyLinesAndComments;
+  Alignment.AlignConsecutiveMacros.Enabled = true;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
+  Alignment.AlignConsecutiveAssignments.AcrossEmptyLines = true;
+  Alignment.AlignConsecutiveAssignments.AcrossComments = true;
   verifyFormat("int a           = 5;\n"
                "int oneTwoThree = 123;",
                Alignment);
@@ -16772,10 +16776,122 @@ TEST_F(FormatTest, 
AlignConsecutiveAssignmentsAcrossEmptyLinesAndComments) {
                    Alignment));
 }
 
+TEST_F(FormatTest, AlignCompoundAssignments) {
+  FormatStyle Alignment = getLLVMStyle();
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
+  Alignment.AlignConsecutiveAssignments.AlignCompound = true;
+  Alignment.AlignConsecutiveAssignments.PadOperators = false;
+  verifyFormat("sfdbddfbdfbb    = 5;\n"
+               "dvsdsv          = 5;\n"
+               "int dsvvdvsdvvv = 123;",
+               Alignment);
+  verifyFormat("sfdbddfbdfbb   ^= 5;\n"
+               "dvsdsv         |= 5;\n"
+               "int dsvvdvsdvvv = 123;",
+               Alignment);
+  verifyFormat("sfdbddfbdfbb   ^= 5;\n"
+               "dvsdsv        <<= 5;\n"
+               "int dsvvdvsdvvv = 123;",
+               Alignment);
+  // Test that `<=` is not treated as a compound assignment.
+  verifyFormat("aa &= 5;\n"
+               "b <= 10;\n"
+               "c = 15;",
+               Alignment);
+  Alignment.AlignConsecutiveAssignments.PadOperators = true;
+  verifyFormat("sfdbddfbdfbb    = 5;\n"
+               "dvsdsv          = 5;\n"
+               "int dsvvdvsdvvv = 123;",
+               Alignment);
+  verifyFormat("sfdbddfbdfbb    ^= 5;\n"
+               "dvsdsv          |= 5;\n"
+               "int dsvvdvsdvvv  = 123;",
+               Alignment);
+  verifyFormat("sfdbddfbdfbb     ^= 5;\n"
+               "dvsdsv          <<= 5;\n"
+               "int dsvvdvsdvvv   = 123;",
+               Alignment);
+  EXPECT_EQ("a   += 5;\n"
+            "one  = 1;\n"
+            "\n"
+            "oneTwoThree = 123;\n",
+            format("a += 5;\n"
+                   "one = 1;\n"
+                   "\n"
+                   "oneTwoThree = 123;\n",
+                   Alignment));
+  EXPECT_EQ("a   += 5;\n"
+            "one  = 1;\n"
+            "//\n"
+            "oneTwoThree = 123;\n",
+            format("a += 5;\n"
+                   "one = 1;\n"
+                   "//\n"
+                   "oneTwoThree = 123;\n",
+                   Alignment));
+  Alignment.AlignConsecutiveAssignments.AcrossEmptyLines = true;
+  EXPECT_EQ("a           += 5;\n"
+            "one          = 1;\n"
+            "\n"
+            "oneTwoThree  = 123;\n",
+            format("a += 5;\n"
+                   "one = 1;\n"
+                   "\n"
+                   "oneTwoThree = 123;\n",
+                   Alignment));
+  EXPECT_EQ("a   += 5;\n"
+            "one  = 1;\n"
+            "//\n"
+            "oneTwoThree = 123;\n",
+            format("a += 5;\n"
+                   "one = 1;\n"
+                   "//\n"
+                   "oneTwoThree = 123;\n",
+                   Alignment));
+  Alignment.AlignConsecutiveAssignments.AcrossEmptyLines = false;
+  Alignment.AlignConsecutiveAssignments.AcrossComments = true;
+  EXPECT_EQ("a   += 5;\n"
+            "one  = 1;\n"
+            "\n"
+            "oneTwoThree = 123;\n",
+            format("a += 5;\n"
+                   "one = 1;\n"
+                   "\n"
+                   "oneTwoThree = 123;\n",
+                   Alignment));
+  EXPECT_EQ("a           += 5;\n"
+            "one          = 1;\n"
+            "//\n"
+            "oneTwoThree  = 123;\n",
+            format("a += 5;\n"
+                   "one = 1;\n"
+                   "//\n"
+                   "oneTwoThree = 123;\n",
+                   Alignment));
+  Alignment.AlignConsecutiveAssignments.AcrossEmptyLines = true;
+  EXPECT_EQ("a            += 5;\n"
+            "one         >>= 1;\n"
+            "\n"
+            "oneTwoThree   = 123;\n",
+            format("a += 5;\n"
+                   "one >>= 1;\n"
+                   "\n"
+                   "oneTwoThree = 123;\n",
+                   Alignment));
+  EXPECT_EQ("a            += 5;\n"
+            "one           = 1;\n"
+            "//\n"
+            "oneTwoThree <<= 123;\n",
+            format("a += 5;\n"
+                   "one = 1;\n"
+                   "//\n"
+                   "oneTwoThree <<= 123;\n",
+                   Alignment));
+}
+
 TEST_F(FormatTest, AlignConsecutiveAssignments) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+  Alignment.AlignConsecutiveMacros.Enabled = true;
   verifyFormat("int a = 5;\n"
                "int oneTwoThree = 123;",
                Alignment);
@@ -16783,14 +16899,15 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
                "int oneTwoThree = 123;",
                Alignment);
 
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
   verifyFormat("int a           = 5;\n"
                "int oneTwoThree = 123;",
                Alignment);
   verifyFormat("int a           = method();\n"
                "int oneTwoThree = 133;",
                Alignment);
-  verifyFormat("a &= 5;\n"
+  verifyFormat("aa <= 5;\n"
+               "a &= 5;\n"
                "bcd *= 5;\n"
                "ghtyf += 5;\n"
                "dvfvdb -= 5;\n"
@@ -16863,8 +16980,7 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
                Alignment);
   // https://llvm.org/PR33697
   FormatStyle AlignmentWithPenalty = getLLVMStyle();
-  AlignmentWithPenalty.AlignConsecutiveAssignments =
-      FormatStyle::ACS_Consecutive;
+  AlignmentWithPenalty.AlignConsecutiveAssignments.Enabled = true;
   AlignmentWithPenalty.PenaltyReturnTypeOnItsOwnLine = 5000;
   verifyFormat("class SSSSSSSSSSSSSSSSSSSSSSSSSSSS {\n"
                "  void f() = delete;\n"
@@ -17083,7 +17199,7 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
 
 TEST_F(FormatTest, AlignConsecutiveBitFields) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveBitFields = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveBitFields.Enabled = true;
   verifyFormat("int const a     : 5;\n"
                "int oneTwoThree : 23;",
                Alignment);
@@ -17093,7 +17209,7 @@ TEST_F(FormatTest, AlignConsecutiveBitFields) {
                "int oneTwoThree : 23 = 0;",
                Alignment);
 
-  Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("int const a           : 5;\n"
                "int       oneTwoThree : 23;",
                Alignment);
@@ -17106,7 +17222,7 @@ TEST_F(FormatTest, AlignConsecutiveBitFields) {
                "int       oneTwoThree : 23 = 0;",
                Alignment);
 
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
   verifyFormat("int const a           : 5  = 1;\n"
                "int       oneTwoThree : 23 = 0;",
                Alignment);
@@ -17140,8 +17256,7 @@ TEST_F(FormatTest, AlignConsecutiveBitFields) {
 
 TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   FormatStyle Alignment = getLLVMStyle();
-  Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
-  Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
+  Alignment.AlignConsecutiveMacros.Enabled = true;
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
   verifyFormat("float const a = 5;\n"
                "int oneTwoThree = 123;",
@@ -17150,7 +17265,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
                "float const oneTwoThree = 123;",
                Alignment);
 
-  Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("float const a = 5;\n"
                "int         oneTwoThree = 123;",
                Alignment);
@@ -17261,7 +17376,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   verifyFormat("int    a(int x, void (*fp)(int y));\n"
                "double b();",
                Alignment);
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
   // Ensure recursive alignment is broken by function braces, so that the
   // "a = 1" does not align with subsequent assignments inside the function
   // body.
@@ -17486,7 +17601,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
                "int     foobar;\n",
                AlignmentMiddle);
 
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+  Alignment.AlignConsecutiveAssignments.Enabled = false;
   Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign;
   verifyFormat("#define A \\\n"
                "  int       aaaa = 12; \\\n"
@@ -17555,7 +17670,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
                "int j = 2;",
                Alignment);
 
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
   verifyFormat("auto lambda = []() {\n"
                "  auto  ii = 0;\n"
                "  float j  = 0;\n"
@@ -17569,7 +17684,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
                "    i = 3    //\n"
                "};",
                Alignment);
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+  Alignment.AlignConsecutiveAssignments.Enabled = false;
 
   verifyFormat(
       "int      i = 1;\n"
@@ -17582,7 +17697,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   // We expect declarations and assignments to align, as long as it doesn't
   // exceed the column limit, starting a new alignment sequence whenever it
   // happens.
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
   Alignment.ColumnLimit = 30;
   verifyFormat("float    ii              = 1;\n"
                "unsigned j               = 2;\n"
@@ -17592,7 +17707,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
                "int              myvar = 1;",
                Alignment);
   Alignment.ColumnLimit = 80;
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+  Alignment.AlignConsecutiveAssignments.Enabled = false;
 
   verifyFormat(
       "template <typename LongTemplate, typename VeryLongTemplateTypeName,\n"
@@ -17606,7 +17721,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   verifyFormat("int   aa = ((1 > 2) ? 3 : 4);\n"
                "float b[1][] = {{3.f}};\n",
                Alignment);
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveAssignments.Enabled = true;
   verifyFormat("float a, b = 1;\n"
                "int   c  = 2;\n"
                "int   dd = 3;\n",
@@ -17614,7 +17729,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   verifyFormat("int   aa     = ((1 > 2) ? 3 : 4);\n"
                "float b[1][] = {{3.f}};\n",
                Alignment);
-  Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+  Alignment.AlignConsecutiveAssignments.Enabled = false;
 
   Alignment.ColumnLimit = 30;
   Alignment.BinPackParameters = false;
@@ -17645,7 +17760,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
 
   // See llvm.org/PR35641
-  Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Alignment.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("int func() { //\n"
                "  int      b;\n"
                "  unsigned c;\n"
@@ -17654,7 +17769,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
 
   // See PR37175
   FormatStyle Style = getMozillaStyle();
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   EXPECT_EQ("DECOR1 /**/ int8_t /**/ DECOR2 /**/\n"
             "foo(int a);",
             format("DECOR1 /**/ int8_t /**/ DECOR2 /**/ foo (int a);", Style));
@@ -17693,7 +17808,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
 
   // See PR46529
   FormatStyle BracedAlign = getLLVMStyle();
-  BracedAlign.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  BracedAlign.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("const auto result{[]() {\n"
                "  const auto something = 1;\n"
                "  return 2;\n"
@@ -17720,8 +17835,13 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
 TEST_F(FormatTest, AlignWithLineBreaks) {
   auto Style = getLLVMStyleWithColumns(120);
 
-  EXPECT_EQ(Style.AlignConsecutiveAssignments, FormatStyle::ACS_None);
-  EXPECT_EQ(Style.AlignConsecutiveDeclarations, FormatStyle::ACS_None);
+  EXPECT_EQ(Style.AlignConsecutiveAssignments,
+            FormatStyle::AlignConsecutiveStyle(
+                {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
+                 /*AcrossComments=*/false, /*AlignCompound=*/false,
+                 /*PadOperators=*/true}));
+  EXPECT_EQ(Style.AlignConsecutiveDeclarations,
+            FormatStyle::AlignConsecutiveStyle({}));
   verifyFormat("void foo() {\n"
                "  int myVar = 5;\n"
                "  double x = 3.14;\n"
@@ -17743,7 +17863,7 @@ TEST_F(FormatTest, AlignWithLineBreaks) {
                Style);
   // clang-format on
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
   verifyFormat("void foo() {\n"
                "  int myVar = 5;\n"
                "  double x  = 3.14;\n"
@@ -17765,8 +17885,8 @@ TEST_F(FormatTest, AlignWithLineBreaks) {
                Style);
   // clang-format on
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_None;
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = false;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("void foo() {\n"
                "  int    myVar = 5;\n"
                "  double x = 3.14;\n"
@@ -17788,8 +17908,8 @@ TEST_F(FormatTest, AlignWithLineBreaks) {
                Style);
   // clang-format on
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
 
   verifyFormat("void foo() {\n"
                "  int    myVar = 5;\n"
@@ -17813,7 +17933,7 @@ TEST_F(FormatTest, AlignWithLineBreaks) {
   // clang-format on
 
   Style = getLLVMStyleWithColumns(120);
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
   Style.ContinuationIndentWidth = 4;
   Style.IndentWidth = 4;
 
@@ -17856,8 +17976,8 @@ TEST_F(FormatTest, AlignWithInitializerPeriods) {
                "}",
                Style);
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
+  Style.AlignConsecutiveAssignments.Enabled = true;
+  Style.AlignConsecutiveDeclarations.Enabled = false;
   verifyFormat("void foo2(void) {\n"
                "  BYTE p[1]    = 1;\n"
                "  A B          = {.one_foooooooooooooooo = 2,\n"
@@ -17867,8 +17987,8 @@ TEST_F(FormatTest, AlignWithInitializerPeriods) {
                "}",
                Style);
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_None;
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = false;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("void foo3(void) {\n"
                "  BYTE p[1] = 1;\n"
                "  A    B = {.one_foooooooooooooooo = 2,\n"
@@ -17878,8 +17998,8 @@ TEST_F(FormatTest, AlignWithInitializerPeriods) {
                "}",
                Style);
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("void foo4(void) {\n"
                "  BYTE p[1]    = 1;\n"
                "  A    B       = {.one_foooooooooooooooo = 2,\n"
@@ -18895,10 +19015,8 @@ TEST_F(FormatTest, CatchExceptionReferenceBinding) {
 TEST_F(FormatTest, CatchAlignArrayOfStructuresRightAlignment) {
   auto Style = getLLVMStyle();
   Style.AlignArrayOfStructures = FormatStyle::AIAS_Right;
-  Style.AlignConsecutiveAssignments =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("struct test demo[] = {\n"
                "    {56,    23, \"hello\"},\n"
                "    {-1, 93463, \"world\"},\n"
@@ -19075,10 +19193,6 @@ TEST_F(FormatTest, 
CatchAlignArrayOfStructuresRightAlignment) {
 
   Style = getLLVMStyleWithColumns(50);
   Style.AlignArrayOfStructures = FormatStyle::AIAS_Right;
-  Style.AlignConsecutiveAssignments =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
   verifyFormat("struct test demo[] = {\n"
                "    {56,    23, \"hello\"},\n"
                "    {-1, 93463, \"world\"},\n"
@@ -19090,10 +19204,8 @@ TEST_F(FormatTest, 
CatchAlignArrayOfStructuresRightAlignment) {
                "};",
                Style);
   Style.ColumnLimit = 100;
-  Style.AlignConsecutiveAssignments =
-      FormatStyle::AlignConsecutiveStyle::ACS_AcrossComments;
-  Style.AlignConsecutiveDeclarations =
-      FormatStyle::AlignConsecutiveStyle::ACS_AcrossComments;
+  Style.AlignConsecutiveAssignments.AcrossComments = true;
+  Style.AlignConsecutiveDeclarations.AcrossComments = true;
   verifyFormat("struct test demo[] = {\n"
                "    {56,    23, \"hello\"},\n"
                "    {-1, 93463, \"world\"},\n"
@@ -19753,69 +19865,54 @@ TEST_F(FormatTest, ParsesConfiguration) {
   CHECK_PARSE("QualifierOrder: [volatile, type]", QualifierOrder,
               std::vector<std::string>({"volatile", "type"}));
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
-  CHECK_PARSE("AlignConsecutiveAssignments: None", AlignConsecutiveAssignments,
-              FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveAssignments: Consecutive",
-              AlignConsecutiveAssignments, FormatStyle::ACS_Consecutive);
-  CHECK_PARSE("AlignConsecutiveAssignments: AcrossEmptyLines",
-              AlignConsecutiveAssignments, FormatStyle::ACS_AcrossEmptyLines);
-  CHECK_PARSE("AlignConsecutiveAssignments: AcrossEmptyLinesAndComments",
-              AlignConsecutiveAssignments,
-              FormatStyle::ACS_AcrossEmptyLinesAndComments);
-  // For backwards compability, false / true should still parse
-  CHECK_PARSE("AlignConsecutiveAssignments: false", 
AlignConsecutiveAssignments,
-              FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveAssignments: true", AlignConsecutiveAssignments,
-              FormatStyle::ACS_Consecutive);
-
-  Style.AlignConsecutiveBitFields = FormatStyle::ACS_Consecutive;
-  CHECK_PARSE("AlignConsecutiveBitFields: None", AlignConsecutiveBitFields,
-              FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveBitFields: Consecutive",
-              AlignConsecutiveBitFields, FormatStyle::ACS_Consecutive);
-  CHECK_PARSE("AlignConsecutiveBitFields: AcrossEmptyLines",
-              AlignConsecutiveBitFields, FormatStyle::ACS_AcrossEmptyLines);
-  CHECK_PARSE("AlignConsecutiveBitFields: AcrossEmptyLinesAndComments",
-              AlignConsecutiveBitFields,
-              FormatStyle::ACS_AcrossEmptyLinesAndComments);
-  // For backwards compability, false / true should still parse
-  CHECK_PARSE("AlignConsecutiveBitFields: false", AlignConsecutiveBitFields,
-              FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveBitFields: true", AlignConsecutiveBitFields,
-              FormatStyle::ACS_Consecutive);
-
-  Style.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
-  CHECK_PARSE("AlignConsecutiveMacros: None", AlignConsecutiveMacros,
-              FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveMacros: Consecutive", AlignConsecutiveMacros,
-              FormatStyle::ACS_Consecutive);
-  CHECK_PARSE("AlignConsecutiveMacros: AcrossEmptyLines",
-              AlignConsecutiveMacros, FormatStyle::ACS_AcrossEmptyLines);
-  CHECK_PARSE("AlignConsecutiveMacros: AcrossEmptyLinesAndComments",
-              AlignConsecutiveMacros,
-              FormatStyle::ACS_AcrossEmptyLinesAndComments);
-  // For backwards compability, false / true should still parse
-  CHECK_PARSE("AlignConsecutiveMacros: false", AlignConsecutiveMacros,
-              FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveMacros: true", AlignConsecutiveMacros,
-              FormatStyle::ACS_Consecutive);
-
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
-  CHECK_PARSE("AlignConsecutiveDeclarations: None",
-              AlignConsecutiveDeclarations, FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveDeclarations: Consecutive",
-              AlignConsecutiveDeclarations, FormatStyle::ACS_Consecutive);
-  CHECK_PARSE("AlignConsecutiveDeclarations: AcrossEmptyLines",
-              AlignConsecutiveDeclarations, FormatStyle::ACS_AcrossEmptyLines);
-  CHECK_PARSE("AlignConsecutiveDeclarations: AcrossEmptyLinesAndComments",
-              AlignConsecutiveDeclarations,
-              FormatStyle::ACS_AcrossEmptyLinesAndComments);
-  // For backwards compability, false / true should still parse
-  CHECK_PARSE("AlignConsecutiveDeclarations: false",
-              AlignConsecutiveDeclarations, FormatStyle::ACS_None);
-  CHECK_PARSE("AlignConsecutiveDeclarations: true",
-              AlignConsecutiveDeclarations, FormatStyle::ACS_Consecutive);
+#define CHECK_ALIGN_CONSECUTIVE(FIELD)                                         
\
+  do {                                                                         
\
+    Style.FIELD.Enabled = true;                                                
\
+    CHECK_PARSE(#FIELD ": None", FIELD,                                        
\
+                FormatStyle::AlignConsecutiveStyle(                            
\
+                    {/*Enabled=*/false, /*AcrossEmptyLines=*/false,            
\
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,        
\
+                     /*PadOperators=*/true}));                                 
\
+    CHECK_PARSE(#FIELD ": Consecutive", FIELD,                                 
\
+                FormatStyle::AlignConsecutiveStyle(                            
\
+                    {/*Enabled=*/true, /*AcrossEmptyLines=*/false,             
\
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,        
\
+                     /*PadOperators=*/true}));                                 
\
+    CHECK_PARSE(#FIELD ": AcrossEmptyLines", FIELD,                            
\
+                FormatStyle::AlignConsecutiveStyle(                            
\
+                    {/*Enabled=*/true, /*AcrossEmptyLines=*/true,              
\
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,        
\
+                     /*PadOperators=*/true}));                                 
\
+    CHECK_PARSE(#FIELD ": AcrossEmptyLinesAndComments", FIELD,                 
\
+                FormatStyle::AlignConsecutiveStyle(                            
\
+                    {/*Enabled=*/true, /*AcrossEmptyLines=*/true,              
\
+                     /*AcrossComments=*/true, /*AlignCompound=*/false,         
\
+                     /*PadOperators=*/true}));                                 
\
+    /* For backwards compability, false / true should still parse */           
\
+    CHECK_PARSE(#FIELD ": false", FIELD,                                       
\
+                FormatStyle::AlignConsecutiveStyle(                            
\
+                    {/*Enabled=*/false, /*AcrossEmptyLines=*/false,            
\
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,        
\
+                     /*PadOperators=*/true}));                                 
\
+    CHECK_PARSE(#FIELD ": true", FIELD,                                        
\
+                FormatStyle::AlignConsecutiveStyle(                            
\
+                    {/*Enabled=*/true, /*AcrossEmptyLines=*/false,             
\
+                     /*AcrossComments=*/false, /*AlignCompound=*/false,        
\
+                     /*PadOperators=*/true}));                                 
\
+                                                                               
\
+    CHECK_PARSE_NESTED_BOOL(FIELD, Enabled);                                   
\
+    CHECK_PARSE_NESTED_BOOL(FIELD, AcrossEmptyLines);                          
\
+    CHECK_PARSE_NESTED_BOOL(FIELD, AcrossComments);                            
\
+    CHECK_PARSE_NESTED_BOOL(FIELD, AlignCompound);                             
\
+    CHECK_PARSE_NESTED_BOOL(FIELD, PadOperators);                              
\
+  } while (false)
+
+  CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveAssignments);
+  CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveBitFields);
+  CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveMacros);
+  CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveDeclarations);
+
+#undef CHECK_ALIGN_CONSECUTIVE
 
   Style.PointerAlignment = FormatStyle::PAS_Middle;
   CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
@@ -23387,7 +23484,7 @@ TEST_F(FormatTest, WhitespaceSensitiveMacros) {
             format("FOO(String-ized&Messy+But,: :\n"
                    "       Still=Intentional);",
                    Style));
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
   EXPECT_EQ("FOO(String-ized=&Messy+But,: :\n"
             "       Still=Intentional);",
             format("FOO(String-ized=&Messy+But,: :\n"
@@ -24275,7 +24372,7 @@ TEST_F(FormatTest, StatementAttributeLikeMacros) {
 
   EXPECT_EQ(Source, format(Source, Style));
 
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   EXPECT_EQ("void Foo::slot() {\n"
             "  unsigned char MyChar = 'x';\n"
             "  emit          signal(MyChar);\n"
@@ -25403,10 +25500,8 @@ TEST_F(FormatTest, UnderstandsDigraphs) {
 TEST_F(FormatTest, AlignArrayOfStructuresLeftAlignmentNonSquare) {
   auto Style = getLLVMStyle();
   Style.AlignArrayOfStructures = FormatStyle::AIAS_Left;
-  Style.AlignConsecutiveAssignments =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
 
   // The AlignArray code is incorrect for non square Arrays and can cause
   // crashes, these tests assert that the array is not changed but will
@@ -25469,10 +25564,8 @@ TEST_F(FormatTest, 
AlignArrayOfStructuresLeftAlignmentNonSquare) {
 TEST_F(FormatTest, AlignArrayOfStructuresRightAlignmentNonSquare) {
   auto Style = getLLVMStyle();
   Style.AlignArrayOfStructures = FormatStyle::AIAS_Right;
-  Style.AlignConsecutiveAssignments =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
-  Style.AlignConsecutiveDeclarations =
-      FormatStyle::AlignConsecutiveStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
 
   // The AlignArray code is incorrect for non square Arrays and can cause
   // crashes, these tests assert that the array is not changed but will

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index 67df2d41731a6..85aad28c085cb 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -2699,7 +2699,7 @@ TEST_F(FormatTestJS, NumericSeparators) {
 
 TEST_F(FormatTestJS, AlignConsecutiveDeclarations) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
   verifyFormat("let    letVariable = 5;\n"
                "double constVariable = 10;",
                Style);
@@ -2736,7 +2736,7 @@ TEST_F(FormatTestJS, AlignConsecutiveDeclarations) {
 TEST_F(FormatTestJS, AlignConsecutiveAssignments) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
 
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveAssignments.Enabled = true;
   verifyFormat("let letVariable      = 5;\n"
                "double constVariable = 10;",
                Style);
@@ -2772,8 +2772,8 @@ TEST_F(FormatTestJS, AlignConsecutiveAssignments) {
 
 TEST_F(FormatTestJS, AlignConsecutiveAssignmentsAndDeclarations) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
-  Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
-  Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+  Style.AlignConsecutiveDeclarations.Enabled = true;
+  Style.AlignConsecutiveAssignments.Enabled = true;
   verifyFormat("let    letVariable   = 5;\n"
                "double constVariable = 10;",
                Style);


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to