summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
authorSaar Raz <saar@raz.email>2020-01-09 15:07:51 +0200
committerSaar Raz <saar@raz.email>2020-01-09 15:07:51 +0200
commitb65b1f322bd88513586a4539d2b5f18aeb698f3f (patch)
treea5d8eb911df5b6d857675415efc125270826a740 /clang/lib/Parse/ParseDeclCXX.cpp
parent9c91d79dadc660cb6a0ec736389341debd8cd118 (diff)
downloadbcm5719-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.cpp61
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.
OpenPOWER on IntegriCloud