Add OpenMP dist_schedule clause to distribute directive and related regression tests.

llvm-svn: 257917
This commit is contained in:
Carlo Bertolli 2016-01-15 18:50:31 +00:00
parent 47f2452da8
commit b4adf55e0f
17 changed files with 488 additions and 2 deletions

View File

@ -3193,6 +3193,135 @@ public:
child_range children() { return child_range(&Hint, &Hint + 1); }
};
/// \brief This represents 'dist_schedule' clause in the '#pragma omp ...'
/// directive.
///
/// \code
/// #pragma omp distribute dist_schedule(static, 3)
/// \endcode
/// In this example directive '#pragma omp distribute' has 'dist_schedule'
/// clause with arguments 'static' and '3'.
///
class OMPDistScheduleClause : public OMPClause {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
/// \brief A kind of the 'schedule' clause.
OpenMPDistScheduleClauseKind Kind;
/// \brief Start location of the schedule kind in source code.
SourceLocation KindLoc;
/// \brief Location of ',' (if any).
SourceLocation CommaLoc;
/// \brief Chunk size and a reference to pseudo variable for combined
/// directives.
enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS };
Stmt *ChunkSizes[NUM_EXPRS];
/// \brief Set schedule kind.
///
/// \param K Schedule kind.
///
void setDistScheduleKind(OpenMPDistScheduleClauseKind K) { Kind = K; }
/// \brief Sets the location of '('.
///
/// \param Loc Location of '('.
///
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Set schedule kind start location.
///
/// \param KLoc Schedule kind location.
///
void setDistScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
/// \brief Set location of ','.
///
/// \param Loc Location of ','.
///
void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; }
/// \brief Set chunk size.
///
/// \param E Chunk size.
///
void setChunkSize(Expr *E) { ChunkSizes[CHUNK_SIZE] = E; }
/// \brief Set helper chunk size.
///
/// \param E Helper chunk size.
///
void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; }
public:
/// \brief Build 'dist_schedule' clause with schedule kind \a Kind and chunk
/// size expression \a ChunkSize.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param KLoc Starting location of the argument.
/// \param CommaLoc Location of ','.
/// \param EndLoc Ending location of the clause.
/// \param Kind DistSchedule kind.
/// \param ChunkSize Chunk size.
/// \param HelperChunkSize Helper chunk size for combined directives.
///
OMPDistScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation KLoc, SourceLocation CommaLoc,
SourceLocation EndLoc,
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
Expr *HelperChunkSize)
: OMPClause(OMPC_dist_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
ChunkSizes[CHUNK_SIZE] = ChunkSize;
ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
}
/// \brief Build an empty clause.
///
explicit OMPDistScheduleClause()
: OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()),
Kind(OMPC_DIST_SCHEDULE_unknown) {
ChunkSizes[CHUNK_SIZE] = nullptr;
ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
}
/// \brief Get kind of the clause.
///
OpenMPDistScheduleClauseKind getDistScheduleKind() const { return Kind; }
/// \brief Get location of '('.
///
SourceLocation getLParenLoc() { return LParenLoc; }
/// \brief Get kind location.
///
SourceLocation getDistScheduleKindLoc() { return KindLoc; }
/// \brief Get location of ','.
///
SourceLocation getCommaLoc() { return CommaLoc; }
/// \brief Get chunk size.
///
Expr *getChunkSize() {
return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
}
/// \brief Get chunk size.
///
Expr *getChunkSize() const {
return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
}
/// \brief Get helper chunk size.
///
Expr *getHelperChunkSize() {
return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
}
/// \brief Get helper chunk size.
///
Expr *getHelperChunkSize() const {
return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
}
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_dist_schedule;
}
child_range children() {
return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
}
};
} // end namespace clang
#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H

View File

@ -2781,6 +2781,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDistScheduleClause(
OMPDistScheduleClause *C) {
TRY_TO(TraverseStmt(C->getChunkSize()));
TRY_TO(TraverseStmt(C->getHelperChunkSize()));
return true;
}
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm

View File

@ -102,6 +102,9 @@
#ifndef OPENMP_MAP_KIND
#define OPENMP_MAP_KIND(Name)
#endif
#ifndef OPENMP_DIST_SCHEDULE_KIND
#define OPENMP_DIST_SCHEDULE_KIND(Name)
#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
@ -175,6 +178,7 @@ OPENMP_CLAUSE(grainsize, OMPGrainsizeClause)
OPENMP_CLAUSE(nogroup, OMPNogroupClause)
OPENMP_CLAUSE(num_tasks, OMPNumTasksClause)
OPENMP_CLAUSE(hint, OMPHintClause)
OPENMP_CLAUSE(dist_schedule, OMPDistScheduleClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
@ -418,6 +422,10 @@ OPENMP_DISTRIBUTE_CLAUSE(private)
OPENMP_DISTRIBUTE_CLAUSE(firstprivate)
OPENMP_DISTRIBUTE_CLAUSE(lastprivate)
OPENMP_DISTRIBUTE_CLAUSE(collapse)
OPENMP_DISTRIBUTE_CLAUSE(dist_schedule)
// Static attributes for 'dist_schedule' clause.
OPENMP_DIST_SCHEDULE_KIND(static)
#undef OPENMP_TASKLOOP_SIMD_CLAUSE
#undef OPENMP_TASKLOOP_CLAUSE
@ -449,3 +457,4 @@ OPENMP_DISTRIBUTE_CLAUSE(collapse)
#undef OPENMP_FOR_SIMD_CLAUSE
#undef OPENMP_MAP_KIND
#undef OPENMP_DISTRIBUTE_CLAUSE
#undef OPENMP_DIST_SCHEDULE_KIND

View File

@ -95,6 +95,13 @@ enum OpenMPMapClauseKind {
OMPC_MAP_unknown
};
/// \brief OpenMP attributes for 'dist_schedule' clause.
enum OpenMPDistScheduleClauseKind {
#define OPENMP_DIST_SCHEDULE_KIND(Name) OMPC_DIST_SCHEDULE_##Name,
#include "clang/Basic/OpenMPKinds.def"
OMPC_DIST_SCHEDULE_unknown
};
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);

View File

@ -8192,6 +8192,11 @@ public:
OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'dist_schedule' clause.
OMPClause *ActOnOpenMPDistScheduleClause(
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc,
SourceLocation CommaLoc, SourceLocation EndLoc);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {

View File

@ -909,6 +909,16 @@ void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
OS << ")";
}
}
void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
OMPC_dist_schedule, Node->getDistScheduleKind());
if (Node->getChunkSize()) {
OS << ", ";
Node->getChunkSize()->printPretty(OS, nullptr, Policy);
}
OS << ")";
}
}
//===----------------------------------------------------------------------===//

View File

@ -611,6 +611,16 @@ void StmtProfiler::VisitOMPDistributeDirective(
VisitOMPLoopDirective(S);
}
void OMPClauseProfiler::VisitOMPDistScheduleClause(
const OMPDistScheduleClause *C) {
if (C->getChunkSize()) {
Profiler->VisitStmt(C->getChunkSize());
if (C->getHelperChunkSize()) {
Profiler->VisitStmt(C->getChunkSize());
}
}
}
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}

View File

@ -109,6 +109,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
#define OPENMP_MAP_KIND(Name) .Case(#Name, OMPC_MAP_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_MAP_unknown);
case OMPC_dist_schedule:
return llvm::StringSwitch<OpenMPDistScheduleClauseKind>(Str)
#define OPENMP_DIST_SCHEDULE_KIND(Name) .Case(#Name, OMPC_DIST_SCHEDULE_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_DIST_SCHEDULE_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@ -219,6 +224,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
break;
}
llvm_unreachable("Invalid OpenMP 'map' clause type");
case OMPC_dist_schedule:
switch (Type) {
case OMPC_DIST_SCHEDULE_unknown:
return "unknown";
#define OPENMP_DIST_SCHEDULE_KIND(Name) \
case OMPC_DIST_SCHEDULE_##Name: \
return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'dist_schedule' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:

View File

@ -2525,6 +2525,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_dist_schedule:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}

View File

@ -494,6 +494,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
Clause = ParseOpenMPSimpleClause(CKind);
break;
case OMPC_schedule:
case OMPC_dist_schedule:
// OpenMP [2.7.1, Restrictions, p. 3]
// Only one schedule clause can appear on a loop directive.
if (!FirstClause) {
@ -744,6 +745,15 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
Tok.is(tok::comma))
DelimLoc = ConsumeAnyToken();
} else if (Kind == OMPC_dist_schedule) {
Arg.push_back(getOpenMPSimpleClauseType(
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
KLoc.push_back(Tok.getLocation());
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
DelimLoc = ConsumeAnyToken();
} else {
assert(Kind == OMPC_if);
KLoc.push_back(Tok.getLocation());
@ -758,8 +768,9 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
}
}
bool NeedAnExpression =
(Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if;
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
Kind == OMPC_if;
if (NeedAnExpression) {
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));

View File

@ -5699,6 +5699,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_simd:
case OMPC_map:
case OMPC_nogroup:
case OMPC_dist_schedule:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -5982,6 +5983,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_dist_schedule:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -6080,6 +6082,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
DelimLoc, EndLoc);
break;
case OMPC_dist_schedule:
Res = ActOnOpenMPDistScheduleClause(
static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
break;
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
@ -6303,6 +6310,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_grainsize:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_dist_schedule:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -6444,6 +6452,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_dist_schedule:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -8542,3 +8551,55 @@ OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPDistScheduleClause(
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
SourceLocation EndLoc) {
if (Kind == OMPC_DIST_SCHEDULE_unknown) {
std::string Values;
Values += "'";
Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
Values += "'";
Diag(KindLoc, diag::err_omp_unexpected_clause_value)
<< Values << getOpenMPClauseName(OMPC_dist_schedule);
return nullptr;
}
Expr *ValExpr = ChunkSize;
Expr *HelperValExpr = nullptr;
if (ChunkSize) {
if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
!ChunkSize->isInstantiationDependent() &&
!ChunkSize->containsUnexpandedParameterPack()) {
SourceLocation ChunkSizeLoc = ChunkSize->getLocStart();
ExprResult Val =
PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
if (Val.isInvalid())
return nullptr;
ValExpr = Val.get();
// OpenMP [2.7.1, Restrictions]
// chunk_size must be a loop invariant integer expression with a positive
// value.
llvm::APSInt Result;
if (ValExpr->isIntegerConstantExpr(Result, Context)) {
if (Result.isSigned() && !Result.isStrictlyPositive()) {
Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
<< "dist_schedule" << ChunkSize->getSourceRange();
return nullptr;
}
} else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
auto *ImpVar = buildVarDecl(*this, ChunkSize->getExprLoc(),
ChunkSize->getType(), ".chunk.");
auto *ImpVarRef = buildDeclRefExpr(*this, ImpVar, ChunkSize->getType(),
ChunkSize->getExprLoc(),
/*RefersToCapture=*/true);
HelperValExpr = ImpVarRef;
}
}
}
return new (Context)
OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
Kind, ValExpr, HelperValExpr);
}

View File

