[clang] [clang-format] Correctly annotate designated initializer with PP if (PR #65409)

Emilia Kond via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 7 11:35:28 PDT 2023


https://github.com/rymiel updated https://github.com/llvm/llvm-project/pull/65409:

>From e15868400981600b7dc68229660391a7874e67af Mon Sep 17 00:00:00 2001
From: Emilia Kond <emilia at rymiel.space>
Date: Tue, 5 Sep 2023 22:44:41 +0300
Subject: [PATCH 1/2] [clang-format] Correctly annotate designated initializer
 with PP if

When encountering braces, such as those of a designated initializer,
clang-format scans ahead to see what is contained within the braces. If
it found a statement, like an if-statement of for-loop, it would deem
the braces as not an initializer, but as a block instead.

However, this heuristic incorrectly included a preprocessor `#if` line as
an if-statement. This manifested in strange results and discrepancies
between `#ifdef` and `#if defined`.

With this patch, `if` is now ignored if it is preceeded by `#`.

Fixes most of https://github.com/llvm/llvm-project/issues/56685
---
 clang/lib/Format/UnwrappedLineParser.cpp      |  2 ++
 clang/unittests/Format/TokenAnnotatorTest.cpp | 35 +++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 5a82b200055a874..eaebc69879b9732 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -626,6 +626,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
     case tok::kw_switch:
     case tok::kw_try:
     case tok::kw___try:
+      if (PrevTok->is(tok::hash))
+        break;
       if (!LBraceStack.empty() && LBraceStack.back().Tok->is(BK_Unknown))
         LBraceStack.back().Tok->setBlockKind(BK_Block);
       break;
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 467ade965d7c86a..ac2b60530f2fb18 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -1998,6 +1998,41 @@ TEST_F(TokenAnnotatorTest, UnderstandsNestedBlocks) {
   EXPECT_BRACE_KIND(Tokens[10], BK_Block);
 }
 
+TEST_F(TokenAnnotatorTest, UnderstandDesignatedInitializers) {
+  auto Tokens = annotate("SomeStruct { .a = 1 };");
+  ASSERT_EQ(Tokens.size(), 9u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
+  EXPECT_TOKEN(Tokens[2], tok::period, TT_DesignatedInitializerPeriod);
+
+  Tokens = annotate("SomeStruct { .a = 1, .b = 2 };");
+  ASSERT_EQ(Tokens.size(), 14u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
+  EXPECT_TOKEN(Tokens[2], tok::period, TT_DesignatedInitializerPeriod);
+  EXPECT_TOKEN(Tokens[7], tok::period, TT_DesignatedInitializerPeriod);
+
+  Tokens = annotate("SomeStruct {\n"
+  "#ifdef FOO\n"
+  "  .a = 1,\n"
+  "#endif\n"
+  "  .b = 2\n"
+  "};");
+  ASSERT_EQ(Tokens.size(), 19u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
+  EXPECT_TOKEN(Tokens[5], tok::period, TT_DesignatedInitializerPeriod);
+  EXPECT_TOKEN(Tokens[12], tok::period, TT_DesignatedInitializerPeriod);
+
+  Tokens = annotate("SomeStruct {\n"
+  "#if defined FOO\n"
+  "  .a = 1,\n"
+  "#endif\n"
+  "  .b = 2\n"
+  "};");
+  ASSERT_EQ(Tokens.size(), 20u) << Tokens;
+  EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
+  EXPECT_TOKEN(Tokens[6], tok::period, TT_DesignatedInitializerPeriod);
+  EXPECT_TOKEN(Tokens[13], tok::period, TT_DesignatedInitializerPeriod);
+}
+
 } // namespace
 } // namespace format
 } // namespace clang

>From 88c1e108cc191ddc1c288b57ae202603d4daa962 Mon Sep 17 00:00:00 2001
From: Emilia Kond <emilia at rymiel.space>
Date: Thu, 7 Sep 2023 21:34:31 +0300
Subject: [PATCH 2/2] address comments

---
 clang/lib/Format/UnwrappedLineParser.cpp      |  7 ++++---
 clang/unittests/Format/TokenAnnotatorTest.cpp | 20 +++++++++----------
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index eaebc69879b9732..dae2742d27fcbde 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -618,16 +618,17 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
       if (Tok->isNot(TT_StatementMacro))
         break;
       [[fallthrough]];
+    case tok::kw_if:
+      if (PrevTok->is(tok::hash))
+        break;
+      [[fallthrough]];
     case tok::at:
     case tok::semi:
-    case tok::kw_if:
     case tok::kw_while:
     case tok::kw_for:
     case tok::kw_switch:
     case tok::kw_try:
     case tok::kw___try:
-      if (PrevTok->is(tok::hash))
-        break;
       if (!LBraceStack.empty() && LBraceStack.back().Tok->is(BK_Unknown))
         LBraceStack.back().Tok->setBlockKind(BK_Block);
       break;
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index ac2b60530f2fb18..7ac6bd32620e3d8 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2011,22 +2011,22 @@ TEST_F(TokenAnnotatorTest, UnderstandDesignatedInitializers) {
   EXPECT_TOKEN(Tokens[7], tok::period, TT_DesignatedInitializerPeriod);
 
   Tokens = annotate("SomeStruct {\n"
-  "#ifdef FOO\n"
-  "  .a = 1,\n"
-  "#endif\n"
-  "  .b = 2\n"
-  "};");
+                    "#ifdef FOO\n"
+                    "  .a = 1,\n"
+                    "#endif\n"
+                    "  .b = 2\n"
+                    "};");
   ASSERT_EQ(Tokens.size(), 19u) << Tokens;
   EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
   EXPECT_TOKEN(Tokens[5], tok::period, TT_DesignatedInitializerPeriod);
   EXPECT_TOKEN(Tokens[12], tok::period, TT_DesignatedInitializerPeriod);
 
   Tokens = annotate("SomeStruct {\n"
-  "#if defined FOO\n"
-  "  .a = 1,\n"
-  "#endif\n"
-  "  .b = 2\n"
-  "};");
+                    "#if defined FOO\n"
+                    "  .a = 1,\n"
+                    "#endif\n"
+                    "  .b = 2\n"
+                    "};");
   ASSERT_EQ(Tokens.size(), 20u) << Tokens;
   EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit);
   EXPECT_TOKEN(Tokens[6], tok::period, TT_DesignatedInitializerPeriod);



More information about the cfe-commits mailing list