aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp425
1 files changed, 332 insertions, 93 deletions
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index db7e967b15ae..18e43c3734ac 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -131,6 +131,7 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
{OMPD_declare, OMPD_simd, OMPD_declare_simd},
{OMPD_declare, OMPD_target, OMPD_declare_target},
{OMPD_declare, OMPD_variant, OMPD_declare_variant},
+ {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
{OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
{OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
{OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
@@ -441,9 +442,9 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
ConsumeToken();
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
Actions.FinalizeDeclaration(OmpPrivParm);
- cutOffParsing();
return;
}
@@ -1664,30 +1665,41 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
}
-Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
- // OpenMP 4.5 syntax with list of entities.
- Sema::NamedDeclSetType SameDirectiveDecls;
- SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
- NamedDecl *>,
- 4>
- DeclareTargetDecls;
- OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
+void Parser::ParseOMPDeclareTargetClauses(
+ Sema::DeclareTargetContextInfo &DTCI) {
SourceLocation DeviceTypeLoc;
+ bool RequiresToOrLinkClause = false;
+ bool HasToOrLinkClause = false;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
- if (Tok.is(tok::identifier)) {
+ bool HasIdentifier = Tok.is(tok::identifier);
+ if (HasIdentifier) {
+ // If we see any clause we need a to or link clause.
+ RequiresToOrLinkClause = true;
IdentifierInfo *II = Tok.getIdentifierInfo();
StringRef ClauseName = II->getName();
bool IsDeviceTypeClause =
getLangOpts().OpenMP >= 50 &&
getOpenMPClauseKind(ClauseName) == OMPC_device_type;
- // Parse 'to|link|device_type' clauses.
- if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
- !IsDeviceTypeClause) {
+
+ bool IsToOrLinkClause =
+ OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
+ assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!");
+
+ if (!IsDeviceTypeClause && DTCI.Kind == OMPD_begin_declare_target) {
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
+ << ClauseName << 0;
break;
}
+ if (!IsDeviceTypeClause && !IsToOrLinkClause) {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
+ << ClauseName << (getLangOpts().OpenMP >= 50 ? 2 : 1);
+ break;
+ }
+
+ if (IsToOrLinkClause)
+ HasToOrLinkClause = true;
+
// Parse 'device_type' clause and go to next clause if any.
if (IsDeviceTypeClause) {
Optional<SimpleClauseData> DevTypeData =
@@ -1697,16 +1709,17 @@ Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
// We already saw another device_type clause, diagnose it.
Diag(DevTypeData.getValue().Loc,
diag::warn_omp_more_one_device_type_clause);
+ break;
}
switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
case OMPC_DEVICE_TYPE_any:
- DT = OMPDeclareTargetDeclAttr::DT_Any;
+ DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
break;
case OMPC_DEVICE_TYPE_host:
- DT = OMPDeclareTargetDeclAttr::DT_Host;
+ DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
break;
case OMPC_DEVICE_TYPE_nohost:
- DT = OMPDeclareTargetDeclAttr::DT_NoHost;
+ DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
break;
case OMPC_DEVICE_TYPE_unknown:
llvm_unreachable("Unexpected device_type");
@@ -1717,37 +1730,47 @@ Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
}
ConsumeToken();
}
- auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
- CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
- NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
- getCurScope(), SS, NameInfo, SameDirectiveDecls);
- if (ND)
- DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
- };
- if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
- /*AllowScopeSpecifier=*/true))
+
+ if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
+ auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo) {
+ NamedDecl *ND =
+ Actions.lookupOpenMPDeclareTargetName(getCurScope(), SS, NameInfo);
+ if (!ND)
+ return;
+ Sema::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
+ bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
+ if (!FirstMapping)
+ Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
+ << NameInfo.getName();
+ };
+ if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
+ /*AllowScopeSpecifier=*/true))
+ break;
+ }
+
+ if (Tok.is(tok::l_paren)) {
+ Diag(Tok,
+ diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
+ break;
+ }
+ if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
+ Diag(Tok,
+ diag::err_omp_declare_target_unexpected_clause_after_implicit_to);
break;
+ }
// Consume optional ','.
if (Tok.is(tok::comma))
ConsumeToken();
}
+
+ // For declare target require at least 'to' or 'link' to be present.
+ if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkClause &&
+ !HasToOrLinkClause)
+ Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause);
+
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- ConsumeAnyToken();
- for (auto &MTLocDecl : DeclareTargetDecls) {
- OMPDeclareTargetDeclAttr::MapTypeTy MT;
- SourceLocation Loc;
- NamedDecl *ND;
- std::tie(MT, Loc, ND) = MTLocDecl;
- // device_type clause is applied only to functions.
- Actions.ActOnOpenMPDeclareTargetName(
- ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
- }
- SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
- SameDirectiveDecls.end());
- if (Decls.empty())
- return DeclGroupPtrTy();
- return Actions.BuildDeclaratorGroup(Decls);
}
void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
@@ -1784,10 +1807,11 @@ void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
-void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
+void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
+ OpenMPDirectiveKind EndDKind,
SourceLocation DKLoc) {
- parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind,
- DKLoc, Tok.getLocation(),
+ parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
+ Tok.getLocation(),
/* SkipUntilOpenMPEnd */ false);
// Skip the last annot_pragma_openmp_end.
if (Tok.is(tok::annot_pragma_openmp_end))
@@ -1833,7 +1857,8 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
DeclSpec::TST TagType, Decl *Tag) {
- assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
+ assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
+ "Not an OpenMP directive!");
ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -1851,7 +1876,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
Toks.push_back(Tok);
while (Cnt && Tok.isNot(tok::eof)) {
(void)ConsumeAnyToken();
- if (Tok.is(tok::annot_pragma_openmp))
+ if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
++Cnt;
else if (Tok.is(tok::annot_pragma_openmp_end))
--Cnt;
@@ -2074,7 +2099,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ConsumeAnyToken();
DeclGroupPtrTy Ptr;
- if (Tok.is(tok::annot_pragma_openmp)) {
+ if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
TagType, Tag);
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
@@ -2101,58 +2126,48 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
return Ptr;
}
+ case OMPD_begin_declare_target:
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- return ParseOMPDeclareTargetClauses();
- }
+ bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
+ bool HasImplicitMappings =
+ DKind == OMPD_begin_declare_target || !HasClauses;
+ Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc);
+ if (HasClauses)
+ ParseOMPDeclareTargetClauses(DTCI);
// Skip the last annot_pragma_openmp_end.
ConsumeAnyToken();
- if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
- return DeclGroupPtrTy();
-
- ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
- llvm::SmallVector<Decl *, 4> Decls;
- DKind = parseOpenMPDirectiveKind(*this);
- while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
- Tok.isNot(tok::r_brace)) {
- DeclGroupPtrTy Ptr;
- // Here we expect to see some function declaration.
- if (AS == AS_none) {
- assert(TagType == DeclSpec::TST_unspecified);
- MaybeParseCXX11Attributes(Attrs);
- ParsingDeclSpec PDS(*this);
- Ptr = ParseExternalDeclaration(Attrs, &PDS);
- } else {
- Ptr =
- ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
- }
- if (Ptr) {
- DeclGroupRef Ref = Ptr.get();
- Decls.append(Ref.begin(), Ref.end());
- }
- if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
- TentativeParsingAction TPA(*this);
- ConsumeAnnotationToken();
- DKind = parseOpenMPDirectiveKind(*this);
- if (DKind != OMPD_end_declare_target)
- TPA.Revert();
- else
- TPA.Commit();
- }
+ if (HasImplicitMappings) {
+ Actions.ActOnStartOpenMPDeclareTargetContext(DTCI);
+ return nullptr;
}
- ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
- Actions.ActOnFinishOpenMPDeclareTargetDirective();
+ Actions.ActOnFinishedOpenMPDeclareTargetContext(DTCI);
+ llvm::SmallVector<Decl *, 4> Decls;
+ for (auto &It : DTCI.ExplicitlyMapped)
+ Decls.push_back(It.first);
return Actions.BuildDeclaratorGroup(Decls);
}
+ case OMPD_end_declare_target: {
+ if (!Actions.isInOpenMPDeclareTargetContext()) {
+ Diag(Tok, diag::err_omp_unexpected_directive)
+ << 1 << getOpenMPDirectiveName(DKind);
+ break;
+ }
+ const Sema::DeclareTargetContextInfo &DTCI =
+ Actions.ActOnOpenMPEndDeclareTargetDirective();
+ ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
+ return nullptr;
+ }
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
break;
case OMPD_parallel:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_task:
case OMPD_taskyield:
case OMPD_barrier:
@@ -2190,7 +2205,6 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_distribute:
- case OMPD_end_declare_target:
case OMPD_target_update:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
@@ -2206,6 +2220,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute_simd:
+ case OMPD_dispatch:
+ case OMPD_masked:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
break;
@@ -2255,12 +2271,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// simd' | 'teams distribute parallel for simd' | 'teams distribute
/// parallel for' | 'target teams' | 'target teams distribute' | 'target
/// teams distribute parallel for' | 'target teams distribute parallel
-/// for simd' | 'target teams distribute simd' {clause}
+/// for simd' | 'target teams distribute simd' | 'masked' {clause}
/// annot_pragma_openmp_end
///
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
- assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
+ assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
+ "Not an OpenMP directive!");
ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<OMPClause *, 5> Clauses;
@@ -2377,6 +2394,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_target_enter_data:
case OMPD_target_exit_data:
case OMPD_target_update:
+ case OMPD_interop:
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
ParsedStmtContext()) {
Diag(Tok, diag::err_omp_immediate_directive)
@@ -2387,6 +2405,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
LLVM_FALLTHROUGH;
case OMPD_parallel:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
@@ -2427,7 +2447,9 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_target_teams_distribute_simd: {
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_dispatch:
+ case OMPD_masked: {
// Special processing for flush and depobj clauses.
Token ImplicitTok;
bool ImplicitClauseAllowed = false;
@@ -2521,6 +2543,11 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
HasAssociatedStatement = false;
}
+ if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) {
+ Diag(Loc, diag::err_omp_required_clause)
+ << getOpenMPDirectiveName(OMPD_tile) << "sizes";
+ }
+
StmtResult AssociatedStmt;
if (HasAssociatedStatement) {
// The body is a block scope like in Lambdas and Blocks.
@@ -2529,7 +2556,15 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
// the captured region. Code elsewhere assumes that any FunctionScopeInfo
// should have at least one compound statement scope within it.
ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
- AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
+ {
+ Sema::CompoundScopeRAII Scope(Actions);
+ AssociatedStmt = ParseStatement();
+
+ if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
+ getLangOpts().OpenMPIRBuilder)
+ AssociatedStmt =
+ Actions.ActOnOpenMPCanonicalLoop(AssociatedStmt.get());
+ }
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
} else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
DKind == OMPD_target_exit_data) {
@@ -2550,6 +2585,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
}
case OMPD_declare_simd:
case OMPD_declare_target:
+ case OMPD_begin_declare_target:
case OMPD_end_declare_target:
case OMPD_requires:
case OMPD_begin_declare_variant:
@@ -2633,6 +2669,37 @@ bool Parser::ParseOpenMPSimpleVarList(
return !IsCorrect;
}
+OMPClause *Parser::ParseOpenMPSizesClause() {
+ SourceLocation ClauseNameLoc = ConsumeToken();
+ SmallVector<Expr *, 4> ValExprs;
+
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.consumeOpen()) {
+ Diag(Tok, diag::err_expected) << tok::l_paren;
+ return nullptr;
+ }
+
+ while (true) {
+ ExprResult Val = ParseConstantExpression();
+ if (!Val.isUsable()) {
+ T.skipToEnd();
+ return nullptr;
+ }
+
+ ValExprs.push_back(Val.get());
+
+ if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
+ break;
+
+ ExpectAndConsume(tok::comma);
+ }
+
+ T.consumeClose();
+
+ return Actions.ActOnOpenMPSizesClause(
+ ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation());
+}
+
OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
SourceLocation Loc = Tok.getLocation();
ConsumeAnyToken();
@@ -2643,7 +2710,8 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
return nullptr;
SmallVector<Sema::UsesAllocatorsData, 4> Data;
do {
- ExprResult Allocator = ParseCXXIdExpression();
+ ExprResult Allocator =
+ getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
if (Allocator.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
@@ -2655,7 +2723,8 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
BalancedDelimiterTracker T(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
T.consumeOpen();
- ExprResult AllocatorTraits = ParseCXXIdExpression();
+ ExprResult AllocatorTraits =
+ getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
T.consumeClose();
if (AllocatorTraits.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
@@ -2727,6 +2796,10 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_allocator:
case OMPC_depobj:
case OMPC_detach:
+ case OMPC_novariants:
+ case OMPC_nocontext:
+ case OMPC_filter:
+ case OMPC_partial:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -2749,13 +2822,17 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// At most one allocator clause can appear on the directive.
// OpenMP 5.0, 2.10.1 task Construct, Restrictions.
// At most one detach clause can appear on the directive.
+ // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
+ // At most one novariants clause can appear on a dispatch directive.
+ // At most one nocontext clause can appear on a dispatch directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
- if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
+ if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
+ PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
Clause = ParseOpenMPClause(CKind, WrongDirective);
else
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
@@ -2818,7 +2895,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_unified_shared_memory:
case OMPC_reverse_offload:
case OMPC_dynamic_allocators:
- case OMPC_destroy:
+ case OMPC_full:
// OpenMP [2.7.1, Restrictions, p. 9]
// Only one ordered clause can appear on a loop directive.
// OpenMP [2.7.1, Restrictions, C/C++, p. 4]
@@ -2870,9 +2947,33 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_affinity:
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
break;
+ case OMPC_sizes:
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+ ErrorFound = true;
+ }
+
+ Clause = ParseOpenMPSizesClause();
+ break;
case OMPC_uses_allocators:
Clause = ParseOpenMPUsesAllocatorClause(DKind);
break;
+ case OMPC_destroy:
+ if (DKind != OMPD_interop) {
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+ ErrorFound = true;
+ }
+ Clause = ParseOpenMPClause(CKind, WrongDirective);
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case OMPC_init:
+ case OMPC_use:
+ Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
+ break;
case OMPC_device_type:
case OMPC_unknown:
skipUntilPragmaOpenMPEnd(DKind);
@@ -2969,6 +3070,144 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
}
+/// Parsing of OpenMP clauses that use an interop-var.
+///
+/// init-clause:
+/// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
+///
+/// destroy-clause:
+/// destroy(interop-var)
+///
+/// use-clause:
+/// use(interop-var)
+///
+/// interop-modifier:
+/// prefer_type(preference-list)
+///
+/// preference-list:
+/// foreign-runtime-id [, foreign-runtime-id]...
+///
+/// foreign-runtime-id:
+/// <string-literal> | <constant-integral-expression>
+///
+/// interop-type:
+/// target | targetsync
+///
+OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
+ bool ParseOnly) {
+ SourceLocation Loc = ConsumeToken();
+ // Parse '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(Kind).data()))
+ return nullptr;
+
+ bool IsTarget = false;
+ bool IsTargetSync = false;
+ SmallVector<Expr *, 4> Prefs;
+
+ if (Kind == OMPC_init) {
+
+ // Parse optional interop-modifier.
+ if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "prefer_type") {
+ ConsumeToken();
+ BalancedDelimiterTracker PT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
+ return nullptr;
+
+ while (Tok.isNot(tok::r_paren)) {
+ SourceLocation Loc = Tok.getLocation();
+ ExprResult LHS = ParseCastExpression(AnyCastExpr);
+ ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
+ ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
+ /*DiscardedValue=*/false);
+ if (PTExpr.isUsable())
+ Prefs.push_back(PTExpr.get());
+ else
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
+ PT.consumeClose();
+ }
+
+ if (!Prefs.empty()) {
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ else
+ Diag(Tok, diag::err_omp_expected_punc_after_interop_mod);
+ }
+
+ // Parse the interop-types.
+ bool HasError = false;
+ while (Tok.is(tok::identifier)) {
+ if (PP.getSpelling(Tok) == "target") {
+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
+ // Each interop-type may be specified on an action-clause at most
+ // once.
+ if (IsTarget)
+ Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
+ IsTarget = true;
+ } else if (PP.getSpelling(Tok) == "targetsync") {
+ if (IsTargetSync)
+ Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
+ IsTargetSync = true;
+ } else {
+ HasError = true;
+ Diag(Tok, diag::err_omp_expected_interop_type);
+ }
+ ConsumeToken();
+
+ if (!Tok.is(tok::comma))
+ break;
+ ConsumeToken();
+ }
+ if (!HasError && !IsTarget && !IsTargetSync)
+ Diag(Tok, diag::err_omp_expected_interop_type);
+
+ if (Tok.is(tok::colon))
+ ConsumeToken();
+ else if (IsTarget || IsTargetSync)
+ Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
+ }
+
+ // Parse the variable.
+ SourceLocation VarLoc = Tok.getLocation();
+ ExprResult InteropVarExpr =
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ if (!InteropVarExpr.isUsable()) {
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
+
+ // Parse ')'.
+ SourceLocation RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
+
+ if (ParseOnly || !InteropVarExpr.isUsable() ||
+ (Kind == OMPC_init && !IsTarget && !IsTargetSync))
+ return nullptr;
+
+ if (Kind == OMPC_init)
+ return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget,
+ IsTargetSync, Loc, T.getOpenLocation(),
+ VarLoc, RLoc);
+ if (Kind == OMPC_use)
+ return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc,
+ T.getOpenLocation(), VarLoc, RLoc);
+
+ if (Kind == OMPC_destroy)
+ return Actions.ActOnOpenMPDestroyClause(InteropVarExpr.get(), Loc,
+ T.getOpenLocation(), VarLoc, RLoc);
+
+ llvm_unreachable("Unexpected interop variable clause.");
+}
+
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause: