diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2180,7 +2180,8 @@ parseBracedList(); break; case tok::less: - if (Style.Language == FormatStyle::LK_Proto) { + if (Style.Language == FormatStyle::LK_Proto || + ClosingBraceKind == tok::greater) { nextToken(); parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false, /*ClosingBraceKind=*/tok::greater); @@ -3220,6 +3221,7 @@ if (!FormatTok->is(tok::less)) return; + nextToken(); parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false, /*ClosingBraceKind=*/tok::greater); break; @@ -3260,9 +3262,11 @@ // Read identifier with optional template declaration. nextToken(); - if (FormatTok->is(tok::less)) + if (FormatTok->is(tok::less)) { + nextToken(); parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false, /*ClosingBraceKind=*/tok::greater); + } break; } } while (!eof()); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -24114,6 +24114,12 @@ verifyFormat("template \n" "concept Same = __is_same_as;"); + verifyFormat( + "template \n" + "concept _Can_reread_dest =\n" + " std::forward_iterator<_OutIt> &&\n" + " std::same_as, std::iter_value_t<_OutIt>>;"); + auto Style = getLLVMStyle(); Style.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Allowed; diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -390,6 +390,18 @@ EXPECT_TOKEN(Tokens[21], tok::r_brace, TT_Unknown); EXPECT_EQ(Tokens[21]->MatchingParen, Tokens[15]); EXPECT_TRUE(Tokens[21]->ClosesRequiresClause); + + Tokens = + annotate("template concept C =" + "std::same_as, std::iter_value_t>;"); + ASSERT_EQ(Tokens.size(), 31u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::kw_concept, TT_Unknown); + EXPECT_TOKEN(Tokens[14], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[18], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[20], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[25], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[27], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[28], tok::greater, TT_TemplateCloser); } TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) {