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

>From e0700f1508d344a957e713ad033aa47c96bc851c 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/2] [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      | 123 +++++++++++----------
 7 files changed, 286 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..b82c387df877d 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..741a6e1740af6 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2047,8 +2047,11 @@ 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, FormatStyle::PointerAlignmentOptions(
+                                        {/*Default=*/FormatStyle::PAS_Right}));
+  EXPECT_EQ(Style.ReferenceAlignment,
+            FormatStyle::ReferenceAlignmentOptions(
+                {/*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 +2107,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 +2165,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 +2203,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 +2256,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 +2379,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 +8641,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 +9978,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 +11468,16 @@ TEST_F(FormatTest, UnderstandsPointersToMembers) {
       "    aaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa));");
 
   FormatStyle Style = getLLVMStyle();
-  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
+  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PointerAlignmentOptions(
+                                        {/*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 +11537,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 +11665,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 +11697,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 +11780,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 +11864,20 @@ TEST_F(FormatTest, PointerAlignmentFallback) {
                            "int *q;\n"
                            "int * r;");
 
-  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
+  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PointerAlignmentOptions(
+                                        {/*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 +12073,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 +12219,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 +12243,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 +12263,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 +12283,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 +12374,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 +12481,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 +12509,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 +12645,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 +16258,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 +16314,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 +18232,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 +18284,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 +18299,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 +18315,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 +19761,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 +20028,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 +20102,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 +20318,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 +20342,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 +20358,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 +25091,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 +25335,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 +25366,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 +25429,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 +25559,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 +25615,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 +25686,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 +27945,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 64ef82be344c0ed103d38563274f8c4df3237874 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/2] [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.

Fixes #136597
---
 clang/docs/ClangFormatStyleOptions.rst     |  60 ++++++++++
 clang/include/clang/Format/Format.h        |  29 ++++-
 clang/lib/Format/Format.cpp                |  69 ++++++++---
 clang/lib/Format/TokenAnnotator.cpp        |  47 ++++++++
 clang/unittests/Format/ConfigParseTest.cpp |  52 ++++++--
 clang/unittests/Format/FormatTest.cpp      | 132 ++++++++++++++++++++-
 6 files changed, 352 insertions(+), 37 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index ab21290260005..e08e22964691d 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 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 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..21369d21796f4 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4017,6 +4017,27 @@ struct FormatStyle {
   /// \version 3.7
   unsigned PenaltyReturnTypeOnItsOwnLine;
 
+  /// \brief The pointer/reference alignment style for 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
+  };
+
   /// The ``&``, ``&&`` and ``*`` alignment style.
   enum PointerAlignmentStyle : int8_t {
     /// Align pointer to the left.
@@ -4040,8 +4061,10 @@ struct FormatStyle {
   struct PointerAlignmentOptions {
     /// The default alignment for pointers and references.
     PointerAlignmentStyle Default;
+    /// The alignment for pointers in 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 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 b82c387df877d..cb7a1a6f07623 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -548,25 +548,42 @@ 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);
+  }
+};
+
+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);
   }
 };
 
@@ -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;
@@ -1953,7 +1977,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
   GoogleStyle.ObjCSpaceAfterProperty = false;
   GoogleStyle.ObjCSpaceBeforeProtocolList = true;
   GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
-  GoogleStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left};
+  GoogleStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                                  /*ReturnType=*/FormatStyle::RTAS_Default};
   GoogleStyle.RawStringFormats = {
       {
           FormatStyle::LK_Cpp,
@@ -2148,7 +2173,8 @@ FormatStyle getMozillaStyle() {
   MozillaStyle.ObjCSpaceAfterProperty = true;
   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
-  MozillaStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left};
+  MozillaStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                                   /*ReturnType=*/FormatStyle::RTAS_Default};
   MozillaStyle.SpaceAfterTemplateKeyword = false;
   return MozillaStyle;
 }
@@ -2171,7 +2197,8 @@ FormatStyle getWebKitStyle() {
   Style.NamespaceIndentation = FormatStyle::NI_Inner;
   Style.ObjCBlockIndentWidth = 4;
   Style.ObjCSpaceAfterProperty = true;
-  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left};
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                            /*ReturnType=*/FormatStyle::RTAS_Default};
   Style.SpaceBeforeCpp11BracedList = true;
   Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
   return Style;
@@ -2904,11 +2931,15 @@ class Formatter : public TokenAnalyzer {
     }
     if (Style.DerivePointerAlignment) {
       const auto NetRightCount = countVariableAlignments(AnnotatedLines);
-      if (NetRightCount > 0)
-        Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right};
-      else if (NetRightCount < 0)
-        Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left};
-      Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer};
+      if (NetRightCount > 0) {
+        Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right,
+                                  /*ReturnType=*/FormatStyle::RTAS_Default};
+      } else if (NetRightCount < 0) {
+        Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                                  /*ReturnType=*/FormatStyle::RTAS_Default};
+      }
+      Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                                  /*ReturnType=*/FormatStyle::RTAS_Default};
     }
     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 f48a02c49c562..a9e7bac343ab4 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -6540,9 +6540,41 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine 
