diff options
author | Owen Pan <owenpiano@gmail.com> | 2023-03-25 19:31:57 -0700 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2023-04-04 11:49:22 -0700 |
commit | dae44c8ccc84ef557b646164c185fcda6c15eb5f (patch) | |
tree | 44772897ee70d0d31831264a60c65318aec310de | |
parent | 86b0c6e4050261823f07a3fbfd272bea0cda778e (diff) | |
download | llvm-dae44c8ccc84ef557b646164c185fcda6c15eb5f.tar.gz |
[clang-format] Don't annotate left brace of struct as FunctionLBrace
Related to a02c3af9f19d. Fixes #61700.
Differential Revision: https://reviews.llvm.org/D146895
(cherry picked from commit 767aee1de9e98256a62ae8b4c2f84381203613c3)
-rw-r--r-- | clang/lib/Format/UnwrappedLineParser.cpp | 26 | ||||
-rw-r--r-- | clang/unittests/Format/FormatTest.cpp | 5 | ||||
-rw-r--r-- | clang/unittests/Format/TokenAnnotatorTest.cpp | 8 |
3 files changed, 26 insertions, 13 deletions
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 7e3957e62d3a..7a49b189b481 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2739,16 +2739,17 @@ void UnwrappedLineParser::handleAttributes() { // Handle AttributeMacro, e.g. `if (x) UNLIKELY`. if (FormatTok->is(TT_AttributeMacro)) nextToken(); - handleCppAttributes(); + if (FormatTok->is(tok::l_square)) + handleCppAttributes(); } bool UnwrappedLineParser::handleCppAttributes() { // Handle [[likely]] / [[unlikely]] attributes. - if (FormatTok->is(tok::l_square) && tryToParseSimpleAttribute()) { - parseSquare(); - return true; - } - return false; + assert(FormatTok->is(tok::l_square)); + if (!tryToParseSimpleAttribute()) + return false; + parseSquare(); + return true; } /// Returns whether \c Tok begins a block. @@ -3849,13 +3850,13 @@ void UnwrappedLineParser::parseJavaEnumBody() { void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { const FormatToken &InitialToken = *FormatTok; nextToken(); - handleAttributes(); // The actual identifier can be a nested name specifier, and in macros // it is often token-pasted. + // An [[attribute]] can be before the identifier. while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash, tok::kw___attribute, tok::kw___declspec, - tok::kw_alignas) || + tok::kw_alignas, tok::l_square) || ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && FormatTok->isOneOf(tok::period, tok::comma))) { if (Style.isJavaScript() && @@ -3869,16 +3870,15 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { continue; } } + if (FormatTok->is(tok::l_square) && handleCppAttributes()) + continue; bool IsNonMacroIdentifier = FormatTok->is(tok::identifier) && FormatTok->TokenText != FormatTok->TokenText.upper(); nextToken(); // We can have macros in between 'class' and the class name. - if (!IsNonMacroIdentifier) { - if (FormatTok->is(tok::l_paren)) { - parseParens(); - } - } + if (!IsNonMacroIdentifier && FormatTok->is(tok::l_paren)) + parseParens(); } // Note that parsing away template declarations here leads to incorrectly diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 189c8ee9e9da..c1280cc9ce58 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -25212,6 +25212,11 @@ TEST_F(FormatTest, RemoveSemicolon) { "};", Style); + verifyFormat("struct EXPORT_MACRO [[nodiscard]] C {\n" + " int i;\n" + "};", + Style); + verifyIncompleteFormat("class C final [[deprecated(l]] {});", Style); // These tests are here to show a problem that may not be easily diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index a74a2992823e..e44d666206b4 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -288,6 +288,14 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) { auto Tokens = annotate("struct S {};"); EXPECT_EQ(Tokens.size(), 6u) << Tokens; EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("struct EXPORT_MACRO [[nodiscard]] C { int i; };"); + EXPECT_EQ(Tokens.size(), 15u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("struct [[deprecated]] [[nodiscard]] C { int i; };"); + EXPECT_EQ(Tokens.size(), 19u) << Tokens; + EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_StructLBrace); } TEST_F(TokenAnnotatorTest, UnderstandsUnions) { |