[clang] [clang-format] Fix handling of C-Style variable definition of a struct (PR #76344)

via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 24 15:25:48 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: None (XDeme)

<details>
<summary>Changes</summary>

Fixes llvm/llvm-project#<!-- -->71939

The problem was happening because we were treating `struct Foo f{};` as a struct definition, so `{` was being treated as `TT_StructLBrace`

---
Full diff: https://github.com/llvm/llvm-project/pull/76344.diff


3 Files Affected:

- (modified) clang/lib/Format/UnwrappedLineParser.cpp (+8) 
- (modified) clang/unittests/Format/FormatTest.cpp (+1) 
- (modified) clang/unittests/Format/TokenAnnotatorTest.cpp (+6) 


``````````diff
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 684609747a5513..9cacb0d175adae 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -3873,6 +3873,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
   const FormatToken &InitialToken = *FormatTok;
   nextToken();
 
+  int NonMacroIdentifierCount = 0;
   // The actual identifier can be a nested name specifier, and in macros
   // it is often token-pasted.
   // An [[attribute]] can be before the identifier.
@@ -3898,6 +3899,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
         FormatTok->is(tok::identifier) &&
         FormatTok->TokenText != FormatTok->TokenText.upper();
     nextToken();
+    if (IsNonMacroIdentifier)
+      ++NonMacroIdentifierCount;
     // We can have macros in between 'class' and the class name.
     if (!IsNonMacroIdentifier && FormatTok->is(tok::l_paren))
       parseParens();
@@ -3960,6 +3963,11 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
     }
   };
   if (FormatTok->is(tok::l_brace)) {
+    // Handles C-Style variable declaration of a struct
+    if (Style.isCpp() && NonMacroIdentifierCount == 2) {
+      parseBracedList();
+      return;
+    }
     auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
     FormatTok->setFinalizedType(OpenBraceType);
     if (ParseAsExpr) {
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 762fc8254bdfc9..d37d1f58b51a4a 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -14548,6 +14548,7 @@ TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {
   verifyFormat("struct foo f() {}\nint n;");
   verifyFormat("class foo f() {}\nint n;");
   verifyFormat("union foo f() {}\nint n;");
+  verifyFormat("struct MACRO foo f{};");
 
   // Templates.
   verifyFormat("template <class X> void f() {}\nint n;");
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 2cafc0438ffb46..568574bf73a872 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -503,6 +503,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsVariables) {
       annotate("inline bool var = is_integral_v<int> && is_signed_v<int>;");
   EXPECT_EQ(Tokens.size(), 15u) << Tokens;
   EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("struct Foo f{};");
+  EXPECT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown);
+  EXPECT_TOKEN(Tokens[2], tok::identifier, TT_StartOfName);
+  EXPECT_TOKEN(Tokens[3], tok::l_brace, TT_Unknown);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsVariableTemplates) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/76344


More information about the cfe-commits mailing list