summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp377
1 files changed, 313 insertions, 64 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
index 0113a31..078f4c3 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
@@ -19,6 +19,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -32,15 +33,18 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
const OpenMPDirectiveKind F[][3] = {
{OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/,
OMPD_cancellation_point},
+ {OMPD_target, OMPD_unknown /*data*/, OMPD_target_data},
{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_sections, OMPD_parallel_sections}};
+ {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
+ {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}};
auto Tok = P.getCurToken();
auto DKind =
Tok.isAnnotation()
? OMPD_unknown
: getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
+
bool TokenMatched = false;
for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
@@ -50,18 +54,24 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
} else {
TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown;
}
+
if (TokenMatched) {
Tok = P.getPreprocessor().LookAhead(0);
+ auto TokenIsAnnotation = Tok.isAnnotation();
auto SDKind =
- Tok.isAnnotation()
+ TokenIsAnnotation
? OMPD_unknown
: getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
- if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
+
+ if (!TokenIsAnnotation && SDKind == OMPD_unknown) {
TokenMatched =
- (i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point");
+ ((i == 0) &&
+ !P.getPreprocessor().getSpelling(Tok).compare("point")) ||
+ ((i == 1) && !P.getPreprocessor().getSpelling(Tok).compare("data"));
} else {
TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown;
}
+
if (TokenMatched) {
P.ConsumeToken();
DKind = F[i][2];
@@ -127,6 +137,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
case OMPD_teams:
case OMPD_cancellation_point:
case OMPD_cancel:
+ case OMPD_target_data:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_distribute:
Diag(Tok, diag::err_omp_unexpected_directive)
<< getOpenMPDirectiveName(DKind);
break;
@@ -146,8 +160,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
-/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup'
-/// {clause}
+/// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
+/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' {clause} |
+/// 'distribute'
/// annot_pragma_openmp_end
///
StmtResult
@@ -200,7 +215,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
case OMPD_cancel:
if (!StandAloneAllowed) {
Diag(Tok, diag::err_omp_immediate_directive)
- << getOpenMPDirectiveName(DKind);
+ << getOpenMPDirectiveName(DKind) << 0;
}
HasAssociatedStatement = false;
// Fall through for further analysis.
@@ -221,7 +236,11 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
case OMPD_atomic:
case OMPD_target:
case OMPD_teams:
- case OMPD_taskgroup: {
+ case OMPD_taskgroup:
+ case OMPD_target_data:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_distribute: {
ConsumeToken();
// Parse directive name of the 'critical' directive if any.
if (DKind == OMPD_critical) {
@@ -276,8 +295,19 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
// Consume final annot_pragma_openmp_end.
ConsumeToken();
+ // 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[OMPC_depend].getInt()) {
+ if (!StandAloneAllowed) {
+ Diag(Loc, diag::err_omp_immediate_directive)
+ << getOpenMPDirectiveName(DKind) << 1
+ << getOpenMPClauseName(OMPC_depend);
+ }
+ HasAssociatedStatement = false;
+ }
+
StmtResult AssociatedStmt;
- bool CreateDirective = true;
if (HasAssociatedStatement) {
// The body is a block scope like in Lambdas and Blocks.
Sema::CompoundScopeRAII CompoundScope(Actions);
@@ -287,12 +317,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
AssociatedStmt = ParseStatement();
Actions.ActOnFinishOfCompoundStmt();
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
- CreateDirective = AssociatedStmt.isUsable();
}
- if (CreateDirective)
- Directive = Actions.ActOnOpenMPExecutableDirective(
- DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
- EndLoc);
+ Directive = Actions.ActOnOpenMPExecutableDirective(
+ DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
+ EndLoc);
// Exit scope.
Actions.EndOpenMPDSABlock(Directive.get());
@@ -385,7 +413,10 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// lastprivate-clause | reduction-clause | proc_bind-clause |
/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
/// mergeable-clause | flush-clause | read-clause | write-clause |
-/// update-clause | capture-clause | seq_cst-clause
+/// update-clause | capture-clause | seq_cst-clause | device-clause |
+/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
+/// thread_limit-clause | priority-clause | grainsize-clause |
+/// nogroup-clause | num_tasks-clause | hint-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -399,27 +430,49 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
}
switch (CKind) {
- case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
+ case OMPC_ordered:
+ case OMPC_device:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_num_tasks:
+ case OMPC_hint:
// OpenMP [2.5, Restrictions]
- // At most one if clause can appear on the directive.
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
// Only one safelen clause can appear on a simd directive.
+ // Only one simdlen clause can appear on a simd directive.
// Only one collapse clause can appear on a simd directive.
+ // OpenMP [2.9.1, target data construct, Restrictions]
+ // At most one device clause can appear on the directive.
// OpenMP [2.11.1, task Construct, Restrictions]
// At most one if clause can appear on the directive.
// At most one final clause can appear on the directive.
+ // OpenMP [teams Construct, Restrictions]
+ // At most one num_teams clause can appear on the directive.
+ // At most one thread_limit clause can appear on the directive.
+ // OpenMP [2.9.1, task Construct, Restrictions]
+ // At most one priority clause can appear on the directive.
+ // OpenMP [2.9.2, taskloop Construct, Restrictions]
+ // At most one grainsize clause can appear on the directive.
+ // OpenMP [2.9.2, taskloop Construct, Restrictions]
+ // At most one num_tasks clause can appear on the directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
- Clause = ParseOpenMPSingleExprClause(CKind);
+ if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
+ Clause = ParseOpenMPClause(CKind);
+ else
+ Clause = ParseOpenMPSingleExprClause(CKind);
break;
case OMPC_default:
case OMPC_proc_bind:
@@ -429,8 +482,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP [2.5, parallel Construct, Restrictions]
// At most one proc_bind clause can appear on the directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
@@ -440,14 +493,14 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP [2.7.1, Restrictions, p. 3]
// Only one schedule clause can appear on a loop directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
+ case OMPC_if:
Clause = ParseOpenMPSingleExprWithArgClause(CKind);
break;
- case OMPC_ordered:
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
@@ -456,13 +509,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_nogroup:
// OpenMP [2.7.1, Restrictions, p. 9]
// Only one ordered clause can appear on a loop directive.
// OpenMP [2.7.1, Restrictions, C/C++, p. 4]
// Only one nowait clause can appear on a for directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
@@ -479,7 +535,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_copyprivate:
case OMPC_flush:
case OMPC_depend:
- Clause = ParseOpenMPVarListClause(CKind);
+ case OMPC_map:
+ Clause = ParseOpenMPVarListClause(DKind, CKind);
break;
case OMPC_unknown:
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
@@ -495,12 +552,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
return ErrorFound ? nullptr : Clause;
}
-/// \brief Parsing of OpenMP clauses with single expressions like 'if',
-/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
-/// 'thread_limit'.
-///
-/// if-clause:
-/// 'if' '(' expression ')'
+/// \brief Parsing of OpenMP clauses with single expressions like 'final',
+/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
+/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
///
/// final-clause:
/// 'final' '(' expression ')'
@@ -511,9 +565,24 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
/// safelen-clause:
/// 'safelen' '(' expression ')'
///
+/// simdlen-clause:
+/// 'simdlen' '(' expression ')'
+///
/// collapse-clause:
/// 'collapse' '(' expression ')'
///
+/// priority-clause:
+/// 'priority' '(' expression ')'
+///
+/// grainsize-clause:
+/// 'grainsize' '(' expression ')'
+///
+/// num_tasks-clause:
+/// 'num_tasks' '(' expression ')'
+///
+/// hint-clause:
+/// 'hint' '(' expression ')'
+///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
SourceLocation Loc = ConsumeToken();
@@ -522,8 +591,10 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
getOpenMPClauseName(Kind)))
return nullptr;
+ SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
// Parse ')'.
T.consumeClose();
@@ -583,6 +654,15 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
/// read-clause:
/// 'read'
///
+/// threads-clause:
+/// 'threads'
+///
+/// simd-clause:
+/// 'simd'
+///
+/// nogroup-clause:
+/// 'nogroup'
+///
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
ConsumeAnyToken();
@@ -595,11 +675,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
/// argument like 'schedule' or 'dist_schedule'.
///
/// schedule-clause:
-/// 'schedule' '(' kind [',' expression ] ')'
+/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
+/// ')'
+///
+/// if-clause:
+/// 'if' '(' [ directive-name-modifier ':' ] expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
SourceLocation Loc = ConsumeToken();
- SourceLocation CommaLoc;
+ SourceLocation DelimLoc;
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
@@ -607,29 +691,86 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
return nullptr;
ExprResult Val;
- unsigned Type = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
- SourceLocation KLoc = Tok.getLocation();
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
+ SmallVector<unsigned, 4> Arg;
+ SmallVector<SourceLocation, 4> KLoc;
+ if (Kind == OMPC_schedule) {
+ enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
+ Arg.resize(NumberOfElements);
+ KLoc.resize(NumberOfElements);
+ Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
+ Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
+ Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
+ auto KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ if (KindModifier > OMPC_SCHEDULE_unknown) {
+ // Parse 'modifier'
+ Arg[Modifier1] = KindModifier;
+ KLoc[Modifier1] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ if (Tok.is(tok::comma)) {
+ // Parse ',' 'modifier'
+ ConsumeAnyToken();
+ KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
+ ? KindModifier
+ : (unsigned)OMPC_SCHEDULE_unknown;
+ KLoc[Modifier2] = 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) << "schedule modifier";
+ KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ }
+ Arg[ScheduleKind] = KindModifier;
+ KLoc[ScheduleKind] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
+ Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
+ Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
+ Tok.is(tok::comma))
+ DelimLoc = ConsumeAnyToken();
+ } else {
+ assert(Kind == OMPC_if);
+ KLoc.push_back(Tok.getLocation());
+ Arg.push_back(ParseOpenMPDirectiveKind(*this));
+ if (Arg.back() != OMPD_unknown) {
+ ConsumeToken();
+ if (Tok.is(tok::colon))
+ DelimLoc = ConsumeToken();
+ else
+ Diag(Tok, diag::warn_pragma_expected_colon)
+ << "directive name modifier";
+ }
+ }
- if (Kind == OMPC_schedule &&
- (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
- Type == OMPC_SCHEDULE_guided) &&
- Tok.is(tok::comma)) {
- CommaLoc = ConsumeAnyToken();
+ bool NeedAnExpression =
+ (Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if;
+ if (NeedAnExpression) {
+ SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
- if (Val.isInvalid())
- return nullptr;
+ Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
}
// Parse ')'.
T.consumeClose();
+ if (NeedAnExpression && Val.isInvalid())
+ return nullptr;
+
return Actions.ActOnOpenMPSingleExprWithArgClause(
- Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
+ Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
T.getCloseLocation());
}
@@ -691,7 +832,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
/// shared-clause:
/// 'shared' '(' list ')'
/// linear-clause:
-/// 'linear' '(' list [ ':' linear-step ] ')'
+/// 'linear' '(' linear-list [ ':' linear-step ] ')'
/// aligned-clause:
/// 'aligned' '(' list [ ':' alignment ] ')'
/// reduction-clause:
@@ -701,9 +842,17 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
/// flush-clause:
/// 'flush' '(' list ')'
/// depend-clause:
-/// 'depend' '(' in | out | inout : list ')'
+/// 'depend' '(' in | out | inout : list | source ')'
+/// map-clause:
+/// 'map' '(' [ [ always , ]
+/// to | from | tofrom | alloc | release | delete ':' ] list ')';
///
-OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
+/// For 'linear' clause linear-list may have the following forms:
+/// list
+/// modifier(list)
+/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
+OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
SourceLocation ColonLoc = SourceLocation();
@@ -712,7 +861,14 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
UnqualifiedId ReductionId;
bool InvalidReductionId = false;
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
- SourceLocation DepLoc;
+ // OpenMP 4.1 [2.15.3.7, linear Clause]
+ // If no modifier is specified it is assumed to be val.
+ OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val;
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
+ OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+ bool MapTypeModifierSpecified = false;
+ bool UnexpectedId = false;
+ SourceLocation DepLinMapLoc;
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
@@ -720,6 +876,9 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
getOpenMPClauseName(Kind)))
return nullptr;
+ bool NeedRParenForLinear = false;
+ BalancedDelimiterTracker LinearT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
// Handle reduction-identifier for reduction clause.
if (Kind == OMPC_reduction) {
ColonProtectionRAIIObject ColonRAII(*this);
@@ -742,25 +901,109 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
ColonProtectionRAIIObject ColonRAII(*this);
DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
- DepLoc = Tok.getLocation();
+ DepLinMapLoc = Tok.getLocation();
if (DepKind == OMPC_DEPEND_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 && DepKind == OMPC_DEPEND_source) {
+ // Parse ')'.
+ T.consumeClose();
+ return Actions.ActOnOpenMPVarListClause(
+ Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen,
+ /*ColonLoc=*/SourceLocation(), Tok.getLocation(),
+ ReductionIdScopeSpec, DeclarationNameInfo(), DepKind,
+ LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
+ }
}
if (Tok.is(tok::colon)) {
ColonLoc = ConsumeToken();
} else {
- Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
+ Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
+ : diag::warn_pragma_expected_colon)
+ << "dependency type";
+ }
+ } else if (Kind == OMPC_linear) {
+ // Try to parse modifier if any.
+ if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
+ LinearModifier = static_cast<OpenMPLinearClauseKind>(
+ getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
+ DepLinMapLoc = ConsumeToken();
+ LinearT.consumeOpen();
+ NeedRParenForLinear = true;
+ }
+ } else if (Kind == OMPC_map) {
+ // Handle map type for map clause.
+ ColonProtectionRAIIObject ColonRAII(*this);
+
+ // the first identifier may be a list item, a map-type or
+ // a map-type-modifier
+ MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ DepLinMapLoc = Tok.getLocation();
+ bool ColonExpected = false;
+
+ if (Tok.is(tok::identifier)) {
+ if (PP.LookAhead(0).is(tok::colon)) {
+ MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ if (MapType == OMPC_MAP_unknown) {
+ Diag(Tok, diag::err_omp_unknown_map_type);
+ } else if (MapType == OMPC_MAP_always) {
+ Diag(Tok, diag::err_omp_map_type_missing);
+ }
+ ConsumeToken();
+ } else if (PP.LookAhead(0).is(tok::comma)) {
+ if (PP.LookAhead(1).is(tok::identifier) &&
+ PP.LookAhead(2).is(tok::colon)) {
+ MapTypeModifier =
+ static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ if (MapTypeModifier != OMPC_MAP_always) {
+ Diag(Tok, diag::err_omp_unknown_map_type_modifier);
+ MapTypeModifier = OMPC_MAP_unknown;
+ } else {
+ MapTypeModifierSpecified = true;
+ }
+
+ ConsumeToken();
+ ConsumeToken();
+
+ MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) {
+ Diag(Tok, diag::err_omp_unknown_map_type);
+ }
+ ConsumeToken();
+ } else {
+ MapType = OMPC_MAP_tofrom;
+ }
+ } else {
+ MapType = OMPC_MAP_tofrom;
+ }
+ } else {
+ UnexpectedId = true;
+ }
+
+ if (Tok.is(tok::colon)) {
+ ColonLoc = ConsumeToken();
+ } else if (ColonExpected) {
+ Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
}
}
SmallVector<Expr *, 5> Vars;
- bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
- ((Kind == OMPC_reduction) && !InvalidReductionId) ||
- ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
+ bool IsComma =
+ ((Kind != OMPC_reduction) && (Kind != OMPC_depend) &&
+ (Kind != OMPC_map)) ||
+ ((Kind == OMPC_reduction) && !InvalidReductionId) ||
+ ((Kind == OMPC_map) && (UnexpectedId || MapType != OMPC_MAP_unknown) &&
+ (!MapTypeModifierSpecified ||
+ (MapTypeModifierSpecified && MapTypeModifier == OMPC_MAP_always))) ||
+ ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_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))) {
@@ -787,14 +1030,18 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
<< (Kind == OMPC_flush);
}
+ // Parse ')' for linear clause with modifier.
+ if (NeedRParenForLinear)
+ LinearT.consumeClose();
+
// Parse ':' linear-step (or ':' alignment).
Expr *TailExpr = nullptr;
const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
if (MustHaveTail) {
ColonLoc = Tok.getLocation();
- ConsumeToken();
- ExprResult Tail =
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ SourceLocation ELoc = ConsumeToken();
+ ExprResult Tail = ParseAssignmentExpression();
+ Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
if (Tail.isUsable())
TailExpr = Tail.get();
else
@@ -806,14 +1053,16 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
T.consumeClose();
if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
(Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
- InvalidReductionId)
+ (Kind == OMPC_map && MapType == OMPC_MAP_unknown) ||
+ InvalidReductionId) {
return nullptr;
+ }
return Actions.ActOnOpenMPVarListClause(
Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
ReductionIdScopeSpec,
ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
: DeclarationNameInfo(),
- DepKind, DepLoc);
+ DepKind, LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
}
OpenPOWER on IntegriCloud