Author: Emilia Dreamer Date: 2023-03-14T12:51:34+02:00 New Revision: c9163901c8e118ec0b7d415ae6ef267c4b6d549f
URL: https://github.com/llvm/llvm-project/commit/c9163901c8e118ec0b7d415ae6ef267c4b6d549f DIFF: https://github.com/llvm/llvm-project/commit/c9163901c8e118ec0b7d415ae6ef267c4b6d549f.diff LOG: [clang-format] Treat &/&& as reference when followed by requires clause Previously, the token annotator would get confused and annotate a member function's ref qualifier as a binary operator, if said function also had a requires clause after it. This patch accounts for that, treating requires clauses more similarly to `noexcept`, which also comes after the ref qualifier. Fixes https://github.com/llvm/llvm-project/issues/61270 Reviewed By: HazardyKnusperkeks, owenpan Differential Revision: https://reviews.llvm.org/D145656 Added: Modified: clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTest.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 5362f2f58e1eb..8613f51cd8a04 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2400,7 +2400,7 @@ class AnnotatingParser { if (!NextToken || NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept, tok::comma, - tok::r_paren) || + tok::r_paren, TT_RequiresClause) || NextToken->canBePointerOrReferenceQualifier() || (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) { return TT_PointerOrReference; @@ -3758,8 +3758,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Right.is(TT_BlockComment)) return true; // foo() -> const Bar * override/final - if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final, - tok::kw_noexcept) && + // S::foo() & noexcept/requires + if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final, tok::kw_noexcept, + TT_RequiresClause) && !Right.is(TT_StartOfName)) { return true; } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index bd0d328719bae..1beb6a75c5225 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -24148,6 +24148,14 @@ TEST_F(FormatTest, RequiresClausesPositions) { "}", Style); + verifyFormat("template <typename T>\n" + "int S::bar(T t) &&\n" + " requires F<T>\n" + "{\n" + " return 5;\n" + "}", + Style); + verifyFormat("template <typename T>\n" "int bar(T t)\n" " requires F<T>;", @@ -24161,6 +24169,14 @@ TEST_F(FormatTest, RequiresClausesPositions) { "}", Style); + verifyFormat("template <typename T>\n" + "int S::bar(T t) &&\n" + "requires F<T>\n" + "{\n" + " return 5;\n" + "}", + Style); + verifyFormat("template <typename T>\n" "int bar(T t)\n" "requires F<T>\n" @@ -24174,6 +24190,7 @@ TEST_F(FormatTest, RequiresClausesPositions) { "template <typename T> requires Foo<T> void bar() {}\n" "template <typename T> void bar() requires Foo<T> {}\n" "template <typename T> void bar() requires Foo<T>;\n" + "template <typename T> void S::bar() && requires Foo<T> {}\n" "template <typename T> requires Foo<T> Bar(T) -> Bar<T>;", Style); @@ -24185,6 +24202,8 @@ TEST_F(FormatTest, RequiresClausesPositions) { "requires Foo<T> void bar() {}\n" "template <typename AAAAAAA>\n" "void bar() requires Foo<T> {}\n" + "template <typename T>\n" + "void S::bar() && requires Foo<T> {}\n" "template <typename AAAAAAA>\n" "requires Foo<T> Baz(T) -> Baz<T>;", ColumnStyle); @@ -24229,6 +24248,9 @@ TEST_F(FormatTest, RequiresClausesPositions) { "void bar()\n" "requires Foo<T>;\n" "template <typename T>\n" + "void S::bar() &&\n" + "requires Foo<T> {}\n" + "template <typename T>\n" "requires Foo<T> Bar(T) -> Bar<T>;", Style); @@ -24259,6 +24281,9 @@ TEST_F(FormatTest, RequiresClausesPositions) { "void bar()\n" " requires Foo<T> {}\n" "template <typename T>\n" + "void S::bar() &&\n" + " requires Foo<T> {}\n" + "template <typename T>\n" " requires Foo<T> Bar(T) -> Bar<T>;", Style); @@ -24289,6 +24314,9 @@ TEST_F(FormatTest, RequiresClausesPositions) { "void bar() requires Foo<T>\n" "{}\n" "template <typename T> void bar() requires Foo<T>;\n" + "template <typename T>\n" + "void S::bar() && requires Foo<T>\n" + "{}\n" "template <typename T> requires Foo<T>\n" "Bar(T) -> Bar<T>;", Style); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 848dab13c8831..bc8f7f36372d2 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -744,10 +744,15 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { "void S::bar() const & requires Baz<T> { }"); ASSERT_EQ(Tokens.size(), 85u) << Tokens; EXPECT_TOKEN(Tokens[13], tok::kw_requires, TT_RequiresClause); + EXPECT_TOKEN(Tokens[24], tok::amp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[25], tok::kw_requires, TT_RequiresClause); + EXPECT_TOKEN(Tokens[35], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[36], tok::kw_requires, TT_RequiresClause); + EXPECT_TOKEN(Tokens[47], tok::amp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[49], tok::kw_requires, TT_RequiresClause); + EXPECT_TOKEN(Tokens[59], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[61], tok::kw_requires, TT_RequiresClause); + EXPECT_TOKEN(Tokens[76], tok::amp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[77], tok::kw_requires, TT_RequiresClause); Tokens = annotate("void Class::member() && requires(Constant) {}"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits