diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1680,8 +1680,8 @@ if (!Tok) return false; - if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_concept, - tok::kw_struct, tok::kw_using)) { + if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct, + tok::kw_using)) { return false; } diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -158,7 +158,6 @@ void parseAccessSpecifier(); bool parseEnum(); bool parseStructLike(); - void parseConcept(); bool parseRequires(); void parseRequiresClause(FormatToken *RequiresToken); void parseRequiresExpression(FormatToken *RequiresToken); 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 @@ -1813,9 +1813,6 @@ break; } break; - case tok::kw_concept: - parseConcept(); - return; case tok::kw_requires: { if (Style.isCpp()) { bool ParsedClause = parseRequires(); @@ -3272,26 +3269,6 @@ } } -/// \brief Parses a concept definition. -/// \pre The current token has to be the concept keyword. -/// -/// Returns if either the concept has been completely parsed, or if it detects -/// that the concept definition is incorrect. -void UnwrappedLineParser::parseConcept() { - assert(FormatTok->is(tok::kw_concept) && "'concept' expected"); - nextToken(); - if (!FormatTok->is(tok::identifier)) - return; - nextToken(); - if (!FormatTok->is(tok::equal)) - return; - nextToken(); - parseConstraintExpression(); - if (FormatTok->is(tok::semi)) - nextToken(); - addUnwrappedLine(); -} - /// \brief Parses a requires, decides if it is a clause or an expression. /// \pre The current token has to be the requires keyword. /// \returns true if it parsed a clause. @@ -3458,6 +3435,8 @@ ? TT_RequiresClauseInARequiresExpression : TT_RequiresClause); + // NOTE: parseConstraintExpression is only ever called from this function. + // It could be inlined into here. parseConstraintExpression(); if (!InRequiresExpression) @@ -3491,9 +3470,8 @@ /// \brief Parses a constraint expression. /// -/// This is either the definition of a concept, or the body of a requires -/// clause. It returns, when the parsing is complete, or the expression is -/// incorrect. +/// This is the body of a requires clause. It returns, when the parsing is +/// complete, or the expression is incorrect. void UnwrappedLineParser::parseConstraintExpression() { // The special handling for lambdas is needed since tryToParseLambda() eats a // token and if a requires expression is the last part of a requires clause 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 @@ -23588,10 +23588,10 @@ "concept DelayedCheck = !!false || requires(T t) { t.bar(); } " "&& sizeof(T) <= 8;"); - verifyFormat( - "template \n" - "concept DelayedCheck = static_cast(0) ||\n" - " requires(T t) { t.bar(); } && sizeof(T) <= 8;"); + verifyFormat("template \n" + "concept DelayedCheck =\n" + " static_cast(0) || requires(T t) { t.bar(); } && " + "sizeof(T) <= 8;"); verifyFormat("template \n" "concept DelayedCheck = bool(0) || requires(T t) { t.bar(); } " @@ -23599,8 +23599,8 @@ verifyFormat( "template \n" - "concept DelayedCheck = (bool)(0) ||\n" - " requires(T t) { t.bar(); } && sizeof(T) <= 8;"); + "concept DelayedCheck =\n" + " (bool)(0) || requires(T t) { t.bar(); } && sizeof(T) <= 8;"); verifyFormat("template \n" "concept DelayedCheck = (bool)0 || requires(T t) { t.bar(); } " @@ -23636,6 +23636,9 @@ verifyFormat("template \n" "concept True = S::Value;"); + verifyFormat("template \n" + "concept True = T.field;"); + verifyFormat( "template \n" "concept C = []() { return true; }() && requires(T t) { t.bar(); } &&\n" @@ -23914,11 +23917,9 @@ verifyFormat("template concept True = true;", Style); verifyFormat( - "template concept C = decltype([]() -> std::true_type {\n" - " return {};\n" - " }())::value &&\n" - " requires(T t) { t.bar(); } && " - "sizeof(T) <= 8;", + "template concept C =\n" + " decltype([]() -> std::true_type { return {}; }())::value &&\n" + " requires(T t) { t.bar(); } && sizeof(T) <= 8;", Style); verifyFormat("template concept Semiregular =\n" @@ -23936,21 +23937,20 @@ // The following tests are invalid C++, we just want to make sure we don't // assert. - verifyFormat("template \n" - "concept C = requires C2;"); + verifyNoCrash("template \n" + "concept C = requires C2;"); - verifyFormat("template \n" - "concept C = 5 + 4;"); + verifyNoCrash("template \n" + "concept C = 5 + 4;"); - verifyFormat("template \n" - "concept C =\n" - "class X;"); + verifyNoCrash("template \n" + "concept C = class X;"); - verifyFormat("template \n" - "concept C = [] && true;"); + verifyNoCrash("template \n" + "concept C = [] && true;"); - verifyFormat("template \n" - "concept C = [] && requires(T t) { typename T::size_type; };"); + verifyNoCrash("template \n" + "concept C = [] && requires(T t) { typename T::size_type; };"); } TEST_F(FormatTest, RequiresClausesPositions) {