[clang] [clang-format] Don't confuse initializer equal signs in for loops (PR #77712)

Emilia Kond via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 10 17:11:24 PST 2024


https://github.com/rymiel created https://github.com/llvm/llvm-project/pull/77712

clang-format has logic to align declarations of multiple variables of the same type, aligning them at the equals sign. This logic is applied in for loops as well. However, this alignment logic also erroneously affected the equals signs of designated initializers.

This patch forbids alignment if the token 2 tokens back from the equals sign is a designated initializer period.

Fixes https://github.com/llvm/llvm-project/issues/73902

>From 3d7ef4670c15116c1402685e8fc0a29cadfe04f6 Mon Sep 17 00:00:00 2001
From: Emilia Kond <emilia at rymiel.space>
Date: Thu, 11 Jan 2024 03:00:44 +0200
Subject: [PATCH] [clang-format] Don't confuse initializer equal signs in for
 loops

clang-format has logic to align declarations of multiple variables of
the same type, aligning them at the equals sign. This logic is applied
in for loops as well. However, this alignment logic also erroneously
affected the equals signs of designated initializers.

This patch forbids alignment if the token 2 tokens back from the equals
sign is a designated initializer period.

Fixes https://github.com/llvm/llvm-project/issues/73902
---
 clang/lib/Format/ContinuationIndenter.cpp |  4 +++-
 clang/unittests/Format/FormatTest.cpp     | 12 ++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 102504182c4505..ce6c17c3b7d927 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -703,7 +703,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
 
   if (Current.is(tok::equal) &&
       (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
-      CurrentState.VariablePos == 0) {
+      CurrentState.VariablePos == 0 &&
+      (!Previous.Previous ||
+       Previous.Previous->isNot(TT_DesignatedInitializerPeriod))) {
     CurrentState.VariablePos = State.Column;
     // Move over * and & if they are bound to the variable name.
     const FormatToken *Tok = &Previous;
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 25ef5c680af862..01678a4971caae 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -4944,6 +4944,18 @@ TEST_F(FormatTest, DesignatedInitializers) {
                "    [3] = cccccccccccccccccccccccccccccccccccccc,\n"
                "    [4] = dddddddddddddddddddddddddddddddddddddd,\n"
                "    [5] = eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee};");
+
+  verifyFormat("for (const TestCase &test_case : {\n"
+               "         TestCase{\n"
+               "             .a = 1,\n"
+               "             .b = 1,\n"
+               "         },\n"
+               "         TestCase{\n"
+               "             .a = 2,\n"
+               "             .b = 2,\n"
+               "         },\n"
+               "     }) {\n"
+               "}\n");
 }
 
 TEST_F(FormatTest, BracedInitializerIndentWidth) {



More information about the cfe-commits mailing list