[clang] [clang-format] Add option to separate comment alignment between ... (PR #165033)
Björn Schäpers via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 28 15:13:21 PDT 2025
https://github.com/HazardyKnusperkeks updated https://github.com/llvm/llvm-project/pull/165033
>From 0bce3192b2e5a293983578c75907850d25674b9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjoern at hazardy.de>
Date: Wed, 22 Oct 2025 00:11:33 +0200
Subject: [PATCH 1/2] [clang-format] Add option to separate comment alignment
between ...
normal lines and PP directives.
Handling PP directives differently can be desired, like in #161848.
Changing the default is not an option, there are tests for exactly the
current behaviour.
---
clang/docs/ClangFormatStyleOptions.rst | 10 ++++
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Format/Format.h | 12 ++++-
clang/lib/Format/Format.cpp | 12 +++--
clang/lib/Format/WhitespaceManager.cpp | 18 ++++++-
clang/unittests/Format/ConfigParseTest.cpp | 11 +++--
clang/unittests/Format/FormatTestComments.cpp | 48 +++++++++++++++++++
7 files changed, 100 insertions(+), 12 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 570cab262c115..0381573793621 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1701,6 +1701,16 @@ the configuration (without a prefix: ``Auto``).
int abcdef; // but this isn't
+ * ``bool AlignPPAndNotPP`` If comments following preprocessor directive should be aligned with
+ comments that don't.
+
+ .. code-block:: c++
+
+ true: false:
+ #define A // Comment vs. #define A // Comment
+ #define AB // Aligned #define AB // Aligned
+ int i; // Aligned int i; // Not aligned
+
.. _AllowAllArgumentsOnNextLine:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fe77f917bb801..5680ea74d8efe 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -609,6 +609,7 @@ clang-format
literals.
- Add ``Leave`` suboption to ``IndentPPDirectives``.
- Add ``AllowBreakBeforeQtProperty`` option.
+- Add ``AlignPPAndNotPP`` suboption to ``AlignTrailingComments``.
libclang
--------
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 2852c4a2916a4..82c3a215fc94d 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -622,9 +622,19 @@ struct FormatStyle {
/// int abcdef; // but this isn't
/// \endcode
unsigned OverEmptyLines;
+ /// If comments following preprocessor directive should be aligned with
+ /// comments that don't.
+ /// \code
+ /// true: false:
+ /// #define A // Comment vs. #define A // Comment
+ /// #define AB // Aligned #define AB // Aligned
+ /// int i; // Aligned int i; // Not aligned
+ /// \endcode
+ bool AlignPPAndNotPP;
bool operator==(const TrailingCommentsAlignmentStyle &R) const {
- return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines;
+ return Kind == R.Kind && OverEmptyLines == R.OverEmptyLines &&
+ AlignPPAndNotPP == R.AlignPPAndNotPP;
}
bool operator!=(const TrailingCommentsAlignmentStyle &R) const {
return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index edd126c7724b8..62b97fbe0ffc4 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -869,27 +869,28 @@ template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
IO.enumCase(Value, "Leave",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Leave, 0}));
+ {FormatStyle::TCAS_Leave, 0, true}));
IO.enumCase(Value, "Always",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
IO.enumCase(Value, "Never",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
// For backwards compatibility
IO.enumCase(Value, "true",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
IO.enumCase(Value, "false",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
}
static void mapping(IO &IO,
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
+ IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP);
IO.mapOptional("Kind", Value.Kind);
IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
}
@@ -1578,6 +1579,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignTrailingComments = {};
LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
+ LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
LLVMStyle.AllowAllArgumentsOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 65fc65e79fdc3..c5f738ebe42ad 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -997,9 +997,13 @@ void WhitespaceManager::alignTrailingComments() {
return;
const int Size = Changes.size();
+ if (Size == 0)
+ return;
+
int MinColumn = 0;
int StartOfSequence = 0;
bool BreakBeforeNext = false;
+ bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
int NewLineThreshold = 1;
if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
@@ -1008,7 +1012,19 @@ void WhitespaceManager::alignTrailingComments() {
auto &C = Changes[I];
if (C.StartOfBlockComment)
continue;
- Newlines += C.NewlinesBefore;
+ if (C.NewlinesBefore != 0) {
+ Newlines += C.NewlinesBefore;
+ const bool WasInPP = std::exchange(
+ IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) ||
+ C.ContinuesPPDirective);
+ if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {
+ alignTrailingComments(StartOfSequence, I, MinColumn);
+ MinColumn = 0;
+ MaxColumn = INT_MAX;
+ StartOfSequence = I;
+ Newlines = 0;
+ }
+ }
if (!C.IsTrailingComment)
continue;
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 6488e38badee7..de22c9f7e2a15 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -576,20 +576,20 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE("AlignTrailingComments: Leave", AlignTrailingComments,
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Leave, 0}));
+ {FormatStyle::TCAS_Leave, 0, true}));
CHECK_PARSE("AlignTrailingComments: Always", AlignTrailingComments,
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
CHECK_PARSE("AlignTrailingComments: Never", AlignTrailingComments,
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
// For backwards compatibility
CHECK_PARSE("AlignTrailingComments: true", AlignTrailingComments,
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
CHECK_PARSE("AlignTrailingComments: false", AlignTrailingComments,
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
CHECK_PARSE_NESTED_VALUE("Kind: Always", AlignTrailingComments, Kind,
FormatStyle::TCAS_Always);
CHECK_PARSE_NESTED_VALUE("Kind: Never", AlignTrailingComments, Kind,
@@ -598,6 +598,7 @@ TEST(ConfigParseTest, ParsesConfiguration) {
FormatStyle::TCAS_Leave);
CHECK_PARSE_NESTED_VALUE("OverEmptyLines: 1234", AlignTrailingComments,
OverEmptyLines, 1234u);
+ CHECK_PARSE_NESTED_BOOL(AlignTrailingComments, AlignPPAndNotPP);
Style.UseTab = FormatStyle::UT_ForIndentation;
CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never);
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 6b433bb384864..00961471664d1 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -3501,6 +3501,54 @@ TEST_F(FormatTestComments, DontAlignOverScope) {
"int foobar; // group");
}
+TEST_F(FormatTestComments, DontAlignOverPPDirective) {
+ auto Style = getLLVMStyle();
+ Style.AlignTrailingComments.AlignPPAndNotPP = false;
+
+ verifyFormat("int i; // Aligned\n"
+ "int long; // with this\n"
+ "#define FOO // only aligned\n"
+ "#define LOOONG // with other pp directives\n"
+ "int loooong; // new alignment",
+ "int i;//Aligned\n"
+ "int long;//with this\n"
+ "#define FOO //only aligned\n"
+ "#define LOOONG //with other pp directives\n"
+ "int loooong; //new alignment",
+ Style);
+
+ verifyFormat("#define A // Comment\n"
+ "#define AB // Comment",
+ Style);
+
+ Style.ColumnLimit = 30;
+ verifyNoChange("#define A // Comment\n"
+ " // Continued\n"
+ "int i = 0; // New Stuff\n"
+ " // Continued\n"
+ "#define Func(X) \\\n"
+ " X(); \\\n"
+ " X(); // Comment\n"
+ " // Continued\n"
+ "long loong = 1; // Dont align",
+ Style);
+
+ Style.AlignTrailingComments.OverEmptyLines = 1;
+ verifyNoChange("#define A // Comment\n"
+ "\n"
+ " // Continued\n"
+ "int i = 0; // New Stuff\n"
+ "\n"
+ " // Continued\n"
+ "#define Func(X) \\\n"
+ " X(); \\\n"
+ " X(); // Comment\n"
+ "\n"
+ " // Continued\n"
+ "long loong = 1; // Dont align",
+ Style);
+}
+
TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
EXPECT_EQ("/*\n"
" */",
>From a1108113180ba0066257774c92b084f4f2cc3ab5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjoern at hazardy.de>
Date: Tue, 28 Oct 2025 23:13:09 +0100
Subject: [PATCH 2/2] Extent tests
---
clang/unittests/Format/FormatTestComments.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 00961471664d1..cfdca45360598 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -3533,6 +3533,18 @@ TEST_F(FormatTestComments, DontAlignOverPPDirective) {
"long loong = 1; // Dont align",
Style);
+ verifyFormat("#define A // Comment that\n"
+ " // would wrap\n"
+ "#define FOO // For the\n"
+ " // alignment\n"
+ "#define B // Also\n"
+ " // aligned",
+ "#define A // Comment that would wrap\n"
+ "#define FOO // For the alignment\n"
+ "#define B // Also\n"
+ " // aligned",
+ Style);
+
Style.AlignTrailingComments.OverEmptyLines = 1;
verifyNoChange("#define A // Comment\n"
"\n"
More information about the cfe-commits
mailing list