[OPENMP 4.1] Parsing/sema analysis for extended format of 'if' clause.

OpenMP 4.1 added special 'directive-name-modifier' to the 'if' clause.
Format of 'if' clause is as follows:
```
if([ directive-name-modifier :] scalar-logical-expression)
```

The restriction rules are also changed.
1. If any 'if' clause on the directive includes a 'directive-name-modifier' then all 'if' clauses on the directive must include a 'directive-name-modifier'.
2. At most one 'if' clause without a 'directive-name-modifier' can appear on the directive.
3. At most one 'if' clause with some particular 'directive-name-modifier' can appear on the directive.

'directive-name-modifier' is important for combined directives and allows to separate conditions in 'if' clause for simple sub-directives in combined directive. This 'directive-name-modifier' identifies the sub-directive to which this 'if' clause must be applied.

llvm-svn: 246747
This commit is contained in:
Alexey Bataev 2015-09-03 07:23:48 +00:00
parent 49948af9cd
commit 6b8046addf
22 changed files with 470 additions and 99 deletions

View File

@ -152,10 +152,10 @@ public:
/// \brief This represents 'if' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp parallel if(a > 5)
/// #pragma omp parallel if(parallel:a > 5)
/// \endcode
/// In this example directive '#pragma omp parallel' has simple 'if'
/// clause with condition 'a > 5'.
/// In this example directive '#pragma omp parallel' has simple 'if' clause with
/// condition 'a > 5' and directive name modifier 'parallel'.
///
class OMPIfClause : public OMPClause {
friend class OMPClauseReader;
@ -163,37 +163,67 @@ class OMPIfClause : public OMPClause {
SourceLocation LParenLoc;
/// \brief Condition of the 'if' clause.
Stmt *Condition;
/// \brief Location of ':' (if any).
SourceLocation ColonLoc;
/// \brief Directive name modifier for the clause.
OpenMPDirectiveKind NameModifier;
/// \brief Name modifier location.
SourceLocation NameModifierLoc;
/// \brief Set condition.
///
void setCondition(Expr *Cond) { Condition = Cond; }
/// \brief Set directive name modifier for the clause.
///
void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; }
/// \brief Set location of directive name modifier for the clause.
///
void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; }
/// \brief Set location of ':'.
///
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
/// \brief Build 'if' clause with condition \a Cond.
///
/// \param NameModifier [OpenMP 4.1] Directive name modifier of clause.
/// \param Cond Condition of the clause.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param Cond Condition of the clause.
/// \param NameModifierLoc Location of directive name modifier.
/// \param ColonLoc [OpenMP 4.1] Location of ':'.
/// \param EndLoc Ending location of the clause.
///
OMPIfClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation NameModifierLoc, SourceLocation ColonLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc),
Condition(Cond) {}
Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier),
NameModifierLoc(NameModifierLoc) {}
/// \brief Build an empty clause.
///
OMPIfClause()
: OMPClause(OMPC_if, SourceLocation(), SourceLocation()),
LParenLoc(SourceLocation()), Condition(nullptr) {}
: OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(),
Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown),
NameModifierLoc() {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
/// \brief Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
/// \brief Return directive name modifier associated with the clause.
OpenMPDirectiveKind getNameModifier() const { return NameModifier; }
/// \brief Return the location of directive name modifier.
SourceLocation getNameModifierLoc() const { return NameModifierLoc; }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_if;

View File

@ -211,4 +211,7 @@ def note_mt_message : Note<"[rewriter] %0">;
def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">;
def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">;
// OpenMP
def err_omp_more_one_clause : Error<
"directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier}2">;
}

View File

@ -987,8 +987,6 @@ def err_omp_expected_punc : Error<
"expected ',' or ')' in '%0' %select{clause|directive}1">;
def err_omp_unexpected_clause : Error<
"unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;
def err_omp_more_one_clause : Error<
"directive '#pragma omp %0' cannot contain more than one '%1' clause">;
def err_omp_immediate_directive : Error<
"'#pragma omp %0' cannot be an immediate substatement">;
def err_omp_expected_identifier_for_critical : Error<

