https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/169160

>From 072d1ab13b478c7e92a698e00fbd76e14ee1542b Mon Sep 17 00:00:00 2001
From: Daan De Meyer <[email protected]>
Date: Fri, 21 Nov 2025 23:11:45 +0100
Subject: [PATCH 1/3] [clang-format][NFC] Upgrade PointerAlignment option to a
 struct

This allows adding other suboptions e.g. ReturnType for #136597.
---
 clang/docs/ClangFormatStyleOptions.rst     | 107 +++++++++++++------
 clang/include/clang/Format/Format.h        |  59 ++++++++++-
 clang/lib/Format/Format.cpp                |  63 +++++++++--
 clang/lib/Format/TokenAnnotator.cpp        |  16 +--
 clang/lib/Format/WhitespaceManager.cpp     |  10 +-
 clang/unittests/Format/ConfigParseTest.cpp |  34 +++---
 clang/unittests/Format/FormatTest.cpp      | 118 ++++++++++-----------
 7 files changed, 281 insertions(+), 126 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 94d6f0d27619f..ab21290260005 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5668,31 +5668,54 @@ the configuration (without a prefix: ``Auto``).
 
 .. _PointerAlignment:
 
-**PointerAlignment** (``PointerAlignmentStyle``) :versionbadge:`clang-format 
3.7` :ref:`¶ <PointerAlignment>`
+**PointerAlignment** (``PointerAlignmentOptions``) :versionbadge:`clang-format 
3.7` :ref:`¶ <PointerAlignment>`
   Pointer and reference alignment style.
 
-  Possible values:
+  Acceptable values (configured as a single string or with suboptions):
+  * ``Left``
+  * ``Right``
+  * ``Middle``
 
-  * ``PAS_Left`` (in configuration: ``Left``)
-    Align pointer to the left.
+  For example, to configure left pointer alignment:
 
-    .. code-block:: c++
+  .. code-block:: yaml
 
-      int* a;
+    PointerAlignment: Left
 
-  * ``PAS_Right`` (in configuration: ``Right``)
-    Align pointer to the right.
+    # or
 
-    .. code-block:: c++
+    PointerAlignment:
+      Default: Left
+
+  Nested configuration flags:
 
-      int *a;
+  Pointer and reference alignment options.
 
-  * ``PAS_Middle`` (in configuration: ``Middle``)
-    Align pointer in the middle.
+  * ``PointerAlignmentStyle Default``
+    The default alignment for pointers and references.
 
-    .. code-block:: c++
+    Possible values:
+
+    * ``PAS_Left`` (in configuration: ``Left``)
+      Align pointer to the left.
+
+      .. code-block:: c++
+
+        int* a;
+
+    * ``PAS_Right`` (in configuration: ``Right``)
+      Align pointer to the right.
+
+      .. code-block:: c++
+
+        int *a;
+
+    * ``PAS_Middle`` (in configuration: ``Middle``)
+      Align pointer in the middle.
+
+      .. code-block:: c++
 
-      int * a;
+        int * a;
 
 
 
@@ -5824,34 +5847,58 @@ the configuration (without a prefix: ``Auto``).
 
 .. _ReferenceAlignment:
 
-**ReferenceAlignment** (``ReferenceAlignmentStyle``) 
:versionbadge:`clang-format 13` :ref:`¶ <ReferenceAlignment>`
+**ReferenceAlignment** (``ReferenceAlignmentOptions``) 
:versionbadge:`clang-format 13` :ref:`¶ <ReferenceAlignment>`
   Reference alignment style (overrides ``PointerAlignment`` for references).
 
-  Possible values:
+  Acceptable values (configured as a single string or with suboptions):
+  * ``Pointer``
+  * ``Left``
+  * ``Right``
+  * ``Middle``
 
-  * ``RAS_Pointer`` (in configuration: ``Pointer``)
-    Align reference like ``PointerAlignment``.
+  For example, to configure right reference alignment:
 
-  * ``RAS_Left`` (in configuration: ``Left``)
-    Align reference to the left.
+  .. code-block:: yaml
 
-    .. code-block:: c++
+    ReferenceAlignment: Right
 
-      int& a;
+    # or
 
-  * ``RAS_Right`` (in configuration: ``Right``)
-    Align reference to the right.
+    ReferenceAlignment:
+      Default: Right
 
-    .. code-block:: c++
+  Nested configuration flags:
 
-      int &a;
+  Reference alignment options.
 
-  * ``RAS_Middle`` (in configuration: ``Middle``)
-    Align reference in the middle.
+  * ``ReferenceAlignmentStyle Default``
+    The default alignment for references.
 
-    .. code-block:: c++
+    Possible values:
+
+    * ``RAS_Pointer`` (in configuration: ``Pointer``)
+      Align reference like ``PointerAlignment``.
+
+    * ``RAS_Left`` (in configuration: ``Left``)
+      Align reference to the left.
+
+      .. code-block:: c++
+
+        int& a;
+
+    * ``RAS_Right`` (in configuration: ``Right``)
+      Align reference to the right.
+
+      .. code-block:: c++
+
+        int &a;
+
+    * ``RAS_Middle`` (in configuration: ``Middle``)
+      Align reference in the middle.
+
+      .. code-block:: c++
 
-      int & a;
+        int & a;
 
 
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index b6f124f948b59..2cd446366cfa4 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4036,9 +4036,36 @@ struct FormatStyle {
     PAS_Middle
   };
 
+  /// Pointer and reference alignment options.
+  struct PointerAlignmentOptions {
+    /// The default alignment for pointers and references.
+    PointerAlignmentStyle Default;
+    bool operator==(const PointerAlignmentOptions &R) const {
+      return Default == R.Default;
+    }
+    bool operator!=(const PointerAlignmentOptions &R) const {
+      return !(*this == R);
+    }
+  };
+
   /// Pointer and reference alignment style.
+  ///
+  /// Acceptable values (configured as a single string or with suboptions):
+  /// * ``Left``
+  /// * ``Right``
+  /// * ``Middle``
+  ///
+  /// For example, to configure left pointer alignment:
+  /// \code{.yaml}
+  ///   PointerAlignment: Left
+  ///
+  ///   # or
+  ///
+  ///   PointerAlignment:
+  ///     Default: Left
+  /// \endcode
   /// \version 3.7
-  PointerAlignmentStyle PointerAlignment;
+  PointerAlignmentOptions PointerAlignment;
 
   /// The number of columns to use for indentation of preprocessor statements.
   /// When set to -1 (default) ``IndentWidth`` is used also for preprocessor
@@ -4208,9 +4235,37 @@ struct FormatStyle {
     RAS_Middle
   };
 
+  /// Reference alignment options.
+  struct ReferenceAlignmentOptions {
+    /// The default alignment for references.
+    ReferenceAlignmentStyle Default;
+    bool operator==(const ReferenceAlignmentOptions &R) const {
+      return Default == R.Default;
+    }
+    bool operator!=(const ReferenceAlignmentOptions &R) const {
+      return !(*this == R);
+    }
+  };
+
   /// Reference alignment style (overrides ``PointerAlignment`` for 
references).
+  ///
+  /// Acceptable values (configured as a single string or with suboptions):
+  /// * ``Pointer``
+  /// * ``Left``
+  /// * ``Right``
+  /// * ``Middle``
+  ///
+  /// For example, to configure right reference alignment:
+  /// \code{.yaml}
+  ///   ReferenceAlignment: Right
+  ///
+  ///   # or
+  ///
+  ///   ReferenceAlignment:
+  ///     Default: Right
+  /// \endcode
   /// \version 13
-  ReferenceAlignmentStyle ReferenceAlignment;
+  ReferenceAlignmentOptions ReferenceAlignment;
 
   // clang-format off
   /// Types of comment reflow style.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 9bbb33cb14502..2140cf66cd5af 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -541,10 +541,32 @@ template <> struct 
ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
     IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
     IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
+  }
+};
+
+template <> struct MappingTraits<FormatStyle::PointerAlignmentOptions> {
+  static void enumInput(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
+    IO.enumCase(Value, "Middle",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*Default=*/FormatStyle::PAS_Middle}));
+    IO.enumCase(Value, "Left",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*Default=*/FormatStyle::PAS_Left}));
+    IO.enumCase(Value, "Right",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*Default=*/FormatStyle::PAS_Right}));
 
     // For backward compatibility.
-    IO.enumCase(Value, "true", FormatStyle::PAS_Left);
-    IO.enumCase(Value, "false", FormatStyle::PAS_Right);
+    IO.enumCase(Value, "true",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*Default=*/FormatStyle::PAS_Left}));
+    IO.enumCase(Value, "false",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*Default=*/FormatStyle::PAS_Right}));
+  }
+
+  static void mapping(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
+    IO.mapOptional("Default", Value.Default);
   }
 };
 
@@ -589,6 +611,27 @@ template <> struct 
ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> {
   }
 };
 
+template <> struct MappingTraits<FormatStyle::ReferenceAlignmentOptions> {
+  static void enumInput(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) 
{
+    IO.enumCase(Value, "Pointer",
+                FormatStyle::ReferenceAlignmentOptions(
+                    {/*Default=*/FormatStyle::RAS_Pointer}));
+    IO.enumCase(Value, "Middle",
+                FormatStyle::ReferenceAlignmentOptions(
+                    {/*Default=*/FormatStyle::RAS_Middle}));
+    IO.enumCase(Value, "Left",
+                FormatStyle::ReferenceAlignmentOptions(
+                    {/*Default=*/FormatStyle::RAS_Left}));
+    IO.enumCase(Value, "Right",
+                FormatStyle::ReferenceAlignmentOptions(
+                    {/*Default=*/FormatStyle::RAS_Right}));
+  }
+
+  static void mapping(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
+    IO.mapOptional("Default", Value.Default);
+  }
+};
+
 template <>
 struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
   static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) 
{
@@ -1785,10 +1828,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.ObjCSpaceAfterProperty = false;
   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
   LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
-  LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
+  LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right};
   LLVMStyle.PPIndentWidth = -1;
   LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
-  LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
+  LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer};
   LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
   LLVMStyle.RemoveBracesLLVM = false;
   LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
@@ -1910,7 +1953,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
   GoogleStyle.ObjCSpaceAfterProperty = false;
   GoogleStyle.ObjCSpaceBeforeProtocolList = true;
   GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