@ -1734,6 +1734,19 @@ public:
return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
}
/// \brief Build a new OpenMP 'dist_schedule' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *
RebuildOMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind,
Expr *ChunkSize, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation KindLoc,
SourceLocation CommaLoc, SourceLocation EndLoc) {
return getSema().ActOnOpenMPDistScheduleClause(
Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
}
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@ -7889,6 +7902,17 @@ OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) {
C->getLParenLoc(), C->getLocEnd());
}
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPDistScheduleClause(
OMPDistScheduleClause *C) {
ExprResult E = getDerived().TransformExpr(C->getChunkSize());
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPDistScheduleClause(
C->getDistScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
C->getDistScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
}
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//

View File

@ -1878,6 +1878,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_hint:
C = new (Context) OMPHintClause();
break;
case OMPC_dist_schedule:
C = new (Context) OMPDistScheduleClause();
break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@ -2240,6 +2243,16 @@ void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
C->setDistScheduleKind(
static_cast<OpenMPDistScheduleClauseKind>(Record[Idx++]));
C->setChunkSize(Reader->Reader.ReadSubExpr());
C->setHelperChunkSize(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
C->setDistScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
}
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//

View File

@ -2037,6 +2037,15 @@ void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
Record.push_back(C->getDistScheduleKind());
Writer->Writer.AddStmt(C->getChunkSize());
Writer->Writer.AddStmt(C->getHelperChunkSize());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getDistScheduleKindLoc(), Record);
Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record);
}
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//

View File

@ -0,0 +1,106 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
void foo() {}
template <class T, int N>
T tmain(T argc) {
T b = argc, c, d, e, f, g;
static T a;
// CHECK: static T a;
#pragma omp distribute dist_schedule(static,10)
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 10)
for (int i=0; i < 2; ++i)a=2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp distribute dist_schedule(static,a)
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, a)
for (int i=0; i < 2; ++i)a=2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target
#pragma omp teams
#pragma omp distribute dist_schedule(static,2)
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 10; ++j)foo();
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 2)
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
// CHECK-NEXT: foo();
#pragma omp target
#pragma omp teams
#pragma omp distribute dist_schedule(static,a)
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 10; ++j)foo();
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
// CHECK-NEXT: foo();
for (int i = 0; i < 10; ++i)foo();
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: foo();
#pragma omp distribute
// CHECK: #pragma omp distribute
for (int i = 0; i < 10; ++i)foo();
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: foo();
return T();
}
int main (int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
// CHECK: static int a;
#pragma omp distribute dist_schedule(static,10)
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 10)
for (int i=0; i < 2; ++i)a=2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp distribute dist_schedule(static,b)
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, b)
for (int i=0; i < 2; ++i)a=2;
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp target
#pragma omp teams
#pragma omp distribute dist_schedule(static,2)
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 10; ++j)foo();
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 2)
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
// CHECK-NEXT: foo();
#pragma omp target
#pragma omp teams
#pragma omp distribute dist_schedule(static,a)
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 10; ++j)foo();
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
// CHECK-NEXT: foo();
for (int i = 0; i < 10; ++i)foo();
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: foo();
#pragma omp distribute
// CHECK: #pragma omp distribute
for (int i = 0; i < 10; ++i)foo();
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: foo();
return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0]));
}
#endif

View File

@ -0,0 +1,63 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
void foo() {
}
bool foobool(int argc) {
return argc;
}
struct S1; // expected-note {{declared here}} expected-note {{declared here}}
template <class T, int N>
T tmain(T argc) {
T b = argc, c, d, e, f, g;
char ** argv;
static T a;
// CHECK: static T a;
#pragma omp distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp distribute' are ignored}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp distribute' cannot contain more than one 'dist_schedule' clause}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
for (int i = 0; i < 10; ++i) foo();
return T();
}
int main(int argc, char **argv) {
#pragma omp distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp distribute' are ignored}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp distribute' cannot contain more than one 'dist_schedule' clause}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 0; i < 10; ++i) foo();
#pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 0; i < 10; ++i) foo();
return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
}

View File

@ -2222,6 +2222,11 @@ void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) {
void OMPClauseEnqueue::VisitOMPMapClause(const OMPMapClause *C) {
VisitOMPClauseList(C);
}
void OMPClauseEnqueue::VisitOMPDistScheduleClause(
const OMPDistScheduleClause *C) {
Visitor->AddStmt(C->getChunkSize());
Visitor->AddStmt(C->getHelperChunkSize());
}
}
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {