Index: include/clang/AST/OpenMPClause.h =================================================================== --- include/clang/AST/OpenMPClause.h +++ include/clang/AST/OpenMPClause.h @@ -3193,6 +3193,135 @@ 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(ChunkSizes[CHUNK_SIZE]); + } + /// \brief Get chunk size. + /// + Expr *getChunkSize() const { + return dyn_cast_or_null(ChunkSizes[CHUNK_SIZE]); + } + /// \brief Get helper chunk size. + /// + Expr *getHelperChunkSize() { + return dyn_cast_or_null(ChunkSizes[HELPER_CHUNK_SIZE]); + } + /// \brief Get helper chunk size. + /// + Expr *getHelperChunkSize() const { + return dyn_cast_or_null(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 Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -2781,6 +2781,14 @@ return true; } +template +bool RecursiveASTVisitor::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 Index: include/clang/Basic/OpenMPKinds.h =================================================================== --- include/clang/Basic/OpenMPKinds.h +++ include/clang/Basic/OpenMPKinds.h @@ -95,6 +95,13 @@ 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); Index: include/clang/Basic/OpenMPKinds.def =================================================================== --- include/clang/Basic/OpenMPKinds.def +++ include/clang/Basic/OpenMPKinds.def @@ -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(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(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 @@ #undef OPENMP_FOR_SIMD_CLAUSE #undef OPENMP_MAP_KIND #undef OPENMP_DISTRIBUTE_CLAUSE +#undef OPENMP_DIST_SCHEDULE_KIND Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -8192,6 +8192,11 @@ 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 { Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -909,6 +909,16 @@ 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 << ")"; +} } //===----------------------------------------------------------------------===// Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -611,6 +611,16 @@ 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); } Index: lib/Basic/OpenMPKinds.cpp =================================================================== --- lib/Basic/OpenMPKinds.cpp +++ lib/Basic/OpenMPKinds.cpp @@ -109,6 +109,11 @@ #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(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 @@ 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: Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -2525,6 +2525,7 @@ case OMPC_nogroup: case OMPC_num_tasks: case OMPC_hint: + case OMPC_dist_schedule: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } } Index: lib/Parse/ParseOpenMP.cpp =================================================================== --- lib/Parse/ParseOpenMP.cpp +++ lib/Parse/ParseOpenMP.cpp @@ -494,6 +494,7 @@ 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 @@ 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 @@ } } - 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)); Index: lib/Sema/SemaOpenMP.cpp =================================================================== --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -5699,6 +5699,7 @@ 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 @@ 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 @@ Expr, StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc); break; + case OMPC_dist_schedule: + Res = ActOnOpenMPDistScheduleClause( + static_cast(Argument.back()), Expr, + StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc); + break; case OMPC_final: case OMPC_num_threads: case OMPC_safelen: @@ -6303,6 +6310,7 @@ 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 @@ 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 @@ 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); +} Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -1734,6 +1734,19 @@ 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 @@ C->getLParenLoc(), C->getLocEnd()); } +template +OMPClause *TreeTransform::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 //===----------------------------------------------------------------------===// Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1878,6 +1878,9 @@ 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 @@ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); } +void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) { + C->setDistScheduleKind( + static_cast(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. //===----------------------------------------------------------------------===// Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -2037,6 +2037,15 @@ 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. //===----------------------------------------------------------------------===// Index: test/OpenMP/distribute_dist_schedule_ast_print.cpp =================================================================== --- /dev/null +++ test/OpenMP/distribute_dist_schedule_ast_print.cpp @@ -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 +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(argc) + tmain(argv[0][0])); +} + +#endif Index: test/OpenMP/distribute_dist_schedule_messages.cpp =================================================================== --- /dev/null +++ test/OpenMP/distribute_dist_schedule_messages.cpp @@ -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 +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(argc) + tmain(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain' requested here}} expected-note {{in instantiation of function template specialization 'tmain' requested here}} +} Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -2222,6 +2222,11 @@ 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) {