-  GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
+  GoogleStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
   GoogleStyle.RawStringFormats = {
       {
           FormatStyle::LK_Cpp,
@@ -2105,7 +2148,7 @@ FormatStyle getMozillaStyle() {
   MozillaStyle.ObjCSpaceAfterProperty = true;
   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
-  MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
+  MozillaStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
   MozillaStyle.SpaceAfterTemplateKeyword = false;
   return MozillaStyle;
 }
@@ -2128,7 +2171,7 @@ FormatStyle getWebKitStyle() {
   Style.NamespaceIndentation = FormatStyle::NI_Inner;
   Style.ObjCBlockIndentWidth = 4;
   Style.ObjCSpaceAfterProperty = true;
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   Style.SpaceBeforeCpp11BracedList = true;
   Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
   return Style;
@@ -2862,10 +2905,10 @@ class Formatter : public TokenAnalyzer {
     if (Style.DerivePointerAlignment) {
       const auto NetRightCount = countVariableAlignments(AnnotatedLines);
       if (NetRightCount > 0)
-        Style.PointerAlignment = FormatStyle::PAS_Right;
+        Style.PointerAlignment.Default = FormatStyle::PAS_Right;
       else if (NetRightCount < 0)
-        Style.PointerAlignment = FormatStyle::PAS_Left;
-      Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
+        Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+      Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
     }
     if (Style.Standard == FormatStyle::LS_Auto) {
       Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index cb41756c56bf7..f48a02c49c562 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4732,7 +4732,7 @@ bool TokenAnnotator::spaceRequiredBetween(const 
AnnotatedLine &Line,
     if (BeforeLeft->is(tok::coloncolon)) {
       if (Left.isNot(tok::star))
         return false;
-      assert(Style.PointerAlignment != FormatStyle::PAS_Right);
+      assert(Style.PointerAlignment.Default != FormatStyle::PAS_Right);
       if (!Right.startsSequence(tok::identifier, tok::r_paren))
         return true;
       assert(Right.Next);
@@ -4744,7 +4744,7 @@ bool TokenAnnotator::spaceRequiredBetween(const 
AnnotatedLine &Line,
   // Ensure right pointer alignment with ellipsis e.g. int *...P
   if (Left.is(tok::ellipsis) && BeforeLeft &&
       BeforeLeft->isPointerOrReference()) {
-    return Style.PointerAlignment != FormatStyle::PAS_Right;
+    return Style.PointerAlignment.Default != FormatStyle::PAS_Right;
   }
 
   if (Right.is(tok::star) && Left.is(tok::l_paren))
@@ -4782,9 +4782,9 @@ bool TokenAnnotator::spaceRequiredBetween(const 
AnnotatedLine &Line,
     // dependent on PointerAlignment style.
     if (Previous) {
       if (Previous->endsSequence(tok::kw_operator))
-        return Style.PointerAlignment != FormatStyle::PAS_Left;
+        return Style.PointerAlignment.Default != FormatStyle::PAS_Left;
       if (Previous->isOneOf(tok::kw_const, tok::kw_volatile)) {
-        return (Style.PointerAlignment != FormatStyle::PAS_Left) ||
+        return (Style.PointerAlignment.Default != FormatStyle::PAS_Left) ||
                (Style.SpaceAroundPointerQualifiers ==
                 FormatStyle::SAPQ_After) ||
                (Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both);
@@ -6543,9 +6543,9 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine 
&Line) const {
 FormatStyle::PointerAlignmentStyle
 TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const 
{
   assert(Reference.isOneOf(tok::amp, tok::ampamp));
-  switch (Style.ReferenceAlignment) {
+  switch (Style.ReferenceAlignment.Default) {
   case FormatStyle::RAS_Pointer:
-    return Style.PointerAlignment;
+    return Style.PointerAlignment.Default;
   case FormatStyle::RAS_Left:
     return FormatStyle::PAS_Left;
   case FormatStyle::RAS_Right:
@@ -6554,7 +6554,7 @@ TokenAnnotator::getTokenReferenceAlignment(const 
FormatToken &Reference) const {
     return FormatStyle::PAS_Middle;
   }
   assert(0); //"Unhandled value of ReferenceAlignment"
-  return Style.PointerAlignment;
+  return Style.PointerAlignment.Default;
 }
 
 FormatStyle::PointerAlignmentStyle
@@ -6563,7 +6563,7 @@ TokenAnnotator::getTokenPointerOrReferenceAlignment(
   if (PointerOrReference.isOneOf(tok::amp, tok::ampamp))
     return getTokenReferenceAlignment(PointerOrReference);
   assert(PointerOrReference.is(tok::star));
-  return Style.PointerAlignment;
+  return Style.PointerAlignment.Default;
 }
 
 } // namespace format
diff --git a/clang/lib/Format/WhitespaceManager.cpp 
b/clang/lib/Format/WhitespaceManager.cpp
index 94ccf9eb7842a..3834f3ca743d6 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -384,14 +384,14 @@ AlignTokenSequence(const FormatStyle &Style, unsigned 
Start, unsigned End,
 
     // If PointerAlignment is PAS_Right, keep *s or &s next to the token,
     // except if the token is equal, then a space is needed.
-    if ((Style.PointerAlignment == FormatStyle::PAS_Right ||
-         Style.ReferenceAlignment == FormatStyle::RAS_Right) &&
+    if ((Style.PointerAlignment.Default == FormatStyle::PAS_Right ||
+         Style.ReferenceAlignment.Default == FormatStyle::RAS_Right) &&
         CurrentChange.Spaces != 0 &&
         CurrentChange.Tok->isNoneOf(tok::equal, tok::r_paren,
                                     TT_TemplateCloser)) {
       const bool ReferenceNotRightAligned =
-          Style.ReferenceAlignment != FormatStyle::RAS_Right &&
-          Style.ReferenceAlignment != FormatStyle::RAS_Pointer;
+          Style.ReferenceAlignment.Default != FormatStyle::RAS_Right &&
+          Style.ReferenceAlignment.Default != FormatStyle::RAS_Pointer;
       for (int Previous = i - 1;
            Previous >= 0 && Changes[Previous].Tok->is(TT_PointerOrReference);
            --Previous) {
@@ -399,7 +399,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned 
Start, unsigned End,
         if (Changes[Previous].Tok->isNot(tok::star)) {
           if (ReferenceNotRightAligned)
             continue;
-        } else if (Style.PointerAlignment != FormatStyle::PAS_Right) {
+        } else if (Style.PointerAlignment.Default != FormatStyle::PAS_Right) {
           continue;
         }
         Changes[Previous + 1].Spaces -= Shift;
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index d578fa7a1a1e8..882f7b1342cc4 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -391,29 +391,39 @@ TEST(ConfigParseTest, ParsesConfiguration) {
 
 #undef CHECK_ALIGN_CONSECUTIVE
 
-  Style.PointerAlignment = FormatStyle::PAS_Middle;
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle};
   CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
-              FormatStyle::PAS_Left);
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Left}));
   CHECK_PARSE("PointerAlignment: Right", PointerAlignment,
-              FormatStyle::PAS_Right);
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Right}));
   CHECK_PARSE("PointerAlignment: Middle", PointerAlignment,
-              FormatStyle::PAS_Middle);
-  Style.ReferenceAlignment = FormatStyle::RAS_Middle;
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Middle}));
+  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle};
   CHECK_PARSE("ReferenceAlignment: Pointer", ReferenceAlignment,
-              FormatStyle::RAS_Pointer);
+              FormatStyle::ReferenceAlignmentOptions(
+                  {/*Default=*/FormatStyle::RAS_Pointer}));
   CHECK_PARSE("ReferenceAlignment: Left", ReferenceAlignment,
-              FormatStyle::RAS_Left);
+              FormatStyle::ReferenceAlignmentOptions(
+                  {/*Default=*/FormatStyle::RAS_Left}));
   CHECK_PARSE("ReferenceAlignment: Right", ReferenceAlignment,
-              FormatStyle::RAS_Right);
+              FormatStyle::ReferenceAlignmentOptions(
+                  {/*Default=*/FormatStyle::RAS_Right}));
   CHECK_PARSE("ReferenceAlignment: Middle", ReferenceAlignment,
-              FormatStyle::RAS_Middle);
+              FormatStyle::ReferenceAlignmentOptions(
+                  {/*Default=*/FormatStyle::RAS_Middle}));
   // For backward compatibility:
   CHECK_PARSE("PointerBindsToType: Left", PointerAlignment,
-              FormatStyle::PAS_Left);
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Left}));
   CHECK_PARSE("PointerBindsToType: Right", PointerAlignment,
-              FormatStyle::PAS_Right);
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Right}));
   CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
-              FormatStyle::PAS_Middle);
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Middle}));
 
   Style.ReflowComments = FormatStyle::RCS_Always;
   CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 81fa7d1d11aa4..4ebcd428a0685 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2047,8 +2047,8 @@ TEST_F(FormatTest, ElseIf) {
 
 TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
   FormatStyle Style = getLLVMStyle();
-  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
-  EXPECT_EQ(Style.ReferenceAlignment, FormatStyle::RAS_Pointer);
+  EXPECT_EQ(Style.PointerAlignment.Default, FormatStyle::PAS_Right);
+  EXPECT_EQ(Style.ReferenceAlignment.Default, FormatStyle::RAS_Pointer);
   verifyFormat("int *f1(int *a, int &b, int &&c);", Style);
   verifyFormat("int &f2(int &&c, int *a, int &b);", Style);
   verifyFormat("int &&f3(int &b, int &&c, int *a);", Style);
@@ -2104,7 +2104,7 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
                "Const unsigned   h;",
                Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("int* f1(int* a, int& b, int&& c);", Style);
   verifyFormat("int& f2(int&& c, int* a, int& b);", Style);
   verifyFormat("int&& f3(int& b, int&& c, int* a);", Style);
@@ -2162,8 +2162,8 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
                "Const unsigned   h;",
                Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Right;
-  Style.ReferenceAlignment = FormatStyle::RAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Left;
   verifyFormat("int *f1(int *a, int& b, int&& c);", Style);
   verifyFormat("int& f2(int&& c, int *a, int& b);", Style);
   verifyFormat("int&& f3(int& b, int&& c, int *a);", Style);
@@ -2200,8 +2200,8 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
                "Const unsigned   h;",
                Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
-  Style.ReferenceAlignment = FormatStyle::RAS_Middle;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Middle;
   verifyFormat("int* f1(int* a, int & b, int && c);", Style);
   verifyFormat("int & f2(int && c, int* a, int & b);", Style);
   verifyFormat("int && f3(int & b, int && c, int* a);", Style);
@@ -2253,8 +2253,8 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
                "Const unsigned    h;",
                Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Middle;
-  Style.ReferenceAlignment = FormatStyle::RAS_Right;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Right;
   verifyFormat("int * f1(int * a, int &b, int &&c);", Style);
   verifyFormat("int &f2(int &&c, int * a, int &b);", Style);
   verifyFormat("int &&f3(int &b, int &&c, int * a);", Style);
@@ -2376,7 +2376,7 @@ TEST_F(FormatTest, FormatsForLoop) {
       NoBinPacking);
 
   FormatStyle AlignLeft = getLLVMStyle();
-  AlignLeft.PointerAlignment = FormatStyle::PAS_Left;
+  AlignLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("for (A* a = start; a < end; ++a, ++value) {\n}", AlignLeft);
 }
 
