Author: mydeveloperday Date: 2020-05-09T11:27:23+01:00 New Revision: 31fd12aa09563d8402b1aefceaa2311b680e138c
URL: https://github.com/llvm/llvm-project/commit/31fd12aa09563d8402b1aefceaa2311b680e138c DIFF: https://github.com/llvm/llvm-project/commit/31fd12aa09563d8402b1aefceaa2311b680e138c.diff LOG: [clang-format] [PR34574] Handle [[nodiscard]] attribute in class declaration Summary: https://bugs.llvm.org/show_bug.cgi?id=34574 https://bugs.llvm.org/show_bug.cgi?id=38401 ``` template <typename T> class [[nodiscard]] result { public: result(T&&) { } }; ``` formats incorrectly to ``` template <typename T> class [[nodiscard]] result{public : result(T &&){}}; ``` Reviewed By: krasimir Subscribers: cfe-commits Tags: #clang, #clang-format Differential Revision: https://reviews.llvm.org/D79354 Added: Modified: clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 96e0bd2276fa..48a4d1d5b3ed 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2399,9 +2399,10 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { // 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, TT_AttributeSquare) || ((Style.Language == FormatStyle::LK_Java || Style.Language == FormatStyle::LK_JavaScript) && FormatTok->isOneOf(tok::period, tok::comma))) { @@ -2421,8 +2422,16 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { FormatTok->TokenText != FormatTok->TokenText.upper(); nextToken(); // We can have macros or attributes in between 'class' and the class name. - if (!IsNonMacroIdentifier && FormatTok->Tok.is(tok::l_paren)) - parseParens(); + if (!IsNonMacroIdentifier) { + if (FormatTok->Tok.is(tok::l_paren)) { + parseParens(); + } else if (FormatTok->is(TT_AttributeSquare)) { + parseSquare(); + // Consume the closing TT_AttributeSquare. + if (FormatTok->Next && FormatTok->is(TT_AttributeSquare)) + nextToken(); + } + } } // 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 9a654d66250c..227e12dfaf73 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -7647,6 +7647,10 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) { verifyFormat("void f() [[deprecated(\"so sorry\")]];"); verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);"); + verifyFormat("[[nodiscard]] bool f() { return false; }"); + verifyFormat("class [[nodiscard]] f {\npublic:\n f() {}\n}"); + verifyFormat("class [[deprecated(\"so sorry\")]] f {\npublic:\n f() {}\n}"); + verifyFormat("class [[gnu::unused]] f {\npublic:\n f() {}\n}"); // Make sure we do not mistake attributes for array subscripts. verifyFormat("int a() {}\n" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits