[clang] [clang-format] Update comment indentation, even with Leave (PR #196760)

Björn Schäpers via cfe-commits cfe-commits at lists.llvm.org
Sat May 9 15:11:38 PDT 2026


https://github.com/HazardyKnusperkeks created https://github.com/llvm/llvm-project/pull/196760

When a comment is already at the "right" place, then move it along, even if Leave is set for AligningComments.

Fixes #196663.

>From 6bd02e810b8e5608e29e51762052ce4f20d33d4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjoern at hazardy.de>
Date: Sun, 10 May 2026 00:09:43 +0200
Subject: [PATCH] [clang-format] Update comment indentation, even with Leave

When a comment is already at the "right" place, then move it along, even
if Leave is set for AligningComments.

Fixes #196663.
---
 clang/lib/Format/WhitespaceManager.cpp        | 19 +++++++++-
 clang/unittests/Format/FormatTestComments.cpp | 36 +++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 74aa8a2795150..92530cd232a01 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -1000,14 +1000,19 @@ void WhitespaceManager::alignTrailingComments() {
   bool BreakBeforeNext = false;
   bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
   int NewLineThreshold = 1;
+  const Change *LastChangeToCompare = nullptr;
+  const Change *LastNewlineChange = nullptr;
   if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
     NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
 
   for (int I = 0, MaxColumn = INT_MAX, Newlines = 0; I < Size; ++I) {
     auto &C = Changes[I];
+    if (LastNewlineChange)
+      LastChangeToCompare = std::exchange(LastNewlineChange, nullptr);
     if (C.StartOfBlockComment)
       continue;
     if (C.NewlinesBefore != 0) {
+      LastNewlineChange = &C;
       Newlines += C.NewlinesBefore;
       const bool WasInPP = std::exchange(
           IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) ||
@@ -1036,7 +1041,19 @@ void WhitespaceManager::alignTrailingComments() {
       if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
         break;
 
-      int Spaces =
+      const auto *NextChange = I + 1 < Size ? &Changes[I + 1] : nullptr;
+      assert(!NextChange || NextChange->NewlinesBefore > 0 ||
+             NextChange->Tok->is(tok::eof));
+      auto ChangeIsMoved = [&C](const Change *ChangeToCompare) {
+        return ChangeToCompare &&
+               C.Tok->OriginalColumn == ChangeToCompare->Tok->OriginalColumn &&
+               C.Spaces == ChangeToCompare->Spaces;
+      };
+      if (C.NewlinesBefore > 0 &&
+          (ChangeIsMoved(LastChangeToCompare) || ChangeIsMoved(NextChange))) {
+        continue;
+      }
+      const int Spaces =
           C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces;
       setChangeSpaces(I, Spaces);
       continue;
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 707016096f7d2..a8620d6e9af40 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -3060,6 +3060,42 @@ TEST_F(FormatTestComments, AlignTrailingCommentsLeave) {
                "}",
                Style);
 
+  // Move comments along, when it appears, that the indentation changed when a
+  // scope has been added or removed.
+  verifyFormat("void func() {\n"
+               "  int i;\n"
+               "  // comment\n"
+               "  // comment 2\n"
+               "}",
+               "void func() {\n"
+               "    int i;\n"
+               "    // comment\n"
+               "    // comment 2\n"
+               "}",
+               Style);
+
+  verifyFormat("void func() {\n"
+               "  // comment\n"
+               "  // comment 2\n"
+               "  int i;\n"
+               "}",
+               "void func() {\n"
+               "    // comment\n"
+               "    // comment 2\n"
+               "    int i;\n"
+               "}",
+               Style);
+
+  verifyFormat("void func() {\n"
+               "     // not moved, was not at normal indentation\n"
+               "  int i;\n"
+               "}",
+               "void func() {\n"
+               "     // not moved, was not at normal indentation\n"
+               "    int i;\n"
+               "}",
+               Style);
+
   Style.AlignEscapedNewlines = FormatStyle::ENAS_Left;
   verifyNoChange("#define FOO    \\\n"
                  "  /* foo(); */ \\\n"



More information about the cfe-commits mailing list