@@ -8638,7 +8638,7 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) {
                "    void f();");
 
   auto Style = getLLVMStyle();
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
                "    aaaaaaaaaaaaaaaaaaaaaaaaa* const aaaaaaaaaaaa) {}",
                Style);
@@ -9975,7 +9975,7 @@ TEST_F(FormatTest, DeclarationsOfMultipleVariables) {
                "          ***c = ccccccccccccccccccc, ***d = 
ddddddddddddddd;");
 
   FormatStyle Style = getGoogleStyle();
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   Style.DerivePointerAlignment = false;
   verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
                "    *aaaaaaaaaaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaa,\n"
@@ -11465,15 +11465,15 @@ TEST_F(FormatTest, UnderstandsPointersToMembers) {
       "    aaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa));");
 
   FormatStyle Style = getLLVMStyle();
-  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
+  EXPECT_EQ(Style.PointerAlignment.Default, FormatStyle::PAS_Right);
   verifyFormat("typedef bool *(Class::*Member)() const;", Style);
   verifyFormat("void f(int A::*p) { int A::*v = &A::B; }", Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("typedef bool* (Class::*Member)() const;", Style);
   verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Middle;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("typedef bool * (Class::*Member)() const;", Style);
   verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style);
 }
@@ -11533,7 +11533,7 @@ TEST_F(FormatTest, UnderstandsUnaryOperators) {
   // Check that * is not treated as a binary operator when we set
   // PointerAlignment as PAS_Left after a keyword and not a declaration.
   FormatStyle PASLeftStyle = getLLVMStyle();
-  PASLeftStyle.PointerAlignment = FormatStyle::PAS_Left;
+  PASLeftStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("co_return *a;", PASLeftStyle);
   verifyFormat("co_await *a;", PASLeftStyle);
   verifyFormat("co_yield *a", PASLeftStyle);
@@ -11661,7 +11661,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) 
{
   verifyFormat("template <typename T> void operator=(T) && {}");
 
   FormatStyle AlignLeft = getLLVMStyle();
-  AlignLeft.PointerAlignment = FormatStyle::PAS_Left;
+  AlignLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("void A::b() && {}", AlignLeft);
   verifyFormat("void A::b() && noexcept {}", AlignLeft);
   verifyFormat("Deleted& operator=(const Deleted&) & = default;", AlignLeft);
@@ -11693,7 +11693,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) 
{
   verifyFormat("for (foo<void() &&>& cb : X)", AlignLeft);
 
   FormatStyle AlignMiddle = getLLVMStyle();
-  AlignMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+  AlignMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("void A::b() && {}", AlignMiddle);
   verifyFormat("void A::b() && noexcept {}", AlignMiddle);
   verifyFormat("Deleted & operator=(const Deleted &) & = default;",
@@ -11776,7 +11776,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) 
{
 
   FormatStyle AlignLeftBreakTemplate = getLLVMStyle();
   AlignLeftBreakTemplate.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
-  AlignLeftBreakTemplate.PointerAlignment = FormatStyle::PAS_Left;
+  AlignLeftBreakTemplate.PointerAlignment.Default = FormatStyle::PAS_Left;
 
   verifyFormat("struct f {\n"
                "  template <class T>\n"
@@ -11860,19 +11860,19 @@ TEST_F(FormatTest, PointerAlignmentFallback) {
                            "int *q;\n"
                            "int * r;");
 
-  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
+  EXPECT_EQ(Style.PointerAlignment.Default, FormatStyle::PAS_Right);
   verifyFormat("int *p;\n"
                "int *q;\n"
                "int *r;",
                Code, Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("int* p;\n"
                "int* q;\n"
                "int* r;",
                Code, Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Middle;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("int * p;\n"
                "int * q;\n"
                "int * r;",
@@ -12068,7 +12068,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
                      "void f(int i = 0, SomeType** temps = NULL);");
 
   FormatStyle Left = getLLVMStyle();
-  Left.PointerAlignment = FormatStyle::PAS_Left;
+  Left.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("x = *a(x) = *a(y);", Left);
   verifyFormat("for (;; *a = b) {\n}", Left);
   verifyFormat("return *this += 1;", Left);
@@ -12214,7 +12214,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
       getGoogleStyleWithColumns(68));
 
   FormatStyle Style = getLLVMStyle();
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("struct {\n"
                "}* ptr;",
                Style);
@@ -12238,7 +12238,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
                Style);
   verifyFormat("bool b = 3 == int{3} && true;");
 
-  Style.PointerAlignment = FormatStyle::PAS_Middle;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("struct {\n"
                "} * ptr;",
                Style);
@@ -12258,7 +12258,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
                "} && ptr = {};",
                Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Right;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
   verifyFormat("struct {\n"
                "} *ptr;",
                Style);
@@ -12278,7 +12278,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
                "} &&ptr = {};",
                Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("delete[] *ptr;", Style);
   verifyFormat("delete[] **ptr;", Style);
   verifyFormat("delete[] *(ptr);", Style);
@@ -12369,7 +12369,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
   verifyFormat("foo<a<b && c> d> v;");
 
   FormatStyle PointerMiddle = getLLVMStyle();
-  PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+  PointerMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("delete *x;", PointerMiddle);
   verifyFormat("int * x;", PointerMiddle);
   verifyFormat("int *[] x;", PointerMiddle);
@@ -12476,7 +12476,7 @@ TEST_F(FormatTest, UnderstandsAttributes) {
 
   auto Style = getLLVMStyleWithColumns(60);
   Style.AttributeMacros.push_back("my_fancy_attr");
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("void foo(const MyLongTypeNameeeeeeeeeeeee* my_fancy_attr\n"
                "             testttttttttt);",
                Style);
@@ -12504,7 +12504,7 @@ TEST_F(FormatTest, UnderstandsPointerQualifiersInCast) {
   // determine that the expression is a cast to a pointer type.
   FormatStyle LongPointerRight = getLLVMStyleWithColumns(999);
   FormatStyle LongPointerLeft = getLLVMStyleWithColumns(999);
-  LongPointerLeft.PointerAlignment = FormatStyle::PAS_Left;
+  LongPointerLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
   StringRef AllQualifiers =
       "const volatile restrict __attribute__((foo)) _Nonnull _Null_unspecified 
"
       "_Nullable [[clang::attr]] __ptr32 __ptr64 __capability";
@@ -12640,12 +12640,12 @@ TEST_F(FormatTest, UnderstandsEllipsis) {
 
   verifyFormat("template <int *...PP> a;", Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("template <class... Ts> void Foo(Ts*... ts) {}", Style);
 
   verifyFormat("template <int*... PP> a;", Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Middle;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("template <int *... PP> a;", Style);
 }
 
@@ -16253,15 +16253,15 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
 
   FormatStyle TabAlignment = Tab;
   TabAlignment.AlignConsecutiveDeclarations.Enabled = true;
-  TabAlignment.PointerAlignment = FormatStyle::PAS_Left;
+  TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("unsigned long long big;\n"
                "char*\t\t   ptr;",
                TabAlignment);
-  TabAlignment.PointerAlignment = FormatStyle::PAS_Middle;
+  TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("unsigned long long big;\n"
                "char *\t\t   ptr;",
                TabAlignment);
-  TabAlignment.PointerAlignment = FormatStyle::PAS_Right;
+  TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Right;
   verifyFormat("unsigned long long big;\n"
                "char\t\t  *ptr;",
                TabAlignment);
@@ -16309,19 +16309,19 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
                Tab);
 
   TabAlignment.UseTab = FormatStyle::UT_ForIndentation;
-  TabAlignment.PointerAlignment = FormatStyle::PAS_Left;
+  TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("void f() {\n"
                "\tunsigned long long big;\n"
                "\tchar*              ptr;\n"
                "}",
                TabAlignment);
-  TabAlignment.PointerAlignment = FormatStyle::PAS_Middle;
+  TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("void f() {\n"
                "\tunsigned long long big;\n"
                "\tchar *             ptr;\n"
                "}",
                TabAlignment);
-  TabAlignment.PointerAlignment = FormatStyle::PAS_Right;
+  TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Right;
   verifyFormat("void f() {\n"
                "\tunsigned long long big;\n"
                "\tchar              *ptr;\n"
@@ -18227,13 +18227,13 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeColon) {
 TEST_F(FormatTest, ConfigurableSpaceAroundPointerQualifiers) {
   FormatStyle Style = getLLVMStyle();
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   Style.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
   verifyFormat("void* const* x = NULL;", Style);
 
 #define verifyQualifierSpaces(Code, Pointers, Qualifiers)                      
\
   do {                                                                         
\
-    Style.PointerAlignment = FormatStyle::Pointers;                            
\
+    Style.PointerAlignment.Default = FormatStyle::Pointers;                    
\
     Style.SpaceAroundPointerQualifiers = FormatStyle::Qualifiers;              
\
     verifyFormat(Code, Style);                                                 
\
   } while (false)
@@ -18279,7 +18279,7 @@ TEST_F(FormatTest, 
ConfigurableSpaceAroundPointerQualifiers) {
 
   FormatStyle Spaces = getLLVMStyle();
   Spaces.AttributeMacros.push_back("qualified");
-  Spaces.PointerAlignment = FormatStyle::PAS_Right;
+  Spaces.PointerAlignment.Default = FormatStyle::PAS_Right;
   Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
   verifyFormat("SomeType *volatile *a = NULL;", Spaces);
   verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces);
@@ -18294,7 +18294,7 @@ TEST_F(FormatTest, 
ConfigurableSpaceAroundPointerQualifiers) {
   verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
 
   // Check that SAPQ_Before doesn't result in extra spaces for PAS_Left.
-  Spaces.PointerAlignment = FormatStyle::PAS_Left;
+  Spaces.PointerAlignment.Default = FormatStyle::PAS_Left;
   Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Before;
   verifyFormat("SomeType* volatile* a = NULL;", Spaces);
   verifyFormat("SomeType* __attribute__((attr))* a = NULL;", Spaces);
@@ -18310,7 +18310,7 @@ TEST_F(FormatTest, 
ConfigurableSpaceAroundPointerQualifiers) {
   verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
 
   // PAS_Middle should not have any noticeable changes even for SAPQ_Both
-  Spaces.PointerAlignment = FormatStyle::PAS_Middle;
+  Spaces.PointerAlignment.Default = FormatStyle::PAS_Middle;
   Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_After;
   verifyFormat("SomeType * volatile * a = NULL;", Spaces);
   verifyFormat("SomeType * __attribute__((attr)) * a = NULL;", Spaces);
@@ -19756,7 +19756,7 @@ TEST_F(FormatTest, AlignConsecutiveBitFields) {
 TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   FormatStyle Alignment = getLLVMStyle();
   Alignment.AlignConsecutiveMacros.Enabled = true;
-  Alignment.PointerAlignment = FormatStyle::PAS_Right;
+  Alignment.PointerAlignment.Default = FormatStyle::PAS_Right;
   verifyFormat("float const a = 5;\n"
                "int oneTwoThree = 123;",
                Alignment);
@@ -20023,7 +20023,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
 
   // PAS_Left
   FormatStyle AlignmentLeft = Alignment;
-  AlignmentLeft.PointerAlignment = FormatStyle::PAS_Left;
+  AlignmentLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("void SomeFunction(int parameter = 0) {\n"
                "  int const i   = 1;\n"
                "  int*      j   = 2;\n"
@@ -20097,7 +20097,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
 
   // PAS_Middle
   FormatStyle AlignmentMiddle = Alignment;
-  AlignmentMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+  AlignmentMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("void SomeFunction(int parameter = 0) {\n"
                "  int const i   = 1;\n"
                "  int *     j   = 2;\n"
@@ -20313,14 +20313,14 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
   Alignment.ColumnLimit = 80;
 
   // Bug 33507
-  Alignment.PointerAlignment = FormatStyle::PAS_Middle;
+  Alignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat(
       "auto found = range::find_if(vsProducts, [&](auto * aProduct) {\n"
       "  static const Version verVs2017;\n"
       "  return true;\n"
       "});",
       Alignment);
-  Alignment.PointerAlignment = FormatStyle::PAS_Right;
+  Alignment.PointerAlignment.Default = FormatStyle::PAS_Right;
 
   // See llvm.org/PR35641
   Alignment.AlignConsecutiveDeclarations.Enabled = true;
@@ -20337,7 +20337,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
                "foo(int a);",
                "DECOR1 /**/ int8_t /**/ DECOR2 /**/ foo (int a);", Style);
 
-  Alignment.PointerAlignment = FormatStyle::PAS_Left;
+  Alignment.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("unsigned int*       a;\n"
                "int*                b;\n"
                "unsigned int Const* c;\n"
@@ -20353,7 +20353,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
                "Const unsigned      h;",
                Alignment);
 
-  Alignment.PointerAlignment = FormatStyle::PAS_Middle;
+  Alignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("unsigned int *       a;\n"
                "int *                b;\n"
                "unsigned int Const * c;\n"
@@ -25086,7 +25086,7 @@ TEST_F(FormatTest, StructuredBindings) {
 
   // Make sure we don't mistake structured bindings for lambdas.
   FormatStyle PointerMiddle = getLLVMStyle();
-  PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+  PointerMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyGoogleFormat("auto [a1, b]{A * i};");
   verifyFormat("auto [a2, b]{A * i};");
   verifyFormat("auto [a3, b]{A * i};", PointerMiddle);
@@ -25330,7 +25330,7 @@ TEST_F(FormatTest, TypenameMacros) {
   verifyFormat("vector<LIST(uint64_t) *attr> x;", Macros);
   verifyFormat("vector<LIST(uint64_t) *const> f(LIST(uint64_t) *arg);", 
Macros);
 
-  Macros.PointerAlignment = FormatStyle::PAS_Left;
+  Macros.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("STACK_OF(int)* a;", Macros);
   verifyFormat("STACK_OF(int*)* a;", Macros);
   verifyFormat("x = (STACK_OF(uint64_t))*a;", Macros);
@@ -25361,7 +25361,7 @@ TEST_F(FormatTest, AtomicQualifier) {
   verifyFormat("_Atomic(uint64_t) *s(InitValue);");
   verifyFormat("_Atomic(uint64_t) *s{InitValue};");
   FormatStyle Style = getLLVMStyle();
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("_Atomic(uint64_t)* s(InitValue);", Style);
   verifyFormat("_Atomic(uint64_t)* s{InitValue};", Style);
   verifyFormat("_Atomic(int)* a;", Style);
@@ -25424,9 +25424,9 @@ TEST_F(FormatTest, C11Generic) {
 TEST_F(FormatTest, AmbersandInLamda) {
   // Test case reported in https://bugs.llvm.org/show_bug.cgi?id=41899
   FormatStyle AlignStyle = getLLVMStyle();
-  AlignStyle.PointerAlignment = FormatStyle::PAS_Left;
+  AlignStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle);
-  AlignStyle.PointerAlignment = FormatStyle::PAS_Right;
+  AlignStyle.PointerAlignment.Default = FormatStyle::PAS_Right;
   verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle);
 }
 
@@ -25554,7 +25554,7 @@ TEST_F(FormatTest, STLWhileNotDefineChed) {
 
 TEST_F(FormatTest, OperatorSpacing) {
   FormatStyle Style = getLLVMStyle();
-  Style.PointerAlignment = FormatStyle::PAS_Right;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
   verifyFormat("Foo::operator*();", Style);
   verifyFormat("Foo::operator void *();", Style);
   verifyFormat("Foo::operator void **();", Style);
@@ -25610,7 +25610,7 @@ TEST_F(FormatTest, OperatorSpacing) {
   verifyFormat("operator const FooRight<Object> *&()", Style);
   verifyFormat("operator const FooRight<Object> *&&()", Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
   verifyFormat("Foo::operator*();", Style);
   verifyFormat("Foo::operator**();", Style);
   verifyFormat("Foo::operator void*();", Style);
@@ -25681,7 +25681,7 @@ TEST_F(FormatTest, OperatorSpacing) {
   verifyFormat("operator/*a*/ const /*b*/ Foo /*c*/<X> /*d*/ ::Bar<Y>*();",
                Style);
 
-  Style.PointerAlignment = FormatStyle::PAS_Middle;
+  Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
   verifyFormat("Foo::operator*();", Style);
   verifyFormat("Foo::operator void *();", Style);
   verifyFormat("Foo::operator()(void *);", Style);
@@ -27940,7 +27940,7 @@ TEST_F(FormatTest, BreakAfterAttributes) {
                "Foo &operator-(Foo &);",
                Style);
 
-  Style.ReferenceAlignment = FormatStyle::RAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Left;
   verifyFormat("[[nodiscard]]\n"
                "Foo& operator-(Foo&);",
                Style);

>From a4ca42e69ed638969ec78c66781fbb09c986e42e Mon Sep 17 00:00:00 2001
From: Daan De Meyer <[email protected]>
Date: Sat, 22 Nov 2025 11:35:28 +0100
Subject: [PATCH 2/3] [clang-format] Allow custom pointer/ref alignment in
 return types

I would like to adopt clang-format in systemd
(https://github.com/systemd/systemd). One major blocker is that
systemd right-aligns pointers by default, except in function return
types, where they are left-aligned.

Let's introduce a ReturnType customization for PointerAlignment and
ReferenceAlignment that allows overriding the alignment used in return
types.

systemd style guide: 
https://github.com/systemd/systemd/blob/main/docs/CODING_STYLE.md

Fixes #136597
---
 clang/docs/ClangFormatStyleOptions.rst     |  60 +++++++
 clang/include/clang/Format/Format.h        |  29 ++-
 clang/lib/Format/Format.cpp                |  46 +++--
 clang/lib/Format/TokenAnnotator.cpp        |  76 +++++++-
 clang/unittests/Format/ConfigParseTest.cpp |  52 ++++--
 clang/unittests/Format/FormatTest.cpp      | 200 +++++++++++++++++++++
 6 files changed, 436 insertions(+), 27 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index ab21290260005..119685d39d347 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5718,6 +5718,36 @@ the configuration (without a prefix: ``Auto``).
         int * a;
 
 
+  * ``ReturnTypeAlignmentStyle ReturnType``
+    The alignment for pointers in function return types.
+
+    Possible values:
+
+    * ``RTAS_Default`` (in configuration: ``Default``)
+      Use default alignment.
+
+    * ``RTAS_Left`` (in configuration: ``Left``)
+      Align pointer/reference to the left.
+
+      .. code-block:: c++
+
+        int* a(void);
+
+    * ``RTAS_Right`` (in configuration: ``Right``)
+      Align pointer/reference to the right.
+
+      .. code-block:: c++
+
+        int *a(void);
+
+    * ``RTAS_Middle`` (in configuration: ``Middle``)
+      Align pointer/reference in the middle.
+
+      .. code-block:: c++
+
+        int * a(void);
+
+
 
 .. _QualifierAlignment:
 
@@ -5901,6 +5931,36 @@ the configuration (without a prefix: ``Auto``).
         int & a;
 
 
+  * ``ReturnTypeAlignmentStyle ReturnType``
+    The alignment for references in function return types.
+
+    Possible values:
+
+    * ``RTAS_Default`` (in configuration: ``Default``)
+      Use default alignment.
+
+    * ``RTAS_Left`` (in configuration: ``Left``)
+      Align pointer/reference to the left.
+
+      .. code-block:: c++
+
+        int* a(void);
+
+    * ``RTAS_Right`` (in configuration: ``Right``)
+      Align pointer/reference to the right.
+
+      .. code-block:: c++
+
+        int *a(void);
+
+    * ``RTAS_Middle`` (in configuration: ``Middle``)
+      Align pointer/reference in the middle.
+
+      .. code-block:: c++
+
+        int * a(void);
+
+
 
 .. _ReflowComments:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 2cd446366cfa4..3919c1d0bc8b3 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4036,12 +4036,35 @@ struct FormatStyle {
     PAS_Middle
   };
 
+  /// \brief The pointer/reference alignment style for function return types.
+  enum ReturnTypeAlignmentStyle : int8_t {
+    /// Use default alignment.
+    RTAS_Default,
+    /// Align pointer/reference to the left.
+    /// \code
+    ///   int* a(void);
+    /// \endcode
+    RTAS_Left,
+    /// Align pointer/reference to the right.
+    /// \code
+    ///   int *a(void);
+    /// \endcode
+    RTAS_Right,
+    /// Align pointer/reference in the middle.
+    /// \code
+    ///   int * a(void);
+    /// \endcode
+    RTAS_Middle
+  };
+
   /// Pointer and reference alignment options.
   struct PointerAlignmentOptions {
     /// The default alignment for pointers and references.
     PointerAlignmentStyle Default;
+    /// The alignment for pointers in function return types.
+    ReturnTypeAlignmentStyle ReturnType;
     bool operator==(const PointerAlignmentOptions &R) const {
-      return Default == R.Default;
+      return Default == R.Default && ReturnType == R.ReturnType;
     }
     bool operator!=(const PointerAlignmentOptions &R) const {
       return !(*this == R);
@@ -4239,8 +4262,10 @@ struct FormatStyle {
   struct ReferenceAlignmentOptions {
     /// The default alignment for references.
     ReferenceAlignmentStyle Default;
+    /// The alignment for references in function return types.
+    ReturnTypeAlignmentStyle ReturnType;
     bool operator==(const ReferenceAlignmentOptions &R) const {
-      return Default == R.Default;
+      return Default == R.Default && ReturnType == R.ReturnType;
     }
     bool operator!=(const ReferenceAlignmentOptions &R) const {
       return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 2140cf66cd5af..f950d64b29436 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -544,29 +544,46 @@ template <> struct 
ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
   }
 };
 
+template <>
+struct ScalarEnumerationTraits<FormatStyle::ReturnTypeAlignmentStyle> {
+  static void enumeration(IO &IO,
+                          FormatStyle::ReturnTypeAlignmentStyle &Value) {
+    IO.enumCase(Value, "Default", FormatStyle::RTAS_Default);
+    IO.enumCase(Value, "Middle", FormatStyle::RTAS_Middle);
+    IO.enumCase(Value, "Left", FormatStyle::RTAS_Left);
+    IO.enumCase(Value, "Right", FormatStyle::RTAS_Right);
+  }
+};
+
 template <> struct MappingTraits<FormatStyle::PointerAlignmentOptions> {
   static void enumInput(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
     IO.enumCase(Value, "Middle",
                 FormatStyle::PointerAlignmentOptions(
-                    {/*Default=*/FormatStyle::PAS_Middle}));
+                    {/*Default=*/FormatStyle::PAS_Middle,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
     IO.enumCase(Value, "Left",
                 FormatStyle::PointerAlignmentOptions(
-                    {/*Default=*/FormatStyle::PAS_Left}));
+                    {/*Default=*/FormatStyle::PAS_Left,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
     IO.enumCase(Value, "Right",
                 FormatStyle::PointerAlignmentOptions(
-                    {/*Default=*/FormatStyle::PAS_Right}));
+                    {/*Default=*/FormatStyle::PAS_Right,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
 
     // For backward compatibility.
     IO.enumCase(Value, "true",
                 FormatStyle::PointerAlignmentOptions(
-                    {/*Default=*/FormatStyle::PAS_Left}));
+                    {/*Default=*/FormatStyle::PAS_Left,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
     IO.enumCase(Value, "false",
                 FormatStyle::PointerAlignmentOptions(
-                    {/*Default=*/FormatStyle::PAS_Right}));
+                    {/*Default=*/FormatStyle::PAS_Right,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
   }
 
   static void mapping(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
     IO.mapOptional("Default", Value.Default);
+    IO.mapOptional("ReturnType", Value.ReturnType);
   }
 };
 
@@ -615,20 +632,25 @@ template <> struct 
MappingTraits<FormatStyle::ReferenceAlignmentOptions> {
   static void enumInput(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) 
{
     IO.enumCase(Value, "Pointer",
                 FormatStyle::ReferenceAlignmentOptions(
-                    {/*Default=*/FormatStyle::RAS_Pointer}));
+                    {/*Default=*/FormatStyle::RAS_Pointer,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
     IO.enumCase(Value, "Middle",
                 FormatStyle::ReferenceAlignmentOptions(
-                    {/*Default=*/FormatStyle::RAS_Middle}));
+                    {/*Default=*/FormatStyle::RAS_Middle,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
     IO.enumCase(Value, "Left",
                 FormatStyle::ReferenceAlignmentOptions(
-                    {/*Default=*/FormatStyle::RAS_Left}));
+                    {/*Default=*/FormatStyle::RAS_Left,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
     IO.enumCase(Value, "Right",
                 FormatStyle::ReferenceAlignmentOptions(
-                    {/*Default=*/FormatStyle::RAS_Right}));
+                    {/*Default=*/FormatStyle::RAS_Right,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
   }
 
   static void mapping(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
     IO.mapOptional("Default", Value.Default);
+    IO.mapOptional("ReturnType", Value.ReturnType);
   }
 };
 
@@ -1828,10 +1850,12 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.ObjCSpaceAfterProperty = false;
   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
   LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
-  LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right};
+  LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right,
+                                /*ReturnType=*/FormatStyle::RTAS_Default};
   LLVMStyle.PPIndentWidth = -1;
   LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
-  LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer};
+  LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                                  /*ReturnType=*/FormatStyle::RTAS_Default};
   LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
   LLVMStyle.RemoveBracesLLVM = false;
   LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index f48a02c49c562..fe53d70eb12d7 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -6540,9 +6540,76 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine 
&Line) const {
   llvm::errs() << "----\n";
 }
 
+static bool isReturnType(const FormatToken &Tok, const LangOptions &LangOpts) {
+  // Look forward to see if there's a function declaration paren.
+  for (const FormatToken *Next = Tok.Next; Next;
+       Next = Next->getNextNonComment()) {
+    if (Next->isOneOf(TT_FunctionDeclarationName, TT_FunctionDeclarationLParen,
+                      TT_FunctionTypeLParen)) {
+      return true;
+    }
+
+    if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
+      Next = Next->MatchingParen;
+      continue;
+    }
+
+    if (Next->isPointerOrReference() || Next->isTypeName(LangOpts) ||
+        Next->isOneOf(tok::identifier, tok::coloncolon) ||
+        Next->canBePointerOrReferenceQualifier()) {
+      continue;
+    }
+
+    break;
+  }
+
+  // Look backward to see if there's a trailing return arrow.
+  for (const FormatToken *Prev = Tok.Previous; Prev;
+       Prev = Prev->getPreviousNonComment()) {
+    if (Prev->is(TT_TrailingReturnArrow))
+      return true;
+
+    if (Prev->is(TT_TemplateCloser) && Prev->MatchingParen) {
+      Prev = Prev->MatchingParen;
+      continue;
+    }
+
+    if (Prev->isPointerOrReference() || Prev->isTypeName(LangOpts) ||
+        Prev->isOneOf(tok::identifier, tok::coloncolon) ||
+        Prev->canBePointerOrReferenceQualifier()) {
+      continue;
+    }
+
+    break;
+  }
+
+  return false;
+}
+
+static FormatStyle::PointerAlignmentStyle
+mapReturnTypeAlignmentStyle(FormatStyle::ReturnTypeAlignmentStyle Style) {
+  switch (Style) {
+  case FormatStyle::RTAS_Left:
+    return FormatStyle::PAS_Left;
+  case FormatStyle::RTAS_Right:
+    return FormatStyle::PAS_Right;
+  case FormatStyle::RTAS_Middle:
+    return FormatStyle::PAS_Middle;
+  case FormatStyle::RTAS_Default:
+    assert(false);
+  }
+  llvm_unreachable("Unknown FormatStyle::ReturnTypeAlignmentStyle enum");
+}
+
 FormatStyle::PointerAlignmentStyle
 TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const 
{
   assert(Reference.isOneOf(tok::amp, tok::ampamp));
+
+  if (Style.ReferenceAlignment.ReturnType != FormatStyle::RTAS_Default &&
+      isReturnType(Reference, LangOpts)) {
+    return mapReturnTypeAlignmentStyle(Style.ReferenceAlignment.ReturnType);
+  }
+
   switch (Style.ReferenceAlignment.Default) {
   case FormatStyle::RAS_Pointer:
     return Style.PointerAlignment.Default;
@@ -6553,8 +6620,7 @@ TokenAnnotator::getTokenReferenceAlignment(const 
FormatToken &Reference) const {
   case FormatStyle::RAS_Middle:
     return FormatStyle::PAS_Middle;
   }
-  assert(0); //"Unhandled value of ReferenceAlignment"
-  return Style.PointerAlignment.Default;
+  llvm_unreachable("Unknown FormatStyle::ReferenceAlignmentStyle enum");
 }
 
 FormatStyle::PointerAlignmentStyle
@@ -6563,6 +6629,12 @@ TokenAnnotator::getTokenPointerOrReferenceAlignment(
   if (PointerOrReference.isOneOf(tok::amp, tok::ampamp))
     return getTokenReferenceAlignment(PointerOrReference);
   assert(PointerOrReference.is(tok::star));
+
+  if (Style.PointerAlignment.ReturnType != FormatStyle::RTAS_Default &&
+      isReturnType(PointerOrReference, LangOpts)) {
+    return mapReturnTypeAlignmentStyle(Style.PointerAlignment.ReturnType);
+  }
+
   return Style.PointerAlignment.Default;
 }
 
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index 882f7b1342cc4..cf54b79bcf8a6 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -391,39 +391,67 @@ TEST(ConfigParseTest, ParsesConfiguration) {
 
 #undef CHECK_ALIGN_CONSECUTIVE
 
-  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle};
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle,
+                            /*ReturnType=*/FormatStyle::RTAS_Default};
   CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
-                  {/*Default=*/FormatStyle::PAS_Left}));
+                  {/*Default=*/FormatStyle::PAS_Left,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
   CHECK_PARSE("PointerAlignment: Right", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
-                  {/*Default=*/FormatStyle::PAS_Right}));
+                  {/*Default=*/FormatStyle::PAS_Right,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
   CHECK_PARSE("PointerAlignment: Middle", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
-                  {/*Default=*/FormatStyle::PAS_Middle}));
-  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle};
+                  {/*Default=*/FormatStyle::PAS_Middle,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+  CHECK_PARSE("PointerAlignment:\n"
+              "  Default: Right\n"
+              "  ReturnType: Left",
+              PointerAlignment,
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Right,
+                   /*ReturnType=*/FormatStyle::RTAS_Left}));
+
+  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle,
+                              /*ReturnType=*/FormatStyle::RTAS_Default};
   CHECK_PARSE("ReferenceAlignment: Pointer", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
-                  {/*Default=*/FormatStyle::RAS_Pointer}));
+                  {/*Default=*/FormatStyle::RAS_Pointer,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
   CHECK_PARSE("ReferenceAlignment: Left", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
-                  {/*Default=*/FormatStyle::RAS_Left}));
+                  {/*Default=*/FormatStyle::RAS_Left,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
   CHECK_PARSE("ReferenceAlignment: Right", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
-                  {/*Default=*/FormatStyle::RAS_Right}));
+                  {/*Default=*/FormatStyle::RAS_Right,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
   CHECK_PARSE("ReferenceAlignment: Middle", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
-                  {/*Default=*/FormatStyle::RAS_Middle}));
+                  {/*Default=*/FormatStyle::RAS_Middle,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+  CHECK_PARSE("ReferenceAlignment:\n"
+              "  Default: Right\n"
+              "  ReturnType: Left",
+              ReferenceAlignment,
+              FormatStyle::ReferenceAlignmentOptions(
+                  {/*Default=*/FormatStyle::RAS_Right,
+                   /*ReturnType=*/FormatStyle::RTAS_Left}));
+
   // For backward compatibility:
   CHECK_PARSE("PointerBindsToType: Left", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
-                  {/*Default=*/FormatStyle::PAS_Left}));
+                  {/*Default=*/FormatStyle::PAS_Left,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
   CHECK_PARSE("PointerBindsToType: Right", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
-                  {/*Default=*/FormatStyle::PAS_Right}));
+                  {/*Default=*/FormatStyle::PAS_Right,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
   CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
-                  {/*Default=*/FormatStyle::PAS_Middle}));
+                  {/*Default=*/FormatStyle::PAS_Middle,
+                   /*ReturnType=*/FormatStyle::RTAS_Default}));
 
   Style.ReflowComments = FormatStyle::RCS_Always;
   CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 4ebcd428a0685..ad14e7d1f0429 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2296,6 +2296,206 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
   // verifyFormat("int Add2(BTree * &Root, char * szToAdd)", Style);
 }
 
+TEST_F(FormatTest, ReturnTypeAlignment) {
+  // Test that ReturnType overrides PointerAlignment for return types
+  FormatStyle Style = getLLVMStyle();
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Left;
+
+  // Return type pointers should be left-aligned despite PAS_Right
+  verifyFormat("int* f1(int *a, int *b);", Style);
+  verifyFormat("int& f2(int &a, int &b);", Style);
+  verifyFormat("int&& f3(int &&a, int &&b);", Style);
+
+  // Multiple pointers in return type
+  verifyFormat("int** f4(int **a);", Style);
+  verifyFormat("const int* f5(const int *a);", Style);
+  verifyFormat("int*** f6(int ***a);", Style);
+
+  // Multiple pointers with const qualifiers
+  verifyFormat("const int** f7(const int **a);", Style);
+  verifyFormat("int* const* f8(int *const *a);", Style);
+  verifyFormat("const int* const* f9(const int *const *a);", Style);
+  verifyFormat("int** const f10(int **const a);", Style);
+  verifyFormat("const int** const f11(const int **const a);", Style);
+
+  // Complex return types
+  verifyFormat("std::vector<int>* f16(std::vector<int> *a);", Style);
+  verifyFormat("const char* f17(const char *str);", Style);
+  verifyFormat("const char** f18(const char **argv);", Style);
+  verifyFormat("char* const* f19(char *const *envp);", Style);
+
+  // Member functions
+  verifyFormat("int* Class::method(int *a);", Style);
+  verifyFormat("int& Class::method(int &a);", Style);
+  verifyFormat("int* (*f8())(int *a);", Style);
+
+  // Variables should still follow the default alignment
+  verifyFormat("int *a = nullptr;", Style);
+  verifyFormat("int *b = f1(a, a);", Style);
+
+  // Now test with PAS_Left base and RTAS_Right return type
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Right;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+  // Return type pointers should be right-aligned despite PAS_Left
+  verifyFormat("int *f1(int* a, int* b);", Style);
+  verifyFormat("int &f2(int& a, int& b);", Style);
+  verifyFormat("int &&f3(int&& a, int&& b);", Style);
+
+  // Multiple pointers with right alignment in return type
+  verifyFormat("int **f4(int** a);", Style);
+  verifyFormat("const int *f5(const int* a);", Style);
+  verifyFormat("int ***f6(int*** a);", Style);
+
+  // Multiple pointers with const qualifiers, right-aligned return type
+  verifyFormat("const int **f7(const int** a);", Style);
+  verifyFormat("int *const *f8(int* const* a);", Style);
+  verifyFormat("const int *const *f9(const int* const* a);", Style);
+  verifyFormat("int **const f10(int** const a);", Style);
+  verifyFormat("const char **f11(const char** argv);", Style);
+
+  // Variables should still follow PointerAlignment (PAS_Left)
+  verifyFormat("int* a = nullptr;", Style);
+  verifyFormat("int* b = f1(a, a);", Style);
+
+  // Test with RTAS_Middle
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Middle;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Middle;
+
+  verifyFormat("int * f1(int *a, int *b);", Style);
+  verifyFormat("int & f2(int &a, int &b);", Style);
+  verifyFormat("int && f3(int &&a, int &&b);", Style);
+
+  // Multiple pointers with const qualifiers, middle-aligned return type
+  verifyFormat("const int * f6(const int *a);", Style);
+  verifyFormat("const int ** f7(const int **a);", Style);
+  verifyFormat("int * const * f8(int *const *a);", Style);
+  verifyFormat("const int * const * f9(const int *const *a);", Style);
+  verifyFormat("int ** const f10(int **const a);", Style);
+  verifyFormat("const char ** f11(const char **argv);", Style);
+
+  // Variables should still follow PointerAlignment (PAS_Right)
+  verifyFormat("int *a = nullptr;", Style);
+
+  // Test that default alignment is used when ReturnType is RTAS_Default
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Default;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Default;
+
+  verifyFormat("int* f1(int* a, int* b);", Style);
+  verifyFormat("int& f2(int& a, int& b);", Style);
+
+  // Test with ReferenceAlignment override
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+  verifyFormat("int* f1(int *a, int &b);", Style);
+  verifyFormat("int &f2(int &a, int *b);", Style);
+  verifyFormat("int &&f3(int &&a, int *b);", Style);
+
+  // Test trailing return types with PAS_Right and RTAS_Left
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Left;
+
+  verifyFormat("auto f1(int *a, int *b) -> int*;", Style);
+  verifyFormat("auto f2(int &a, int &b) -> int&;", Style);
+  verifyFormat("auto f3(int &&a, int &&b) -> int&&;", Style);
+
+  // Multiple pointers in trailing return type
+  verifyFormat("auto f4(int **a) -> int**;", Style);
+  verifyFormat("auto f5(const int *a) -> const int*;", Style);
+  verifyFormat("auto f6(int ***a) -> int***;", Style);
+
+  // Multiple pointers with const qualifiers
+  verifyFormat("auto f7(const int **a) -> const int**;", Style);
+  verifyFormat("auto f8(int *const *a) -> int* const*;", Style);
+  verifyFormat("auto f9(const int *const *a) -> const int* const*;", Style);
+  verifyFormat("auto f10(int **const a) -> int** const;", Style);
+  verifyFormat("auto f11(const int **const a) -> const int** const;", Style);
+
+  // Complex trailing return types
+  verifyFormat("auto f16(std::vector<int> *a) -> std::vector<int>*;", Style);
+  verifyFormat("auto f17(const char *str) -> const char*;", Style);
+  verifyFormat("auto f18(const char **argv) -> const char**;", Style);
+  verifyFormat("auto f19(char *const *envp) -> char* const*;", Style);
+
+  // Member functions with trailing return types
+  verifyFormat("auto Class::method(int *a) -> int*;", Style);
+  verifyFormat("auto Class::method(int &a) -> int&;", Style);
+
+  // Now test with PAS_Left base and RTAS_Right trailing return type
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Right;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+  verifyFormat("auto f1(int* a, int* b) -> int *;", Style);
+  verifyFormat("auto f2(int& a, int& b) -> int &;", Style);
+  verifyFormat("auto f3(int&& a, int&& b) -> int &&;", Style);
+
+  // Multiple pointers with right alignment in trailing return type
+  verifyFormat("auto f4(int** a) -> int **;", Style);
+  verifyFormat("auto f5(const int* a) -> const int *;", Style);
+  verifyFormat("auto f6(int*** a) -> int ***;", Style);
+
+  // Multiple pointers with const qualifiers, right-aligned trailing return 
type
+  verifyFormat("auto f7(const int** a) -> const int **;", Style);
+  verifyFormat("auto f8(int* const* a) -> int *const *;", Style);
+  verifyFormat("auto f9(const int* const* a) -> const int *const *;", Style);
+  verifyFormat("auto f10(int** const a) -> int **const;", Style);
+  verifyFormat("auto f11(const char** argv) -> const char **;", Style);
+
+  // Test with RTAS_Middle trailing return type
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Middle;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Middle;
+
+  verifyFormat("auto f1(int *a, int *b) -> int *;", Style);
+  verifyFormat("auto f2(int &a, int &b) -> int &;", Style);
+  verifyFormat("auto f3(int &&a, int &&b) -> int &&;", Style);
+
+  // Multiple pointers with const qualifiers, middle-aligned trailing return
+  // type
+  verifyFormat("auto f6(const int *a) -> const int *;", Style);
+  verifyFormat("auto f7(const int **a) -> const int **;", Style);
+  verifyFormat("auto f8(int *const *a) -> int * const *;", Style);
+  verifyFormat("auto f9(const int *const *a) -> const int * const *;", Style);
+  verifyFormat("auto f10(int **const a) -> int ** const;", Style);
+  verifyFormat("auto f11(const char **argv) -> const char **;", Style);
+
+  // Test that default alignment is used when ReturnType is RTAS_Default
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Default;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Default;
+
+  verifyFormat("auto f1(int* a, int* b) -> int*;", Style);
+  verifyFormat("auto f2(int& a, int& b) -> int&;", Style);
+
+  // Test with ReferenceAlignment override for trailing return types
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+  verifyFormat("auto f1(int *a, int &b) -> int*;", Style);
+  verifyFormat("auto f2(int &a, int *b) -> int &;", Style);
+  verifyFormat("auto f3(int &&a, int *b) -> int &&;", Style);
+}
+
 TEST_F(FormatTest, FormatsForLoop) {
   verifyFormat(
       "for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n"

>From 3f29d19b98117c5699cd141bb78cbaa7ea6e6d84 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <[email protected]>
Date: Sat, 22 Nov 2025 21:10:04 +0100
Subject: [PATCH 3/3] [clang-format] Allow custom pointer/ref alignment for
 C-style casts

I would like to adopt clang-format in systemd
(https://github.com/systemd/systemd). One major blocker is that
systemd right-aligns pointers by default, except in function return
types and c-style casts, where they are left-aligned.

Let's introduce a CStyleCast customization for PointerAlignment and
ReferenceAlignment that allows overriding the alignment used for
C-style casts.

systemd style guide: 
https://github.com/systemd/systemd/blob/main/docs/CODING_STYLE.md
---
 clang/docs/ClangFormatStyleOptions.rst     | 46 ++++++++++
 clang/include/clang/Format/Format.h        | 26 +++++-
 clang/lib/Format/Format.cpp                | 43 +++++++---
 clang/lib/Format/TokenAnnotator.cpp        | 45 ++++++++++
 clang/unittests/Format/ConfigParseTest.cpp | 58 +++++++++----
 clang/unittests/Format/FormatTest.cpp      | 98 ++++++++++++++++++++++
 6 files changed, 287 insertions(+), 29 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 119685d39d347..9a523bfe5fea3 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5748,6 +5748,29 @@ the configuration (without a prefix: ``Auto``).
         int * a(void);
 
 
+  * ``CastAlignmentStyle CStyleCast``
+    The alignment for pointers in C-style casts.
+
+    Possible values:
+
+    * ``CAS_Default`` (in configuration: ``Default``)
+      Use default alignment.
+
+    * ``CAS_Left`` (in configuration: ``Left``)
+      Align pointer/reference to the left.
+
+      .. code-block:: c++
+
+        (char*)s;
+
+    * ``CAS_Right`` (in configuration: ``Right``)
+      Align pointer/reference to the right.
+
+      .. code-block:: c++
+
+        (char *)s;
+
+
 
 .. _QualifierAlignment:
 
@@ -5961,6 +5984,29 @@ the configuration (without a prefix: ``Auto``).
         int * a(void);
 
 
+  * ``CastAlignmentStyle CStyleCast``
+    The alignment for references in C-style casts.
+
+    Possible values:
+
+    * ``CAS_Default`` (in configuration: ``Default``)
+      Use default alignment.
+
+    * ``CAS_Left`` (in configuration: ``Left``)
+      Align pointer/reference to the left.
+
+      .. code-block:: c++
+
+        (char*)s;
+
+    * ``CAS_Right`` (in configuration: ``Right``)
+      Align pointer/reference to the right.
+
+      .. code-block:: c++
+
+        (char *)s;
+
+
 
 .. _ReflowComments:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3919c1d0bc8b3..5a611a1141582 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4057,14 +4057,33 @@ struct FormatStyle {
     RTAS_Middle
   };
 
+  /// \brief The pointer/reference alignment style for C-style casts.
+  enum CastAlignmentStyle : int8_t {
+    /// Use default alignment.
+    CAS_Default,
+    /// Align pointer/reference to the left.
+    /// \code
+    ///   (char*)s;
+    /// \endcode
+    CAS_Left,
+    /// Align pointer/reference to the right.
+    /// \code
+    ///   (char *)s;
+    /// \endcode
+    CAS_Right,
+  };
+
   /// Pointer and reference alignment options.
   struct PointerAlignmentOptions {
     /// The default alignment for pointers and references.
     PointerAlignmentStyle Default;
     /// The alignment for pointers in function return types.
     ReturnTypeAlignmentStyle ReturnType;
+    /// The alignment for pointers in C-style casts.
+    CastAlignmentStyle CStyleCast;
     bool operator==(const PointerAlignmentOptions &R) const {
-      return Default == R.Default && ReturnType == R.ReturnType;
+      return Default == R.Default && ReturnType == R.ReturnType &&
+             CStyleCast == R.CStyleCast;
     }
     bool operator!=(const PointerAlignmentOptions &R) const {
       return !(*this == R);
@@ -4264,8 +4283,11 @@ struct FormatStyle {
     ReferenceAlignmentStyle Default;
     /// The alignment for references in function return types.
     ReturnTypeAlignmentStyle ReturnType;
+    /// The alignment for references in C-style casts.
+    CastAlignmentStyle CStyleCast;
     bool operator==(const ReferenceAlignmentOptions &R) const {
-      return Default == R.Default && ReturnType == R.ReturnType;
+      return Default == R.Default && ReturnType == R.ReturnType &&
+             CStyleCast == R.CStyleCast;
     }
     bool operator!=(const ReferenceAlignmentOptions &R) const {
       return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index f950d64b29436..057fe92ccc966 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -555,35 +555,49 @@ struct 
ScalarEnumerationTraits<FormatStyle::ReturnTypeAlignmentStyle> {
   }
 };
 
+template <> struct ScalarEnumerationTraits<FormatStyle::CastAlignmentStyle> {
+  static void enumeration(IO &IO, FormatStyle::CastAlignmentStyle &Value) {
+    IO.enumCase(Value, "Default", FormatStyle::CAS_Default);
+    IO.enumCase(Value, "Left", FormatStyle::CAS_Left);
+    IO.enumCase(Value, "Right", FormatStyle::CAS_Right);
+  }
+};
+
 template <> struct MappingTraits<FormatStyle::PointerAlignmentOptions> {
   static void enumInput(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
     IO.enumCase(Value, "Middle",
                 FormatStyle::PointerAlignmentOptions(
                     {/*Default=*/FormatStyle::PAS_Middle,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
     IO.enumCase(Value, "Left",
                 FormatStyle::PointerAlignmentOptions(
                     {/*Default=*/FormatStyle::PAS_Left,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
     IO.enumCase(Value, "Right",
                 FormatStyle::PointerAlignmentOptions(
                     {/*Default=*/FormatStyle::PAS_Right,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
 
     // For backward compatibility.
     IO.enumCase(Value, "true",
                 FormatStyle::PointerAlignmentOptions(
                     {/*Default=*/FormatStyle::PAS_Left,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
     IO.enumCase(Value, "false",
                 FormatStyle::PointerAlignmentOptions(
                     {/*Default=*/FormatStyle::PAS_Right,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
   }
 
   static void mapping(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
     IO.mapOptional("Default", Value.Default);
     IO.mapOptional("ReturnType", Value.ReturnType);
+    IO.mapOptional("CStyleCast", Value.CStyleCast);
   }
 };
 
@@ -633,24 +647,29 @@ template <> struct 
MappingTraits<FormatStyle::ReferenceAlignmentOptions> {
     IO.enumCase(Value, "Pointer",
                 FormatStyle::ReferenceAlignmentOptions(
                     {/*Default=*/FormatStyle::RAS_Pointer,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
     IO.enumCase(Value, "Middle",
                 FormatStyle::ReferenceAlignmentOptions(
                     {/*Default=*/FormatStyle::RAS_Middle,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
     IO.enumCase(Value, "Left",
                 FormatStyle::ReferenceAlignmentOptions(
                     {/*Default=*/FormatStyle::RAS_Left,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
     IO.enumCase(Value, "Right",
                 FormatStyle::ReferenceAlignmentOptions(
                     {/*Default=*/FormatStyle::RAS_Right,
-                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+                     /*ReturnType=*/FormatStyle::RTAS_Default,
+                     /*CStyleCast=*/FormatStyle::CAS_Default}));
   }
 
   static void mapping(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
     IO.mapOptional("Default", Value.Default);
     IO.mapOptional("ReturnType", Value.ReturnType);
+    IO.mapOptional("CStyleCast", Value.CStyleCast);
   }
 };
 
@@ -1851,11 +1870,13 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
   LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
   LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right,
-                                /*ReturnType=*/FormatStyle::RTAS_Default};
+                                /*ReturnType=*/FormatStyle::RTAS_Default,
+                                /*CStyleCast=*/FormatStyle::CAS_Default};
   LLVMStyle.PPIndentWidth = -1;
   LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
   LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
-                                  /*ReturnType=*/FormatStyle::RTAS_Default};
+                                  /*ReturnType=*/FormatStyle::RTAS_Default,
+                                  /*CStyleCast=*/FormatStyle::CAS_Default};
   LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
   LLVMStyle.RemoveBracesLLVM = false;
   LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index fe53d70eb12d7..a7c00e19352cf 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -6586,6 +6586,28 @@ static bool isReturnType(const FormatToken &Tok, const 
LangOptions &LangOpts) {
   return false;
 }
 
+static bool isCStyleCast(const FormatToken &Tok, const LangOptions &LangOpts) {
+  // Look forward to see if there's a TT_CastRParen.
+  for (const FormatToken *Next = Tok.Next; Next;
+       Next = Next->getNextNonComment()) {
+    if (Next->is(TT_CastRParen))
+      return true;
+
+    if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
+      Next = Next->MatchingParen;
+      continue;
+    }
+
+    if (Next->isPointerOrReference() || Next->isTypeName(LangOpts) ||
+        Next->canBePointerOrReferenceQualifier()) {
+      continue;
+    }
+
+    break;
+  }
+  return false;
+}
+
 static FormatStyle::PointerAlignmentStyle
 mapReturnTypeAlignmentStyle(FormatStyle::ReturnTypeAlignmentStyle Style) {
   switch (Style) {
@@ -6601,6 +6623,19 @@ 
mapReturnTypeAlignmentStyle(FormatStyle::ReturnTypeAlignmentStyle Style) {
   llvm_unreachable("Unknown FormatStyle::ReturnTypeAlignmentStyle enum");
 }
 
+static FormatStyle::PointerAlignmentStyle
+mapCastAlignmentStyle(FormatStyle::CastAlignmentStyle Style) {
+  switch (Style) {
+  case FormatStyle::CAS_Left:
+    return FormatStyle::PAS_Left;
+  case FormatStyle::CAS_Right:
+    return FormatStyle::PAS_Right;
+  case FormatStyle::CAS_Default:
+    assert(false);
+  }
+  llvm_unreachable("Unknown FormatStyle::CastAlignmentStyle enum");
+}
+
 FormatStyle::PointerAlignmentStyle
 TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const 
{
   assert(Reference.isOneOf(tok::amp, tok::ampamp));
@@ -6610,6 +6645,11 @@ TokenAnnotator::getTokenReferenceAlignment(const 
FormatToken &Reference) const {
     return mapReturnTypeAlignmentStyle(Style.ReferenceAlignment.ReturnType);
   }
 
+  if (Style.ReferenceAlignment.CStyleCast != FormatStyle::CAS_Default &&
+      isCStyleCast(Reference, LangOpts)) {
+    return mapCastAlignmentStyle(Style.ReferenceAlignment.CStyleCast);
+  }
+
   switch (Style.ReferenceAlignment.Default) {
   case FormatStyle::RAS_Pointer:
     return Style.PointerAlignment.Default;
@@ -6635,6 +6675,11 @@ TokenAnnotator::getTokenPointerOrReferenceAlignment(
     return mapReturnTypeAlignmentStyle(Style.PointerAlignment.ReturnType);
   }
 
+  if (Style.PointerAlignment.CStyleCast != FormatStyle::CAS_Default &&
+      isCStyleCast(PointerOrReference, LangOpts)) {
+    return mapCastAlignmentStyle(Style.PointerAlignment.CStyleCast);
+  }
+
   return Style.PointerAlignment.Default;
 }
 
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index cf54b79bcf8a6..825487628ccfe 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -392,66 +392,92 @@ TEST(ConfigParseTest, ParsesConfiguration) {
 #undef CHECK_ALIGN_CONSECUTIVE
 
   Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle,
-                            /*ReturnType=*/FormatStyle::RTAS_Default};
+                            /*ReturnType=*/FormatStyle::RTAS_Default,
+                            /*CStyleCast=*/FormatStyle::CAS_Default};
   CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
                   {/*Default=*/FormatStyle::PAS_Left,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("PointerAlignment: Right", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
                   {/*Default=*/FormatStyle::PAS_Right,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("PointerAlignment: Middle", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
                   {/*Default=*/FormatStyle::PAS_Middle,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("PointerAlignment:\n"
               "  Default: Right\n"
               "  ReturnType: Left",
               PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
                   {/*Default=*/FormatStyle::PAS_Right,
-                   /*ReturnType=*/FormatStyle::RTAS_Left}));
-
-  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle,
-                              /*ReturnType=*/FormatStyle::RTAS_Default};
+                   /*ReturnType=*/FormatStyle::RTAS_Left,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
+  CHECK_PARSE("PointerAlignment:\n"
+              "  Default: Right\n"
+              "  CStyleCast: Left",
+              PointerAlignment,
+              FormatStyle::PointerAlignmentOptions(
+                  {/*Default=*/FormatStyle::PAS_Right,
+                   /*ReturnType=*/FormatStyle::RTAS_Left,
+                   /*CStyleCast=*/FormatStyle::CAS_Left}));
   CHECK_PARSE("ReferenceAlignment: Pointer", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
                   {/*Default=*/FormatStyle::RAS_Pointer,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("ReferenceAlignment: Left", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
                   {/*Default=*/FormatStyle::RAS_Left,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("ReferenceAlignment: Right", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
                   {/*Default=*/FormatStyle::RAS_Right,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("ReferenceAlignment: Middle", ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
                   {/*Default=*/FormatStyle::RAS_Middle,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("ReferenceAlignment:\n"
               "  Default: Right\n"
               "  ReturnType: Left",
               ReferenceAlignment,
               FormatStyle::ReferenceAlignmentOptions(
                   {/*Default=*/FormatStyle::RAS_Right,
-                   /*ReturnType=*/FormatStyle::RTAS_Left}));
+                   /*ReturnType=*/FormatStyle::RTAS_Left,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
+  CHECK_PARSE("ReferenceAlignment:\n"
+              "  Default: Right\n"
+              "  CStyleCast: Left",
+              ReferenceAlignment,
+              FormatStyle::ReferenceAlignmentOptions(
+                  {/*Default=*/FormatStyle::RAS_Right,
+                   /*ReturnType=*/FormatStyle::RTAS_Left,
+                   /*CStyleCast=*/FormatStyle::CAS_Left}));
 
   // For backward compatibility:
   CHECK_PARSE("PointerBindsToType: Left", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
                   {/*Default=*/FormatStyle::PAS_Left,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("PointerBindsToType: Right", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
                   {/*Default=*/FormatStyle::PAS_Right,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
   CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
               FormatStyle::PointerAlignmentOptions(
                   {/*Default=*/FormatStyle::PAS_Middle,
-                   /*ReturnType=*/FormatStyle::RTAS_Default}));
+                   /*ReturnType=*/FormatStyle::RTAS_Default,
+                   /*CStyleCast=*/FormatStyle::CAS_Default}));
 
   Style.ReflowComments = FormatStyle::RCS_Always;
   CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index ad14e7d1f0429..5cd2ad8947fbe 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2496,6 +2496,104 @@ TEST_F(FormatTest, ReturnTypeAlignment) {
   verifyFormat("auto f3(int &&a, int *b) -> int &&;", Style);
 }
 
+TEST_F(FormatTest, CStyleCastAlignment) {
+  // Test that CStyleCast overrides PointerAlignment for C-style casts
+  FormatStyle Style = getLLVMStyle();
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Left;
+
+  // Basic C-style casts with pointers should be left-aligned despite PAS_Right
+  verifyFormat("int *a = (int*)b;", Style);
+  verifyFormat("int &c = (int&)d;", Style);
+  verifyFormat("int &&e = (int&&)f;", Style);
+
+  // Multiple pointers in C-style casts
+  verifyFormat("int **a = (int**)b;", Style);
+  verifyFormat("const int *c = (const int*)d;", Style);
+  verifyFormat("int ***e = (int***)f;", Style);
+
+  // Multiple pointers with const qualifiers
+  verifyFormat("const int **a = (const int**)b;", Style);
+  verifyFormat("int *const *c = (int* const*)d;", Style);
+  verifyFormat("const int *const *e = (const int* const*)f;", Style);
+  verifyFormat("int **const g = (int** const)h;", Style);
+  verifyFormat("const int **const i = (const int** const)j;", Style);
+
+  // Complex types in C-style casts
+  verifyFormat("std::vector<int> *a = (std::vector<int>*)b;", Style);
+  verifyFormat("const char *c = (const char*)d;", Style);
+  verifyFormat("const char **e = (const char**)f;", Style);
+  verifyFormat("char *const *g = (char* const*)h;", Style);
+
+  // Variables should still follow the default alignment
+  verifyFormat("int *a = nullptr;", Style);
+  verifyFormat("int *b = (int*)c;", Style);
+
+  // Now test with PAS_Left base and CAS_Right cast
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+  Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Right;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Right;
+
+  // C-style casts should be right-aligned despite PAS_Left
+  verifyFormat("int* a = (int *)b;", Style);
+  verifyFormat("int& c = (int &)d;", Style);
+  verifyFormat("int&& e = (int &&)f;", Style);
+
+  // Multiple pointers with right alignment in casts
+  verifyFormat("int** a = (int **)b;", Style);
+  verifyFormat("const int* c = (const int *)d;", Style);
+  verifyFormat("int*** e = (int ***)f;", Style);
+
+  // Multiple pointers with const qualifiers, right-aligned casts
+  verifyFormat("const int** a = (const int **)b;", Style);
+  verifyFormat("int* const* c = (int *const *)d;", Style);
+  verifyFormat("const int* const* e = (const int *const *)f;", Style);
+  verifyFormat("int** const g = (int **const)h;", Style);
+  verifyFormat("const char** i = (const char **)j;", Style);
+
+  // Variables should still follow PointerAlignment (PAS_Left)
+  verifyFormat("int* a = nullptr;", Style);
+  verifyFormat("int* b = (int *)c;", Style);
+
+  // Test that default alignment is used when CStyleCast is CAS_Default
+  Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+  Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Default;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Default;
+
+  verifyFormat("int* a = (int*)b;", Style);
+  verifyFormat("int& c = (int&)d;", Style);
+
+  // Test with ReferenceAlignment override
+  Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+  Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Left;
+  Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+  Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Right;
+
+  verifyFormat("int *a = (int*)b;", Style);
+  verifyFormat("int &c = (int &)d;", Style);
+  verifyFormat("int &&e = (int &&)f;", Style);
+
+  // Chained casts
+  verifyFormat("int *a = (int*)(void*)b;", Style);
+  verifyFormat("const char *c = (const char*)(void*)d;", Style);
+
+  // Casts with arithmetic
+  verifyFormat("int *a = (int*)b + 1;", Style);
+  verifyFormat("void *c = (void*)(d + sizeof(int));", Style);
+
+  // Test function calls with casts
+  verifyFormat("foo((int*)bar);", Style);
+  verifyFormat("foo((int &)bar, (int*)baz);", Style);
+
+  // Test C-style casts in expressions
+  verifyFormat("if ((int*)a == b)\n  return;", Style);
+  verifyFormat("return (int*)a;", Style);
+}
+
 TEST_F(FormatTest, FormatsForLoop) {
   verifyFormat(
       "for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n"

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to