aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Parse/ParseOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseOpenMP.cpp')
-rw-r--r--lib/Parse/ParseOpenMP.cpp478
1 files changed, 428 insertions, 50 deletions
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 52a68f6d6935..91fe10e667db 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -17,6 +17,7 @@
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/UniqueVector.h"
using namespace clang;
@@ -42,6 +43,8 @@ enum OpenMPDirectiveKindEx {
OMPD_teams_distribute_parallel,
OMPD_target_teams_distribute_parallel,
OMPD_mapper,
+ OMPD_variant,
+ OMPD_parallel_master,
};
class DeclDirectiveListParserHelper final {
@@ -80,6 +83,7 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) {
.Case("reduction", OMPD_reduction)
.Case("update", OMPD_update)
.Case("mapper", OMPD_mapper)
+ .Case("variant", OMPD_variant)
.Default(OMPD_unknown);
}
@@ -93,6 +97,7 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
{OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
{OMPD_declare, OMPD_simd, OMPD_declare_simd},
{OMPD_declare, OMPD_target, OMPD_declare_target},
+ {OMPD_declare, OMPD_variant, OMPD_declare_variant},
{OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
{OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
{OMPD_distribute_parallel_for, OMPD_simd,
@@ -131,7 +136,11 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
{OMPD_target_teams_distribute_parallel, OMPD_for,
OMPD_target_teams_distribute_parallel_for},
{OMPD_target_teams_distribute_parallel_for, OMPD_simd,
- OMPD_target_teams_distribute_parallel_for_simd}};
+ OMPD_target_teams_distribute_parallel_for_simd},
+ {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
+ {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
+ {OMPD_parallel, OMPD_master, OMPD_parallel_master},
+ {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}};
enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
Token Tok = P.getCurToken();
unsigned DKind =
@@ -752,6 +761,7 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
/*IsReinject*/ true);
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
FNContextRAII FnContext(*this, Ptr);
OMPDeclareSimdDeclAttr::BranchStateTy BS =
@@ -782,25 +792,386 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
LinModifiers, Steps, SourceRange(Loc, EndLoc));
}
+/// Parse optional 'score' '(' <expr> ')' ':'.
+static ExprResult parseContextScore(Parser &P) {
+ ExprResult ScoreExpr;
+ SmallString<16> Buffer;
+ StringRef SelectorName =
+ P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
+ OMPDeclareVariantAttr::ScoreType ScoreKind =
+ OMPDeclareVariantAttr::ScoreUnknown;
+ (void)OMPDeclareVariantAttr::ConvertStrToScoreType(SelectorName, ScoreKind);
+ if (ScoreKind == OMPDeclareVariantAttr::ScoreUnknown)
+ return ScoreExpr;
+ assert(ScoreKind == OMPDeclareVariantAttr::ScoreSpecified &&
+ "Expected \"score\" clause.");
+ (void)P.ConsumeToken();
+ SourceLocation RLoc;
+ ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
+ // Parse ':'
+ if (P.getCurToken().is(tok::colon))
+ (void)P.ConsumeAnyToken();
+ else
+ P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon)
+ << "context selector score clause";
+ return ScoreExpr;
+}
+
+/// Parse context selector for 'implementation' selector set:
+/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
+/// ')'
+static void parseImplementationSelector(
+ Parser &P, SourceLocation Loc, llvm::StringMap<SourceLocation> &UsedCtx,
+ llvm::function_ref<void(SourceRange,
+ const Sema::OpenMPDeclareVariantCtsSelectorData &)>
+ Callback) {
+ const Token &Tok = P.getCurToken();
+ // Parse inner context selector set name, if any.
+ if (!Tok.is(tok::identifier)) {
+ P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+ << "implementation";
+ // Skip until either '}', ')', or end of directive.
+ while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ return;
+ }
+ SmallString<16> Buffer;
+ StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
+ auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
+ if (!Res.second) {
+ // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
+ // Each trait-selector-name can only be specified once.
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
+ << CtxSelectorName << "implementation";
+ P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
+ << CtxSelectorName;
+ }
+ OMPDeclareVariantAttr::CtxSelectorType CSKind =
+ OMPDeclareVariantAttr::CtxUnknown;
+ (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName,
+ CSKind);
+ (void)P.ConsumeToken();
+ switch (CSKind) {
+ case OMPDeclareVariantAttr::CtxVendor: {
+ // Parse '('.
+ BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
+ (void)T.expectAndConsume(diag::err_expected_lparen_after,
+ CtxSelectorName.data());
+ const ExprResult Score = parseContextScore(P);
+ llvm::UniqueVector<llvm::SmallString<16>> Vendors;
+ do {
+ // Parse <vendor>.
+ StringRef VendorName;
+ if (Tok.is(tok::identifier)) {
+ Buffer.clear();
+ VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
+ (void)P.ConsumeToken();
+ if (!VendorName.empty())
+ Vendors.insert(VendorName);
+ } else {
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
+ << "vendor identifier"
+ << "vendor"
+ << "implementation";
+ }
+ if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
+ P.Diag(Tok, diag::err_expected_punc)
+ << (VendorName.empty() ? "vendor name" : VendorName);
+ }
+ } while (Tok.is(tok::identifier));
+ // Parse ')'.
+ (void)T.consumeClose();
+ if (!Vendors.empty()) {
+ SmallVector<StringRef, 4> ImplVendors(Vendors.size());
+ llvm::copy(Vendors, ImplVendors.begin());
+ Sema::OpenMPDeclareVariantCtsSelectorData Data(
+ OMPDeclareVariantAttr::CtxSetImplementation, CSKind,
+ llvm::makeMutableArrayRef(ImplVendors.begin(), ImplVendors.size()),
+ Score);
+ Callback(SourceRange(Loc, Tok.getLocation()), Data);
+ }
+ break;
+ }
+ case OMPDeclareVariantAttr::CtxUnknown:
+ P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+ << "implementation";
+ // Skip until either '}', ')', or end of directive.
+ while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ return;
+ }
+}
+
+/// Parses clauses for 'declare variant' directive.
+/// clause:
+/// <selector_set_name> '=' '{' <context_selectors> '}'
+/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
+bool Parser::parseOpenMPContextSelectors(
+ SourceLocation Loc,
+ llvm::function_ref<void(SourceRange,
+ const Sema::OpenMPDeclareVariantCtsSelectorData &)>
+ Callback) {
+ llvm::StringMap<SourceLocation> UsedCtxSets;
+ do {
+ // Parse inner context selector set name.
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
+ << getOpenMPClauseName(OMPC_match);
+ return true;
+ }
+ SmallString<16> Buffer;
+ StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
+ auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation());
+ if (!Res.second) {
+ // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
+ // Each trait-set-selector-name can only be specified once.
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use)
+ << CtxSelectorSetName;
+ Diag(Res.first->getValue(),
+ diag::note_omp_declare_variant_ctx_set_used_here)
+ << CtxSelectorSetName;
+ }
+ // Parse '='.
+ (void)ConsumeToken();
+ if (Tok.isNot(tok::equal)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
+ << CtxSelectorSetName;
+ return true;
+ }
+ (void)ConsumeToken();
+ // TBD: add parsing of known context selectors.
+ // Unknown selector - just ignore it completely.
+ {
+ // Parse '{'.
+ BalancedDelimiterTracker TBr(*this, tok::l_brace,
+ tok::annot_pragma_openmp_end);
+ if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
+ return true;
+ OMPDeclareVariantAttr::CtxSelectorSetType CSSKind =
+ OMPDeclareVariantAttr::CtxSetUnknown;
+ (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType(
+ CtxSelectorSetName, CSSKind);
+ llvm::StringMap<SourceLocation> UsedCtx;
+ do {
+ switch (CSSKind) {
+ case OMPDeclareVariantAttr::CtxSetImplementation:
+ parseImplementationSelector(*this, Loc, UsedCtx, Callback);
+ break;
+ case OMPDeclareVariantAttr::CtxSetUnknown:
+ // Skip until either '}', ')', or end of directive.
+ while (!SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ break;
+ }
+ const Token PrevTok = Tok;
+ if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
+ Diag(Tok, diag::err_omp_expected_comma_brace)
+ << (PrevTok.isAnnotation() ? "context selector trait"
+ : PP.getSpelling(PrevTok));
+ } while (Tok.is(tok::identifier));
+ // Parse '}'.
+ (void)TBr.consumeClose();
+ }
+ // Consume ','
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
+ (void)ExpectAndConsume(tok::comma);
+ } while (Tok.isAnyIdentifier());
+ return false;
+}
+
+/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
+void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
+ CachedTokens &Toks,
+ SourceLocation Loc) {
+ PP.EnterToken(Tok, /*IsReinject*/ true);
+ PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
+ /*IsReinject*/ true);
+ // Consume the previously pushed token.
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+
+ FNContextRAII FnContext(*this, Ptr);
+ // Parse function declaration id.
+ SourceLocation RLoc;
+ // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
+ // instead of MemberExprs.
+ ExprResult AssociatedFunction =
+ ParseOpenMPParensExpr(getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
+ /*IsAddressOfOperand=*/true);
+ if (!AssociatedFunction.isUsable()) {
+ if (!Tok.is(tok::annot_pragma_openmp_end))
+ while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return;
+ }
+ Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
+ Actions.checkOpenMPDeclareVariantFunction(
+ Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation()));
+
+ // Parse 'match'.
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ if (CKind != OMPC_match) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
+ << getOpenMPClauseName(OMPC_match);
+ while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return;
+ }
+ (void)ConsumeToken();
+ // Parse '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(OMPC_match))) {
+ while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return;
+ }
+
+ // Parse inner context selectors.
+ if (!parseOpenMPContextSelectors(
+ Loc, [this, &DeclVarData](
+ SourceRange SR,
+ const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
+ if (DeclVarData.hasValue())
+ Actions.ActOnOpenMPDeclareVariantDirective(
+ DeclVarData.getValue().first, DeclVarData.getValue().second,
+ SR, Data);
+ })) {
+ // Parse ')'.
+ (void)T.consumeClose();
+ // Need to check for extra tokens.
+ if (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
+ << getOpenMPDirectiveName(OMPD_declare_variant);
+ }
+ }
+
+ // Skip last tokens.
+ while (Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+}
+
+/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
+///
+/// default-clause:
+/// 'default' '(' 'none' | 'shared' ')
+///
+/// proc_bind-clause:
+/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
+///
+/// device_type-clause:
+/// 'device_type' '(' 'host' | 'nohost' | 'any' )'
+namespace {
+ struct SimpleClauseData {
+ unsigned Type;
+ SourceLocation Loc;
+ SourceLocation LOpen;
+ SourceLocation TypeLoc;
+ SourceLocation RLoc;
+ SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
+ SourceLocation TypeLoc, SourceLocation RLoc)
+ : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
+ };
+} // anonymous namespace
+
+static Optional<SimpleClauseData>
+parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
+ const Token &Tok = P.getCurToken();
+ SourceLocation Loc = Tok.getLocation();
+ SourceLocation LOpen = P.ConsumeToken();
+ // Parse '('.
+ BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(Kind)))
+ return llvm::None;
+
+ unsigned Type = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok));
+ SourceLocation TypeLoc = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ P.ConsumeAnyToken();
+
+ // Parse ')'.
+ SourceLocation RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
+
+ 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;
+ SourceLocation DeviceTypeLoc;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
if (Tok.is(tok::identifier)) {
IdentifierInfo *II = Tok.getIdentifierInfo();
StringRef ClauseName = II->getName();
- // Parse 'to|link' clauses.
- if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) {
- Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName;
+ bool IsDeviceTypeClause =
+ getLangOpts().OpenMP >= 50 &&
+ getOpenMPClauseKind(ClauseName) == OMPC_device_type;
+ // Parse 'to|link|device_type' clauses.
+ if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
+ !IsDeviceTypeClause) {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
+ << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
break;
}
+ // Parse 'device_type' clause and go to next clause if any.
+ if (IsDeviceTypeClause) {
+ Optional<SimpleClauseData> DevTypeData =
+ parseOpenMPSimpleClause(*this, OMPC_device_type);
+ if (DevTypeData.hasValue()) {
+ if (DeviceTypeLoc.isValid()) {
+ // We already saw another device_type clause, diagnose it.
+ Diag(DevTypeData.getValue().Loc,
+ diag::warn_omp_more_one_device_type_clause);
+ }
+ switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
+ case OMPC_DEVICE_TYPE_any:
+ DT = OMPDeclareTargetDeclAttr::DT_Any;
+ break;
+ case OMPC_DEVICE_TYPE_host:
+ DT = OMPDeclareTargetDeclAttr::DT_Host;
+ break;
+ case OMPC_DEVICE_TYPE_nohost:
+ DT = OMPDeclareTargetDeclAttr::DT_NoHost;
+ break;
+ case OMPC_DEVICE_TYPE_unknown:
+ llvm_unreachable("Unexpected device_type");
+ }
+ DeviceTypeLoc = DevTypeData.getValue().Loc;
+ }
+ continue;
+ }
ConsumeToken();
}
- auto &&Callback = [this, MT, &SameDirectiveDecls](
- CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
- Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
- SameDirectiveDecls);
+ 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))
@@ -812,6 +1183,15 @@ Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
}
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())
@@ -1005,13 +1385,15 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
break;
}
+ case OMPD_declare_variant:
case OMPD_declare_simd: {
// The syntax is:
- // { #pragma omp declare simd }
+ // { #pragma omp declare {simd|variant} }
// <function-declaration-or-definition>
//
- ConsumeToken();
CachedTokens Toks;
+ Toks.push_back(Tok);
+ ConsumeToken();
while(Tok.isNot(tok::annot_pragma_openmp_end)) {
Toks.push_back(Tok);
ConsumeAnyToken();
@@ -1035,10 +1417,16 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
}
if (!Ptr) {
- Diag(Loc, diag::err_omp_decl_in_declare_simd);
+ Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
+ << (DKind == OMPD_declare_simd ? 0 : 1);
return DeclGroupPtrTy();
}
- return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
+ if (DKind == OMPD_declare_simd)
+ return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
+ assert(DKind == OMPD_declare_variant &&
+ "Expected declare variant directive only");
+ ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
+ return Ptr;
}
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
@@ -1120,6 +1508,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_target_parallel_for:
case OMPD_taskloop:
case OMPD_taskloop_simd:
+ case OMPD_master_taskloop:
+ case OMPD_master_taskloop_simd:
+ case OMPD_parallel_master_taskloop:
case OMPD_distribute:
case OMPD_end_declare_target:
case OMPD_target_update:
@@ -1174,20 +1565,17 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
/// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
-/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
-/// 'distribute' | 'target enter data' | 'target exit data' |
-/// 'target parallel' | 'target parallel for' |
-/// 'target update' | 'distribute parallel for' |
-/// 'distribute paralle for simd' | 'distribute simd' |
-/// 'target parallel for simd' | 'target simd' |
-/// 'teams distribute' | 'teams distribute 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}
-/// annot_pragma_openmp_end
+/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 'master
+/// taskloop' | 'master taskloop simd' | 'parallel master taskloop' |
+/// 'distribute' | 'target enter data' | 'target exit data' | 'target
+/// parallel' | 'target parallel for' | 'target update' | 'distribute
+/// parallel for' | 'distribute paralle for simd' | 'distribute simd' |
+/// 'target parallel for simd' | 'target simd' | 'teams distribute' |
+/// 'teams distribute 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} annot_pragma_openmp_end
///
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
@@ -1362,6 +1750,9 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_target_parallel_for:
case OMPD_taskloop:
case OMPD_taskloop_simd:
+ case OMPD_master_taskloop:
+ case OMPD_master_taskloop_simd:
+ case OMPD_parallel_master_taskloop:
case OMPD_distribute:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
@@ -1474,6 +1865,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_requires:
+ case OMPD_declare_variant:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end);
@@ -1712,6 +2104,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_allocate:
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
break;
+ case OMPC_device_type:
case OMPC_unknown:
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
<< getOpenMPDirectiveName(DKind);
@@ -1719,6 +2112,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
break;
case OMPC_threadprivate:
case OMPC_uniform:
+ case OMPC_match:
if (!WrongDirective)
Diag(Tok, diag::err_omp_unexpected_clause)
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
@@ -1732,14 +2126,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
/// constructs.
/// \param RLoc Returned location of right paren.
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
- SourceLocation &RLoc) {
+ SourceLocation &RLoc,
+ bool IsAddressOfOperand) {
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
return ExprError();
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(
- /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
+ /*isUnaryExpression=*/false, IsAddressOfOperand, NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
@@ -1811,29 +2206,12 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
bool ParseOnly) {
- SourceLocation Loc = Tok.getLocation();
- SourceLocation LOpen = ConsumeToken();
- // Parse '('.
- BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPClauseName(Kind)))
- return nullptr;
-
- unsigned Type = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
- SourceLocation TypeLoc = Tok.getLocation();
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
-
- // Parse ')'.
- SourceLocation RLoc = Tok.getLocation();
- if (!T.consumeClose())
- RLoc = T.getCloseLocation();
-
- if (ParseOnly)
+ llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
+ if (!Val || ParseOnly)
return nullptr;
- return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
+ return Actions.ActOnOpenMPSimpleClause(
+ Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
+ Val.getValue().Loc, Val.getValue().RLoc);
}
/// Parsing of OpenMP clauses like 'ordered'.