View File

@ -7694,6 +7694,14 @@ def err_omp_wrong_linear_modifier_non_reference : Error<
"variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">;
def err_omp_wrong_simdlen_safelen_values : Error<
"the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter">;
def err_omp_wrong_if_directive_name_modifier : Error<
"directive name modifier '%0' is not allowed for '#pragma omp %1'">;
def err_omp_no_more_if_clause : Error<
"no more 'if' clause is allowed">;
def err_omp_unnamed_if_clause : Error<
"expected %select{|one of}0 %1 directive name modifier%select{|s}0">;
def note_omp_previous_named_if_clause : Note<
"previous clause with directive name modifier specified here">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {

View File

@ -7889,8 +7889,11 @@ public:
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'if' clause.
OMPClause *ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation NameModifierLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'final' clause.
OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc,
@ -7945,7 +7948,7 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation ArgumentLoc,
SourceLocation CommaLoc,
SourceLocation DelimLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'schedule' clause.
OMPClause *ActOnOpenMPScheduleClause(OpenMPScheduleClauseKind Kind,

View File

@ -602,6 +602,8 @@ public:
void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << "if(";
if (Node->getNameModifier() != OMPD_unknown)
OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": ";
Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}

View File

@ -288,7 +288,6 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
ConsumeToken();
StmtResult AssociatedStmt;
bool CreateDirective = true;
if (HasAssociatedStatement) {
// The body is a block scope like in Lambdas and Blocks.
Sema::CompoundScopeRAII CompoundScope(Actions);
@ -298,12 +297,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());
@ -411,7 +408,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
}
switch (CKind) {
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
@ -420,7 +416,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_ordered:
case OMPC_device:
// 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.
@ -432,8 +427,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// At most one if clause can appear on the directive.
// At most one final 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;
}
@ -450,8 +445,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;
}
@ -461,11 +456,12 @@ 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_nowait:
@ -481,8 +477,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// 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;
}
@ -515,12 +511,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',
/// 'thread_limit' or 'simdlen'.
///
/// if-clause:
/// 'if' '(' expression ')'
/// \brief Parsing of OpenMP clauses with single expressions like 'final',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 'thread_limit'
/// or 'simdlen'.
///
/// final-clause:
/// 'final' '(' expression ')'
@ -545,8 +538,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();
@ -620,9 +615,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
/// schedule-clause:
/// 'schedule' '(' 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,
@ -630,29 +628,50 @@ 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();
unsigned Arg;
SourceLocation KLoc;
if (Kind == OMPC_schedule) {
Arg = getOpenMPSimpleClauseType(
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
KLoc = Tok.getLocation();
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
if ((Arg == OMPC_SCHEDULE_static || Arg == OMPC_SCHEDULE_dynamic ||
Arg == OMPC_SCHEDULE_guided) &&
Tok.is(tok::comma))
DelimLoc = ConsumeAnyToken();
} else {
assert(Kind == OMPC_if);
KLoc = Tok.getLocation();
Arg = ParseOpenMPDirectiveKind(*this);
if (Arg != 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());
}
@ -838,9 +857,9 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
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

View File

@ -1985,6 +1985,82 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
return false;
}
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
ArrayRef<OMPClause *> Clauses,
ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
bool ErrorFound = false;
unsigned NamedModifiersNumber = 0;
SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers(
OMPD_unknown + 1);
for (const auto *C : Clauses) {
if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
// At most one if clause without a directive-name-modifier can appear on
// the directive.
OpenMPDirectiveKind CurNM = IC->getNameModifier();
if (FoundNameModifiers[CurNM]) {
S.Diag(C->getLocStart(), diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
<< (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
ErrorFound = true;
} else if (CurNM != OMPD_unknown)
++NamedModifiersNumber;
FoundNameModifiers[CurNM] = IC;
if (CurNM == OMPD_unknown)
continue;
// Check if the specified name modifier is allowed for the current
// directive.
// At most one if clause with the particular directive-name-modifier can
// appear on the directive.
bool MatchFound = false;
for (auto NM : AllowedNameModifiers) {
if (CurNM == NM) {
MatchFound = true;
break;
}
}
if (!MatchFound) {
S.Diag(IC->getNameModifierLoc(),
diag::err_omp_wrong_if_directive_name_modifier)
<< getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
ErrorFound = true;
}
}
}
// If any if clause on the directive includes a directive-name-modifier then
// all if clauses on the directive must include a directive-name-modifier.
if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
if (NamedModifiersNumber == AllowedNameModifiers.size()) {
S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(),
diag::err_omp_no_more_if_clause);
} else {
std::string Values;
std::string Sep(", ");
unsigned AllowedCnt = 0;
unsigned TotalAllowedNum =
AllowedNameModifiers.size() - NamedModifiersNumber;
for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
++Cnt) {
OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
if (!FoundNameModifiers[NM]) {
Values += "'";
Values += getOpenMPDirectiveName(NM);
Values += "'";
if (AllowedCnt + 2 == TotalAllowedNum)
Values += " or ";
else if (AllowedCnt + 1 != TotalAllowedNum)
Values += Sep;
++AllowedCnt;
}
}
S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(),
diag::err_omp_unnamed_if_clause)
<< (TotalAllowedNum > 1) << Values;
}
ErrorFound = true;
}
return ErrorFound;
}
StmtResult Sema::ActOnOpenMPExecutableDirective(
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
@ -2021,10 +2097,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
}
}
llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
switch (Kind) {
case OMPD_parallel:
Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_simd:
Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
@ -2064,18 +2142,22 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_parallel_for:
Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc, VarsWithInheritedDSA);
AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_parallel_for_simd:
Res = ActOnOpenMPParallelForSimdDirective(
ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_parallel_sections:
Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_task:
Res =
ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
AllowedNameModifiers.push_back(OMPD_task);
break;
case OMPD_taskyield:
assert(ClausesWithImplicit.empty() &&
@ -2124,6 +2206,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_target:
Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
AllowedNameModifiers.push_back(OMPD_target);
break;
case OMPD_cancellation_point:
assert(ClausesWithImplicit.empty() &&
@ -2142,6 +2225,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_target_data:
Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
AllowedNameModifiers.push_back(OMPD_target_data);
break;
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
@ -2153,8 +2237,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
<< P.first << P.second->getSourceRange();
}
if (!VarsWithInheritedDSA.empty())
return StmtError();
ErrorFound = !VarsWithInheritedDSA.empty() || ErrorFound;
if (!AllowedNameModifiers.empty())
ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
ErrorFound;
if (ErrorFound)
return StmtError();
@ -2165,7 +2252,9 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@ -3557,6 +3646,10 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
@ -3606,6 +3699,10 @@ StmtResult Sema::ActOnOpenMPForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
@ -3637,6 +3734,10 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
@ -3687,7 +3788,10 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
@ -3719,7 +3823,10 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@ -3730,7 +3837,10 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@ -3757,7 +3867,10 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@ -3768,7 +3881,10 @@ StmtResult
Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@ -3780,7 +3896,9 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@ -3821,7 +3939,9 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@ -3877,7 +3997,10 @@ StmtResult
Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
@ -3910,7 +4033,9 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@ -3942,7 +4067,10 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
StmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@ -3959,7 +4087,10 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@ -4210,7 +4341,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
auto CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@ -4631,7 +4764,10 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
// OpenMP [2.16, Nesting of Regions]
// If specified, a teams construct must be contained within a target
@ -4672,6 +4808,11 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
@ -4681,7 +4822,9 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
if (!AStmt)
return StmtError();
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@ -4743,9 +4886,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_if:
Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_final:
Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
@ -4767,6 +4907,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_device:
Res = ActOnOpenMPDeviceClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_schedule:
@ -4796,8 +4937,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
return Res;
}
OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation NameModifierLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc) {
Expr *ValExpr = Condition;
if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
@ -4811,7 +4955,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
ValExpr = Val.get();
}
return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc);
return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc,
NameModifierLoc, ColonLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
@ -5129,16 +5274,20 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, unsigned Argument, Expr *Expr,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ArgumentLoc, SourceLocation CommaLoc,
SourceLocation ArgumentLoc, SourceLocation DelimLoc,
SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_schedule:
Res = ActOnOpenMPScheduleClause(
static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc,
LParenLoc, ArgumentLoc, CommaLoc, EndLoc);
LParenLoc, ArgumentLoc, DelimLoc, EndLoc);
break;
case OMPC_if:
Res =
ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument), Expr,
StartLoc, LParenLoc, ArgumentLoc, DelimLoc, EndLoc);
break;
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
@ -6382,9 +6531,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
BO_Assign, LHSDRE, ConditionalOp);
}
if (ReductionOp.isUsable()) {
ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
}
ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
}
if (ReductionOp.isInvalid())
continue;
@ -6551,6 +6698,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
ExprResult CalcStep =
BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
CalcStep = ActOnFinishFullExpr(CalcStep.get());
// Warn about zero linear step (it would be probably better specified as
// making corresponding variables 'const').
@ -6607,13 +6755,15 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
ExprResult Update =
BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
InitExpr, IV, Step, /* Subtract */ false);
Update = SemaRef.ActOnFinishFullExpr(Update.get());
Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(),
/*DiscardedValue=*/true);
// Build final: Var = InitExpr + NumIterations * Step
ExprResult Final =
BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
InitExpr, NumIterations, Step, /* Subtract */ false);
Final = SemaRef.ActOnFinishFullExpr(Final.get());
Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(),
/*DiscardedValue=*/true);
if (!Update.isUsable() || !Final.isUsable()) {
Updates.push_back(nullptr);
Finals.push_back(nullptr);

View File

@ -1355,12 +1355,15 @@ public:
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPIfClause(Expr *Condition,
SourceLocation StartLoc,
OMPClause *RebuildOMPIfClause(OpenMPDirectiveKind NameModifier,
Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation NameModifierLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPIfClause(Condition, StartLoc,
LParenLoc, EndLoc);
return getSema().ActOnOpenMPIfClause(NameModifier, Condition, StartLoc,
LParenLoc, NameModifierLoc, ColonLoc,
EndLoc);
}
/// \brief Build a new OpenMP 'final' clause.
@ -7214,8 +7217,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
ExprResult Cond = getDerived().TransformExpr(C->getCondition());
if (Cond.isInvalid())
return nullptr;
return getDerived().RebuildOMPIfClause(Cond.get(), C->getLocStart(),
C->getLParenLoc(), C->getLocEnd());
return getDerived().RebuildOMPIfClause(
C->getNameModifier(), Cond.get(), C->getLocStart(), C->getLParenLoc(),
C->getNameModifierLoc(), C->getColonLoc(), C->getLocEnd());
}
template <typename Derived>

View File

@ -1812,6 +1812,9 @@ OMPClause *OMPClauseReader::readClause() {
}
void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
C->setNameModifier(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
C->setNameModifierLoc(Reader->ReadSourceLocation(Record, Idx));
C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
C->setCondition(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}

View File

@ -1728,6 +1728,9 @@ void OMPClauseWriter::writeClause(OMPClause *C) {
}
void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
Record.push_back(C->getNameModifier());
Writer->Writer.AddSourceLocation(C->getNameModifierLoc(), Record);
Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
Writer->Writer.AddStmt(C->getCondition());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}

View File

@ -39,7 +39,7 @@ T tmain(T argc, S **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp for schedule (static, foobool(argc)), schedule (dynamic, true), schedule (guided, -5)
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp for schedule (static, S) // expected-error {{'S' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
#pragma omp for schedule (static, S) // expected-error {{'S' does not refer to a value}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+1 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp for schedule (guided, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
@ -76,14 +76,14 @@ int main(int argc, char **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp for schedule (guided, foobool(argc)), schedule (static, true), schedule (dynamic, -5)
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp for schedule (guided, S1) // expected-error {{'S1' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
#pragma omp for schedule (guided, S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp for schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+3 {{statement after '#pragma omp for' must be a for loop}}
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
#pragma omp for schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp for schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
foo();
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
return tmain<int, char, 1, 0>(argc, argv);

View File

@ -39,7 +39,7 @@ T tmain(T argc, S **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp for simd schedule (static, foobool(argc)), schedule (dynamic, true), schedule (guided, -5)
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp for simd schedule (static, S) // expected-error {{'S' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp for simd' are ignored}}
#pragma omp for simd schedule (static, S) // expected-error {{'S' does not refer to a value}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+1 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp for simd schedule (guided, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
@ -76,14 +76,14 @@ int main(int argc, char **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp for simd schedule (guided, foobool(argc)), schedule (static, true), schedule (dynamic, -5)
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp for simd schedule (guided, S1) // expected-error {{'S1' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp for simd' are ignored}}
#pragma omp for simd schedule (guided, S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp for simd schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+3 {{statement after '#pragma omp for simd' must be a for loop}}
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
#pragma omp for simd schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp for simd schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
foo();
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
return tmain<int, char, 1, 0>(argc, argv);

View File

@ -34,6 +34,20 @@ int tmain(T argc, S **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(argc)
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc)
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel for'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel for' cannot contain more than one 'if' clause with 'parallel' name modifier}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
for (i = 0; i < argc; ++i) foo();
return 0;
}
@ -64,6 +78,20 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc)
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel for'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel for' cannot contain more than one 'if' clause with 'parallel' name modifier}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
for (i = 0; i < argc; ++i) foo();
return tmain(argc, argv);
}

