diff options
author | Saar Raz <saar@raz.email> | 2020-01-09 15:07:51 +0200 |
---|---|---|
committer | Saar Raz <saar@raz.email> | 2020-01-09 15:07:51 +0200 |
commit | b65b1f322bd88513586a4539d2b5f18aeb698f3f (patch) | |
tree | a5d8eb911df5b6d857675415efc125270826a740 /clang/lib/Parse/ParseDeclCXX.cpp | |
parent | 9c91d79dadc660cb6a0ec736389341debd8cd118 (diff) | |
download | bcm5719-llvm-b65b1f322bd88513586a4539d2b5f18aeb698f3f.tar.gz bcm5719-llvm-b65b1f322bd88513586a4539d2b5f18aeb698f3f.zip |
[Concepts] Function trailing requires clauses
Function trailing requires clauses now parsed, supported in overload resolution and when calling, referencing and taking the address of functions or function templates.
Differential Revision: https://reviews.llvm.org/D43357
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index af3403403c1..081d4d8b120 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2301,6 +2301,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( LateParsedAttrList &LateParsedAttrs) { // member-declarator: // declarator pure-specifier[opt] + // declarator requires-clause // declarator brace-or-equal-initializer[opt] // identifier[opt] ':' constant-expression if (Tok.isNot(tok::colon)) @@ -2314,6 +2315,8 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( BitfieldSize = ParseConstantExpression(); if (BitfieldSize.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + } else if (Tok.is(tok::kw_requires)) { + ParseTrailingRequiresClause(DeclaratorInfo); } else { ParseOptionalCXX11VirtSpecifierSeq( VS, getCurrentClass().IsInterface, @@ -2436,6 +2439,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// /// member-declarator: /// declarator virt-specifier-seq[opt] pure-specifier[opt] +/// [C++2a] declarator requires-clause /// declarator constant-initializer[opt] /// [C++11] declarator brace-or-equal-initializer[opt] /// identifier[opt] ':' constant-expression @@ -2669,6 +2673,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SmallVector<Decl *, 8> DeclsInGroup; ExprResult BitfieldSize; + ExprResult TrailingRequiresClause; bool ExpectSemi = true; // Parse the first declarator. @@ -3793,6 +3798,62 @@ TypeResult Parser::ParseTrailingReturnType(SourceRange &Range, : DeclaratorContext::TrailingReturnContext); } +/// Parse a requires-clause as part of a function declaration. +void Parser::ParseTrailingRequiresClause(Declarator &D) { + assert(Tok.is(tok::kw_requires) && "expected requires"); + + SourceLocation RequiresKWLoc = ConsumeToken(); + + ExprResult TrailingRequiresClause; + ParseScope ParamScope(this, + Scope::DeclScope | + Scope::FunctionDeclarationScope | + Scope::FunctionPrototypeScope); + + Actions.ActOnStartTrailingRequiresClause(getCurScope(), D); + + llvm::Optional<Sema::CXXThisScopeRAII> ThisScope; + InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope); + + TrailingRequiresClause = + ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true); + + TrailingRequiresClause = + Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause); + + if (!D.isDeclarationOfFunction()) { + Diag(RequiresKWLoc, + diag::err_requires_clause_on_declarator_not_declaring_a_function); + return; + } + + if (TrailingRequiresClause.isInvalid()) + SkipUntil({tok::l_brace, tok::arrow, tok::kw_try, tok::comma, tok::colon}, + StopAtSemi | StopBeforeMatch); + else + D.setTrailingRequiresClause(TrailingRequiresClause.get()); + + // Did the user swap the trailing return type and requires clause? + if (D.isFunctionDeclarator() && Tok.is(tok::arrow) && + D.getDeclSpec().getTypeSpecType() == TST_auto) { + SourceLocation ArrowLoc = Tok.getLocation(); + SourceRange Range; + TypeResult TrailingReturnType = + ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit=*/false); + + if (!TrailingReturnType.isInvalid()) { + Diag(ArrowLoc, + diag::err_requires_clause_must_appear_after_trailing_return) + << Range; + auto &FunctionChunk = D.getFunctionTypeInfo(); + FunctionChunk.HasTrailingReturnType = TrailingReturnType.isUsable(); + FunctionChunk.TrailingReturnType = TrailingReturnType.get(); + } else + SkipUntil({tok::equal, tok::l_brace, tok::arrow, tok::kw_try, tok::comma}, + StopAtSemi | StopBeforeMatch); + } +} + /// We have just started parsing the definition of a new class, /// so push that class onto our stack of classes that is currently /// being parsed. |