[clang] [clang-format] Allow custom pointer/ref alignment in return types (PR #169160)
Daan De Meyer via cfe-commits
cfe-commits at lists.llvm.org
Sun Nov 23 02:56:16 PST 2025
https://github.com/DaanDeMeyer updated https://github.com/llvm/llvm-project/pull/169160
>From 072d1ab13b478c7e92a698e00fbd76e14ee1542b Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer at gmail.com>
Date: Fri, 21 Nov 2025 23:11:45 +0100
Subject: [PATCH 1/3] [clang-format][NFC] Upgrade PointerAlignment option to a
struct
This allows adding other suboptions e.g. ReturnType for #136597.
---
clang/docs/ClangFormatStyleOptions.rst | 107 +++++++++++++------
clang/include/clang/Format/Format.h | 59 ++++++++++-
clang/lib/Format/Format.cpp | 63 +++++++++--
clang/lib/Format/TokenAnnotator.cpp | 16 +--
clang/lib/Format/WhitespaceManager.cpp | 10 +-
clang/unittests/Format/ConfigParseTest.cpp | 34 +++---
clang/unittests/Format/FormatTest.cpp | 118 ++++++++++-----------
7 files changed, 281 insertions(+), 126 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 94d6f0d27619f..ab21290260005 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5668,31 +5668,54 @@ the configuration (without a prefix: ``Auto``).
.. _PointerAlignment:
-**PointerAlignment** (``PointerAlignmentStyle``) :versionbadge:`clang-format 3.7` :ref:`¶ <PointerAlignment>`
+**PointerAlignment** (``PointerAlignmentOptions``) :versionbadge:`clang-format 3.7` :ref:`¶ <PointerAlignment>`
Pointer and reference alignment style.
- Possible values:
+ Acceptable values (configured as a single string or with suboptions):
+ * ``Left``
+ * ``Right``
+ * ``Middle``
- * ``PAS_Left`` (in configuration: ``Left``)
- Align pointer to the left.
+ For example, to configure left pointer alignment:
- .. code-block:: c++
+ .. code-block:: yaml
- int* a;
+ PointerAlignment: Left
- * ``PAS_Right`` (in configuration: ``Right``)
- Align pointer to the right.
+ # or
- .. code-block:: c++
+ PointerAlignment:
+ Default: Left
+
+ Nested configuration flags:
- int *a;
+ Pointer and reference alignment options.
- * ``PAS_Middle`` (in configuration: ``Middle``)
- Align pointer in the middle.
+ * ``PointerAlignmentStyle Default``
+ The default alignment for pointers and references.
- .. code-block:: c++
+ Possible values:
+
+ * ``PAS_Left`` (in configuration: ``Left``)
+ Align pointer to the left.
+
+ .. code-block:: c++
+
+ int* a;
+
+ * ``PAS_Right`` (in configuration: ``Right``)
+ Align pointer to the right.
+
+ .. code-block:: c++
+
+ int *a;
+
+ * ``PAS_Middle`` (in configuration: ``Middle``)
+ Align pointer in the middle.
+
+ .. code-block:: c++
- int * a;
+ int * a;
@@ -5824,34 +5847,58 @@ the configuration (without a prefix: ``Auto``).
.. _ReferenceAlignment:
-**ReferenceAlignment** (``ReferenceAlignmentStyle``) :versionbadge:`clang-format 13` :ref:`¶ <ReferenceAlignment>`
+**ReferenceAlignment** (``ReferenceAlignmentOptions``) :versionbadge:`clang-format 13` :ref:`¶ <ReferenceAlignment>`
Reference alignment style (overrides ``PointerAlignment`` for references).
- Possible values:
+ Acceptable values (configured as a single string or with suboptions):
+ * ``Pointer``
+ * ``Left``
+ * ``Right``
+ * ``Middle``
- * ``RAS_Pointer`` (in configuration: ``Pointer``)
- Align reference like ``PointerAlignment``.
+ For example, to configure right reference alignment:
- * ``RAS_Left`` (in configuration: ``Left``)
- Align reference to the left.
+ .. code-block:: yaml
- .. code-block:: c++
+ ReferenceAlignment: Right
- int& a;
+ # or
- * ``RAS_Right`` (in configuration: ``Right``)
- Align reference to the right.
+ ReferenceAlignment:
+ Default: Right
- .. code-block:: c++
+ Nested configuration flags:
- int &a;
+ Reference alignment options.
- * ``RAS_Middle`` (in configuration: ``Middle``)
- Align reference in the middle.
+ * ``ReferenceAlignmentStyle Default``
+ The default alignment for references.
- .. code-block:: c++
+ Possible values:
+
+ * ``RAS_Pointer`` (in configuration: ``Pointer``)
+ Align reference like ``PointerAlignment``.
+
+ * ``RAS_Left`` (in configuration: ``Left``)
+ Align reference to the left.
+
+ .. code-block:: c++
+
+ int& a;
+
+ * ``RAS_Right`` (in configuration: ``Right``)
+ Align reference to the right.
+
+ .. code-block:: c++
+
+ int &a;
+
+ * ``RAS_Middle`` (in configuration: ``Middle``)
+ Align reference in the middle.
+
+ .. code-block:: c++
- int & a;
+ int & a;
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index b6f124f948b59..2cd446366cfa4 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4036,9 +4036,36 @@ struct FormatStyle {
PAS_Middle
};
+ /// Pointer and reference alignment options.
+ struct PointerAlignmentOptions {
+ /// The default alignment for pointers and references.
+ PointerAlignmentStyle Default;
+ bool operator==(const PointerAlignmentOptions &R) const {
+ return Default == R.Default;
+ }
+ bool operator!=(const PointerAlignmentOptions &R) const {
+ return !(*this == R);
+ }
+ };
+
/// Pointer and reference alignment style.
+ ///
+ /// Acceptable values (configured as a single string or with suboptions):
+ /// * ``Left``
+ /// * ``Right``
+ /// * ``Middle``
+ ///
+ /// For example, to configure left pointer alignment:
+ /// \code{.yaml}
+ /// PointerAlignment: Left
+ ///
+ /// # or
+ ///
+ /// PointerAlignment:
+ /// Default: Left
+ /// \endcode
/// \version 3.7
- PointerAlignmentStyle PointerAlignment;
+ PointerAlignmentOptions PointerAlignment;
/// The number of columns to use for indentation of preprocessor statements.
/// When set to -1 (default) ``IndentWidth`` is used also for preprocessor
@@ -4208,9 +4235,37 @@ struct FormatStyle {
RAS_Middle
};
+ /// Reference alignment options.
+ struct ReferenceAlignmentOptions {
+ /// The default alignment for references.
+ ReferenceAlignmentStyle Default;
+ bool operator==(const ReferenceAlignmentOptions &R) const {
+ return Default == R.Default;
+ }
+ bool operator!=(const ReferenceAlignmentOptions &R) const {
+ return !(*this == R);
+ }
+ };
+
/// Reference alignment style (overrides ``PointerAlignment`` for references).
+ ///
+ /// Acceptable values (configured as a single string or with suboptions):
+ /// * ``Pointer``
+ /// * ``Left``
+ /// * ``Right``
+ /// * ``Middle``
+ ///
+ /// For example, to configure right reference alignment:
+ /// \code{.yaml}
+ /// ReferenceAlignment: Right
+ ///
+ /// # or
+ ///
+ /// ReferenceAlignment:
+ /// Default: Right
+ /// \endcode
/// \version 13
- ReferenceAlignmentStyle ReferenceAlignment;
+ ReferenceAlignmentOptions ReferenceAlignment;
// clang-format off
/// Types of comment reflow style.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 9bbb33cb14502..2140cf66cd5af 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -541,10 +541,32 @@ template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
+ }
+};
+
+template <> struct MappingTraits<FormatStyle::PointerAlignmentOptions> {
+ static void enumInput(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
+ IO.enumCase(Value, "Middle",
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Middle}));
+ IO.enumCase(Value, "Left",
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Left}));
+ IO.enumCase(Value, "Right",
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Right}));
// For backward compatibility.
- IO.enumCase(Value, "true", FormatStyle::PAS_Left);
- IO.enumCase(Value, "false", FormatStyle::PAS_Right);
+ IO.enumCase(Value, "true",
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Left}));
+ IO.enumCase(Value, "false",
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Right}));
+ }
+
+ static void mapping(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
+ IO.mapOptional("Default", Value.Default);
}
};
@@ -589,6 +611,27 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::ReferenceAlignmentOptions> {
+ static void enumInput(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
+ IO.enumCase(Value, "Pointer",
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Pointer}));
+ IO.enumCase(Value, "Middle",
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Middle}));
+ IO.enumCase(Value, "Left",
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Left}));
+ IO.enumCase(Value, "Right",
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Right}));
+ }
+
+ static void mapping(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
+ IO.mapOptional("Default", Value.Default);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
@@ -1785,10 +1828,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ObjCSpaceAfterProperty = false;
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
- LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
+ LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right};
LLVMStyle.PPIndentWidth = -1;
LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
- LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
+ LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer};
LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
LLVMStyle.RemoveBracesLLVM = false;
LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
@@ -1910,7 +1953,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.ObjCSpaceAfterProperty = false;
GoogleStyle.ObjCSpaceBeforeProtocolList = true;
GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
- GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
+ GoogleStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
GoogleStyle.RawStringFormats = {
{
FormatStyle::LK_Cpp,
@@ -2105,7 +2148,7 @@ FormatStyle getMozillaStyle() {
MozillaStyle.ObjCSpaceAfterProperty = true;
MozillaStyle.ObjCSpaceBeforeProtocolList = false;
MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
- MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
+ MozillaStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
MozillaStyle.SpaceAfterTemplateKeyword = false;
return MozillaStyle;
}
@@ -2128,7 +2171,7 @@ FormatStyle getWebKitStyle() {
Style.NamespaceIndentation = FormatStyle::NI_Inner;
Style.ObjCBlockIndentWidth = 4;
Style.ObjCSpaceAfterProperty = true;
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
Style.SpaceBeforeCpp11BracedList = true;
Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
return Style;
@@ -2862,10 +2905,10 @@ class Formatter : public TokenAnalyzer {
if (Style.DerivePointerAlignment) {
const auto NetRightCount = countVariableAlignments(AnnotatedLines);
if (NetRightCount > 0)
- Style.PointerAlignment = FormatStyle::PAS_Right;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
else if (NetRightCount < 0)
- Style.PointerAlignment = FormatStyle::PAS_Left;
- Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
}
if (Style.Standard == FormatStyle::LS_Auto) {
Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index cb41756c56bf7..f48a02c49c562 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4732,7 +4732,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (BeforeLeft->is(tok::coloncolon)) {
if (Left.isNot(tok::star))
return false;
- assert(Style.PointerAlignment != FormatStyle::PAS_Right);
+ assert(Style.PointerAlignment.Default != FormatStyle::PAS_Right);
if (!Right.startsSequence(tok::identifier, tok::r_paren))
return true;
assert(Right.Next);
@@ -4744,7 +4744,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
// Ensure right pointer alignment with ellipsis e.g. int *...P
if (Left.is(tok::ellipsis) && BeforeLeft &&
BeforeLeft->isPointerOrReference()) {
- return Style.PointerAlignment != FormatStyle::PAS_Right;
+ return Style.PointerAlignment.Default != FormatStyle::PAS_Right;
}
if (Right.is(tok::star) && Left.is(tok::l_paren))
@@ -4782,9 +4782,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
// dependent on PointerAlignment style.
if (Previous) {
if (Previous->endsSequence(tok::kw_operator))
- return Style.PointerAlignment != FormatStyle::PAS_Left;
+ return Style.PointerAlignment.Default != FormatStyle::PAS_Left;
if (Previous->isOneOf(tok::kw_const, tok::kw_volatile)) {
- return (Style.PointerAlignment != FormatStyle::PAS_Left) ||
+ return (Style.PointerAlignment.Default != FormatStyle::PAS_Left) ||
(Style.SpaceAroundPointerQualifiers ==
FormatStyle::SAPQ_After) ||
(Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both);
@@ -6543,9 +6543,9 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
FormatStyle::PointerAlignmentStyle
TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
assert(Reference.isOneOf(tok::amp, tok::ampamp));
- switch (Style.ReferenceAlignment) {
+ switch (Style.ReferenceAlignment.Default) {
case FormatStyle::RAS_Pointer:
- return Style.PointerAlignment;
+ return Style.PointerAlignment.Default;
case FormatStyle::RAS_Left:
return FormatStyle::PAS_Left;
case FormatStyle::RAS_Right:
@@ -6554,7 +6554,7 @@ TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
return FormatStyle::PAS_Middle;
}
assert(0); //"Unhandled value of ReferenceAlignment"
- return Style.PointerAlignment;
+ return Style.PointerAlignment.Default;
}
FormatStyle::PointerAlignmentStyle
@@ -6563,7 +6563,7 @@ TokenAnnotator::getTokenPointerOrReferenceAlignment(
if (PointerOrReference.isOneOf(tok::amp, tok::ampamp))
return getTokenReferenceAlignment(PointerOrReference);
assert(PointerOrReference.is(tok::star));
- return Style.PointerAlignment;
+ return Style.PointerAlignment.Default;
}
} // namespace format
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 94ccf9eb7842a..3834f3ca743d6 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -384,14 +384,14 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// If PointerAlignment is PAS_Right, keep *s or &s next to the token,
// except if the token is equal, then a space is needed.
- if ((Style.PointerAlignment == FormatStyle::PAS_Right ||
- Style.ReferenceAlignment == FormatStyle::RAS_Right) &&
+ if ((Style.PointerAlignment.Default == FormatStyle::PAS_Right ||
+ Style.ReferenceAlignment.Default == FormatStyle::RAS_Right) &&
CurrentChange.Spaces != 0 &&
CurrentChange.Tok->isNoneOf(tok::equal, tok::r_paren,
TT_TemplateCloser)) {
const bool ReferenceNotRightAligned =
- Style.ReferenceAlignment != FormatStyle::RAS_Right &&
- Style.ReferenceAlignment != FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.Default != FormatStyle::RAS_Right &&
+ Style.ReferenceAlignment.Default != FormatStyle::RAS_Pointer;
for (int Previous = i - 1;
Previous >= 0 && Changes[Previous].Tok->is(TT_PointerOrReference);
--Previous) {
@@ -399,7 +399,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
if (Changes[Previous].Tok->isNot(tok::star)) {
if (ReferenceNotRightAligned)
continue;
- } else if (Style.PointerAlignment != FormatStyle::PAS_Right) {
+ } else if (Style.PointerAlignment.Default != FormatStyle::PAS_Right) {
continue;
}
Changes[Previous + 1].Spaces -= Shift;
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index d578fa7a1a1e8..882f7b1342cc4 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -391,29 +391,39 @@ TEST(ConfigParseTest, ParsesConfiguration) {
#undef CHECK_ALIGN_CONSECUTIVE
- Style.PointerAlignment = FormatStyle::PAS_Middle;
+ Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle};
CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
- FormatStyle::PAS_Left);
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Left}));
CHECK_PARSE("PointerAlignment: Right", PointerAlignment,
- FormatStyle::PAS_Right);
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Right}));
CHECK_PARSE("PointerAlignment: Middle", PointerAlignment,
- FormatStyle::PAS_Middle);
- Style.ReferenceAlignment = FormatStyle::RAS_Middle;
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Middle}));
+ Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle};
CHECK_PARSE("ReferenceAlignment: Pointer", ReferenceAlignment,
- FormatStyle::RAS_Pointer);
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Pointer}));
CHECK_PARSE("ReferenceAlignment: Left", ReferenceAlignment,
- FormatStyle::RAS_Left);
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Left}));
CHECK_PARSE("ReferenceAlignment: Right", ReferenceAlignment,
- FormatStyle::RAS_Right);
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Right}));
CHECK_PARSE("ReferenceAlignment: Middle", ReferenceAlignment,
- FormatStyle::RAS_Middle);
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Middle}));
// For backward compatibility:
CHECK_PARSE("PointerBindsToType: Left", PointerAlignment,
- FormatStyle::PAS_Left);
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Left}));
CHECK_PARSE("PointerBindsToType: Right", PointerAlignment,
- FormatStyle::PAS_Right);
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Right}));
CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
- FormatStyle::PAS_Middle);
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Middle}));
Style.ReflowComments = FormatStyle::RCS_Always;
CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 81fa7d1d11aa4..4ebcd428a0685 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2047,8 +2047,8 @@ TEST_F(FormatTest, ElseIf) {
TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
FormatStyle Style = getLLVMStyle();
- EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
- EXPECT_EQ(Style.ReferenceAlignment, FormatStyle::RAS_Pointer);
+ EXPECT_EQ(Style.PointerAlignment.Default, FormatStyle::PAS_Right);
+ EXPECT_EQ(Style.ReferenceAlignment.Default, FormatStyle::RAS_Pointer);
verifyFormat("int *f1(int *a, int &b, int &&c);", Style);
verifyFormat("int &f2(int &&c, int *a, int &b);", Style);
verifyFormat("int &&f3(int &b, int &&c, int *a);", Style);
@@ -2104,7 +2104,7 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
"Const unsigned h;",
Style);
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("int* f1(int* a, int& b, int&& c);", Style);
verifyFormat("int& f2(int&& c, int* a, int& b);", Style);
verifyFormat("int&& f3(int& b, int&& c, int* a);", Style);
@@ -2162,8 +2162,8 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
"Const unsigned h;",
Style);
- Style.PointerAlignment = FormatStyle::PAS_Right;
- Style.ReferenceAlignment = FormatStyle::RAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Left;
verifyFormat("int *f1(int *a, int& b, int&& c);", Style);
verifyFormat("int& f2(int&& c, int *a, int& b);", Style);
verifyFormat("int&& f3(int& b, int&& c, int *a);", Style);
@@ -2200,8 +2200,8 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
"Const unsigned h;",
Style);
- Style.PointerAlignment = FormatStyle::PAS_Left;
- Style.ReferenceAlignment = FormatStyle::RAS_Middle;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Middle;
verifyFormat("int* f1(int* a, int & b, int && c);", Style);
verifyFormat("int & f2(int && c, int* a, int & b);", Style);
verifyFormat("int && f3(int & b, int && c, int* a);", Style);
@@ -2253,8 +2253,8 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
"Const unsigned h;",
Style);
- Style.PointerAlignment = FormatStyle::PAS_Middle;
- Style.ReferenceAlignment = FormatStyle::RAS_Right;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Right;
verifyFormat("int * f1(int * a, int &b, int &&c);", Style);
verifyFormat("int &f2(int &&c, int * a, int &b);", Style);
verifyFormat("int &&f3(int &b, int &&c, int * a);", Style);
@@ -2376,7 +2376,7 @@ TEST_F(FormatTest, FormatsForLoop) {
NoBinPacking);
FormatStyle AlignLeft = getLLVMStyle();
- AlignLeft.PointerAlignment = FormatStyle::PAS_Left;
+ AlignLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("for (A* a = start; a < end; ++a, ++value) {\n}", AlignLeft);
}
@@ -8638,7 +8638,7 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) {
" void f();");
auto Style = getLLVMStyle();
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaa* const aaaaaaaaaaaa) {}",
Style);
@@ -9975,7 +9975,7 @@ TEST_F(FormatTest, DeclarationsOfMultipleVariables) {
" ***c = ccccccccccccccccccc, ***d = ddddddddddddddd;");
FormatStyle Style = getGoogleStyle();
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
Style.DerivePointerAlignment = false;
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
" *aaaaaaaaaaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaa,\n"
@@ -11465,15 +11465,15 @@ TEST_F(FormatTest, UnderstandsPointersToMembers) {
" aaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa));");
FormatStyle Style = getLLVMStyle();
- EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
+ EXPECT_EQ(Style.PointerAlignment.Default, FormatStyle::PAS_Right);
verifyFormat("typedef bool *(Class::*Member)() const;", Style);
verifyFormat("void f(int A::*p) { int A::*v = &A::B; }", Style);
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("typedef bool* (Class::*Member)() const;", Style);
verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style);
- Style.PointerAlignment = FormatStyle::PAS_Middle;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("typedef bool * (Class::*Member)() const;", Style);
verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style);
}
@@ -11533,7 +11533,7 @@ TEST_F(FormatTest, UnderstandsUnaryOperators) {
// Check that * is not treated as a binary operator when we set
// PointerAlignment as PAS_Left after a keyword and not a declaration.
FormatStyle PASLeftStyle = getLLVMStyle();
- PASLeftStyle.PointerAlignment = FormatStyle::PAS_Left;
+ PASLeftStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("co_return *a;", PASLeftStyle);
verifyFormat("co_await *a;", PASLeftStyle);
verifyFormat("co_yield *a", PASLeftStyle);
@@ -11661,7 +11661,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
verifyFormat("template <typename T> void operator=(T) && {}");
FormatStyle AlignLeft = getLLVMStyle();
- AlignLeft.PointerAlignment = FormatStyle::PAS_Left;
+ AlignLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("void A::b() && {}", AlignLeft);
verifyFormat("void A::b() && noexcept {}", AlignLeft);
verifyFormat("Deleted& operator=(const Deleted&) & = default;", AlignLeft);
@@ -11693,7 +11693,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
verifyFormat("for (foo<void() &&>& cb : X)", AlignLeft);
FormatStyle AlignMiddle = getLLVMStyle();
- AlignMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+ AlignMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("void A::b() && {}", AlignMiddle);
verifyFormat("void A::b() && noexcept {}", AlignMiddle);
verifyFormat("Deleted & operator=(const Deleted &) & = default;",
@@ -11776,7 +11776,7 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
FormatStyle AlignLeftBreakTemplate = getLLVMStyle();
AlignLeftBreakTemplate.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
- AlignLeftBreakTemplate.PointerAlignment = FormatStyle::PAS_Left;
+ AlignLeftBreakTemplate.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("struct f {\n"
" template <class T>\n"
@@ -11860,19 +11860,19 @@ TEST_F(FormatTest, PointerAlignmentFallback) {
"int *q;\n"
"int * r;");
- EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
+ EXPECT_EQ(Style.PointerAlignment.Default, FormatStyle::PAS_Right);
verifyFormat("int *p;\n"
"int *q;\n"
"int *r;",
Code, Style);
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("int* p;\n"
"int* q;\n"
"int* r;",
Code, Style);
- Style.PointerAlignment = FormatStyle::PAS_Middle;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("int * p;\n"
"int * q;\n"
"int * r;",
@@ -12068,7 +12068,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
"void f(int i = 0, SomeType** temps = NULL);");
FormatStyle Left = getLLVMStyle();
- Left.PointerAlignment = FormatStyle::PAS_Left;
+ Left.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("x = *a(x) = *a(y);", Left);
verifyFormat("for (;; *a = b) {\n}", Left);
verifyFormat("return *this += 1;", Left);
@@ -12214,7 +12214,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
getGoogleStyleWithColumns(68));
FormatStyle Style = getLLVMStyle();
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("struct {\n"
"}* ptr;",
Style);
@@ -12238,7 +12238,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
Style);
verifyFormat("bool b = 3 == int{3} && true;");
- Style.PointerAlignment = FormatStyle::PAS_Middle;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("struct {\n"
"} * ptr;",
Style);
@@ -12258,7 +12258,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
"} && ptr = {};",
Style);
- Style.PointerAlignment = FormatStyle::PAS_Right;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
verifyFormat("struct {\n"
"} *ptr;",
Style);
@@ -12278,7 +12278,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
"} &&ptr = {};",
Style);
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("delete[] *ptr;", Style);
verifyFormat("delete[] **ptr;", Style);
verifyFormat("delete[] *(ptr);", Style);
@@ -12369,7 +12369,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyFormat("foo<a<b && c> d> v;");
FormatStyle PointerMiddle = getLLVMStyle();
- PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+ PointerMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("delete *x;", PointerMiddle);
verifyFormat("int * x;", PointerMiddle);
verifyFormat("int *[] x;", PointerMiddle);
@@ -12476,7 +12476,7 @@ TEST_F(FormatTest, UnderstandsAttributes) {
auto Style = getLLVMStyleWithColumns(60);
Style.AttributeMacros.push_back("my_fancy_attr");
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("void foo(const MyLongTypeNameeeeeeeeeeeee* my_fancy_attr\n"
" testttttttttt);",
Style);
@@ -12504,7 +12504,7 @@ TEST_F(FormatTest, UnderstandsPointerQualifiersInCast) {
// determine that the expression is a cast to a pointer type.
FormatStyle LongPointerRight = getLLVMStyleWithColumns(999);
FormatStyle LongPointerLeft = getLLVMStyleWithColumns(999);
- LongPointerLeft.PointerAlignment = FormatStyle::PAS_Left;
+ LongPointerLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
StringRef AllQualifiers =
"const volatile restrict __attribute__((foo)) _Nonnull _Null_unspecified "
"_Nullable [[clang::attr]] __ptr32 __ptr64 __capability";
@@ -12640,12 +12640,12 @@ TEST_F(FormatTest, UnderstandsEllipsis) {
verifyFormat("template <int *...PP> a;", Style);
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("template <class... Ts> void Foo(Ts*... ts) {}", Style);
verifyFormat("template <int*... PP> a;", Style);
- Style.PointerAlignment = FormatStyle::PAS_Middle;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("template <int *... PP> a;", Style);
}
@@ -16253,15 +16253,15 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
FormatStyle TabAlignment = Tab;
TabAlignment.AlignConsecutiveDeclarations.Enabled = true;
- TabAlignment.PointerAlignment = FormatStyle::PAS_Left;
+ TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("unsigned long long big;\n"
"char*\t\t ptr;",
TabAlignment);
- TabAlignment.PointerAlignment = FormatStyle::PAS_Middle;
+ TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("unsigned long long big;\n"
"char *\t\t ptr;",
TabAlignment);
- TabAlignment.PointerAlignment = FormatStyle::PAS_Right;
+ TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Right;
verifyFormat("unsigned long long big;\n"
"char\t\t *ptr;",
TabAlignment);
@@ -16309,19 +16309,19 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
Tab);
TabAlignment.UseTab = FormatStyle::UT_ForIndentation;
- TabAlignment.PointerAlignment = FormatStyle::PAS_Left;
+ TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("void f() {\n"
"\tunsigned long long big;\n"
"\tchar* ptr;\n"
"}",
TabAlignment);
- TabAlignment.PointerAlignment = FormatStyle::PAS_Middle;
+ TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("void f() {\n"
"\tunsigned long long big;\n"
"\tchar * ptr;\n"
"}",
TabAlignment);
- TabAlignment.PointerAlignment = FormatStyle::PAS_Right;
+ TabAlignment.PointerAlignment.Default = FormatStyle::PAS_Right;
verifyFormat("void f() {\n"
"\tunsigned long long big;\n"
"\tchar *ptr;\n"
@@ -18227,13 +18227,13 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeColon) {
TEST_F(FormatTest, ConfigurableSpaceAroundPointerQualifiers) {
FormatStyle Style = getLLVMStyle();
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
Style.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
verifyFormat("void* const* x = NULL;", Style);
#define verifyQualifierSpaces(Code, Pointers, Qualifiers) \
do { \
- Style.PointerAlignment = FormatStyle::Pointers; \
+ Style.PointerAlignment.Default = FormatStyle::Pointers; \
Style.SpaceAroundPointerQualifiers = FormatStyle::Qualifiers; \
verifyFormat(Code, Style); \
} while (false)
@@ -18279,7 +18279,7 @@ TEST_F(FormatTest, ConfigurableSpaceAroundPointerQualifiers) {
FormatStyle Spaces = getLLVMStyle();
Spaces.AttributeMacros.push_back("qualified");
- Spaces.PointerAlignment = FormatStyle::PAS_Right;
+ Spaces.PointerAlignment.Default = FormatStyle::PAS_Right;
Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
verifyFormat("SomeType *volatile *a = NULL;", Spaces);
verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces);
@@ -18294,7 +18294,7 @@ TEST_F(FormatTest, ConfigurableSpaceAroundPointerQualifiers) {
verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
// Check that SAPQ_Before doesn't result in extra spaces for PAS_Left.
- Spaces.PointerAlignment = FormatStyle::PAS_Left;
+ Spaces.PointerAlignment.Default = FormatStyle::PAS_Left;
Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Before;
verifyFormat("SomeType* volatile* a = NULL;", Spaces);
verifyFormat("SomeType* __attribute__((attr))* a = NULL;", Spaces);
@@ -18310,7 +18310,7 @@ TEST_F(FormatTest, ConfigurableSpaceAroundPointerQualifiers) {
verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
// PAS_Middle should not have any noticeable changes even for SAPQ_Both
- Spaces.PointerAlignment = FormatStyle::PAS_Middle;
+ Spaces.PointerAlignment.Default = FormatStyle::PAS_Middle;
Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_After;
verifyFormat("SomeType * volatile * a = NULL;", Spaces);
verifyFormat("SomeType * __attribute__((attr)) * a = NULL;", Spaces);
@@ -19756,7 +19756,7 @@ TEST_F(FormatTest, AlignConsecutiveBitFields) {
TEST_F(FormatTest, AlignConsecutiveDeclarations) {
FormatStyle Alignment = getLLVMStyle();
Alignment.AlignConsecutiveMacros.Enabled = true;
- Alignment.PointerAlignment = FormatStyle::PAS_Right;
+ Alignment.PointerAlignment.Default = FormatStyle::PAS_Right;
verifyFormat("float const a = 5;\n"
"int oneTwoThree = 123;",
Alignment);
@@ -20023,7 +20023,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
// PAS_Left
FormatStyle AlignmentLeft = Alignment;
- AlignmentLeft.PointerAlignment = FormatStyle::PAS_Left;
+ AlignmentLeft.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("void SomeFunction(int parameter = 0) {\n"
" int const i = 1;\n"
" int* j = 2;\n"
@@ -20097,7 +20097,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
// PAS_Middle
FormatStyle AlignmentMiddle = Alignment;
- AlignmentMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+ AlignmentMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("void SomeFunction(int parameter = 0) {\n"
" int const i = 1;\n"
" int * j = 2;\n"
@@ -20313,14 +20313,14 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
Alignment.ColumnLimit = 80;
// Bug 33507
- Alignment.PointerAlignment = FormatStyle::PAS_Middle;
+ Alignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat(
"auto found = range::find_if(vsProducts, [&](auto * aProduct) {\n"
" static const Version verVs2017;\n"
" return true;\n"
"});",
Alignment);
- Alignment.PointerAlignment = FormatStyle::PAS_Right;
+ Alignment.PointerAlignment.Default = FormatStyle::PAS_Right;
// See llvm.org/PR35641
Alignment.AlignConsecutiveDeclarations.Enabled = true;
@@ -20337,7 +20337,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
"foo(int a);",
"DECOR1 /**/ int8_t /**/ DECOR2 /**/ foo (int a);", Style);
- Alignment.PointerAlignment = FormatStyle::PAS_Left;
+ Alignment.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("unsigned int* a;\n"
"int* b;\n"
"unsigned int Const* c;\n"
@@ -20353,7 +20353,7 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) {
"Const unsigned h;",
Alignment);
- Alignment.PointerAlignment = FormatStyle::PAS_Middle;
+ Alignment.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("unsigned int * a;\n"
"int * b;\n"
"unsigned int Const * c;\n"
@@ -25086,7 +25086,7 @@ TEST_F(FormatTest, StructuredBindings) {
// Make sure we don't mistake structured bindings for lambdas.
FormatStyle PointerMiddle = getLLVMStyle();
- PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle;
+ PointerMiddle.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyGoogleFormat("auto [a1, b]{A * i};");
verifyFormat("auto [a2, b]{A * i};");
verifyFormat("auto [a3, b]{A * i};", PointerMiddle);
@@ -25330,7 +25330,7 @@ TEST_F(FormatTest, TypenameMacros) {
verifyFormat("vector<LIST(uint64_t) *attr> x;", Macros);
verifyFormat("vector<LIST(uint64_t) *const> f(LIST(uint64_t) *arg);", Macros);
- Macros.PointerAlignment = FormatStyle::PAS_Left;
+ Macros.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("STACK_OF(int)* a;", Macros);
verifyFormat("STACK_OF(int*)* a;", Macros);
verifyFormat("x = (STACK_OF(uint64_t))*a;", Macros);
@@ -25361,7 +25361,7 @@ TEST_F(FormatTest, AtomicQualifier) {
verifyFormat("_Atomic(uint64_t) *s(InitValue);");
verifyFormat("_Atomic(uint64_t) *s{InitValue};");
FormatStyle Style = getLLVMStyle();
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("_Atomic(uint64_t)* s(InitValue);", Style);
verifyFormat("_Atomic(uint64_t)* s{InitValue};", Style);
verifyFormat("_Atomic(int)* a;", Style);
@@ -25424,9 +25424,9 @@ TEST_F(FormatTest, C11Generic) {
TEST_F(FormatTest, AmbersandInLamda) {
// Test case reported in https://bugs.llvm.org/show_bug.cgi?id=41899
FormatStyle AlignStyle = getLLVMStyle();
- AlignStyle.PointerAlignment = FormatStyle::PAS_Left;
+ AlignStyle.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle);
- AlignStyle.PointerAlignment = FormatStyle::PAS_Right;
+ AlignStyle.PointerAlignment.Default = FormatStyle::PAS_Right;
verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle);
}
@@ -25554,7 +25554,7 @@ TEST_F(FormatTest, STLWhileNotDefineChed) {
TEST_F(FormatTest, OperatorSpacing) {
FormatStyle Style = getLLVMStyle();
- Style.PointerAlignment = FormatStyle::PAS_Right;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
verifyFormat("Foo::operator*();", Style);
verifyFormat("Foo::operator void *();", Style);
verifyFormat("Foo::operator void **();", Style);
@@ -25610,7 +25610,7 @@ TEST_F(FormatTest, OperatorSpacing) {
verifyFormat("operator const FooRight<Object> *&()", Style);
verifyFormat("operator const FooRight<Object> *&&()", Style);
- Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
verifyFormat("Foo::operator*();", Style);
verifyFormat("Foo::operator**();", Style);
verifyFormat("Foo::operator void*();", Style);
@@ -25681,7 +25681,7 @@ TEST_F(FormatTest, OperatorSpacing) {
verifyFormat("operator/*a*/ const /*b*/ Foo /*c*/<X> /*d*/ ::Bar<Y>*();",
Style);
- Style.PointerAlignment = FormatStyle::PAS_Middle;
+ Style.PointerAlignment.Default = FormatStyle::PAS_Middle;
verifyFormat("Foo::operator*();", Style);
verifyFormat("Foo::operator void *();", Style);
verifyFormat("Foo::operator()(void *);", Style);
@@ -27940,7 +27940,7 @@ TEST_F(FormatTest, BreakAfterAttributes) {
"Foo &operator-(Foo &);",
Style);
- Style.ReferenceAlignment = FormatStyle::RAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Left;
verifyFormat("[[nodiscard]]\n"
"Foo& operator-(Foo&);",
Style);
>From a4ca42e69ed638969ec78c66781fbb09c986e42e Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer at gmail.com>
Date: Sat, 22 Nov 2025 11:35:28 +0100
Subject: [PATCH 2/3] [clang-format] Allow custom pointer/ref alignment in
return types
I would like to adopt clang-format in systemd
(https://github.com/systemd/systemd). One major blocker is that
systemd right-aligns pointers by default, except in function return
types, where they are left-aligned.
Let's introduce a ReturnType customization for PointerAlignment and
ReferenceAlignment that allows overriding the alignment used in return
types.
systemd style guide: https://github.com/systemd/systemd/blob/main/docs/CODING_STYLE.md
Fixes #136597
---
clang/docs/ClangFormatStyleOptions.rst | 60 +++++++
clang/include/clang/Format/Format.h | 29 ++-
clang/lib/Format/Format.cpp | 46 +++--
clang/lib/Format/TokenAnnotator.cpp | 76 +++++++-
clang/unittests/Format/ConfigParseTest.cpp | 52 ++++--
clang/unittests/Format/FormatTest.cpp | 200 +++++++++++++++++++++
6 files changed, 436 insertions(+), 27 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index ab21290260005..119685d39d347 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5718,6 +5718,36 @@ the configuration (without a prefix: ``Auto``).
int * a;
+ * ``ReturnTypeAlignmentStyle ReturnType``
+ The alignment for pointers in function return types.
+
+ Possible values:
+
+ * ``RTAS_Default`` (in configuration: ``Default``)
+ Use default alignment.
+
+ * ``RTAS_Left`` (in configuration: ``Left``)
+ Align pointer/reference to the left.
+
+ .. code-block:: c++
+
+ int* a(void);
+
+ * ``RTAS_Right`` (in configuration: ``Right``)
+ Align pointer/reference to the right.
+
+ .. code-block:: c++
+
+ int *a(void);
+
+ * ``RTAS_Middle`` (in configuration: ``Middle``)
+ Align pointer/reference in the middle.
+
+ .. code-block:: c++
+
+ int * a(void);
+
+
.. _QualifierAlignment:
@@ -5901,6 +5931,36 @@ the configuration (without a prefix: ``Auto``).
int & a;
+ * ``ReturnTypeAlignmentStyle ReturnType``
+ The alignment for references in function return types.
+
+ Possible values:
+
+ * ``RTAS_Default`` (in configuration: ``Default``)
+ Use default alignment.
+
+ * ``RTAS_Left`` (in configuration: ``Left``)
+ Align pointer/reference to the left.
+
+ .. code-block:: c++
+
+ int* a(void);
+
+ * ``RTAS_Right`` (in configuration: ``Right``)
+ Align pointer/reference to the right.
+
+ .. code-block:: c++
+
+ int *a(void);
+
+ * ``RTAS_Middle`` (in configuration: ``Middle``)
+ Align pointer/reference in the middle.
+
+ .. code-block:: c++
+
+ int * a(void);
+
+
.. _ReflowComments:
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 2cd446366cfa4..3919c1d0bc8b3 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4036,12 +4036,35 @@ struct FormatStyle {
PAS_Middle
};
+ /// \brief The pointer/reference alignment style for function return types.
+ enum ReturnTypeAlignmentStyle : int8_t {
+ /// Use default alignment.
+ RTAS_Default,
+ /// Align pointer/reference to the left.
+ /// \code
+ /// int* a(void);
+ /// \endcode
+ RTAS_Left,
+ /// Align pointer/reference to the right.
+ /// \code
+ /// int *a(void);
+ /// \endcode
+ RTAS_Right,
+ /// Align pointer/reference in the middle.
+ /// \code
+ /// int * a(void);
+ /// \endcode
+ RTAS_Middle
+ };
+
/// Pointer and reference alignment options.
struct PointerAlignmentOptions {
/// The default alignment for pointers and references.
PointerAlignmentStyle Default;
+ /// The alignment for pointers in function return types.
+ ReturnTypeAlignmentStyle ReturnType;
bool operator==(const PointerAlignmentOptions &R) const {
- return Default == R.Default;
+ return Default == R.Default && ReturnType == R.ReturnType;
}
bool operator!=(const PointerAlignmentOptions &R) const {
return !(*this == R);
@@ -4239,8 +4262,10 @@ struct FormatStyle {
struct ReferenceAlignmentOptions {
/// The default alignment for references.
ReferenceAlignmentStyle Default;
+ /// The alignment for references in function return types.
+ ReturnTypeAlignmentStyle ReturnType;
bool operator==(const ReferenceAlignmentOptions &R) const {
- return Default == R.Default;
+ return Default == R.Default && ReturnType == R.ReturnType;
}
bool operator!=(const ReferenceAlignmentOptions &R) const {
return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 2140cf66cd5af..f950d64b29436 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -544,29 +544,46 @@ template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
}
};
+template <>
+struct ScalarEnumerationTraits<FormatStyle::ReturnTypeAlignmentStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::ReturnTypeAlignmentStyle &Value) {
+ IO.enumCase(Value, "Default", FormatStyle::RTAS_Default);
+ IO.enumCase(Value, "Middle", FormatStyle::RTAS_Middle);
+ IO.enumCase(Value, "Left", FormatStyle::RTAS_Left);
+ IO.enumCase(Value, "Right", FormatStyle::RTAS_Right);
+ }
+};
+
template <> struct MappingTraits<FormatStyle::PointerAlignmentOptions> {
static void enumInput(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
IO.enumCase(Value, "Middle",
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Middle}));
+ {/*Default=*/FormatStyle::PAS_Middle,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
IO.enumCase(Value, "Left",
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Left}));
+ {/*Default=*/FormatStyle::PAS_Left,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
IO.enumCase(Value, "Right",
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Right}));
+ {/*Default=*/FormatStyle::PAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
// For backward compatibility.
IO.enumCase(Value, "true",
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Left}));
+ {/*Default=*/FormatStyle::PAS_Left,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
IO.enumCase(Value, "false",
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Right}));
+ {/*Default=*/FormatStyle::PAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
}
static void mapping(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
IO.mapOptional("Default", Value.Default);
+ IO.mapOptional("ReturnType", Value.ReturnType);
}
};
@@ -615,20 +632,25 @@ template <> struct MappingTraits<FormatStyle::ReferenceAlignmentOptions> {
static void enumInput(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
IO.enumCase(Value, "Pointer",
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Pointer}));
+ {/*Default=*/FormatStyle::RAS_Pointer,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
IO.enumCase(Value, "Middle",
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Middle}));
+ {/*Default=*/FormatStyle::RAS_Middle,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
IO.enumCase(Value, "Left",
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Left}));
+ {/*Default=*/FormatStyle::RAS_Left,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
IO.enumCase(Value, "Right",
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Right}));
+ {/*Default=*/FormatStyle::RAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
}
static void mapping(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
IO.mapOptional("Default", Value.Default);
+ IO.mapOptional("ReturnType", Value.ReturnType);
}
};
@@ -1828,10 +1850,12 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ObjCSpaceAfterProperty = false;
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
- LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right};
+ LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Default};
LLVMStyle.PPIndentWidth = -1;
LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
- LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer};
+ LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
+ /*ReturnType=*/FormatStyle::RTAS_Default};
LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
LLVMStyle.RemoveBracesLLVM = false;
LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index f48a02c49c562..fe53d70eb12d7 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -6540,9 +6540,76 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
llvm::errs() << "----\n";
}
+static bool isReturnType(const FormatToken &Tok, const LangOptions &LangOpts) {
+ // Look forward to see if there's a function declaration paren.
+ for (const FormatToken *Next = Tok.Next; Next;
+ Next = Next->getNextNonComment()) {
+ if (Next->isOneOf(TT_FunctionDeclarationName, TT_FunctionDeclarationLParen,
+ TT_FunctionTypeLParen)) {
+ return true;
+ }
+
+ if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
+ Next = Next->MatchingParen;
+ continue;
+ }
+
+ if (Next->isPointerOrReference() || Next->isTypeName(LangOpts) ||
+ Next->isOneOf(tok::identifier, tok::coloncolon) ||
+ Next->canBePointerOrReferenceQualifier()) {
+ continue;
+ }
+
+ break;
+ }
+
+ // Look backward to see if there's a trailing return arrow.
+ for (const FormatToken *Prev = Tok.Previous; Prev;
+ Prev = Prev->getPreviousNonComment()) {
+ if (Prev->is(TT_TrailingReturnArrow))
+ return true;
+
+ if (Prev->is(TT_TemplateCloser) && Prev->MatchingParen) {
+ Prev = Prev->MatchingParen;
+ continue;
+ }
+
+ if (Prev->isPointerOrReference() || Prev->isTypeName(LangOpts) ||
+ Prev->isOneOf(tok::identifier, tok::coloncolon) ||
+ Prev->canBePointerOrReferenceQualifier()) {
+ continue;
+ }
+
+ break;
+ }
+
+ return false;
+}
+
+static FormatStyle::PointerAlignmentStyle
+mapReturnTypeAlignmentStyle(FormatStyle::ReturnTypeAlignmentStyle Style) {
+ switch (Style) {
+ case FormatStyle::RTAS_Left:
+ return FormatStyle::PAS_Left;
+ case FormatStyle::RTAS_Right:
+ return FormatStyle::PAS_Right;
+ case FormatStyle::RTAS_Middle:
+ return FormatStyle::PAS_Middle;
+ case FormatStyle::RTAS_Default:
+ assert(false);
+ }
+ llvm_unreachable("Unknown FormatStyle::ReturnTypeAlignmentStyle enum");
+}
+
FormatStyle::PointerAlignmentStyle
TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
assert(Reference.isOneOf(tok::amp, tok::ampamp));
+
+ if (Style.ReferenceAlignment.ReturnType != FormatStyle::RTAS_Default &&
+ isReturnType(Reference, LangOpts)) {
+ return mapReturnTypeAlignmentStyle(Style.ReferenceAlignment.ReturnType);
+ }
+
switch (Style.ReferenceAlignment.Default) {
case FormatStyle::RAS_Pointer:
return Style.PointerAlignment.Default;
@@ -6553,8 +6620,7 @@ TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
case FormatStyle::RAS_Middle:
return FormatStyle::PAS_Middle;
}
- assert(0); //"Unhandled value of ReferenceAlignment"
- return Style.PointerAlignment.Default;
+ llvm_unreachable("Unknown FormatStyle::ReferenceAlignmentStyle enum");
}
FormatStyle::PointerAlignmentStyle
@@ -6563,6 +6629,12 @@ TokenAnnotator::getTokenPointerOrReferenceAlignment(
if (PointerOrReference.isOneOf(tok::amp, tok::ampamp))
return getTokenReferenceAlignment(PointerOrReference);
assert(PointerOrReference.is(tok::star));
+
+ if (Style.PointerAlignment.ReturnType != FormatStyle::RTAS_Default &&
+ isReturnType(PointerOrReference, LangOpts)) {
+ return mapReturnTypeAlignmentStyle(Style.PointerAlignment.ReturnType);
+ }
+
return Style.PointerAlignment.Default;
}
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 882f7b1342cc4..cf54b79bcf8a6 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -391,39 +391,67 @@ TEST(ConfigParseTest, ParsesConfiguration) {
#undef CHECK_ALIGN_CONSECUTIVE
- Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle};
+ Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle,
+ /*ReturnType=*/FormatStyle::RTAS_Default};
CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Left}));
+ {/*Default=*/FormatStyle::PAS_Left,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
CHECK_PARSE("PointerAlignment: Right", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Right}));
+ {/*Default=*/FormatStyle::PAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
CHECK_PARSE("PointerAlignment: Middle", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Middle}));
- Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle};
+ {/*Default=*/FormatStyle::PAS_Middle,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
+ CHECK_PARSE("PointerAlignment:\n"
+ " Default: Right\n"
+ " ReturnType: Left",
+ PointerAlignment,
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Left}));
+
+ Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle,
+ /*ReturnType=*/FormatStyle::RTAS_Default};
CHECK_PARSE("ReferenceAlignment: Pointer", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Pointer}));
+ {/*Default=*/FormatStyle::RAS_Pointer,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
CHECK_PARSE("ReferenceAlignment: Left", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Left}));
+ {/*Default=*/FormatStyle::RAS_Left,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
CHECK_PARSE("ReferenceAlignment: Right", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Right}));
+ {/*Default=*/FormatStyle::RAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
CHECK_PARSE("ReferenceAlignment: Middle", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
- {/*Default=*/FormatStyle::RAS_Middle}));
+ {/*Default=*/FormatStyle::RAS_Middle,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
+ CHECK_PARSE("ReferenceAlignment:\n"
+ " Default: Right\n"
+ " ReturnType: Left",
+ ReferenceAlignment,
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Left}));
+
// For backward compatibility:
CHECK_PARSE("PointerBindsToType: Left", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Left}));
+ {/*Default=*/FormatStyle::PAS_Left,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
CHECK_PARSE("PointerBindsToType: Right", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Right}));
+ {/*Default=*/FormatStyle::PAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
- {/*Default=*/FormatStyle::PAS_Middle}));
+ {/*Default=*/FormatStyle::PAS_Middle,
+ /*ReturnType=*/FormatStyle::RTAS_Default}));
Style.ReflowComments = FormatStyle::RCS_Always;
CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 4ebcd428a0685..ad14e7d1f0429 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2296,6 +2296,206 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
// verifyFormat("int Add2(BTree * &Root, char * szToAdd)", Style);
}
+TEST_F(FormatTest, ReturnTypeAlignment) {
+ // Test that ReturnType overrides PointerAlignment for return types
+ FormatStyle Style = getLLVMStyle();
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Left;
+
+ // Return type pointers should be left-aligned despite PAS_Right
+ verifyFormat("int* f1(int *a, int *b);", Style);
+ verifyFormat("int& f2(int &a, int &b);", Style);
+ verifyFormat("int&& f3(int &&a, int &&b);", Style);
+
+ // Multiple pointers in return type
+ verifyFormat("int** f4(int **a);", Style);
+ verifyFormat("const int* f5(const int *a);", Style);
+ verifyFormat("int*** f6(int ***a);", Style);
+
+ // Multiple pointers with const qualifiers
+ verifyFormat("const int** f7(const int **a);", Style);
+ verifyFormat("int* const* f8(int *const *a);", Style);
+ verifyFormat("const int* const* f9(const int *const *a);", Style);
+ verifyFormat("int** const f10(int **const a);", Style);
+ verifyFormat("const int** const f11(const int **const a);", Style);
+
+ // Complex return types
+ verifyFormat("std::vector<int>* f16(std::vector<int> *a);", Style);
+ verifyFormat("const char* f17(const char *str);", Style);
+ verifyFormat("const char** f18(const char **argv);", Style);
+ verifyFormat("char* const* f19(char *const *envp);", Style);
+
+ // Member functions
+ verifyFormat("int* Class::method(int *a);", Style);
+ verifyFormat("int& Class::method(int &a);", Style);
+ verifyFormat("int* (*f8())(int *a);", Style);
+
+ // Variables should still follow the default alignment
+ verifyFormat("int *a = nullptr;", Style);
+ verifyFormat("int *b = f1(a, a);", Style);
+
+ // Now test with PAS_Left base and RTAS_Right return type
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Right;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+ // Return type pointers should be right-aligned despite PAS_Left
+ verifyFormat("int *f1(int* a, int* b);", Style);
+ verifyFormat("int &f2(int& a, int& b);", Style);
+ verifyFormat("int &&f3(int&& a, int&& b);", Style);
+
+ // Multiple pointers with right alignment in return type
+ verifyFormat("int **f4(int** a);", Style);
+ verifyFormat("const int *f5(const int* a);", Style);
+ verifyFormat("int ***f6(int*** a);", Style);
+
+ // Multiple pointers with const qualifiers, right-aligned return type
+ verifyFormat("const int **f7(const int** a);", Style);
+ verifyFormat("int *const *f8(int* const* a);", Style);
+ verifyFormat("const int *const *f9(const int* const* a);", Style);
+ verifyFormat("int **const f10(int** const a);", Style);
+ verifyFormat("const char **f11(const char** argv);", Style);
+
+ // Variables should still follow PointerAlignment (PAS_Left)
+ verifyFormat("int* a = nullptr;", Style);
+ verifyFormat("int* b = f1(a, a);", Style);
+
+ // Test with RTAS_Middle
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Middle;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Middle;
+
+ verifyFormat("int * f1(int *a, int *b);", Style);
+ verifyFormat("int & f2(int &a, int &b);", Style);
+ verifyFormat("int && f3(int &&a, int &&b);", Style);
+
+ // Multiple pointers with const qualifiers, middle-aligned return type
+ verifyFormat("const int * f6(const int *a);", Style);
+ verifyFormat("const int ** f7(const int **a);", Style);
+ verifyFormat("int * const * f8(int *const *a);", Style);
+ verifyFormat("const int * const * f9(const int *const *a);", Style);
+ verifyFormat("int ** const f10(int **const a);", Style);
+ verifyFormat("const char ** f11(const char **argv);", Style);
+
+ // Variables should still follow PointerAlignment (PAS_Right)
+ verifyFormat("int *a = nullptr;", Style);
+
+ // Test that default alignment is used when ReturnType is RTAS_Default
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Default;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Default;
+
+ verifyFormat("int* f1(int* a, int* b);", Style);
+ verifyFormat("int& f2(int& a, int& b);", Style);
+
+ // Test with ReferenceAlignment override
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+ verifyFormat("int* f1(int *a, int &b);", Style);
+ verifyFormat("int &f2(int &a, int *b);", Style);
+ verifyFormat("int &&f3(int &&a, int *b);", Style);
+
+ // Test trailing return types with PAS_Right and RTAS_Left
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Left;
+
+ verifyFormat("auto f1(int *a, int *b) -> int*;", Style);
+ verifyFormat("auto f2(int &a, int &b) -> int&;", Style);
+ verifyFormat("auto f3(int &&a, int &&b) -> int&&;", Style);
+
+ // Multiple pointers in trailing return type
+ verifyFormat("auto f4(int **a) -> int**;", Style);
+ verifyFormat("auto f5(const int *a) -> const int*;", Style);
+ verifyFormat("auto f6(int ***a) -> int***;", Style);
+
+ // Multiple pointers with const qualifiers
+ verifyFormat("auto f7(const int **a) -> const int**;", Style);
+ verifyFormat("auto f8(int *const *a) -> int* const*;", Style);
+ verifyFormat("auto f9(const int *const *a) -> const int* const*;", Style);
+ verifyFormat("auto f10(int **const a) -> int** const;", Style);
+ verifyFormat("auto f11(const int **const a) -> const int** const;", Style);
+
+ // Complex trailing return types
+ verifyFormat("auto f16(std::vector<int> *a) -> std::vector<int>*;", Style);
+ verifyFormat("auto f17(const char *str) -> const char*;", Style);
+ verifyFormat("auto f18(const char **argv) -> const char**;", Style);
+ verifyFormat("auto f19(char *const *envp) -> char* const*;", Style);
+
+ // Member functions with trailing return types
+ verifyFormat("auto Class::method(int *a) -> int*;", Style);
+ verifyFormat("auto Class::method(int &a) -> int&;", Style);
+
+ // Now test with PAS_Left base and RTAS_Right trailing return type
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Right;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+ verifyFormat("auto f1(int* a, int* b) -> int *;", Style);
+ verifyFormat("auto f2(int& a, int& b) -> int &;", Style);
+ verifyFormat("auto f3(int&& a, int&& b) -> int &&;", Style);
+
+ // Multiple pointers with right alignment in trailing return type
+ verifyFormat("auto f4(int** a) -> int **;", Style);
+ verifyFormat("auto f5(const int* a) -> const int *;", Style);
+ verifyFormat("auto f6(int*** a) -> int ***;", Style);
+
+ // Multiple pointers with const qualifiers, right-aligned trailing return type
+ verifyFormat("auto f7(const int** a) -> const int **;", Style);
+ verifyFormat("auto f8(int* const* a) -> int *const *;", Style);
+ verifyFormat("auto f9(const int* const* a) -> const int *const *;", Style);
+ verifyFormat("auto f10(int** const a) -> int **const;", Style);
+ verifyFormat("auto f11(const char** argv) -> const char **;", Style);
+
+ // Test with RTAS_Middle trailing return type
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Middle;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Middle;
+
+ verifyFormat("auto f1(int *a, int *b) -> int *;", Style);
+ verifyFormat("auto f2(int &a, int &b) -> int &;", Style);
+ verifyFormat("auto f3(int &&a, int &&b) -> int &&;", Style);
+
+ // Multiple pointers with const qualifiers, middle-aligned trailing return
+ // type
+ verifyFormat("auto f6(const int *a) -> const int *;", Style);
+ verifyFormat("auto f7(const int **a) -> const int **;", Style);
+ verifyFormat("auto f8(int *const *a) -> int * const *;", Style);
+ verifyFormat("auto f9(const int *const *a) -> const int * const *;", Style);
+ verifyFormat("auto f10(int **const a) -> int ** const;", Style);
+ verifyFormat("auto f11(const char **argv) -> const char **;", Style);
+
+ // Test that default alignment is used when ReturnType is RTAS_Default
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Default;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Default;
+
+ verifyFormat("auto f1(int* a, int* b) -> int*;", Style);
+ verifyFormat("auto f2(int& a, int& b) -> int&;", Style);
+
+ // Test with ReferenceAlignment override for trailing return types
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.ReturnType = FormatStyle::RTAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.ReturnType = FormatStyle::RTAS_Right;
+
+ verifyFormat("auto f1(int *a, int &b) -> int*;", Style);
+ verifyFormat("auto f2(int &a, int *b) -> int &;", Style);
+ verifyFormat("auto f3(int &&a, int *b) -> int &&;", Style);
+}
+
TEST_F(FormatTest, FormatsForLoop) {
verifyFormat(
"for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n"
>From 7f56a96be5381ef1b04cf53f000e2e9f12fab1a2 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer at gmail.com>
Date: Sat, 22 Nov 2025 21:10:04 +0100
Subject: [PATCH 3/3] [clang-format] Allow custom pointer/ref alignment for
C-style casts
I would like to adopt clang-format in systemd
(https://github.com/systemd/systemd). One major blocker is that
systemd right-aligns pointers by default, except in function return
types and c-style casts, where they are left-aligned.
Let's introduce a CStyleCast customization for PointerAlignment and
ReferenceAlignment that allows overriding the alignment used for
C-style casts.
systemd style guide: https://github.com/systemd/systemd/blob/main/docs/CODING_STYLE.md
---
clang/docs/ClangFormatStyleOptions.rst | 46 ++++++++++
clang/include/clang/Format/Format.h | 26 +++++-
clang/lib/Format/Format.cpp | 43 +++++++---
clang/lib/Format/TokenAnnotator.cpp | 45 ++++++++++
clang/unittests/Format/ConfigParseTest.cpp | 58 +++++++++----
clang/unittests/Format/FormatTest.cpp | 98 ++++++++++++++++++++++
6 files changed, 289 insertions(+), 27 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 119685d39d347..9a523bfe5fea3 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5748,6 +5748,29 @@ the configuration (without a prefix: ``Auto``).
int * a(void);
+ * ``CastAlignmentStyle CStyleCast``
+ The alignment for pointers in C-style casts.
+
+ Possible values:
+
+ * ``CAS_Default`` (in configuration: ``Default``)
+ Use default alignment.
+
+ * ``CAS_Left`` (in configuration: ``Left``)
+ Align pointer/reference to the left.
+
+ .. code-block:: c++
+
+ (char*)s;
+
+ * ``CAS_Right`` (in configuration: ``Right``)
+ Align pointer/reference to the right.
+
+ .. code-block:: c++
+
+ (char *)s;
+
+
.. _QualifierAlignment:
@@ -5961,6 +5984,29 @@ the configuration (without a prefix: ``Auto``).
int * a(void);
+ * ``CastAlignmentStyle CStyleCast``
+ The alignment for references in C-style casts.
+
+ Possible values:
+
+ * ``CAS_Default`` (in configuration: ``Default``)
+ Use default alignment.
+
+ * ``CAS_Left`` (in configuration: ``Left``)
+ Align pointer/reference to the left.
+
+ .. code-block:: c++
+
+ (char*)s;
+
+ * ``CAS_Right`` (in configuration: ``Right``)
+ Align pointer/reference to the right.
+
+ .. code-block:: c++
+
+ (char *)s;
+
+
.. _ReflowComments:
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 3919c1d0bc8b3..5a611a1141582 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4057,14 +4057,33 @@ struct FormatStyle {
RTAS_Middle
};
+ /// \brief The pointer/reference alignment style for C-style casts.
+ enum CastAlignmentStyle : int8_t {
+ /// Use default alignment.
+ CAS_Default,
+ /// Align pointer/reference to the left.
+ /// \code
+ /// (char*)s;
+ /// \endcode
+ CAS_Left,
+ /// Align pointer/reference to the right.
+ /// \code
+ /// (char *)s;
+ /// \endcode
+ CAS_Right,
+ };
+
/// Pointer and reference alignment options.
struct PointerAlignmentOptions {
/// The default alignment for pointers and references.
PointerAlignmentStyle Default;
/// The alignment for pointers in function return types.
ReturnTypeAlignmentStyle ReturnType;
+ /// The alignment for pointers in C-style casts.
+ CastAlignmentStyle CStyleCast;
bool operator==(const PointerAlignmentOptions &R) const {
- return Default == R.Default && ReturnType == R.ReturnType;
+ return Default == R.Default && ReturnType == R.ReturnType &&
+ CStyleCast == R.CStyleCast;
}
bool operator!=(const PointerAlignmentOptions &R) const {
return !(*this == R);
@@ -4264,8 +4283,11 @@ struct FormatStyle {
ReferenceAlignmentStyle Default;
/// The alignment for references in function return types.
ReturnTypeAlignmentStyle ReturnType;
+ /// The alignment for references in C-style casts.
+ CastAlignmentStyle CStyleCast;
bool operator==(const ReferenceAlignmentOptions &R) const {
- return Default == R.Default && ReturnType == R.ReturnType;
+ return Default == R.Default && ReturnType == R.ReturnType &&
+ CStyleCast == R.CStyleCast;
}
bool operator!=(const ReferenceAlignmentOptions &R) const {
return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index f950d64b29436..057fe92ccc966 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -555,35 +555,49 @@ struct ScalarEnumerationTraits<FormatStyle::ReturnTypeAlignmentStyle> {
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::CastAlignmentStyle> {
+ static void enumeration(IO &IO, FormatStyle::CastAlignmentStyle &Value) {
+ IO.enumCase(Value, "Default", FormatStyle::CAS_Default);
+ IO.enumCase(Value, "Left", FormatStyle::CAS_Left);
+ IO.enumCase(Value, "Right", FormatStyle::CAS_Right);
+ }
+};
+
template <> struct MappingTraits<FormatStyle::PointerAlignmentOptions> {
static void enumInput(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
IO.enumCase(Value, "Middle",
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Middle,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
IO.enumCase(Value, "Left",
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Left,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
IO.enumCase(Value, "Right",
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
// For backward compatibility.
IO.enumCase(Value, "true",
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Left,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
IO.enumCase(Value, "false",
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
}
static void mapping(IO &IO, FormatStyle::PointerAlignmentOptions &Value) {
IO.mapOptional("Default", Value.Default);
IO.mapOptional("ReturnType", Value.ReturnType);
+ IO.mapOptional("CStyleCast", Value.CStyleCast);
}
};
@@ -633,24 +647,29 @@ template <> struct MappingTraits<FormatStyle::ReferenceAlignmentOptions> {
IO.enumCase(Value, "Pointer",
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Pointer,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
IO.enumCase(Value, "Middle",
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Middle,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
IO.enumCase(Value, "Left",
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Left,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
IO.enumCase(Value, "Right",
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
}
static void mapping(IO &IO, FormatStyle::ReferenceAlignmentOptions &Value) {
IO.mapOptional("Default", Value.Default);
IO.mapOptional("ReturnType", Value.ReturnType);
+ IO.mapOptional("CStyleCast", Value.CStyleCast);
}
};
@@ -1851,11 +1870,13 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
LLVMStyle.PointerAlignment = {/*Default=*/FormatStyle::PAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Default};
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default};
LLVMStyle.PPIndentWidth = -1;
LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
LLVMStyle.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Pointer,
- /*ReturnType=*/FormatStyle::RTAS_Default};
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default};
LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
LLVMStyle.RemoveBracesLLVM = false;
LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index fe53d70eb12d7..a7c00e19352cf 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -6586,6 +6586,28 @@ static bool isReturnType(const FormatToken &Tok, const LangOptions &LangOpts) {
return false;
}
+static bool isCStyleCast(const FormatToken &Tok, const LangOptions &LangOpts) {
+ // Look forward to see if there's a TT_CastRParen.
+ for (const FormatToken *Next = Tok.Next; Next;
+ Next = Next->getNextNonComment()) {
+ if (Next->is(TT_CastRParen))
+ return true;
+
+ if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
+ Next = Next->MatchingParen;
+ continue;
+ }
+
+ if (Next->isPointerOrReference() || Next->isTypeName(LangOpts) ||
+ Next->canBePointerOrReferenceQualifier()) {
+ continue;
+ }
+
+ break;
+ }
+ return false;
+}
+
static FormatStyle::PointerAlignmentStyle
mapReturnTypeAlignmentStyle(FormatStyle::ReturnTypeAlignmentStyle Style) {
switch (Style) {
@@ -6601,6 +6623,19 @@ mapReturnTypeAlignmentStyle(FormatStyle::ReturnTypeAlignmentStyle Style) {
llvm_unreachable("Unknown FormatStyle::ReturnTypeAlignmentStyle enum");
}
+static FormatStyle::PointerAlignmentStyle
+mapCastAlignmentStyle(FormatStyle::CastAlignmentStyle Style) {
+ switch (Style) {
+ case FormatStyle::CAS_Left:
+ return FormatStyle::PAS_Left;
+ case FormatStyle::CAS_Right:
+ return FormatStyle::PAS_Right;
+ case FormatStyle::CAS_Default:
+ assert(false);
+ }
+ llvm_unreachable("Unknown FormatStyle::CastAlignmentStyle enum");
+}
+
FormatStyle::PointerAlignmentStyle
TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
assert(Reference.isOneOf(tok::amp, tok::ampamp));
@@ -6610,6 +6645,11 @@ TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
return mapReturnTypeAlignmentStyle(Style.ReferenceAlignment.ReturnType);
}
+ if (Style.ReferenceAlignment.CStyleCast != FormatStyle::CAS_Default &&
+ isCStyleCast(Reference, LangOpts)) {
+ return mapCastAlignmentStyle(Style.ReferenceAlignment.CStyleCast);
+ }
+
switch (Style.ReferenceAlignment.Default) {
case FormatStyle::RAS_Pointer:
return Style.PointerAlignment.Default;
@@ -6635,6 +6675,11 @@ TokenAnnotator::getTokenPointerOrReferenceAlignment(
return mapReturnTypeAlignmentStyle(Style.PointerAlignment.ReturnType);
}
+ if (Style.PointerAlignment.CStyleCast != FormatStyle::CAS_Default &&
+ isCStyleCast(PointerOrReference, LangOpts)) {
+ return mapCastAlignmentStyle(Style.PointerAlignment.CStyleCast);
+ }
+
return Style.PointerAlignment.Default;
}
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index cf54b79bcf8a6..0c5e85beed3fb 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -392,66 +392,96 @@ TEST(ConfigParseTest, ParsesConfiguration) {
#undef CHECK_ALIGN_CONSECUTIVE
Style.PointerAlignment = {/*Default=*/FormatStyle::PAS_Middle,
- /*ReturnType=*/FormatStyle::RTAS_Default};
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default};
CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Left,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("PointerAlignment: Right", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("PointerAlignment: Middle", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Middle,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("PointerAlignment:\n"
" Default: Right\n"
" ReturnType: Left",
PointerAlignment,
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Left}));
+ /*ReturnType=*/FormatStyle::RTAS_Left,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
+ CHECK_PARSE("PointerAlignment:\n"
+ " Default: Right\n"
+ " CStyleCast: Left",
+ PointerAlignment,
+ FormatStyle::PointerAlignmentOptions(
+ {/*Default=*/FormatStyle::PAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Left,
+ /*CStyleCast=*/FormatStyle::CAS_Left}));
Style.ReferenceAlignment = {/*Default=*/FormatStyle::RAS_Middle,
- /*ReturnType=*/FormatStyle::RTAS_Default};
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default};
CHECK_PARSE("ReferenceAlignment: Pointer", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Pointer,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("ReferenceAlignment: Left", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Left,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("ReferenceAlignment: Right", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("ReferenceAlignment: Middle", ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Middle,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("ReferenceAlignment:\n"
" Default: Right\n"
" ReturnType: Left",
ReferenceAlignment,
FormatStyle::ReferenceAlignmentOptions(
{/*Default=*/FormatStyle::RAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Left}));
+ /*ReturnType=*/FormatStyle::RTAS_Left,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
+ CHECK_PARSE("ReferenceAlignment:\n"
+ " Default: Right\n"
+ " CStyleCast: Left",
+ ReferenceAlignment,
+ FormatStyle::ReferenceAlignmentOptions(
+ {/*Default=*/FormatStyle::RAS_Right,
+ /*ReturnType=*/FormatStyle::RTAS_Left,
+ /*CStyleCast=*/FormatStyle::CAS_Left}));
// For backward compatibility:
CHECK_PARSE("PointerBindsToType: Left", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Left,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("PointerBindsToType: Right", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Right,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
CHECK_PARSE("PointerBindsToType: Middle", PointerAlignment,
FormatStyle::PointerAlignmentOptions(
{/*Default=*/FormatStyle::PAS_Middle,
- /*ReturnType=*/FormatStyle::RTAS_Default}));
+ /*ReturnType=*/FormatStyle::RTAS_Default,
+ /*CStyleCast=*/FormatStyle::CAS_Default}));
Style.ReflowComments = FormatStyle::RCS_Always;
CHECK_PARSE("ReflowComments: Never", ReflowComments, FormatStyle::RCS_Never);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index ad14e7d1f0429..5cd2ad8947fbe 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -2496,6 +2496,104 @@ TEST_F(FormatTest, ReturnTypeAlignment) {
verifyFormat("auto f3(int &&a, int *b) -> int &&;", Style);
}
+TEST_F(FormatTest, CStyleCastAlignment) {
+ // Test that CStyleCast overrides PointerAlignment for C-style casts
+ FormatStyle Style = getLLVMStyle();
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Left;
+
+ // Basic C-style casts with pointers should be left-aligned despite PAS_Right
+ verifyFormat("int *a = (int*)b;", Style);
+ verifyFormat("int &c = (int&)d;", Style);
+ verifyFormat("int &&e = (int&&)f;", Style);
+
+ // Multiple pointers in C-style casts
+ verifyFormat("int **a = (int**)b;", Style);
+ verifyFormat("const int *c = (const int*)d;", Style);
+ verifyFormat("int ***e = (int***)f;", Style);
+
+ // Multiple pointers with const qualifiers
+ verifyFormat("const int **a = (const int**)b;", Style);
+ verifyFormat("int *const *c = (int* const*)d;", Style);
+ verifyFormat("const int *const *e = (const int* const*)f;", Style);
+ verifyFormat("int **const g = (int** const)h;", Style);
+ verifyFormat("const int **const i = (const int** const)j;", Style);
+
+ // Complex types in C-style casts
+ verifyFormat("std::vector<int> *a = (std::vector<int>*)b;", Style);
+ verifyFormat("const char *c = (const char*)d;", Style);
+ verifyFormat("const char **e = (const char**)f;", Style);
+ verifyFormat("char *const *g = (char* const*)h;", Style);
+
+ // Variables should still follow the default alignment
+ verifyFormat("int *a = nullptr;", Style);
+ verifyFormat("int *b = (int*)c;", Style);
+
+ // Now test with PAS_Left base and CAS_Right cast
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Right;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Right;
+
+ // C-style casts should be right-aligned despite PAS_Left
+ verifyFormat("int* a = (int *)b;", Style);
+ verifyFormat("int& c = (int &)d;", Style);
+ verifyFormat("int&& e = (int &&)f;", Style);
+
+ // Multiple pointers with right alignment in casts
+ verifyFormat("int** a = (int **)b;", Style);
+ verifyFormat("const int* c = (const int *)d;", Style);
+ verifyFormat("int*** e = (int ***)f;", Style);
+
+ // Multiple pointers with const qualifiers, right-aligned casts
+ verifyFormat("const int** a = (const int **)b;", Style);
+ verifyFormat("int* const* c = (int *const *)d;", Style);
+ verifyFormat("const int* const* e = (const int *const *)f;", Style);
+ verifyFormat("int** const g = (int **const)h;", Style);
+ verifyFormat("const char** i = (const char **)j;", Style);
+
+ // Variables should still follow PointerAlignment (PAS_Left)
+ verifyFormat("int* a = nullptr;", Style);
+ verifyFormat("int* b = (int *)c;", Style);
+
+ // Test that default alignment is used when CStyleCast is CAS_Default
+ Style.PointerAlignment.Default = FormatStyle::PAS_Left;
+ Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Default;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Default;
+
+ verifyFormat("int* a = (int*)b;", Style);
+ verifyFormat("int& c = (int&)d;", Style);
+
+ // Test with ReferenceAlignment override
+ Style.PointerAlignment.Default = FormatStyle::PAS_Right;
+ Style.PointerAlignment.CStyleCast = FormatStyle::CAS_Left;
+ Style.ReferenceAlignment.Default = FormatStyle::RAS_Pointer;
+ Style.ReferenceAlignment.CStyleCast = FormatStyle::CAS_Right;
+
+ verifyFormat("int *a = (int*)b;", Style);
+ verifyFormat("int &c = (int &)d;", Style);
+ verifyFormat("int &&e = (int &&)f;", Style);
+
+ // Chained casts
+ verifyFormat("int *a = (int*)(void*)b;", Style);
+ verifyFormat("const char *c = (const char*)(void*)d;", Style);
+
+ // Casts with arithmetic
+ verifyFormat("int *a = (int*)b + 1;", Style);
+ verifyFormat("void *c = (void*)(d + sizeof(int));", Style);
+
+ // Test function calls with casts
+ verifyFormat("foo((int*)bar);", Style);
+ verifyFormat("foo((int &)bar, (int*)baz);", Style);
+
+ // Test C-style casts in expressions
+ verifyFormat("if ((int*)a == b)\n return;", Style);
+ verifyFormat("return (int*)a;", Style);
+}
+
TEST_F(FormatTest, FormatsForLoop) {
verifyFormat(
"for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n"
More information about the cfe-commits
mailing list