View File

@ -39,7 +39,7 @@ T tmain(T argc, S **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp parallel for schedule (static, foobool(argc)), schedule (dynamic, true), schedule (guided, -5)
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp parallel for schedule (static, S) // expected-error {{'S' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp parallel for' are ignored}}
#pragma omp parallel for schedule (static, S) // expected-error {{'S' does not refer to a value}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+1 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp parallel for schedule (guided, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
@ -76,14 +76,14 @@ int main(int argc, char **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp parallel for schedule (guided, foobool(argc)), schedule (static, true), schedule (dynamic, -5)
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp parallel for schedule (guided, S1) // expected-error {{'S1' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp parallel for' are ignored}}
#pragma omp parallel for schedule (guided, S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp parallel for schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+3 {{statement after '#pragma omp parallel for' must be a for loop}}
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
#pragma omp parallel for schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel for schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
foo();
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
return tmain<int, char, 1, 0>(argc, argv);

View File

@ -34,6 +34,20 @@ int tmain(T argc, S **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(argc)
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc)
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel for simd'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel for simd' cannot contain more than one 'if' clause with 'parallel' name modifier}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
for (i = 0; i < argc; ++i) foo();
return 0;
}
@ -64,6 +78,20 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc)
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel for simd'}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel for simd' cannot contain more than one 'if' clause with 'parallel' name modifier}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
for (i = 0; i < argc; ++i) foo();
return tmain(argc, argv);
}

View File

@ -39,7 +39,7 @@ T tmain(T argc, S **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp parallel for simd schedule (static, foobool(argc)), schedule (dynamic, true), schedule (guided, -5)
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp parallel for simd schedule (static, S) // expected-error {{'S' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp parallel for simd' are ignored}}
#pragma omp parallel for simd schedule (static, S) // expected-error {{'S' does not refer to a value}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+1 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp parallel for simd schedule (guided, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
@ -76,14 +76,14 @@ int main(int argc, char **argv) {
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
#pragma omp parallel for simd schedule (guided, foobool(argc)), schedule (static, true), schedule (dynamic, -5)
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp parallel for simd schedule (guided, S1) // expected-error {{'S1' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp parallel for simd' are ignored}}
#pragma omp parallel for simd schedule (guided, S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp parallel for simd schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+3 {{statement after '#pragma omp parallel for simd' must be a for loop}}
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
#pragma omp parallel for simd schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel for simd schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
foo();
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
return tmain<int, char, 1, 0>(argc, argv);

View File

@ -22,6 +22,13 @@ int tmain(T argc, S **argv) {
#pragma omp parallel if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(argc)
#pragma omp parallel if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc)
#pragma omp parallel if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel'}}
#pragma omp parallel if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel' cannot contain more than one 'if' clause with 'parallel' name modifier}}
#pragma omp parallel if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
foo();
return 0;
@ -40,6 +47,13 @@ int main(int argc, char **argv) {
#pragma omp parallel if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc)
#pragma omp parallel if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel'}}
#pragma omp parallel if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel' cannot contain more than one 'if' clause with 'parallel' name modifier}}
#pragma omp parallel if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
foo();
return tmain(argc, argv);

View File

@ -55,6 +55,30 @@ int tmain(T argc, S **argv) {
{
foo();
}
#pragma omp parallel sections if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc)
{
foo();
}
#pragma omp parallel sections if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel sections'}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel sections' cannot contain more than one 'if' clause with 'parallel' name modifier}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
{
foo();
}
return 0;
}
@ -108,6 +132,30 @@ int main(int argc, char **argv) {
{
foo();
}
#pragma omp parallel sections if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc)
{
foo();
}
#pragma omp parallel sections if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel sections'}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel sections' cannot contain more than one 'if' clause with 'parallel' name modifier}}
{
foo();
}
#pragma omp parallel sections if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
{
foo();
}
return tmain(argc, argv);
}

View File

@ -20,6 +20,12 @@ int main(int argc, char **argv) {
#pragma omp target data if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target data' cannot contain more than one 'if' clause}}
#pragma omp target data if (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp target data if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target data if(target data : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target data if(target data : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target data if(target data : argc)
#pragma omp target data if(target data : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target data'}}
#pragma omp target data if(target data : argc) if (target data:argc) // expected-error {{directive '#pragma omp target data' cannot contain more than one 'if' clause with 'target data' name modifier}}
#pragma omp target data if(target data : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
foo();
return 0;

View File

@ -22,6 +22,12 @@ int tmain(T argc, S **argv) {
#pragma omp target if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if(argc)
#pragma omp target if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if(target : argc)
#pragma omp target if(target : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target'}}
#pragma omp target if(target : argc) if (target:argc) // expected-error {{directive '#pragma omp target' cannot contain more than one 'if' clause with 'target' name modifier}}
#pragma omp target if(target : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
foo();
return 0;
@ -40,6 +46,12 @@ int main(int argc, char **argv) {
#pragma omp target if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target if(target : argc)
#pragma omp target if(target : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target'}}
#pragma omp target if(target : argc) if (target:argc) // expected-error {{directive '#pragma omp target' cannot contain more than one 'if' clause with 'target' name modifier}}
#pragma omp target if(target : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
foo();
return tmain(argc, argv);

View File

@ -22,6 +22,12 @@ int tmain(T argc, S **argv) {
#pragma omp task if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if(argc)
#pragma omp task if(task : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if(task : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if(task : argc)
#pragma omp task if(task : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp task'}}
#pragma omp task if(task : argc) if (task:argc) // expected-error {{directive '#pragma omp task' cannot contain more than one 'if' clause with 'task' name modifier}}
#pragma omp task if(task : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
foo();
return 0;
@ -40,6 +46,12 @@ int main(int argc, char **argv) {
#pragma omp task if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if(task : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if(task : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task if(task : argc)
#pragma omp task if(task : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp task'}}
#pragma omp task if(task : argc) if (task:argc) // expected-error {{directive '#pragma omp task' cannot contain more than one 'if' clause with 'task' name modifier}}
#pragma omp task if(task : argc) if (argc) // expected-error {{no more 'if' clause is allowed}}
foo();
return tmain(argc, argv);