[clang] [clang-format] Fix handling of C-Style variable definition of a struct (PR #76344)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 26 09:11:32 PST 2023
https://github.com/XDeme updated https://github.com/llvm/llvm-project/pull/76344
>From a55c720f344645bdad3838aaa39b136c8b8ee6dc Mon Sep 17 00:00:00 2001
From: XDeme <fernando.tagawa.gamail.com at gmail.com>
Date: Sun, 24 Dec 2023 20:18:02 -0300
Subject: [PATCH 1/2] [clang-format] Fix handling of C-Style variable
definition of a struct
---
clang/lib/Format/UnwrappedLineParser.cpp | 8 ++++++++
clang/unittests/Format/FormatTest.cpp | 1 +
clang/unittests/Format/TokenAnnotatorTest.cpp | 6 ++++++
3 files changed, 15 insertions(+)
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) {
>From 9e2e88495e86f040aeca2a0f0bc69bff3e6986e4 Mon Sep 17 00:00:00 2001
From: XDeme <fernando.tagawa.gamail.com at gmail.com>
Date: Tue, 26 Dec 2023 14:11:09 -0300
Subject: [PATCH 2/2] Added support for templated structs
---
clang/lib/Format/UnwrappedLineParser.cpp | 13 +++++++++++++
clang/unittests/Format/FormatTest.cpp | 3 ++-
clang/unittests/Format/TokenAnnotatorTest.cpp | 6 ++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 9cacb0d175adae..e79eefd530451b 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -3917,6 +3917,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
// (this would still leave us with an ambiguity between template function
// and class declarations).
if (FormatTok->isOneOf(tok::colon, tok::less)) {
+ int AngleNestingLevel = 0;
+ bool ColonFound = false;
do {
if (FormatTok->is(tok::l_brace)) {
calculateBraceTypes(/*ExpectClassBody=*/true);
@@ -3944,6 +3946,17 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
parseCSharpGenericTypeConstraint();
break;
}
+ // Do not count identifiers inside a template angle brackets
+ if(FormatTok->is(tok::colon))
+ ColonFound = true;
+ if (FormatTok->is(tok::less))
+ ++AngleNestingLevel;
+ else if (FormatTok->is(tok::greater))
+ --AngleNestingLevel;
+ if (AngleNestingLevel == 0 && !ColonFound && FormatTok->is(tok::identifier) &&
+ FormatTok->TokenText != FormatTok->TokenText.upper()) {
+ ++NonMacroIdentifierCount;
+ }
nextToken();
} while (!eof());
}
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index d37d1f58b51a4a..04505e25b00c03 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -14543,12 +14543,13 @@ TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {
verifyFormat("struct foo a = {bar};\nint n;");
verifyFormat("class foo a = {bar};\nint n;");
verifyFormat("union foo a = {bar};\nint n;");
+ verifyFormat("struct MACRO foo f{};");
+ verifyFormat("struct MACRO foo<int> f{};");
// Elaborate types inside function definitions.
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 568574bf73a872..a78d9a4df16025 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -509,6 +509,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsVariables) {
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);
+
+ Tokens = annotate("struct Foo<int> f{};");
+ EXPECT_EQ(Tokens.size(), 10u) << Tokens;
+ EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown);
+ EXPECT_TOKEN(Tokens[5], tok::identifier, TT_StartOfName);
+ EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_Unknown);
}
TEST_F(TokenAnnotatorTest, UnderstandsVariableTemplates) {
More information about the cfe-commits
mailing list