diff options
author | Saar Raz <saar@raz.email> | 2019-07-10 21:25:49 +0000 |
---|---|---|
committer | Saar Raz <saar@raz.email> | 2019-07-10 21:25:49 +0000 |
commit | fa50bf0cf89f59254ae0969e936c597ec1da78b9 (patch) | |
tree | f1a60f25fbdf3627a9e87eda4c6afe056e9dd412 /lib/Parse | |
parent | 0f7a450afd00f19c5fda94c88b9bce48c8980851 (diff) | |
download | clang-fa50bf0cf89f59254ae0969e936c597ec1da78b9.tar.gz |
[Concepts] Concept definitions (D40381)
First in a series of patches to land C++2a Concepts support.
This patch adds AST and parsing support for concept-declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@365699 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 78e0c04f53..6ae75eda24 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -49,6 +49,15 @@ Decl *Parser::ParseDeclarationStartingWithTemplate( /// template-declaration: [C++ temp] /// 'export'[opt] 'template' '<' template-parameter-list '>' declaration /// +/// template-declaration: [C++2a] +/// template-head declaration +/// template-head concept-definition +/// +/// TODO: requires-clause +/// template-head: [C++2a] +/// 'template' '<' template-parameter-list '>' +/// requires-clause[opt] +/// /// explicit-specialization: [ C++ temp.expl.spec] /// 'template' '<' '>' declaration Decl *Parser::ParseTemplateDeclarationOrSpecialization( @@ -142,6 +151,12 @@ Decl *Parser::ParseTemplateDeclarationOrSpecialization( ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization); // Parse the actual template declaration. + if (Tok.is(tok::kw_concept)) + return ParseConceptDefinition( + ParsedTemplateInfo(&ParamLists, isSpecialization, + LastParamListWasEmpty), + DeclEnd); + return ParseSingleDeclarationAfterTemplate( Context, ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty), @@ -315,6 +330,85 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate( return ThisDecl; } +/// \brief Parse a single declaration that declares a concept. +/// +/// \param DeclEnd will receive the source location of the last token +/// within this declaration. +/// +/// \returns the new declaration. +Decl * +Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, + SourceLocation &DeclEnd) { + assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && + "Template information required"); + assert(Tok.is(tok::kw_concept) && + "ParseConceptDefinition must be called when at a 'concept' keyword"); + + ConsumeToken(); // Consume 'concept' + + SourceLocation BoolKWLoc; + if (TryConsumeToken(tok::kw_bool, BoolKWLoc)) + Diag(Tok.getLocation(), diag::ext_concept_legacy_bool_keyword) << + FixItHint::CreateRemoval(SourceLocation(BoolKWLoc)); + + DiagnoseAndSkipCXX11Attributes(); + + CXXScopeSpec SS; + if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), + /*EnteringContext=*/false, /*MayBePseudoDestructor=*/nullptr, + /*IsTypename=*/false, /*LastII=*/nullptr, /*OnlyNamespace=*/true) || + SS.isInvalid()) { + SkipUntil(tok::semi); + return nullptr; + } + + if (SS.isNotEmpty()) + Diag(SS.getBeginLoc(), + diag::err_concept_definition_not_identifier); + + UnqualifiedId Result; + if (ParseUnqualifiedId(SS, /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*AllowDeductionGuide=*/false, + /*ObjectType=*/ParsedType(), /*TemplateKWLoc=*/nullptr, + Result)) { + SkipUntil(tok::semi); + return nullptr; + } + + if (Result.getKind() != UnqualifiedIdKind::IK_Identifier) { + Diag(Result.getBeginLoc(), diag::err_concept_definition_not_identifier); + SkipUntil(tok::semi); + return nullptr; + } + + IdentifierInfo *Id = Result.Identifier; + SourceLocation IdLoc = Result.getBeginLoc(); + + DiagnoseAndSkipCXX11Attributes(); + + if (!TryConsumeToken(tok::equal)) { + Diag(Tok.getLocation(), diag::err_expected) << tok::equal; + SkipUntil(tok::semi); + return nullptr; + } + + ExprResult ConstraintExprResult = + Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression()); + if (ConstraintExprResult.isInvalid()) { + SkipUntil(tok::semi); + return nullptr; + } + + DeclEnd = Tok.getLocation(); + ExpectAndConsumeSemi(diag::err_expected_semi_declaration); + Expr *ConstraintExpr = ConstraintExprResult.get(); + return Actions.ActOnConceptDefinition(getCurScope(), + *TemplateInfo.TemplateParams, + Id, IdLoc, ConstraintExpr); +} + /// ParseTemplateParameters - Parses a template-parameter-list enclosed in /// angle brackets. Depth is the depth of this template-parameter-list, which /// is the number of template headers directly enclosing this template header. |