https://github.com/rymiel updated https://github.com/llvm/llvm-project/pull/78847
>From 79ebbdc60cfa0635c9d889823a8b37710d9a4fb5 Mon Sep 17 00:00:00 2001 From: Emilia Kond <emilia@rymiel.space> Date: Sat, 20 Jan 2024 15:44:16 +0200 Subject: [PATCH 1/3] [clang-format] Allow decltype in requires clause If clang-format is not sure whether a `requires` keyword starts a requires clause or a requires expression, it looks ahead to see if any token disqualifies it from being a requires clause. Among these tokens was `decltype`, since it fell through the switch. This patch allows decltype to exist in a require clause. I'm not 100% sure this change won't have repercussions, but that just means we need more test coverage! Fixes https://github.com/llvm/llvm-project/issues/78645 --- clang/lib/Format/UnwrappedLineParser.cpp | 1 + clang/unittests/Format/TokenAnnotatorTest.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index c08ce86449b6ea..62a6018580a0d1 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -3433,6 +3433,7 @@ bool clang::format::UnwrappedLineParser::parseRequires() { case tok::coloncolon: LastWasColonColon = true; break; + case tok::kw_decltype: case tok::identifier: if (FoundType && !LastWasColonColon && OpenAngles == 0) { FormatTok = Tokens->setPosition(StoredPosition); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 64b2abac5cce53..3f94c464b41343 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1071,6 +1071,16 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { "concept C = (!Foo<T>) && Bar;"); ASSERT_EQ(Tokens.size(), 19u) << Tokens; EXPECT_TOKEN(Tokens[15], tok::ampamp, TT_BinaryOperator); + + Tokens = annotate("void f() & requires(C<decltype(x)>) {}"); + ASSERT_EQ(Tokens.size(), 18u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference); + EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause); + + Tokens = annotate("auto f() -> int& requires(C<decltype(x)>) {}"); + ASSERT_EQ(Tokens.size(), 20u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::amp, TT_PointerOrReference); + EXPECT_TOKEN(Tokens[7], tok::kw_requires, TT_RequiresClause); } TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) { >From bef8c027504e1e0c0f28da090e1859be714a3ab1 Mon Sep 17 00:00:00 2001 From: Emilia Kond <emilia@rymiel.space> Date: Mon, 22 Jan 2024 00:31:23 +0200 Subject: [PATCH 2/3] address review and add more tests --- clang/lib/Format/UnwrappedLineParser.cpp | 9 +++++--- clang/unittests/Format/TokenAnnotatorTest.cpp | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 62a6018580a0d1..75721a3f79eca8 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -3423,9 +3423,12 @@ bool clang::format::UnwrappedLineParser::parseRequires() { break; case tok::r_paren: case tok::pipepipe: - FormatTok = Tokens->setPosition(StoredPosition); - parseRequiresClause(RequiresToken); - return true; + if (OpenAngles == 0) { + FormatTok = Tokens->setPosition(StoredPosition); + parseRequiresClause(RequiresToken); + return true; + } + break; case tok::eof: // Break out of the loop. Lookahead = 50; diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 3f94c464b41343..a1b24dc86bf0ff 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1081,6 +1081,27 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { ASSERT_EQ(Tokens.size(), 20u) << Tokens; EXPECT_TOKEN(Tokens[6], tok::amp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[7], tok::kw_requires, TT_RequiresClause); + + Tokens = annotate("int foo(auto t) {\n" + " if (requires (decltype(t) x) {x.foo();}) {\n" + " return 1;\n" + " }\n" + " return 0;\n" + "}\n"); + ASSERT_EQ(Tokens.size(), 36u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::kw_requires, TT_RequiresExpression); + + Tokens = annotate("bool x = t && requires(decltype(t) x) { x.foo(); };"); + ASSERT_EQ(Tokens.size(), 23u) << Tokens; + EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression); + + Tokens = annotate("bool x = t && requires(Foo<decltype(t)> x) { x.foo(); };"); + ASSERT_EQ(Tokens.size(), 26u) << Tokens; + EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression); + + Tokens = annotate("bool x = t && requires(Foo<C1 || C2> x) { x.foo(); };"); + ASSERT_EQ(Tokens.size(), 25u) << Tokens; + EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression); } TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) { >From 5d3909aed5342e9c0b78513199b149eae6cc5991 Mon Sep 17 00:00:00 2001 From: Emilia Kond <emilia@rymiel.space> Date: Mon, 22 Jan 2024 14:40:34 +0200 Subject: [PATCH 3/3] remove the check, remove test that doesn't use parseRequires --- clang/lib/Format/UnwrappedLineParser.cpp | 8 -------- clang/unittests/Format/TokenAnnotatorTest.cpp | 9 --------- 2 files changed, 17 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 75721a3f79eca8..f9295e926e1970 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -3421,14 +3421,6 @@ bool clang::format::UnwrappedLineParser::parseRequires() { return false; } break; - case tok::r_paren: - case tok::pipepipe: - if (OpenAngles == 0) { - FormatTok = Tokens->setPosition(StoredPosition); - parseRequiresClause(RequiresToken); - return true; - } - break; case tok::eof: // Break out of the loop. Lookahead = 50; diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index a1b24dc86bf0ff..167138fcbe4148 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1082,15 +1082,6 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { EXPECT_TOKEN(Tokens[6], tok::amp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[7], tok::kw_requires, TT_RequiresClause); - Tokens = annotate("int foo(auto t) {\n" - " if (requires (decltype(t) x) {x.foo();}) {\n" - " return 1;\n" - " }\n" - " return 0;\n" - "}\n"); - ASSERT_EQ(Tokens.size(), 36u) << Tokens; - EXPECT_TOKEN(Tokens[9], tok::kw_requires, TT_RequiresExpression); - Tokens = annotate("bool x = t && requires(decltype(t) x) { x.foo(); };"); ASSERT_EQ(Tokens.size(), 23u) << Tokens; EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits