Skip to content

Conversation

@DaanDeMeyer
Copy link
Contributor

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

@llvmbot
Copy link
Member

llvmbot commented Nov 22, 2025

@llvm/pr-subscribers-clang-format

Author: Daan De Meyer (DaanDeMeyer)

Changes

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


Patch is 54.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169160.diff

7 Files Affected:

  • (modified) clang/docs/ClangFormatStyleOptions.rst (+137-30)
  • (modified) clang/include/clang/Format/Format.h (+82-2)
  • (modified) clang/lib/Format/Format.cpp (+86-12)
  • (modified) clang/lib/Format/TokenAnnotator.cpp (+55-8)
  • (modified) clang/lib/Format/WhitespaceManager.cpp (+5-5)
  • (modified) clang/unittests/Format/ConfigParseTest.cpp (+50-12)
  • (modified) clang/unittests/Format/FormatTest.cpp (+188-59)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 94d6f0d27619f..e08e22964691d 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5668,31 +5668,84 @@ 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
 
-      int *a;
+  Nested configuration flags:
 
-  * ``PAS_Middle`` (in configuration: ``Middle``)
-    Align pointer in the middle.
+  Pointer and reference alignment options.
 
-    .. code-block:: c++
+  * ``PointerAlignmentStyle Default``
+    The default alignment for pointers and references.
+
+    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;
+
+
+  * ``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;
+        int *a(void);
 
 
 
@@ -5824,34 +5877,88 @@ 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;
+
+
+  * ``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;
+        int *a(void);
 
 
 
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index b6f124f948b59..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.
@@ -4036,9 +4057,38 @@ struct FormatStyle {
     PAS_Middle
   };
 
+  /// Pointer and reference alignment options.
+  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 && ReturnType == R.ReturnType;
+    }
+    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 +4258,39 @@ struct FormatStyle {
     RAS_Middle
   };
 
+  /// Reference alignment options.
+  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 && ReturnType == R.ReturnType;
+    }
+    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..cb7a1a6f07623 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -541,10 +541,49 @@ 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,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+    IO.enumCase(Value, "Left",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*Default=*/FormatStyle::PAS_Left,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+    IO.enumCase(Value, "Right",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*Default=*/FormatStyle::PAS_Right,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
 
     // 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,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+    IO.enumCase(Value, "false",
+                FormatStyle::PointerAlignmentOptions(
+                    {/*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);
   }
 };
 
@@ -589,6 +628,32 @@ 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,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+    IO.enumCase(Value, "Middle",
+                FormatStyle::ReferenceAlignmentOptions(
+                    {/*Default=*/FormatStyle::RAS_Middle,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+    IO.enumCase(Value, "Left",
+                FormatStyle::ReferenceAlignmentOptions(
+                    {/*Default=*/FormatStyle::RAS_Left,
+                     /*ReturnType=*/FormatStyle::RTAS_Default}));
+    IO.enumCase(Value, "Right",
+                FormatStyle::ReferenceAlignmentOptions(
+                    {/*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);
+  }
+};
+
 template <>
 struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
   static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
@@ -1785,10 +1850,12 @@ 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,
+                                /*ReturnType=*/FormatStyle::RTAS_Default};
   LLVMStyle.PPIndentWidth = -1;
   LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
-  LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
+  LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+                                  /*ReturnType=*/FormatStyle::RTAS_Default};
   LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
   LLVMStyle.RemoveBracesLLVM = false;
   LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
@@ -1910,7 +1977,8 @@ 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,
+                                  /*ReturnType=*/FormatStyle::RTAS_Default};
   GoogleStyle.RawStringFormats = {
       {
           FormatStyle::LK_Cpp,
@@ -2105,7 +2173,8 @@ FormatStyle getMozillaStyle() {
   MozillaStyle.ObjCSpaceAfterProperty = true;
   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
-  MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
+  MozillaStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                                   /*ReturnType=*/FormatStyle::RTAS_Default};
   MozillaStyle.SpaceAfterTemplateKeyword = false;
   return MozillaStyle;
 }
@@ -2128,7 +2197,8 @@ FormatStyle getWebKitStyle() {
   Style.NamespaceIndentation = FormatStyle::NI_Inner;
   Style.ObjCBlockIndentWidth = 4;
   Style.ObjCSpaceAfterProperty = true;
-  Style.PointerAlignment = FormatStyle::PAS_Left;
+  Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Left,
+                            /*ReturnType=*/FormatStyle::RTAS_Default};
   Style.SpaceBeforeCpp11BracedList = true;
   Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
   return Style;
@@ -2861,11 +2931,15 @@ class Formatter : public TokenAnalyzer {
     }
     if (Style.DerivePointerAlignment) {
       const auto NetRightCount = countVariableAlignments(AnnotatedLines);
-      if (NetRightCount > 0)
-        Style.PointerAlignment = FormatStyle::PAS_Right;
-      else if (NetRightCount < 0)
-        Style.PointerAlignment = FormatStyle::PAS_Left;
-      Style.ReferenceAlignment = 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 cb41756c56bf7..a9e7bac343ab4 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);
@@ -6540,12 +6540,44 @@ 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));
-  switch (Style.ReferenceAlignment) {
+
+  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;
+    return Style.PointerAlignment.Default;
   case FormatStyle::RAS_Left:
     return FormatStyle::PAS_Left;
   case FormatStyle::RAS_Right:
@@ -6554,7 +6586,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 +6595,22 @@ TokenAnnotator::getTokenPointerOrReferenceAlignment(
   if (PointerOrReference.isOneOf(tok::amp, tok::ampamp))
     return getTokenReferenceAlignment(PointerOrReference);
   assert(PointerOrReference.is(tok::star));
-  return Style.PointerAlignment;
+
+  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_...
[truncated]

@github-actions
Copy link

github-actions bot commented Nov 22, 2025

🐧 Linux x64 Test Results

  • 111400 tests passed
  • 4452 tests skipped

Copy link
Contributor

@HazardyKnusperkeks HazardyKnusperkeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you link to a style guide?

This allows adding other suboptions e.g. ReturnType for llvm#136597.
@DaanDeMeyer DaanDeMeyer force-pushed the pointer-alignment branch 5 times, most recently from 42f1660 to 3f29d19 Compare November 23, 2025 09:46
@HazardyKnusperkeks
Copy link
Contributor

Can you link to a style guide?

Can you link to a style guide?

For the review process is it better to just add commits and not amend them. On merge they will all be squashed into one commit.

@DaanDeMeyer
Copy link
Contributor Author

Can you link to a style guide?

Can you link to a style guide?

For the review process is it better to just add commits and not amend them. On merge they will all be squashed into one commit.

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

@DaanDeMeyer DaanDeMeyer force-pushed the pointer-alignment branch 3 times, most recently from cab1eb2 to ed75a41 Compare November 23, 2025 14:56
Copy link
Contributor

@HazardyKnusperkeks HazardyKnusperkeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from that look okay to me.

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 llvm#136597
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
@DaanDeMeyer
Copy link
Contributor Author

Ah my bad force pushed again, only change was to add full stops to all comments in the added tests.

};

/// \brief The pointer/reference alignment style for function return types.
enum ReturnTypeAlignmentStyle : int8_t {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can these be alphabetic ordering

};

/// \brief The pointer/reference alignment style for C-style casts.
enum CastAlignmentStyle : int8_t {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C before R

Acceptable values (configured as a single string or with suboptions):
* ``Left``
* ``Right``
* ``Middle``
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like it should be Left/Right/Middle/Custom/Leave where Custom lets you change what you have here

I don't feel like the "Default" follows the pattern of other options as a struct

Copy link
Contributor Author

@DaanDeMeyer DaanDeMeyer Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mydeveloperday I'm not sure I follow, do you suggest PointerAlignment: Custom and then another option PointerAlignmentOptions struct to configure the individual options?

I'm fine to rework it like that if that's what you want for consistency but I also have to mention that I find my approach much nicer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if yes, doesn't that still need a Default option in the struct, unless you want me to add separate options for every possible case where pointer/reference alignment could be different?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't feel like the "Default" pattern is followed elsewhere, but the Custom pattern is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mydeveloperday Thanks for the response, but you didn't answer my questions from above. I do not see how the Custom pattern solves the problem of still having to set a default alignment.

* ``Pointer``
* ``Left``
* ``Right``
* ``Middle``
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto comment above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[clang-format] Pointer alignment option for function return types

4 participants