&Line) const {
   llvm::errs() << "----\n";
 }
 
+static bool isReturnType(const FormatToken &Tok) {
+  // Look forward to see if there's a function declaration paren
+  const FormatToken *Next = Tok.Next;
+  while (Next) {
+    if (Next->isOneOf(TT_FunctionDeclarationLParen, TT_FunctionTypeLParen))
+      return true;
+    // Stop at certain tokens that indicate we're not in a return type
+    if (Next->isOneOf(tok::semi, tok::l_brace, tok::comma, tok::equal,
+                      TT_LambdaLSquare)) {
+      break;
+    }
+
+    Next = Next->Next;
+  }
+  return false;
+}
+
 FormatStyle::PointerAlignmentStyle
 TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const 
{
   assert(Reference.isOneOf(tok::amp, tok::ampamp));
+
+  if (Style.ReferenceAlignment.ReturnType != FormatStyle::RTAS_Default &&
+      isReturnType(Reference)) {
+    switch (Style.ReferenceAlignment.ReturnType) {
+    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(0);
+    }
+  }
+
   switch (Style.ReferenceAlignment.Default) {
   case FormatStyle::RAS_Pointer:
     return Style.PointerAlignment.Default;
@@ -6563,6 +6595,21 @@ 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)) {
+    switch (Style.PointerAlignment.ReturnType) {
+    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(0);
+    }
+  }
+
   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 741a6e1740af6..bcdbc0f10b719 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2299,6 +2299,126 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
   // verifyFormat("int Add2(BTree * &Root, char * szToAdd)", Style);
 }
 
+TEST_F(FormatTest, ReturnTypeAlignment) {
+  // Test that ReturnTypeAlignment overrides PointerAlignment for return types
+  FormatStyle Style = getLLVMStyle();
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right,
+                            /*ReturnType=*/FormatStyle::RTAS_Left};
+  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                              /*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);
+
+  // Triple pointers with const
+  verifyFormat("int*** const f12(int ***const a);", Style);
+  verifyFormat("const int*** f13(const int ***a);", Style);
+  verifyFormat("int* const* const* f14(int *const *const *a);", Style);
+  verifyFormat("const int* const* const* f15(const int *const *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 PointerAlignment, not ReturnTypeAlignment
+  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,
+                            /*ReturnType=*/FormatStyle::RTAS_Right};
+  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                              /*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,
+                            /*ReturnType=*/FormatStyle::RTAS_Middle};
+  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                              /*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 middle alignment in return type
+  verifyFormat("int ** f4(int **a);", Style);
+  verifyFormat("int *** f5(int ***a);", 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 Pointer alignment is used when ReturnTypeAlignment is
+  // RTAS_Default
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                            /*ReturnType=*/FormatStyle::RTAS_Default};
+  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                              /*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,
+                            /*ReturnType=*/FormatStyle::RTAS_Left};
+  Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                              /*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_F(FormatTest, FormatsForLoop) {
   verifyFormat(
       "for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n"
@@ -11468,16 +11588,20 @@ TEST_F(FormatTest, UnderstandsPointersToMembers) {
       "    aaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa));");
 
   FormatStyle Style = getLLVMStyle();
-  EXPECT_EQ(Style.PointerAlignment, FormatStyle::PointerAlignmentOptions(
-                                        {/*Default=*/FormatStyle::PAS_Right}));
+  EXPECT_EQ(Style.PointerAlignment,
+            FormatStyle::PointerAlignmentOptions(
+                {/*Default=*/FormatStyle::PAS_Right,
+                 /*ReturnType=*/FormatStyle::RTAS_Default}));
   verifyFormat("typedef bool *(Class::*Member)() const;", Style);
   verifyFormat("void f(int A::*p) { int A::*v = &A::B; }", Style);
 
-  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left};
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                            /*ReturnType=*/FormatStyle::RTAS_Default};
   verifyFormat("typedef bool* (Class::*Member)() const;", Style);
   verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style);
 
-  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle};
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle,
+                            /*ReturnType=*/FormatStyle::RTAS_Default};
   verifyFormat("typedef bool * (Class::*Member)() const;", Style);
   verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style);
 }

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

Reply via email to