aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp1388
1 files changed, 1122 insertions, 266 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp
index 18e43c3734ac..da5f6605c6ff 100644
--- a/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp
+++ b/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp
@@ -19,11 +19,14 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
+#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/UniqueVector.h"
+#include "llvm/Frontend/OpenMP/OMPAssume.h"
#include "llvm/Frontend/OpenMP/OMPContext.h"
+#include <optional>
using namespace clang;
using namespace llvm::omp;
@@ -149,10 +152,12 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
{OMPD_for, OMPD_simd, OMPD_for_simd},
{OMPD_parallel, OMPD_for, OMPD_parallel_for},
{OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
+ {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
{OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
{OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
{OMPD_target, OMPD_parallel, OMPD_target_parallel},
{OMPD_target, OMPD_simd, OMPD_target_simd},
+ {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
{OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
{OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
{OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
@@ -162,8 +167,10 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
OMPD_teams_distribute_parallel_for},
{OMPD_teams_distribute_parallel_for, OMPD_simd,
OMPD_teams_distribute_parallel_for_simd},
+ {OMPD_teams, OMPD_loop, OMPD_teams_loop},
{OMPD_target, OMPD_teams, OMPD_target_teams},
{OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
+ {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
{OMPD_target_teams_distribute, OMPD_parallel,
OMPD_target_teams_distribute_parallel},
{OMPD_target_teams_distribute, OMPD_simd,
@@ -173,11 +180,17 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
{OMPD_target_teams_distribute_parallel_for, OMPD_simd,
OMPD_target_teams_distribute_parallel_for_simd},
{OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
+ {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
{OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
+ {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
{OMPD_parallel, OMPD_master, OMPD_parallel_master},
+ {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
{OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
+ {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
{OMPD_parallel_master_taskloop, OMPD_simd,
- OMPD_parallel_master_taskloop_simd}};
+ OMPD_parallel_master_taskloop_simd},
+ {OMPD_parallel_masked_taskloop, OMPD_simd,
+ OMPD_parallel_masked_taskloop_simd}};
enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
Token Tok = P.getCurToken();
OpenMPDirectiveKindExWrapper DKind =
@@ -187,8 +200,8 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
if (DKind == OMPD_unknown)
return OMPD_unknown;
- for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
- if (DKind != F[I][0])
+ for (const auto &I : F) {
+ if (DKind != I[0])
continue;
Tok = P.getPreprocessor().LookAhead(0);
@@ -199,9 +212,9 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
if (SDKind == OMPD_unknown)
continue;
- if (SDKind == F[I][1]) {
+ if (SDKind == I[1]) {
P.ConsumeToken();
- DKind = F[I][2];
+ DKind = I[2];
}
}
return unsigned(DKind) < llvm::omp::Directive_enumSize
@@ -248,7 +261,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) {
case tok::identifier: // identifier
if (!WithOperator)
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
@@ -464,17 +477,16 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
T.consumeOpen();
ExprVector Exprs;
- CommaLocsTy CommaLocs;
SourceLocation LParLoc = T.getOpenLocation();
auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
- getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
- OmpPrivParm->getLocation(), Exprs, LParLoc);
+ OmpPrivParm->getType()->getCanonicalTypeInternal(),
+ OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
CalledSignatureHelp = true;
return PreferredType;
};
- if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ if (ParseExpressionList(Exprs, [&] {
PreferredType.enterFunctionArgument(Tok.getLocation(),
RunSignatureHelp);
})) {
@@ -488,9 +500,6 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
if (!T.consumeClose())
RLoc = T.getCloseLocation();
- assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
- "Unexpected number of commas!");
-
ExprResult Initializer =
Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
@@ -634,7 +643,7 @@ TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
// Parse the declarator.
DeclaratorContext Context = DeclaratorContext::Prototype;
- Declarator DeclaratorInfo(DS, Context);
+ Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
ParseDeclarator(DeclaratorInfo);
Range = DeclaratorInfo.getSourceRange();
if (DeclaratorInfo.getIdentifier() == nullptr) {
@@ -739,7 +748,7 @@ static bool parseDeclareSimdClauses(
OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
CKind == OMPC_linear) {
- Parser::OpenMPVarListDataTy Data;
+ Sema::OpenMPVarListDataTy Data;
SmallVectorImpl<Expr *> *Vars = &Uniforms;
if (CKind == OMPC_aligned) {
Vars = &Aligneds;
@@ -828,7 +837,7 @@ static StringRef stringLiteralParser(Parser &P) {
static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
OMPContextLvl Lvl) {
- if (Tok.is(tok::identifier)) {
+ if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
llvm::SmallString<16> Buffer;
StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
(void)P.ConsumeToken();
@@ -952,6 +961,10 @@ static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
TraitProperty::implementation_extension_allow_templates)
return true;
+ if (TIProperty.Kind ==
+ TraitProperty::implementation_extension_bind_to_declaration)
+ return true;
+
auto IsMatchExtension = [](OMPTraitProperty &TP) {
return (TP.Kind ==
llvm::omp::TraitProperty::implementation_extension_match_all ||
@@ -1402,26 +1415,129 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
ASTContext &ASTCtx = Actions.getASTContext();
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
- if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
- return;
+ SmallVector<Expr *, 6> AdjustNothing;
+ SmallVector<Expr *, 6> AdjustNeedDevicePtr;
+ SmallVector<OMPInteropInfo, 3> AppendArgs;
+ SourceLocation AdjustArgsLoc, AppendArgsLoc;
+
+ // At least one clause is required.
+ if (Tok.is(tok::annot_pragma_openmp_end)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
+ << (getLangOpts().OpenMP < 51 ? 0 : 1);
+ }
+
+ bool IsError = false;
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
+ getLangOpts().OpenMP)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
+ << (getLangOpts().OpenMP < 51 ? 0 : 1);
+ IsError = true;
+ }
+ if (!IsError) {
+ switch (CKind) {
+ case OMPC_match:
+ IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
+ break;
+ case OMPC_adjust_args: {
+ AdjustArgsLoc = Tok.getLocation();
+ ConsumeToken();
+ Sema::OpenMPVarListDataTy Data;
+ SmallVector<Expr *> Vars;
+ IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
+ Vars, Data);
+ if (!IsError)
+ llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
+ ? AdjustNothing
+ : AdjustNeedDevicePtr,
+ Vars);
+ break;
+ }
+ case OMPC_append_args:
+ if (!AppendArgs.empty()) {
+ Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(OMPD_declare_variant)
+ << getOpenMPClauseName(CKind) << 0;
+ IsError = true;
+ }
+ if (!IsError) {
+ AppendArgsLoc = Tok.getLocation();
+ ConsumeToken();
+ IsError = parseOpenMPAppendArgs(AppendArgs);
+ }
+ break;
+ default:
+ llvm_unreachable("Unexpected clause for declare variant.");
+ }
+ }
+ if (IsError) {
+ while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return;
+ }
+ // Skip ',' if any.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
- Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
+ std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
Actions.checkOpenMPDeclareVariantFunction(
- Ptr, AssociatedFunction.get(), TI,
+ Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
SourceRange(Loc, Tok.getLocation()));
- // Skip last tokens.
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
if (DeclVarData && !TI.Sets.empty())
Actions.ActOnOpenMPDeclareVariantDirective(
- DeclVarData->first, DeclVarData->second, TI,
+ DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
+ AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
SourceRange(Loc, Tok.getLocation()));
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
}
+bool Parser::parseOpenMPAppendArgs(
+ SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
+ bool HasError = false;
+ // Parse '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(OMPC_append_args).data()))
+ return true;
+
+ // Parse the list of append-ops, each is;
+ // interop(interop-type[,interop-type]...)
+ while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
+ ConsumeToken();
+ BalancedDelimiterTracker IT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
+ return true;
+
+ OMPInteropInfo InteropInfo;
+ if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
+ HasError = true;
+ else
+ InteropInfos.push_back(InteropInfo);
+
+ IT.consumeClose();
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
+ if (!HasError && InteropInfos.empty()) {
+ HasError = true;
+ Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
+ HasError = T.consumeClose() || HasError;
+ return HasError;
+}
+
bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
OMPTraitInfo &TI,
OMPTraitInfo *ParentTI) {
@@ -1431,24 +1547,15 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
: 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();
+ << (getLangOpts().OpenMP < 51 ? 0 : 1);
return true;
}
(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).data())) {
- while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
- ;
- // Skip the last annot_pragma_openmp_end.
- (void)ConsumeAnnotationToken();
+ getOpenMPClauseName(OMPC_match).data()))
return true;
- }
// Parse inner context selectors.
parseOMPContextSelectors(Loc, TI);
@@ -1518,6 +1625,42 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
return false;
}
+/// <clause> [clause[ [,] clause] ... ]
+///
+/// clauses: for error directive
+/// 'at' '(' compilation | execution ')'
+/// 'severity' '(' fatal | warning ')'
+/// 'message' '(' msg-string ')'
+/// ....
+void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
+ SmallVectorImpl<OMPClause *> &Clauses,
+ SourceLocation Loc) {
+ SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
+ llvm::omp::Clause_enumSize + 1>
+ FirstClauses(llvm::omp::Clause_enumSize + 1);
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ Actions.StartOpenMPClause(CKind);
+ OMPClause *Clause = ParseOpenMPClause(
+ DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
+ SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ FirstClauses[unsigned(CKind)].setInt(true);
+ if (Clause != nullptr)
+ Clauses.push_back(Clause);
+ if (Tok.is(tok::annot_pragma_openmp_end)) {
+ Actions.EndOpenMPClause();
+ break;
+ }
+ // Skip ',' if any.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ Actions.EndOpenMPClause();
+ }
+}
+
/// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
/// where
///
@@ -1532,7 +1675,7 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
///
void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
SourceLocation Loc) {
- SmallVector<StringRef, 4> Assumptions;
+ SmallVector<std::string, 4> Assumptions;
bool SkippedClauses = false;
auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
@@ -1599,9 +1742,11 @@ void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
}
assert(II && "Expected an identifier clause!");
- StringRef Assumption = II->getName();
+ std::string Assumption = II->getName().str();
if (ACMI.StartsWith)
- Assumption = Assumption.substr(ACMI.Identifier.size());
+ Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
+ else
+ Assumption = "omp_" + Assumption;
Assumptions.push_back(Assumption);
}
@@ -1618,7 +1763,7 @@ void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
-/// 'default' '(' 'none' | 'shared' | 'firstprivate' ')
+/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')
///
/// proc_bind-clause:
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
@@ -1638,7 +1783,7 @@ struct SimpleClauseData {
};
} // anonymous namespace
-static Optional<SimpleClauseData>
+static std::optional<SimpleClauseData>
parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
const Token &Tok = P.getCurToken();
SourceLocation Loc = Tok.getLocation();
@@ -1647,11 +1792,11 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(Kind).data()))
- return llvm::None;
+ return std::nullopt;
unsigned Type = getOpenMPSimpleClauseType(
Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
- P.getLangOpts().OpenMP);
+ P.getLangOpts());
SourceLocation TypeLoc = Tok.getLocation();
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
@@ -1668,50 +1813,81 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
void Parser::ParseOMPDeclareTargetClauses(
Sema::DeclareTargetContextInfo &DTCI) {
SourceLocation DeviceTypeLoc;
- bool RequiresToOrLinkClause = false;
- bool HasToOrLinkClause = false;
+ bool RequiresToOrLinkOrIndirectClause = false;
+ bool HasToOrLinkOrIndirectClause = false;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
bool HasIdentifier = Tok.is(tok::identifier);
if (HasIdentifier) {
// If we see any clause we need a to or link clause.
- RequiresToOrLinkClause = true;
+ RequiresToOrLinkOrIndirectClause = true;
IdentifierInfo *II = Tok.getIdentifierInfo();
StringRef ClauseName = II->getName();
bool IsDeviceTypeClause =
getLangOpts().OpenMP >= 50 &&
getOpenMPClauseKind(ClauseName) == OMPC_device_type;
- bool IsToOrLinkClause =
+ bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
+ getOpenMPClauseKind(ClauseName) == OMPC_indirect;
+ if (DTCI.Indirect && IsIndirectClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(OMPD_declare_target)
+ << getOpenMPClauseName(OMPC_indirect) << 0;
+ break;
+ }
+ bool IsToEnterOrLinkClause =
OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
- assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!");
+ assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
+ "Cannot be both!");
- if (!IsDeviceTypeClause && DTCI.Kind == OMPD_begin_declare_target) {
- Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName << 0;
+ // Starting with OpenMP 5.2 the `to` clause has been replaced by the
+ // `enter` clause.
+ if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
+ break;
+ }
+ if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
break;
}
- if (!IsDeviceTypeClause && !IsToOrLinkClause) {
+
+ if (!IsDeviceTypeClause && !IsIndirectClause &&
+ DTCI.Kind == OMPD_begin_declare_target) {
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName << (getLangOpts().OpenMP >= 50 ? 2 : 1);
+ << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
+ break;
+ }
+ if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
+ Diag(Tok, getLangOpts().OpenMP >= 52
+ ? diag::err_omp_declare_target_unexpected_clause_52
+ : diag::err_omp_declare_target_unexpected_clause)
+ << ClauseName
+ << (getLangOpts().OpenMP >= 51
+ ? 4
+ : getLangOpts().OpenMP >= 50 ? 2 : 1);
break;
}
- if (IsToOrLinkClause)
- HasToOrLinkClause = true;
+ if (IsToEnterOrLinkClause || IsIndirectClause)
+ HasToOrLinkOrIndirectClause = true;
+ if (IsIndirectClause) {
+ if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
+ break;
+ continue;
+ }
// Parse 'device_type' clause and go to next clause if any.
if (IsDeviceTypeClause) {
- Optional<SimpleClauseData> DevTypeData =
+ std::optional<SimpleClauseData> DevTypeData =
parseOpenMPSimpleClause(*this, OMPC_device_type);
- if (DevTypeData.hasValue()) {
+ if (DevTypeData) {
if (DeviceTypeLoc.isValid()) {
// We already saw another device_type clause, diagnose it.
- Diag(DevTypeData.getValue().Loc,
+ Diag(DevTypeData->Loc,
diag::warn_omp_more_one_device_type_clause);
break;
}
- switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
+ switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
case OMPC_DEVICE_TYPE_any:
DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
break;
@@ -1724,7 +1900,7 @@ void Parser::ParseOMPDeclareTargetClauses(
case OMPC_DEVICE_TYPE_unknown:
llvm_unreachable("Unexpected device_type");
}
- DeviceTypeLoc = DevTypeData.getValue().Loc;
+ DeviceTypeLoc = DevTypeData->Loc;
}
continue;
}
@@ -1756,7 +1932,9 @@ void Parser::ParseOMPDeclareTargetClauses(
}
if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok,
- diag::err_omp_declare_target_unexpected_clause_after_implicit_to);
+ getLangOpts().OpenMP >= 52
+ ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
+ : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
break;
}
@@ -1765,10 +1943,17 @@ void Parser::ParseOMPDeclareTargetClauses(
ConsumeToken();
}
+ if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
+ Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
+
// 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);
+ if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
+ !HasToOrLinkOrIndirectClause)
+ Diag(DTCI.Loc,
+ getLangOpts().OpenMP >= 52
+ ? diag::err_omp_declare_target_missing_enter_or_link_clause
+ : diag::err_omp_declare_target_missing_to_or_link_clause)
+ << (getLangOpts().OpenMP >= 51 ? 1 : 0);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
@@ -1855,7 +2040,7 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
/// annot_pragma_openmp_end
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
- AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
+ AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
DeclSpec::TST TagType, Decl *Tag) {
assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
"Not an OpenMP directive!");
@@ -1992,6 +2177,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ConsumeAnnotationToken();
return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
}
+ case OMPD_error: {
+ SmallVector<OMPClause *, 1> Clauses;
+ SourceLocation StartLoc = ConsumeToken();
+ ParseOpenMPClauses(DKind, Clauses, StartLoc);
+ Actions.ActOnOpenMPErrorDirective(Clauses, StartLoc, SourceLocation(),
+ /*InExContext = */ false);
+ break;
+ }
case OMPD_assumes:
case OMPD_begin_assumes:
ParseOpenMPAssumesDirective(DKind, ConsumeToken());
@@ -2027,8 +2220,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
ASTContext &ASTCtx = Actions.getASTContext();
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
- if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
+ if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
+ while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
break;
+ }
// Skip last tokens.
skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
@@ -2038,14 +2236,16 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
VariantMatchInfo VMI;
TI.getAsVariantMatchInfo(ASTCtx, VMI);
- std::function<void(StringRef)> DiagUnknownTrait = [this, Loc](
- StringRef ISATrait) {
- // TODO Track the selector locations in a way that is accessible here to
- // improve the diagnostic location.
- Diag(Loc, diag::warn_unknown_begin_declare_variant_isa_trait) << ISATrait;
- };
- TargetOMPContext OMPCtx(ASTCtx, std::move(DiagUnknownTrait),
- /* CurrentFunctionDecl */ nullptr);
+ std::function<void(StringRef)> DiagUnknownTrait =
+ [this, Loc](StringRef ISATrait) {
+ // TODO Track the selector locations in a way that is accessible here
+ // to improve the diagnostic location.
+ Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
+ };
+ TargetOMPContext OMPCtx(
+ ASTCtx, std::move(DiagUnknownTrait),
+ /* CurrentFunctionDecl */ nullptr,
+ /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>());
if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI);
@@ -2106,9 +2306,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
// Here we expect to see some function declaration.
if (AS == AS_none) {
assert(TagType == DeclSpec::TST_unspecified);
+ ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
MaybeParseCXX11Attributes(Attrs);
ParsingDeclSpec PDS(*this);
- Ptr = ParseExternalDeclaration(Attrs, &PDS);
+ Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
} else {
Ptr =
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
@@ -2130,11 +2331,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
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);
+ bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
+ !HasClauses ||
+ (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
// Skip the last annot_pragma_openmp_end.
ConsumeAnyToken();
@@ -2188,6 +2390,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_parallel_for_simd:
case OMPD_parallel_sections:
case OMPD_parallel_master:
+ case OMPD_parallel_masked:
case OMPD_atomic:
case OMPD_target:
case OMPD_teams:
@@ -2204,6 +2407,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_master_taskloop_simd:
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
+ case OMPD_masked_taskloop:
+ case OMPD_masked_taskloop_simd:
+ case OMPD_parallel_masked_taskloop:
+ case OMPD_parallel_masked_taskloop_simd:
case OMPD_distribute:
case OMPD_target_update:
case OMPD_distribute_parallel_for:
@@ -2211,6 +2418,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_distribute_simd:
case OMPD_target_parallel_for_simd:
case OMPD_target_simd:
+ case OMPD_scope:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
case OMPD_teams_distribute_parallel_for_simd:
@@ -2222,6 +2430,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_target_teams_distribute_simd:
case OMPD_dispatch:
case OMPD_masked:
+ case OMPD_metadirective:
+ case OMPD_loop:
+ case OMPD_teams_loop:
+ case OMPD_target_teams_loop:
+ case OMPD_parallel_loop:
+ case OMPD_target_parallel_loop:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
break;
@@ -2259,8 +2473,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
/// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
-/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
-/// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
+/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
+/// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
/// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
/// 'master taskloop' | 'master taskloop simd' | 'parallel master
/// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
@@ -2271,13 +2485,14 @@ 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' | 'masked' {clause}
-/// annot_pragma_openmp_end
+/// for simd' | 'target teams distribute simd' | 'masked' |
+/// 'parallel masked' {clause} annot_pragma_openmp_end
///
-StmtResult
-Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
- assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
- "Not an OpenMP directive!");
+StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
+ ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
+ if (!ReadDirectiveWithinMetadirective)
+ 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;
@@ -2286,8 +2501,15 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
FirstClauses(llvm::omp::Clause_enumSize + 1);
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
- SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
+ SourceLocation Loc = ReadDirectiveWithinMetadirective
+ ? Tok.getLocation()
+ : ConsumeAnnotationToken(),
+ EndLoc;
OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
+ if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
+ Diag(Tok, diag::err_omp_unknown_directive);
+ return StmtError();
+ }
OpenMPDirectiveKind CancelRegion = OMPD_unknown;
// Name of critical directive.
DeclarationNameInfo DirName;
@@ -2295,9 +2517,163 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
bool HasAssociatedStatement = true;
switch (DKind) {
+ case OMPD_nothing:
+ ConsumeToken();
+ // If we are parsing the directive within a metadirective, the directive
+ // ends with a ')'.
+ if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
+ while (Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ else
+ skipUntilPragmaOpenMPEnd(DKind);
+ if (Tok.is(tok::annot_pragma_openmp_end))
+ ConsumeAnnotationToken();
+ // return an empty statement
+ return StmtEmpty();
+ case OMPD_metadirective: {
+ ConsumeToken();
+ SmallVector<VariantMatchInfo, 4> VMIs;
+
+ // First iteration of parsing all clauses of metadirective.
+ // This iteration only parses and collects all context selector ignoring the
+ // associated directives.
+ TentativeParsingAction TPA(*this);
+ ASTContext &ASTContext = Actions.getASTContext();
+
+ BalancedDelimiterTracker T(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ SourceLocation Loc = ConsumeToken();
+
+ // Parse '('.
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(CKind).data()))
+ return Directive;
+
+ OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
+ if (CKind == OMPC_when) {
+ // parse and get OMPTraitInfo to pass to the When clause
+ parseOMPContextSelectors(Loc, TI);
+ if (TI.Sets.size() == 0) {
+ Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
+ TPA.Commit();
+ return Directive;
+ }
+
+ // Parse ':'
+ if (Tok.is(tok::colon))
+ ConsumeAnyToken();
+ else {
+ Diag(Tok, diag::err_omp_expected_colon) << "when clause";
+ TPA.Commit();
+ return Directive;
+ }
+ }
+ // Skip Directive for now. We will parse directive in the second iteration
+ int paren = 0;
+ while (Tok.isNot(tok::r_paren) || paren != 0) {
+ if (Tok.is(tok::l_paren))
+ paren++;
+ if (Tok.is(tok::r_paren))
+ paren--;
+ if (Tok.is(tok::annot_pragma_openmp_end)) {
+ Diag(Tok, diag::err_omp_expected_punc)
+ << getOpenMPClauseName(CKind) << 0;
+ TPA.Commit();
+ return Directive;
+ }
+ ConsumeAnyToken();
+ }
+ // Parse ')'
+ if (Tok.is(tok::r_paren))
+ T.consumeClose();
+
+ VariantMatchInfo VMI;
+ TI.getAsVariantMatchInfo(ASTContext, VMI);
+
+ VMIs.push_back(VMI);
+ }
+
+ TPA.Revert();
+ // End of the first iteration. Parser is reset to the start of metadirective
+
+ std::function<void(StringRef)> DiagUnknownTrait =
+ [this, Loc](StringRef ISATrait) {
+ // TODO Track the selector locations in a way that is accessible here
+ // to improve the diagnostic location.
+ Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
+ };
+ TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
+ /* CurrentFunctionDecl */ nullptr,
+ ArrayRef<llvm::omp::TraitProperty>());
+
+ // A single match is returned for OpenMP 5.0
+ int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
+
+ int Idx = 0;
+ // In OpenMP 5.0 metadirective is either replaced by another directive or
+ // ignored.
+ // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
+ // found by getBestWhenMatchForContext.
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ // OpenMP 5.0 implementation - Skip to the best index found.
+ if (Idx++ != BestIdx) {
+ ConsumeToken(); // Consume clause name
+ T.consumeOpen(); // Consume '('
+ int paren = 0;
+ // Skip everything inside the clause
+ while (Tok.isNot(tok::r_paren) || paren != 0) {
+ if (Tok.is(tok::l_paren))
+ paren++;
+ if (Tok.is(tok::r_paren))
+ paren--;
+ ConsumeAnyToken();
+ }
+ // Parse ')'
+ if (Tok.is(tok::r_paren))
+ T.consumeClose();
+ continue;
+ }
+
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ SourceLocation Loc = ConsumeToken();
+
+ // Parse '('.
+ T.consumeOpen();
+
+ // Skip ContextSelectors for when clause
+ if (CKind == OMPC_when) {
+ OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
+ // parse and skip the ContextSelectors
+ parseOMPContextSelectors(Loc, TI);
+
+ // Parse ':'
+ ConsumeAnyToken();
+ }
+
+ // If no directive is passed, skip in OpenMP 5.0.
+ // TODO: Generate nothing directive from OpenMP 5.1.
+ if (Tok.is(tok::r_paren)) {
+ SkipUntil(tok::annot_pragma_openmp_end);
+ break;
+ }
+
+ // Parse Directive
+ Directive = ParseOpenMPDeclarativeOrExecutableDirective(
+ StmtCtx,
+ /*ReadDirectiveWithinMetadirective=*/true);
+ break;
+ }
+ break;
+ }
case OMPD_threadprivate: {
// FIXME: Should this be permitted in C++?
- if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
+ if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
ParsedStmtContext()) {
Diag(Tok, diag::err_omp_immediate_directive)
<< getOpenMPDirectiveName(DKind) << 0;
@@ -2316,7 +2692,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
}
case OMPD_allocate: {
// FIXME: Should this be permitted in C++?
- if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
+ if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
ParsedStmtContext()) {
Diag(Tok, diag::err_omp_immediate_directive)
<< getOpenMPDirectiveName(DKind) << 0;
@@ -2387,6 +2763,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_depobj:
case OMPD_scan:
case OMPD_taskyield:
+ case OMPD_error:
case OMPD_barrier:
case OMPD_taskwait:
case OMPD_cancellation_point:
@@ -2399,10 +2776,14 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
ParsedStmtContext()) {
Diag(Tok, diag::err_omp_immediate_directive)
<< getOpenMPDirectiveName(DKind) << 0;
+ if (DKind == OMPD_error) {
+ SkipUntil(tok::annot_pragma_openmp_end);
+ break;
+ }
}
HasAssociatedStatement = false;
// Fall through for further analysis.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OMPD_parallel:
case OMPD_simd:
case OMPD_tile:
@@ -2418,6 +2799,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_parallel_for_simd:
case OMPD_parallel_sections:
case OMPD_parallel_master:
+ case OMPD_parallel_masked:
case OMPD_task:
case OMPD_ordered:
case OMPD_atomic:
@@ -2427,12 +2809,22 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_target_data:
case OMPD_target_parallel:
case OMPD_target_parallel_for:
+ case OMPD_loop:
+ case OMPD_teams_loop:
+ case OMPD_target_teams_loop:
+ case OMPD_parallel_loop:
+ case OMPD_target_parallel_loop:
+ case OMPD_scope:
case OMPD_taskloop:
case OMPD_taskloop_simd:
case OMPD_master_taskloop:
+ case OMPD_masked_taskloop:
case OMPD_master_taskloop_simd:
+ case OMPD_masked_taskloop_simd:
case OMPD_parallel_master_taskloop:
+ case OMPD_parallel_masked_taskloop:
case OMPD_parallel_master_taskloop_simd:
+ case OMPD_parallel_masked_taskloop_simd:
case OMPD_distribute:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
@@ -2486,6 +2878,13 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ // If we are parsing for a directive within a metadirective, the directive
+ // ends with a ')'.
+ if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
+ while (Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ break;
+ }
bool HasImplicitClause = false;
if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
HasImplicitClause = true;
@@ -2530,17 +2929,20 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
// Consume final annot_pragma_openmp_end.
ConsumeAnnotationToken();
- // OpenMP [2.13.8, ordered Construct, Syntax]
- // If the depend clause is specified, the ordered construct is a stand-alone
- // directive.
- if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) {
- if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
- ParsedStmtContext()) {
- Diag(Loc, diag::err_omp_immediate_directive)
- << getOpenMPDirectiveName(DKind) << 1
- << getOpenMPClauseName(OMPC_depend);
+ if (DKind == OMPD_ordered) {
+ // If the depend or doacross clause is specified, the ordered construct
+ // is a stand-alone directive.
+ for (auto CK : {OMPC_depend, OMPC_doacross}) {
+ if (FirstClauses[unsigned(CK)].getInt()) {
+ if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
+ ParsedStmtContext()) {
+ Diag(Loc, diag::err_omp_immediate_directive)
+ << getOpenMPDirectiveName(DKind) << 1
+ << getOpenMPClauseName(CK);
+ }
+ HasAssociatedStatement = false;
+ }
}
- HasAssociatedStatement = false;
}
if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) {
@@ -2562,15 +2964,14 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
getLangOpts().OpenMPIRBuilder)
- AssociatedStmt =
- Actions.ActOnOpenMPCanonicalLoop(AssociatedStmt.get());
+ AssociatedStmt = Actions.ActOnOpenMPLoopnest(AssociatedStmt.get());
}
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
} else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
DKind == OMPD_target_exit_data) {
Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
- Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
+ Actions.ActOnCompoundStmt(Loc, Loc, std::nullopt,
/*isStmtExpr=*/false));
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
}
@@ -2631,7 +3032,7 @@ bool Parser::ParseOpenMPSimpleVarList(
if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
- /*ObjectHadErrors=*/false, false)) {
+ /*ObjectHasErrors=*/false, false)) {
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
@@ -2710,8 +3111,13 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
return nullptr;
SmallVector<Sema::UsesAllocatorsData, 4> Data;
do {
+ CXXScopeSpec SS;
+ Token Replacement;
ExprResult Allocator =
- getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
+ getLangOpts().CPlusPlus
+ ? ParseCXXIdExpression()
+ : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
+ Replacement);
if (Allocator.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
@@ -2751,7 +3157,7 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
/// clause:
/// if-clause | final-clause | num_threads-clause | safelen-clause |
/// default-clause | private-clause | firstprivate-clause | shared-clause
-/// | linear-clause | aligned-clause | collapse-clause |
+/// | linear-clause | aligned-clause | collapse-clause | bind-clause |
/// lastprivate-clause | reduction-clause | proc_bind-clause |
/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
/// mergeable-clause | flush-clause | read-clause | write-clause |
@@ -2763,7 +3169,8 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
/// in_reduction-clause | allocator-clause | allocate-clause |
/// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
/// depobj-clause | destroy-clause | detach-clause | inclusive-clause |
-/// exclusive-clause | uses_allocators-clause | use_device_addr-clause
+/// exclusive-clause | uses_allocators-clause | use_device_addr-clause |
+/// has_device_addr
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -2800,6 +3207,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_nocontext:
case OMPC_filter:
case OMPC_partial:
+ case OMPC_align:
+ case OMPC_message:
+ case OMPC_ompx_dyn_cgroup_mem:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -2825,6 +3235,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// 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.
+ // OpenMP [5.1, error directive, Restrictions]
+ // At most one message clause can appear on the directive
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
@@ -2834,13 +3246,18 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
Clause = ParseOpenMPClause(CKind, WrongDirective);
+ else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
+ Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
else
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
break;
+ case OMPC_fail:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_atomic_default_mem_order:
- case OMPC_order:
+ case OMPC_at:
+ case OMPC_severity:
+ case OMPC_bind:
// OpenMP [2.14.3.1, Restrictions]
// Only a single default clause may be specified on a parallel, task or
// teams directive.
@@ -2849,7 +3266,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP [5.0, Requires directive, Restrictions]
// At most one atomic_default_mem_order clause can appear
// on the directive
- if (!FirstClause && CKind != OMPC_order) {
+ // OpenMP [5.1, error directive, Restrictions]
+ // At most one at clause can appear on the directive
+ // At most one severity clause can appear on the directive
+ // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
+ // At most one bind clause can appear on a loop directive.
+ if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
@@ -2861,19 +3283,22 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_schedule:
case OMPC_dist_schedule:
case OMPC_defaultmap:
+ case OMPC_order:
// OpenMP [2.7.1, Restrictions, p. 3]
// Only one schedule clause can appear on a loop directive.
// OpenMP 4.5 [2.10.4, Restrictions, p. 106]
// At most one defaultmap clause can appear on the directive.
// OpenMP 5.0 [2.12.5, target construct, Restrictions]
// At most one device clause can appear on the directive.
+ // OpenMP 5.1 [2.11.3, order clause, Restrictions]
+ // At most one order clause may appear on a construct.
if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
- !FirstClause) {
+ (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OMPC_if:
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
break;
@@ -2883,6 +3308,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_read:
case OMPC_write:
case OMPC_capture:
+ case OMPC_compare:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
@@ -2940,11 +3366,17 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_use_device_ptr:
case OMPC_use_device_addr:
case OMPC_is_device_ptr:
+ case OMPC_has_device_addr:
case OMPC_allocate:
case OMPC_nontemporal:
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_affinity:
+ case OMPC_doacross:
+ case OMPC_enter:
+ if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
+ CKind == OMPC_depend)
+ Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
break;
case OMPC_sizes:
@@ -2969,7 +3401,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
Clause = ParseOpenMPClause(CKind, WrongDirective);
break;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OMPC_init:
case OMPC_use:
Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
@@ -2986,6 +3418,20 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
+ case OMPC_ompx_attribute:
+ Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
+ break;
+ case OMPC_ompx_bare:
+ if (WrongDirective)
+ Diag(Tok, diag::note_ompx_bare_clause)
+ << getOpenMPClauseName(CKind) << "target teams";
+ if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
+ Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
+ << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ ErrorFound = true;
+ }
+ Clause = ParseOpenMPClause(CKind, WrongDirective);
+ break;
default:
break;
}
@@ -3054,6 +3500,9 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
/// detach-clause:
/// 'detach' '(' event-handler-expression ')'
///
+/// align-clause
+/// 'align' '(' positive-integer-constant ')'
+///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
bool ParseOnly) {
SourceLocation Loc = ConsumeToken();
@@ -3070,6 +3519,131 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
}
+/// Parse indirect clause for '#pragma omp declare target' directive.
+/// 'indirect' '[' '(' invoked-by-fptr ')' ']'
+/// where invoked-by-fptr is a constant boolean expression that evaluates to
+/// true or false at compile time.
+bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI,
+ bool ParseOnly) {
+ SourceLocation Loc = ConsumeToken();
+ SourceLocation RLoc;
+
+ if (Tok.isNot(tok::l_paren)) {
+ if (ParseOnly)
+ return false;
+ DTCI.Indirect = nullptr;
+ return true;
+ }
+
+ ExprResult Val =
+ ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
+ if (Val.isInvalid())
+ return false;
+
+ if (ParseOnly)
+ return false;
+
+ if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
+ !Val.get()->isInstantiationDependent() &&
+ !Val.get()->containsUnexpandedParameterPack()) {
+ ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
+ if (Ret.isInvalid())
+ return false;
+ llvm::APSInt Result;
+ Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
+ Sema::AllowFold);
+ if (Ret.isInvalid())
+ return false;
+ DTCI.Indirect = Val.get();
+ return true;
+ }
+ return false;
+}
+
+/// Parses a comma-separated list of interop-types and a prefer_type list.
+///
+bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
+ OpenMPClauseKind Kind) {
+ const Token &Tok = getCurToken();
+ bool HasError = false;
+ bool IsTarget = false;
+ bool IsTargetSync = false;
+
+ while (Tok.is(tok::identifier)) {
+ // Currently prefer_type is only allowed with 'init' and it must be first.
+ bool PreferTypeAllowed = Kind == OMPC_init &&
+ InteropInfo.PreferTypes.empty() && !IsTarget &&
+ !IsTargetSync;
+ if (Tok.getIdentifierInfo()->isStr("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;
+ ConsumeToken();
+ } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
+ if (IsTargetSync)
+ Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
+ IsTargetSync = true;
+ ConsumeToken();
+ } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
+ PreferTypeAllowed) {
+ ConsumeToken();
+ BalancedDelimiterTracker PT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
+ HasError = true;
+
+ 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()) {
+ InteropInfo.PreferTypes.push_back(PTExpr.get());
+ } else {
+ HasError = true;
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
+ PT.consumeClose();
+ } 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);
+ HasError = true;
+ }
+
+ if (Kind == OMPC_init) {
+ if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
+ Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
+ if (Tok.is(tok::colon))
+ ConsumeToken();
+ }
+
+ // As of OpenMP 5.1,there are two interop-types, "target" and
+ // "targetsync". Either or both are allowed for a single interop.
+ InteropInfo.IsTarget = IsTarget;
+ InteropInfo.IsTargetSync = IsTargetSync;
+
+ return HasError;
+}
+
/// Parsing of OpenMP clauses that use an interop-var.
///
/// init-clause:
@@ -3102,78 +3676,10 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
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";
- }
+ bool InteropError = false;
+ OMPInteropInfo InteropInfo;
+ if (Kind == OMPC_init)
+ InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
// Parse the variable.
SourceLocation VarLoc = Tok.getLocation();
@@ -3189,14 +3695,12 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
if (!T.consumeClose())
RLoc = T.getCloseLocation();
- if (ParseOnly || !InteropVarExpr.isUsable() ||
- (Kind == OMPC_init && !IsTarget && !IsTargetSync))
+ if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
return nullptr;
if (Kind == OMPC_init)
- return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget,
- IsTargetSync, Loc, T.getOpenLocation(),
- VarLoc, RLoc);
+ return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), InteropInfo, Loc,
+ T.getOpenLocation(), VarLoc, RLoc);
if (Kind == OMPC_use)
return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc,
T.getOpenLocation(), VarLoc, RLoc);
@@ -3208,33 +3712,98 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
llvm_unreachable("Unexpected interop variable clause.");
}
+OMPClause *Parser::ParseOpenMPOMPXAttributesClause(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(OMPC_ompx_attribute).data()))
+ return nullptr;
+
+ ParsedAttributes ParsedAttrs(AttrFactory);
+ ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
+
+ // Parse ')'.
+ if (T.consumeClose())
+ return nullptr;
+
+ if (ParseOnly)
+ return nullptr;
+
+ SmallVector<Attr *> Attrs;
+ for (const ParsedAttr &PA : ParsedAttrs) {
+ switch (PA.getKind()) {
+ case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
+ if (!PA.checkExactlyNumArgs(Actions, 2))
+ continue;
+ if (auto *A = Actions.CreateAMDGPUFlatWorkGroupSizeAttr(
+ PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
+ Attrs.push_back(A);
+ continue;
+ case ParsedAttr::AT_AMDGPUWavesPerEU:
+ if (!PA.checkAtLeastNumArgs(Actions, 1) ||
+ !PA.checkAtMostNumArgs(Actions, 2))
+ continue;
+ if (auto *A = Actions.CreateAMDGPUWavesPerEUAttr(
+ PA, PA.getArgAsExpr(0),
+ PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
+ Attrs.push_back(A);
+ continue;
+ case ParsedAttr::AT_CUDALaunchBounds:
+ if (!PA.checkAtLeastNumArgs(Actions, 1) ||
+ !PA.checkAtMostNumArgs(Actions, 2))
+ continue;
+ if (auto *A = Actions.CreateLaunchBoundsAttr(
+ PA, PA.getArgAsExpr(0),
+ PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
+ PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
+ Attrs.push_back(A);
+ continue;
+ default:
+ Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
+ continue;
+ };
+ }
+
+ return Actions.ActOnOpenMPXAttributeClause(Attrs, Loc, T.getOpenLocation(),
+ T.getCloseLocation());
+}
+
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
-/// 'default' '(' 'none' | 'shared' | 'firstprivate' ')'
+/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')'
///
/// proc_bind-clause:
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')'
///
+/// bind-clause:
+/// 'bind' '(' 'teams' | 'parallel' | 'thread' ')'
+///
/// update-clause:
-/// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')'
+/// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' |
+/// 'inoutset' ')'
///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
bool ParseOnly) {
- llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
+ std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
if (!Val || ParseOnly)
return nullptr;
if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
- static_cast<DefaultKind>(Val.getValue().Type) ==
- OMP_DEFAULT_firstprivate) {
- Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa)
- << getOpenMPClauseName(OMPC_firstprivate)
+ (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
+ static_cast<DefaultKind>(Val->Type) ==
+ OMP_DEFAULT_firstprivate)) {
+ Diag(Val->LOpen, diag::err_omp_invalid_dsa)
+ << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
+ OMP_DEFAULT_private
+ ? OMPC_private
+ : OMPC_firstprivate)
<< getOpenMPClauseName(OMPC_default) << "5.1";
return nullptr;
}
- return Actions.ActOnOpenMPSimpleClause(
- Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
- Val.getValue().Loc, Val.getValue().RLoc);
+ return Actions.ActOnOpenMPSimpleClause(Kind, Val->Type,
+ Val->TypeLoc, Val->LOpen,
+ Val->Loc, Val->RLoc);
}
/// Parsing of OpenMP clauses like 'ordered'.
@@ -3310,8 +3879,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
unsigned KindModifier = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
- getLangOpts().OpenMP);
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
if (KindModifier > OMPC_SCHEDULE_unknown) {
// Parse 'modifier'
Arg[Modifier1] = KindModifier;
@@ -3323,8 +3891,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
// Parse ',' 'modifier'
ConsumeAnyToken();
KindModifier = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
- getLangOpts().OpenMP);
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
? KindModifier
: (unsigned)OMPC_SCHEDULE_unknown;
@@ -3339,8 +3906,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
else
Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
KindModifier = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
- getLangOpts().OpenMP);
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
}
Arg[ScheduleKind] = KindModifier;
KLoc[ScheduleKind] = Tok.getLocation();
@@ -3354,8 +3920,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
DelimLoc = ConsumeAnyToken();
} else if (Kind == OMPC_dist_schedule) {
Arg.push_back(getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
- getLangOpts().OpenMP));
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
KLoc.push_back(Tok.getLocation());
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
@@ -3365,8 +3930,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
} else if (Kind == OMPC_defaultmap) {
// Get a defaultmap modifier
unsigned Modifier = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
- getLangOpts().OpenMP);
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
// Set defaultmap modifier to unknown if it is either scalar, aggregate, or
// pointer
if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
@@ -3384,8 +3948,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
// Get a defaultmap kind
Arg.push_back(getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
- getLangOpts().OpenMP));
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
KLoc.push_back(Tok.getLocation());
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
@@ -3394,14 +3957,41 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Arg.push_back(OMPC_DEFAULTMAP_unknown);
KLoc.push_back(SourceLocation());
}
+ } else if (Kind == OMPC_order) {
+ enum { Modifier, OrderKind, NumberOfElements };
+ Arg.resize(NumberOfElements);
+ KLoc.resize(NumberOfElements);
+ Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
+ Arg[OrderKind] = OMPC_ORDER_unknown;
+ unsigned KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ if (KindModifier > OMPC_ORDER_unknown) {
+ // Parse 'modifier'
+ Arg[Modifier] = KindModifier;
+ KLoc[Modifier] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ // Parse ':'
+ if (Tok.is(tok::colon))
+ ConsumeAnyToken();
+ else
+ Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
+ KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ }
+ Arg[OrderKind] = KindModifier;
+ KLoc[OrderKind] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
} else if (Kind == OMPC_device) {
// Only target executable directives support extended device construct.
if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
NextToken().is(tok::colon)) {
// Parse optional <device modifier> ':'
Arg.push_back(getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
- getLangOpts().OpenMP));
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
KLoc.push_back(Tok.getLocation());
ConsumeAnyToken();
// Parse ':'
@@ -3410,6 +4000,60 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Arg.push_back(OMPC_DEVICE_unknown);
KLoc.emplace_back();
}
+ } else if (Kind == OMPC_grainsize) {
+ // Parse optional <grainsize modifier> ':'
+ OpenMPGrainsizeClauseModifier Modifier =
+ static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
+ getLangOpts()));
+ if (getLangOpts().OpenMP >= 51) {
+ if (NextToken().is(tok::colon)) {
+ Arg.push_back(Modifier);
+ KLoc.push_back(Tok.getLocation());
+ // Parse modifier
+ ConsumeAnyToken();
+ // Parse ':'
+ ConsumeAnyToken();
+ } else {
+ if (Modifier == OMPC_GRAINSIZE_strict) {
+ Diag(Tok, diag::err_modifier_expected_colon) << "strict";
+ // Parse modifier
+ ConsumeAnyToken();
+ }
+ Arg.push_back(OMPC_GRAINSIZE_unknown);
+ KLoc.emplace_back();
+ }
+ } else {
+ Arg.push_back(OMPC_GRAINSIZE_unknown);
+ KLoc.emplace_back();
+ }
+ } else if (Kind == OMPC_num_tasks) {
+ // Parse optional <num_tasks modifier> ':'
+ OpenMPNumTasksClauseModifier Modifier =
+ static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
+ getLangOpts()));
+ if (getLangOpts().OpenMP >= 51) {
+ if (NextToken().is(tok::colon)) {
+ Arg.push_back(Modifier);
+ KLoc.push_back(Tok.getLocation());
+ // Parse modifier
+ ConsumeAnyToken();
+ // Parse ':'
+ ConsumeAnyToken();
+ } else {
+ if (Modifier == OMPC_NUMTASKS_strict) {
+ Diag(Tok, diag::err_modifier_expected_colon) << "strict";
+ // Parse modifier
+ ConsumeAnyToken();
+ }
+ Arg.push_back(OMPC_NUMTASKS_unknown);
+ KLoc.emplace_back();
+ }
+ } else {
+ Arg.push_back(OMPC_NUMTASKS_unknown);
+ KLoc.emplace_back();
+ }
} else {
assert(Kind == OMPC_if);
KLoc.push_back(Tok.getLocation());
@@ -3432,7 +4076,8 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
- Kind == OMPC_if || Kind == OMPC_device;
+ Kind == OMPC_if || Kind == OMPC_device ||
+ Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
if (NeedAnExpression) {
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
@@ -3512,12 +4157,12 @@ static OpenMPMapModifierKind isMapModifier(Parser &P) {
Preprocessor &PP = P.getPreprocessor();
OpenMPMapModifierKind TypeModifier =
static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
- OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP));
+ OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
return TypeModifier;
}
/// Parse the mapper modifier in map, to, and from clauses.
-bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
+bool Parser::parseMapperModifier(Sema::OpenMPVarListDataTy &Data) {
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
@@ -3529,7 +4174,7 @@ bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
if (getLangOpts().CPlusPlus)
ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
/*ObjectType=*/nullptr,
- /*ObjectHadErrors=*/false,
+ /*ObjectHasErrors=*/false,
/*EnteringContext=*/false);
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
@@ -3549,14 +4194,19 @@ bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
/// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
/// present
-bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
+bool Parser::parseMapTypeModifiers(Sema::OpenMPVarListDataTy &Data) {
while (getCurToken().isNot(tok::colon)) {
OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
if (TypeModifier == OMPC_MAP_MODIFIER_always ||
TypeModifier == OMPC_MAP_MODIFIER_close ||
- TypeModifier == OMPC_MAP_MODIFIER_present) {
+ TypeModifier == OMPC_MAP_MODIFIER_present ||
+ TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
Data.MapTypeModifiers.push_back(TypeModifier);
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
+ if (PP.LookAhead(0).isNot(tok::comma) &&
+ PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
+ Diag(Tok.getLocation(), diag::err_omp_missing_comma)
+ << "map type modifier";
ConsumeToken();
} else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
Data.MapTypeModifiers.push_back(TypeModifier);
@@ -3564,6 +4214,11 @@ bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
ConsumeToken();
if (parseMapperModifier(Data))
return true;
+ if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
+ getLangOpts().OpenMP >= 52)
+ Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
+ << "map type modifier";
+
} else {
// For the case of unknown map-type-modifier or a map-type.
// Map-type is followed by a colon; the function returns when it
@@ -3577,7 +4232,9 @@ bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
if (PP.LookAhead(0).is(tok::colon))
return false;
Diag(Tok, diag::err_omp_unknown_map_type_modifier)
- << (getLangOpts().OpenMP >= 51 ? 1 : 0);
+ << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
+ : 0)
+ << getLangOpts().OpenMPExtensions;
ConsumeToken();
}
if (getCurToken().is(tok::comma))
@@ -3596,14 +4253,14 @@ static OpenMPMapClauseKind isMapType(Parser &P) {
Preprocessor &PP = P.getPreprocessor();
OpenMPMapClauseKind MapType =
static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
- OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP));
+ OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
return MapType;
}
/// Parse map-type in map clause.
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
/// where, map-type ::= to | from | tofrom | alloc | release | delete
-static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
+static void parseMapType(Parser &P, Sema::OpenMPVarListDataTy &Data) {
Token Tok = P.getCurToken();
if (Tok.is(tok::colon)) {
P.Diag(Tok, diag::err_omp_map_type_missing);
@@ -3722,11 +4379,57 @@ ExprResult Parser::ParseOpenMPIteratorsExpr() {
Data);
}
+bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,
+ Sema::OpenMPVarListDataTy &Data,
+ const LangOptions &LangOpts) {
+ // Currently the only reserved locator is 'omp_all_memory' which is only
+ // allowed on a depend clause.
+ if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
+ return false;
+
+ if (Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
+
+ if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
+ Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
+ Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
+ else if (Data.ExtraModifier != OMPC_DEPEND_out &&
+ Data.ExtraModifier != OMPC_DEPEND_inout)
+ Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
+ else
+ Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
+ ? OMPC_DEPEND_outallmemory
+ : OMPC_DEPEND_inoutallmemory;
+ ConsumeToken();
+ return true;
+ }
+ return false;
+}
+
+/// Parse step size expression. Returns true if parsing is successfull,
+/// otherwise returns false.
+static bool parseStepSize(Parser &P, Sema::OpenMPVarListDataTy &Data,
+ OpenMPClauseKind CKind, SourceLocation ELoc) {
+ ExprResult Tail = P.ParseAssignmentExpression();
+ Sema &Actions = P.getActions();
+ Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
+ /*DiscardedValue*/ false);
+ if (Tail.isUsable()) {
+ Data.DepModOrTailExpr = Tail.get();
+ Token CurTok = P.getCurToken();
+ if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
+ P.Diag(CurTok, diag::err_expected_punc) << "step expression";
+ }
+ return true;
+ }
+ return false;
+}
+
/// Parses clauses with list.
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
OpenMPClauseKind Kind,
SmallVectorImpl<Expr *> &Vars,
- OpenMPVarListDataTy &Data) {
+ Sema::OpenMPVarListDataTy &Data) {
UnqualifiedId UnqualifiedReductionId;
bool InvalidReductionId = false;
bool IsInvalidMapperModifier = false;
@@ -3738,6 +4441,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
return true;
bool HasIterator = false;
+ bool InvalidIterator = false;
bool NeedRParenForLinear = false;
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
@@ -3749,8 +4453,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
(Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
NextToken().is(tok::comma)) {
// Parse optional reduction modifier.
- Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
- getLangOpts().OpenMP);
+ Data.ExtraModifier =
+ getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
Data.ExtraModifierLoc = Tok.getLocation();
ConsumeToken();
assert(Tok.is(tok::comma) && "Expected comma.");
@@ -3760,7 +4464,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (getLangOpts().CPlusPlus)
ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
/*ObjectType=*/nullptr,
- /*ObjectHadErrors=*/false,
+ /*ObjectHasErrors=*/false,
/*EnteringContext=*/false);
InvalidReductionId = ParseReductionId(
*this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
@@ -3775,7 +4479,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (!InvalidReductionId)
Data.ReductionOrMapperId =
Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
- } else if (Kind == OMPC_depend) {
+ } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
if (getLangOpts().OpenMP >= 50) {
if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
// Handle optional dependence modifier.
@@ -3796,15 +4500,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
ColonProtectionRAIIObject ColonRAII(*this);
Data.ExtraModifier = getOpenMPSimpleClauseType(
Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
- getLangOpts().OpenMP);
+ getLangOpts());
Data.ExtraModifierLoc = Tok.getLocation();
- if (Data.ExtraModifier == OMPC_DEPEND_unknown) {
+ if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
+ (Kind == OMPC_doacross &&
+ Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
} else {
ConsumeToken();
// Special processing for depend(source) clause.
- if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {
+ if (DKind == OMPD_ordered && Kind == OMPC_depend &&
+ Data.ExtraModifier == OMPC_DEPEND_source) {
// Parse ')'.
T.consumeClose();
return false;
@@ -3812,20 +4519,69 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
}
if (Tok.is(tok::colon)) {
Data.ColonLoc = ConsumeToken();
- } else {
+ } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
: diag::warn_pragma_expected_colon)
- << "dependency type";
+ << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
+ }
+ if (Kind == OMPC_doacross) {
+ if (Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
+ Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
+ ? OMPC_DOACROSS_source_omp_cur_iteration
+ : OMPC_DOACROSS_sink_omp_cur_iteration;
+ ConsumeToken();
+ }
+ if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
+ if (Tok.isNot(tok::minus)) {
+ Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
+ << getOpenMPClauseName(Kind) << 0 << 0;
+ SkipUntil(tok::r_paren);
+ return false;
+ } else {
+ ConsumeToken();
+ SourceLocation Loc = Tok.getLocation();
+ uint64_t Value = 0;
+ if (Tok.isNot(tok::numeric_constant) ||
+ (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
+ Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
+ << getOpenMPClauseName(Kind) << 0 << 0;
+ SkipUntil(tok::r_paren);
+ return false;
+ }
+ }
+ }
+ if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
+ << getOpenMPClauseName(Kind) << 1 << 1;
+ SkipUntil(tok::r_paren);
+ return false;
+ }
+ }
+ // Only the 'sink' case has the expression list.
+ if (Kind == OMPC_doacross &&
+ (Data.ExtraModifier == OMPC_DOACROSS_source ||
+ Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
+ Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
+ // Parse ')'.
+ T.consumeClose();
+ return false;
+ }
}
} else if (Kind == OMPC_linear) {
// Try to parse modifier if any.
Data.ExtraModifier = OMPC_LINEAR_val;
if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
- Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
- getLangOpts().OpenMP);
+ Data.ExtraModifier =
+ getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
Data.ExtraModifierLoc = ConsumeToken();
LinearT.consumeOpen();
NeedRParenForLinear = true;
+ if (getLangOpts().OpenMP >= 52)
+ Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
+ << "linear-modifier(list)" << getOpenMPClauseName(Kind)
+ << "linear(list: [linear-modifier,] step(step-size))";
}
} else if (Kind == OMPC_lastprivate) {
// Try to parse modifier if any.
@@ -3835,14 +4591,31 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
!isOpenMPTaskLoopDirective(DKind)) &&
Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
- Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
- getLangOpts().OpenMP);
+ Data.ExtraModifier =
+ getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
Data.ExtraModifierLoc = Tok.getLocation();
ConsumeToken();
assert(Tok.is(tok::colon) && "Expected colon.");
Data.ColonLoc = ConsumeToken();
}
} else if (Kind == OMPC_map) {
+ // Handle optional iterator map modifier.
+ if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
+ HasIterator = true;
+ EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
+ Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
+ Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
+ ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
+ Data.IteratorExpr = IteratorRes.get();
+ // Parse ','
+ ExpectAndConsume(tok::comma);
+ if (getLangOpts().OpenMP < 52) {
+ Diag(Tok, diag::err_omp_unknown_map_type_modifier)
+ << (getLangOpts().OpenMP >= 51 ? 1 : 0)
+ << getLangOpts().OpenMPExtensions;
+ InvalidIterator = true;
+ }
+ }
// Handle map type for map clause.
ColonProtectionRAIIObject ColonRAII(*this);
@@ -3872,6 +4645,12 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
}
if (Data.ExtraModifier == OMPC_MAP_unknown) {
Data.ExtraModifier = OMPC_MAP_tofrom;
+ if (getLangOpts().OpenMP >= 52) {
+ if (DKind == OMPD_target_enter_data)
+ Data.ExtraModifier = OMPC_MAP_to;
+ else if (DKind == OMPD_target_exit_data)
+ Data.ExtraModifier = OMPC_MAP_from;
+ }
Data.IsMapTypeImplicit = true;
}
@@ -3879,9 +4658,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.ColonLoc = ConsumeToken();
} else if (Kind == OMPC_to || Kind == OMPC_from) {
while (Tok.is(tok::identifier)) {
- auto Modifier =
- static_cast<OpenMPMotionModifierKind>(getOpenMPSimpleClauseType(
- Kind, PP.getSpelling(Tok), getLangOpts().OpenMP));
+ auto Modifier = static_cast<OpenMPMotionModifierKind>(
+ getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
if (Modifier == OMPC_MOTION_MODIFIER_unknown)
break;
Data.MotionModifiers.push_back(Modifier);
@@ -3951,27 +4729,50 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
}
+ } else if (Kind == OMPC_adjust_args) {
+ // Handle adjust-op for adjust_args clause.
+ ColonProtectionRAIIObject ColonRAII(*this);
+ Data.ExtraModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
+ getLangOpts());
+ Data.ExtraModifierLoc = Tok.getLocation();
+ if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
+ SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ } else {
+ ConsumeToken();
+ if (Tok.is(tok::colon))
+ Data.ColonLoc = Tok.getLocation();
+ ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
+ "adjust-op");
+ }
}
bool IsComma =
(Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
- Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
+ Kind != OMPC_in_reduction && Kind != OMPC_depend &&
+ Kind != OMPC_doacross && Kind != OMPC_map) ||
(Kind == OMPC_reduction && !InvalidReductionId) ||
(Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
- (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
+ (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
+ (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
+ (Kind == OMPC_adjust_args &&
+ Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
- // Parse variable
- ExprResult VarExpr =
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
- if (VarExpr.isUsable()) {
- Vars.push_back(VarExpr.get());
- } else {
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
+ if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {
+ // Parse variable
+ ExprResult VarExpr =
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ if (VarExpr.isUsable()) {
+ Vars.push_back(VarExpr.get());
+ } else {
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
}
// Skip ',' if any
IsComma = Tok.is(tok::comma);
@@ -3990,19 +4791,76 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (NeedRParenForLinear)
LinearT.consumeClose();
- // Parse ':' linear-step (or ':' alignment).
+ // Parse ':' linear modifiers (val, uval, ref or step(step-size))
+ // or parse ':' alignment.
const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
+ bool StepFound = false;
+ bool ModifierFound = false;
if (MustHaveTail) {
Data.ColonLoc = Tok.getLocation();
SourceLocation ELoc = ConsumeToken();
- ExprResult Tail = ParseAssignmentExpression();
- Tail =
- Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
- if (Tail.isUsable())
- Data.DepModOrTailExpr = Tail.get();
- else
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
+
+ if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
+ while (Tok.isNot(tok::r_paren)) {
+ if (Tok.is(tok::identifier)) {
+ // identifier could be a linear kind (val, uval, ref) or step
+ // modifier or step size
+ OpenMPLinearClauseKind LinKind =
+ static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
+ getLangOpts()));
+
+ if (LinKind == OMPC_LINEAR_step) {
+ if (StepFound)
+ Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
+
+ BalancedDelimiterTracker StepT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ SourceLocation StepModifierLoc = ConsumeToken();
+ // parse '('
+ if (StepT.consumeOpen())
+ Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
+
+ // parse step size expression
+ StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
+ if (StepFound)
+ Data.StepModifierLoc = StepModifierLoc;
+
+ // parse ')'
+ StepT.consumeClose();
+ } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
+ if (ModifierFound)
+ Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
+
+ Data.ExtraModifier = LinKind;
+ Data.ExtraModifierLoc = ConsumeToken();
+ ModifierFound = true;
+ } else {
+ StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
+ }
+ } else {
+ // parse an integer expression as step size
+ StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
+ }
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
+ break;
+ }
+ if (!StepFound && !ModifierFound)
+ Diag(ELoc, diag::err_expected_expression);
+ } else {
+ // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
+ ExprResult Tail = ParseAssignmentExpression();
+ Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
+ /*DiscardedValue*/ false);
+ if (Tail.isUsable())
+ Data.DepModOrTailExpr = Tail.get();
+ else
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
}
// Parse ')'.
@@ -4012,9 +4870,10 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
// Exit from scope when the iterator is used in depend clause.
if (HasIterator)
ExitScope();
- return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
- (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId ||
- IsInvalidMapperModifier;
+ return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
+ Vars.empty()) ||
+ (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
+ InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
}
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
@@ -4059,6 +4918,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/// 'use_device_addr' '(' list ')'
/// is_device_ptr-clause:
/// 'is_device_ptr' '(' list ')'
+/// has_device_addr-clause:
+/// 'has_device_addr' '(' list ')'
/// allocate-clause:
/// 'allocate' '(' [ allocator ':' ] list ')'
/// nontemporal-clause:
@@ -4078,7 +4939,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
SmallVector<Expr *, 4> Vars;
- OpenMPVarListDataTy Data;
+ Sema::OpenMPVarListDataTy Data;
if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
return nullptr;
@@ -4086,10 +4947,5 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
if (ParseOnly)
return nullptr;
OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
- return Actions.ActOnOpenMPVarListClause(
- Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc,
- Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
- Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
- Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers,
- Data.MotionModifiersLoc);
+ return Actions.ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
}