r256487 - [OPENMP 4.5] Sema/parsing support for extended format of 'schedule' clause.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 27 23:25:52 PST 2015


Author: abataev
Date: Mon Dec 28 01:25:51 2015
New Revision: 256487

URL: http://llvm.org/viewvc/llvm-project?rev=256487&view=rev
Log:
[OPENMP 4.5] Sema/parsing support for extended format of 'schedule' clause.
OpenMP 4.0-3.1 supports the next format of ‘schedule’ clause: schedule(kind[, chunk_size])
Where kind can be one of ‘static’, ‘dynamic’, ‘guided’, ‘auto’ or ‘runtime’.
OpenMP 4.5 defines the format: schedule([modifier [, modifier]:]kind[, chunk_size])
Modifier can be one of ‘monotonic’, ‘nonmonotonic’ or ‘simd’.


Modified:
    cfe/trunk/include/clang/AST/OpenMPClause.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/OpenMPKinds.def
    cfe/trunk/include/clang/Basic/OpenMPKinds.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Basic/OpenMPKinds.cpp
    cfe/trunk/lib/Parse/ParseOpenMP.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/OpenMP/for_schedule_messages.cpp
    cfe/trunk/test/OpenMP/for_simd_schedule_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_schedule_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_simd_schedule_messages.cpp

Modified: cfe/trunk/include/clang/AST/OpenMPClause.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OpenMPClause.h (original)
+++ cfe/trunk/include/clang/AST/OpenMPClause.h Mon Dec 28 01:25:51 2015
@@ -664,6 +664,11 @@ class OMPScheduleClause : public OMPClau
   SourceLocation LParenLoc;
   /// \brief A kind of the 'schedule' clause.
   OpenMPScheduleClauseKind Kind;
+  /// \brief Modifiers for 'schedule' clause.
+  enum {FIRST, SECOND, NUM_MODIFIERS};
+  OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS];
+  /// \brief Locations of modifiers.
+  SourceLocation ModifiersLoc[NUM_MODIFIERS];
   /// \brief Start location of the schedule ind in source code.
   SourceLocation KindLoc;
   /// \brief Location of ',' (if any).
@@ -678,6 +683,42 @@ class OMPScheduleClause : public OMPClau
   /// \param K Schedule kind.
   ///
   void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
+  /// \brief Set the first schedule modifier.
+  ///
+  /// \param M Schedule modifier.
+  ///
+  void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) {
+    Modifiers[FIRST] = M;
+  }
+  /// \brief Set the second schedule modifier.
+  ///
+  /// \param M Schedule modifier.
+  ///
+  void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) {
+    Modifiers[SECOND] = M;
+  }
+  /// \brief Set location of the first schedule modifier.
+  ///
+  void setFirstScheduleModifierLoc(SourceLocation Loc) {
+    ModifiersLoc[FIRST] = Loc;
+  }
+  /// \brief Set location of the second schedule modifier.
+  ///
+  void setSecondScheduleModifierLoc(SourceLocation Loc) {
+    ModifiersLoc[SECOND] = Loc;
+  }
+  /// \brief Set schedule modifier location.
+  ///
+  /// \param M Schedule modifier location.
+  ///
+  void setScheduleModifer(OpenMPScheduleClauseModifier M) {
+    if (Modifiers[FIRST] == OMPC_SCHEDULE_MODIFIER_unknown)
+      Modifiers[FIRST] = M;
+    else {
+      assert(Modifiers[SECOND] == OMPC_SCHEDULE_MODIFIER_unknown);
+      Modifiers[SECOND] = M;
+    }
+  }
   /// \brief Sets the location of '('.
   ///
   /// \param Loc Location of '('.
@@ -716,15 +757,25 @@ public:
   /// \param Kind Schedule kind.
   /// \param ChunkSize Chunk size.
   /// \param HelperChunkSize Helper chunk size for combined directives.
+  /// \param M1 The first modifier applied to 'schedule' clause.
+  /// \param M1Loc Location of the first modifier
+  /// \param M2 The second modifier applied to 'schedule' clause.
+  /// \param M2Loc Location of the second modifier
   ///
   OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
                     SourceLocation KLoc, SourceLocation CommaLoc,
                     SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
-                    Expr *ChunkSize, Expr *HelperChunkSize)
+                    Expr *ChunkSize, Expr *HelperChunkSize,
+                    OpenMPScheduleClauseModifier M1, SourceLocation M1Loc,
+                    OpenMPScheduleClauseModifier M2, SourceLocation M2Loc)
       : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
         Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
     ChunkSizes[CHUNK_SIZE] = ChunkSize;
     ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
+    Modifiers[FIRST] = M1;
+    Modifiers[SECOND] = M2;
+    ModifiersLoc[FIRST] = M1Loc;
+    ModifiersLoc[SECOND] = M2Loc;
   }
 
   /// \brief Build an empty clause.
@@ -734,17 +785,39 @@ public:
         Kind(OMPC_SCHEDULE_unknown) {
     ChunkSizes[CHUNK_SIZE] = nullptr;
     ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
+    Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown;
+    Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown;
   }
 
   /// \brief Get kind of the clause.
   ///
   OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
+  /// \brief Get the first modifier of the clause.
+  ///
+  OpenMPScheduleClauseModifier getFirstScheduleModifier() const {
+    return Modifiers[FIRST];
+  }
+  /// \brief Get the second modifier of the clause.
+  ///
+  OpenMPScheduleClauseModifier getSecondScheduleModifier() const {
+    return Modifiers[SECOND];
+  }
   /// \brief Get location of '('.
   ///
   SourceLocation getLParenLoc() { return LParenLoc; }
   /// \brief Get kind location.
   ///
   SourceLocation getScheduleKindLoc() { return KindLoc; }
+  /// \brief Get the first modifier location.
+  ///
+  SourceLocation getFirstScheduleModifierLoc() const {
+    return ModifiersLoc[FIRST];
+  }
+  /// \brief Get the second modifier location.
+  ///
+  SourceLocation getSecondScheduleModifierLoc() const {
+    return ModifiersLoc[SECOND];
+  }
   /// \brief Get location of ','.
   ///
   SourceLocation getCommaLoc() { return CommaLoc; }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Dec 28 01:25:51 2015
@@ -7963,6 +7963,12 @@ def err_omp_depend_sink_source_not_allow
   "'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">;
 def err_omp_linear_ordered : Error<
   "'linear' clause cannot be specified along with 'ordered' clause with a parameter">;
+def err_omp_unexpected_schedule_modifier : Error<
+  "modifier '%0' cannot be used along with modifier '%1'">;
+def err_omp_schedule_nonmonotonic_static : Error<
+  "'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">;
+def err_omp_schedule_nonmonotonic_ordered : Error<
+  "'schedule' clause with 'nonmonotonic' modifier cannot be specified if an 'ordered' clause is specified">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {

Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Mon Dec 28 01:25:51 2015
@@ -90,6 +90,9 @@
 #ifndef OPENMP_SCHEDULE_KIND
 #define OPENMP_SCHEDULE_KIND(Name)
 #endif
+#ifndef OPENMP_SCHEDULE_MODIFIER
+#define OPENMP_SCHEDULE_MODIFIER(Name)
+#endif
 #ifndef OPENMP_DEPEND_KIND
 #define OPENMP_DEPEND_KIND(Name)
 #endif
@@ -250,6 +253,11 @@ OPENMP_SCHEDULE_KIND(guided)
 OPENMP_SCHEDULE_KIND(auto)
 OPENMP_SCHEDULE_KIND(runtime)
 
+// Modifiers for 'schedule' clause.
+OPENMP_SCHEDULE_MODIFIER(monotonic)
+OPENMP_SCHEDULE_MODIFIER(nonmonotonic)
+OPENMP_SCHEDULE_MODIFIER(simd)
+
 // Static attributes for 'depend' clause.
 OPENMP_DEPEND_KIND(in)
 OPENMP_DEPEND_KIND(out)
@@ -413,6 +421,7 @@ OPENMP_DISTRIBUTE_CLAUSE(collapse)
 #undef OPENMP_TASKLOOP_CLAUSE
 #undef OPENMP_LINEAR_KIND
 #undef OPENMP_DEPEND_KIND
+#undef OPENMP_SCHEDULE_MODIFIER
 #undef OPENMP_SCHEDULE_KIND
 #undef OPENMP_PROC_BIND_KIND
 #undef OPENMP_DEFAULT_KIND

Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.h?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.h (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.h Mon Dec 28 01:25:51 2015
@@ -62,6 +62,15 @@ enum OpenMPScheduleClauseKind {
   OMPC_SCHEDULE_unknown
 };
 
+/// \brief OpenMP modifiers for 'schedule' clause.
+enum OpenMPScheduleClauseModifier {
+  OMPC_SCHEDULE_MODIFIER_unknown = OMPC_SCHEDULE_unknown,
+#define OPENMP_SCHEDULE_MODIFIER(Name) \
+  OMPC_SCHEDULE_MODIFIER_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+  OMPC_SCHEDULE_MODIFIER_last
+};
+
 /// \brief OpenMP attributes for 'depend' clause.
 enum OpenMPDependClauseKind {
 #define OPENMP_DEPEND_KIND(Name) \

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Dec 28 01:25:51 2015
@@ -8042,20 +8042,17 @@ public:
                                        SourceLocation LParenLoc,
                                        SourceLocation EndLoc);
 
-  OMPClause *ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
-                                                unsigned Argument, Expr *Expr,
-                                                SourceLocation StartLoc,
-                                                SourceLocation LParenLoc,
-                                                SourceLocation ArgumentLoc,
-                                                SourceLocation DelimLoc,
-                                                SourceLocation EndLoc);
+  OMPClause *ActOnOpenMPSingleExprWithArgClause(
+      OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
+      SourceLocation StartLoc, SourceLocation LParenLoc,
+      ArrayRef<SourceLocation> ArgumentsLoc, SourceLocation DelimLoc,
+      SourceLocation EndLoc);
   /// \brief Called on well-formed 'schedule' clause.
-  OMPClause *ActOnOpenMPScheduleClause(OpenMPScheduleClauseKind Kind,
-                                       Expr *ChunkSize, SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation KindLoc,
-                                       SourceLocation CommaLoc,
-                                       SourceLocation EndLoc);
+  OMPClause *ActOnOpenMPScheduleClause(
+      OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
+      OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+      SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+      SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc);
 
   OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc,
                                SourceLocation EndLoc);

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Dec 28 01:25:51 2015
@@ -651,8 +651,18 @@ void OMPClausePrinter::VisitOMPProcBindC
 }
 
 void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
-  OS << "schedule("
-     << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
+  OS << "schedule(";
+  if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
+    OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
+                                        Node->getFirstScheduleModifier());
+    if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
+      OS << ", ";
+      OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
+                                          Node->getSecondScheduleModifier());
+    }
+    OS << ": ";
+  }
+  OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
   if (Node->getChunkSize()) {
     OS << ", ";
     Node->getChunkSize()->printPretty(OS, nullptr, Policy);

Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Mon Dec 28 01:25:51 2015
@@ -87,8 +87,11 @@ unsigned clang::getOpenMPSimpleClauseTyp
 #include "clang/Basic/OpenMPKinds.def"
         .Default(OMPC_PROC_BIND_unknown);
   case OMPC_schedule:
-    return llvm::StringSwitch<OpenMPScheduleClauseKind>(Str)
-#define OPENMP_SCHEDULE_KIND(Name) .Case(#Name, OMPC_SCHEDULE_##Name)
+    return llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_SCHEDULE_KIND(Name)                                             \
+  .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_##Name))
+#define OPENMP_SCHEDULE_MODIFIER(Name)                                         \
+  .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_MODIFIER_##Name))
 #include "clang/Basic/OpenMPKinds.def"
         .Default(OMPC_SCHEDULE_unknown);
   case OMPC_depend:
@@ -173,12 +176,17 @@ const char *clang::getOpenMPSimpleClause
   case OMPC_schedule:
     switch (Type) {
     case OMPC_SCHEDULE_unknown:
+    case OMPC_SCHEDULE_MODIFIER_last:
       return "unknown";
 #define OPENMP_SCHEDULE_KIND(Name)                                             \
-  case OMPC_SCHEDULE_##Name:                                                   \
-    return #Name;
+    case OMPC_SCHEDULE_##Name:                                                 \
+      return #Name;
+#define OPENMP_SCHEDULE_MODIFIER(Name)                                         \
+    case OMPC_SCHEDULE_MODIFIER_##Name:                                        \
+      return #Name;
 #include "clang/Basic/OpenMPKinds.def"
     }
+    llvm_unreachable("Invalid OpenMP 'schedule' clause type");
   case OMPC_depend:
     switch (Type) {
     case OMPC_DEPEND_unknown:
@@ -188,7 +196,7 @@ const char *clang::getOpenMPSimpleClause
     return #Name;
 #include "clang/Basic/OpenMPKinds.def"
     }
-    llvm_unreachable("Invalid OpenMP 'schedule' clause type");
+    llvm_unreachable("Invalid OpenMP 'depend' clause type");
   case OMPC_linear:
     switch (Type) {
     case OMPC_LINEAR_unknown:

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Mon Dec 28 01:25:51 2015
@@ -675,7 +675,8 @@ OMPClause *Parser::ParseOpenMPClause(Ope
 /// argument like 'schedule' or 'dist_schedule'.
 ///
 ///    schedule-clause:
-///      'schedule' '(' kind [',' expression ] ')'
+///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
+///      ')'
 ///
 ///    if-clause:
 ///      'if' '(' [ directive-name-modifier ':' ] expression ')'
@@ -690,24 +691,60 @@ OMPClause *Parser::ParseOpenMPSingleExpr
     return nullptr;
 
   ExprResult Val;
-  unsigned Arg;
-  SourceLocation KLoc;
+  SmallVector<unsigned, 4> Arg;
+  SmallVector<SourceLocation, 4> KLoc;
   if (Kind == OMPC_schedule) {
-    Arg = getOpenMPSimpleClauseType(
+    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
+    Arg.resize(NumberOfElements);
+    KLoc.resize(NumberOfElements);
+    Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
+    Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
+    Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
+    auto KindModifier = getOpenMPSimpleClauseType(
         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
-    KLoc = Tok.getLocation();
+    if (KindModifier > OMPC_SCHEDULE_unknown) {
+      // Parse 'modifier'
+      Arg[Modifier1] = KindModifier;
+      KLoc[Modifier1] = Tok.getLocation();
+      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+          Tok.isNot(tok::annot_pragma_openmp_end))
+        ConsumeAnyToken();
+      if (Tok.is(tok::comma)) {
+        // Parse ',' 'modifier'
+        ConsumeAnyToken();
+        KindModifier = getOpenMPSimpleClauseType(
+            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+        Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
+                             ? KindModifier
+                             : OMPC_SCHEDULE_unknown;
+        KLoc[Modifier2] = Tok.getLocation();
+        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+            Tok.isNot(tok::annot_pragma_openmp_end))
+          ConsumeAnyToken();
+      }
+      // Parse ':'
+      if (Tok.is(tok::colon))
+        ConsumeAnyToken();
+      else
+        Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
+      KindModifier = getOpenMPSimpleClauseType(
+          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+    }
+    Arg[ScheduleKind] = KindModifier;
+    KLoc[ScheduleKind] = Tok.getLocation();
     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
         Tok.isNot(tok::annot_pragma_openmp_end))
       ConsumeAnyToken();
-    if ((Arg == OMPC_SCHEDULE_static || Arg == OMPC_SCHEDULE_dynamic ||
-         Arg == OMPC_SCHEDULE_guided) &&
+    if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
+         Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
+         Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
         Tok.is(tok::comma))
       DelimLoc = ConsumeAnyToken();
   } else {
     assert(Kind == OMPC_if);
-    KLoc = Tok.getLocation();
-    Arg = ParseOpenMPDirectiveKind(*this);
-    if (Arg != OMPD_unknown) {
+    KLoc.push_back(Tok.getLocation());
+    Arg.push_back(ParseOpenMPDirectiveKind(*this));
+    if (Arg.back() != OMPD_unknown) {
       ConsumeToken();
       if (Tok.is(tok::colon))
         DelimLoc = ConsumeToken();

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Mon Dec 28 01:25:51 2015
@@ -1624,6 +1624,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(St
   }
 
   OMPOrderedClause *OC = nullptr;
+  OMPScheduleClause *SC = nullptr;
   SmallVector<OMPLinearClause *, 4> LCs;
   // This is required for proper codegen.
   for (auto *Clause : Clauses) {
@@ -1646,20 +1647,40 @@ StmtResult Sema::ActOnOpenMPRegionEnd(St
       // Required for proper codegen of combined directives.
       // TODO: add processing for other clauses.
       if (auto *E = cast_or_null<Expr>(
-              cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) {
-          MarkDeclarationsReferencedInExpr(E);
-        }
+              cast<OMPScheduleClause>(Clause)->getHelperChunkSize()))
+        MarkDeclarationsReferencedInExpr(E);
     }
-    if (Clause->getClauseKind() == OMPC_ordered)
+    if (Clause->getClauseKind() == OMPC_schedule)
+      SC = cast<OMPScheduleClause>(Clause);
+    else if (Clause->getClauseKind() == OMPC_ordered)
       OC = cast<OMPOrderedClause>(Clause);
     else if (Clause->getClauseKind() == OMPC_linear)
       LCs.push_back(cast<OMPLinearClause>(Clause));
   }
+  bool ErrorFound = false;
+  // OpenMP, 2.7.1 Loop Construct, Restrictions
+  // The nonmonotonic modifier cannot be specified if an ordered clause is
+  // specified.
+  if (SC &&
+      (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
+       SC->getSecondScheduleModifier() ==
+           OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
+      OC) {
+    Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
+             ? SC->getFirstScheduleModifierLoc()
+             : SC->getSecondScheduleModifierLoc(),
+         diag::err_omp_schedule_nonmonotonic_ordered)
+        << SourceRange(OC->getLocStart(), OC->getLocEnd());
+    ErrorFound = true;
+  }
   if (!LCs.empty() && OC && OC->getNumForLoops()) {
     for (auto *C : LCs) {
       Diag(C->getLocStart(), diag::err_omp_linear_ordered)
           << SourceRange(OC->getLocStart(), OC->getLocEnd());
     }
+    ErrorFound = true;
+  }
+  if (ErrorFound) {
     ActOnCapturedRegionError();
     return StmtError();
   }
@@ -5960,33 +5981,41 @@ OMPClause *Sema::ActOnOpenMPSimpleClause
   return Res;
 }
 
+static std::string
+getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
+                        ArrayRef<unsigned> Exclude = llvm::None) {
+  std::string Values;
+  unsigned Bound = Last >= 2 ? Last - 2 : 0;
+  unsigned Skipped = Exclude.size();
+  auto S = Exclude.begin(), E = Exclude.end();
+  for (unsigned i = First; i < Last; ++i) {
+    if (std::find(S, E, i) != E) {
+      --Skipped;
+      continue;
+    }
+    Values += "'";
+    Values += getOpenMPSimpleClauseTypeName(K, i);
+    Values += "'";
+    if (i == Bound - Skipped)
+      Values += " or ";
+    else if (i != Bound + 1 - Skipped)
+      Values += ", ";
+  }
+  return Values;
+}
+
 OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
                                           SourceLocation KindKwLoc,
                                           SourceLocation StartLoc,
                                           SourceLocation LParenLoc,
                                           SourceLocation EndLoc) {
   if (Kind == OMPC_DEFAULT_unknown) {
-    std::string Values;
     static_assert(OMPC_DEFAULT_unknown > 0,
                   "OMPC_DEFAULT_unknown not greater than 0");
-    std::string Sep(", ");
-    for (unsigned i = 0; i < OMPC_DEFAULT_unknown; ++i) {
-      Values += "'";
-      Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
-      Values += "'";
-      switch (i) {
-      case OMPC_DEFAULT_unknown - 2:
-        Values += " or ";
-        break;
-      case OMPC_DEFAULT_unknown - 1:
-        break;
-      default:
-        Values += Sep;
-        break;
-      }
-    }
     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
-        << Values << getOpenMPClauseName(OMPC_default);
+        << getListOfPossibleValues(OMPC_default, /*First=*/0,
+                                   /*Last=*/OMPC_DEFAULT_unknown)
+        << getOpenMPClauseName(OMPC_default);
     return nullptr;
   }
   switch (Kind) {
@@ -6010,25 +6039,10 @@ OMPClause *Sema::ActOnOpenMPProcBindClau
                                            SourceLocation LParenLoc,
                                            SourceLocation EndLoc) {
   if (Kind == OMPC_PROC_BIND_unknown) {
-    std::string Values;
-    std::string Sep(", ");
-    for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) {
-      Values += "'";
-      Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i);
-      Values += "'";
-      switch (i) {
-      case OMPC_PROC_BIND_unknown - 2:
-        Values += " or ";
-        break;
-      case OMPC_PROC_BIND_unknown - 1:
-        break;
-      default:
-        Values += Sep;
-        break;
-      }
-    }
     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
-        << Values << getOpenMPClauseName(OMPC_proc_bind);
+        << getListOfPossibleValues(OMPC_proc_bind, /*First=*/0,
+                                   /*Last=*/OMPC_PROC_BIND_unknown)
+        << getOpenMPClauseName(OMPC_proc_bind);
     return nullptr;
   }
   return new (Context)
@@ -6036,21 +6050,28 @@ OMPClause *Sema::ActOnOpenMPProcBindClau
 }
 
 OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
-    OpenMPClauseKind Kind, unsigned Argument, Expr *Expr,
+    OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
     SourceLocation StartLoc, SourceLocation LParenLoc,
-    SourceLocation ArgumentLoc, SourceLocation DelimLoc,
+    ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
     SourceLocation EndLoc) {
   OMPClause *Res = nullptr;
   switch (Kind) {
   case OMPC_schedule:
+    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
+    assert(Argument.size() == NumberOfElements &&
+           ArgumentLoc.size() == NumberOfElements);
     Res = ActOnOpenMPScheduleClause(
-        static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc,
-        LParenLoc, ArgumentLoc, DelimLoc, EndLoc);
+        static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
+        static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
+        static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
+        StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
+        ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
     break;
   case OMPC_if:
-    Res =
-        ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument), Expr,
-                            StartLoc, LParenLoc, ArgumentLoc, DelimLoc, EndLoc);
+    assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
+    Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
+                              Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
+                              DelimLoc, EndLoc);
     break;
   case OMPC_final:
   case OMPC_num_threads:
@@ -6097,32 +6118,74 @@ OMPClause *Sema::ActOnOpenMPSingleExprWi
   return Res;
 }
 
+static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
+                                   OpenMPScheduleClauseModifier M2,
+                                   SourceLocation M1Loc, SourceLocation M2Loc) {
+  if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
+    SmallVector<unsigned, 2> Excluded;
+    if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
+      Excluded.push_back(M2);
+    if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
+      Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
+    if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
+      Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
+    S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
+        << getListOfPossibleValues(OMPC_schedule,
+                                   /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
+                                   /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
+                                   Excluded)
+        << getOpenMPClauseName(OMPC_schedule);
+    return true;
+  }
+  return false;
+}
+
 OMPClause *Sema::ActOnOpenMPScheduleClause(
+    OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
     OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
-    SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
-    SourceLocation EndLoc) {
+    SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+    SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
+  if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
+      checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
+    return nullptr;
+  // OpenMP, 2.7.1, Loop Construct, Restrictions
+  // Either the monotonic modifier or the nonmonotonic modifier can be specified
+  // but not both.
+  if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
+      (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
+       M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
+      (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
+       M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
+    Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
+        << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
+        << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
+    return nullptr;
+  }
   if (Kind == OMPC_SCHEDULE_unknown) {
     std::string Values;
-    std::string Sep(", ");
-    for (unsigned i = 0; i < OMPC_SCHEDULE_unknown; ++i) {
-      Values += "'";
-      Values += getOpenMPSimpleClauseTypeName(OMPC_schedule, i);
-      Values += "'";
-      switch (i) {
-      case OMPC_SCHEDULE_unknown - 2:
-        Values += " or ";
-        break;
-      case OMPC_SCHEDULE_unknown - 1:
-        break;
-      default:
-        Values += Sep;
-        break;
-      }
+    if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
+      unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
+      Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
+                                       /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
+                                       Exclude);
+    } else {
+      Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
+                                       /*Last=*/OMPC_SCHEDULE_unknown);
     }
     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
         << Values << getOpenMPClauseName(OMPC_schedule);
     return nullptr;
   }
+  // OpenMP, 2.7.1, Loop Construct, Restrictions
+  // The nonmonotonic modifier can only be specified with schedule(dynamic) or
+  // schedule(guided).
+  if ((M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
+       M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
+      Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
+    Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
+         diag::err_omp_schedule_nonmonotonic_static);
+    return nullptr;
+  }
   Expr *ValExpr = ChunkSize;
   Expr *HelperValExpr = nullptr;
   if (ChunkSize) {
@@ -6158,8 +6221,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClau
     }
   }
 
-  return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc,
-                                         EndLoc, Kind, ValExpr, HelperValExpr);
+  return new (Context)
+      OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
+                        ValExpr, HelperValExpr, M1, M1Loc, M2, M2Loc);
 }
 
 OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
@@ -8046,39 +8110,18 @@ Sema::ActOnOpenMPDependClause(OpenMPDepe
                               SourceLocation LParenLoc, SourceLocation EndLoc) {
   if (DSAStack->getCurrentDirective() == OMPD_ordered &&
       DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
-    std::string Values = "'";
-    Values += getOpenMPSimpleClauseTypeName(OMPC_depend, OMPC_DEPEND_source);
-    Values += "' or '";
-    Values += getOpenMPSimpleClauseTypeName(OMPC_depend, OMPC_DEPEND_sink);
-    Values += "'";
     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
-        << Values << getOpenMPClauseName(OMPC_depend);
+        << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
     return nullptr;
   }
   if (DSAStack->getCurrentDirective() != OMPD_ordered &&
       (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
        DepKind == OMPC_DEPEND_sink)) {
-    std::string Values;
-    std::string Sep(", ");
-    for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) {
-      if (i == OMPC_DEPEND_source || i == OMPC_DEPEND_sink)
-        continue;
-      Values += "'";
-      Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i);
-      Values += "'";
-      switch (i) {
-      case OMPC_DEPEND_unknown - 4:
-        Values += " or ";
-        break;
-      case OMPC_DEPEND_unknown - 3:
-        break;
-      default:
-        Values += Sep;
-        break;
-      }
-    }
+    unsigned Except[] = {OMPC_DEPEND_source, OMPC_DEPEND_sink};
     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
-        << Values << getOpenMPClauseName(OMPC_depend);
+        << getListOfPossibleValues(OMPC_depend, /*First=*/0,
+                                   /*Last=*/OMPC_DEPEND_unknown, Except)
+        << getOpenMPClauseName(OMPC_depend);
     return nullptr;
   }
   SmallVector<Expr *, 8> Vars;

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Dec 28 01:25:51 2015
@@ -1478,15 +1478,14 @@ public:
   ///
   /// By default, performs semantic analysis to build the new OpenMP clause.
   /// Subclasses may override this routine to provide different behavior.
-  OMPClause *RebuildOMPScheduleClause(OpenMPScheduleClauseKind Kind,
-                                      Expr *ChunkSize,
-                                      SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation KindLoc,
-                                      SourceLocation CommaLoc,
-                                      SourceLocation EndLoc) {
+  OMPClause *RebuildOMPScheduleClause(
+      OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
+      OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+      SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+      SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
     return getSema().ActOnOpenMPScheduleClause(
-        Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
+        M1, M2, Kind, ChunkSize, StartLoc, LParenLoc, M1Loc, M2Loc, KindLoc,
+        CommaLoc, EndLoc);
   }
 
   /// \brief Build a new OpenMP 'ordered' clause.
@@ -7504,7 +7503,9 @@ TreeTransform<Derived>::TransformOMPSche
   if (E.isInvalid())
     return nullptr;
   return getDerived().RebuildOMPScheduleClause(
+      C->getFirstScheduleModifier(), C->getSecondScheduleModifier(),
       C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
+      C->getFirstScheduleModifierLoc(), C->getSecondScheduleModifierLoc(),
       C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
 }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Dec 28 01:25:51 2015
@@ -1929,9 +1929,15 @@ void OMPClauseReader::VisitOMPProcBindCl
 void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
   C->setScheduleKind(
        static_cast<OpenMPScheduleClauseKind>(Record[Idx++]));
+  C->setFirstScheduleModifier(
+      static_cast<OpenMPScheduleClauseModifier>(Record[Idx++]));
+  C->setSecondScheduleModifier(
+      static_cast<OpenMPScheduleClauseModifier>(Record[Idx++]));
   C->setChunkSize(Reader->Reader.ReadSubExpr());
   C->setHelperChunkSize(Reader->Reader.ReadSubExpr());
   C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+  C->setFirstScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
+  C->setSecondScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
   C->setScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
   C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
 }

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Dec 28 01:25:51 2015
@@ -1811,9 +1811,13 @@ void OMPClauseWriter::VisitOMPProcBindCl
 
 void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
   Record.push_back(C->getScheduleKind());
+  Record.push_back(C->getFirstScheduleModifier());
+  Record.push_back(C->getSecondScheduleModifier());
   Writer->Writer.AddStmt(C->getChunkSize());
   Writer->Writer.AddStmt(C->getHelperChunkSize());
   Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+  Writer->Writer.AddSourceLocation(C->getFirstScheduleModifierLoc(), Record);
+  Writer->Writer.AddSourceLocation(C->getSecondScheduleModifierLoc(), Record);
   Writer->Writer.AddSourceLocation(C->getScheduleKindLoc(), Record);
   Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record);
 }

Modified: cfe/trunk/test/OpenMP/for_schedule_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_schedule_messages.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_schedule_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_schedule_messages.cpp Mon Dec 28 01:25:51 2015
@@ -13,13 +13,23 @@ template <class T, typename S, int N, in
 T tmain(T argc, S **argv) {
   #pragma omp for schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp for schedule (auto // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for schedule (monotonic // expected-error {{expected ')'}} expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-warning {{missing ':' after schedule modifier - ignoring}} expected-note {{to match this '('}}
+  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic, // expected-error {{expected ')'}} expected-error {{expected 'simd' in OpenMP clause 'schedule'}} expected-warning {{missing ':' after schedule modifier - ignoring}} expected-note {{to match this '('}}
+  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (simd: // expected-error {{expected ')'}} expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-note {{to match this '('}}
+  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (monotonic, auto // expected-error {{expected ')'}} expected-warning {{missing ':' after schedule modifier - ignoring}} expected-error {{expected 'simd' in OpenMP clause 'schedule'}} expected-note {{to match this '('}}
+  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic: auto, // expected-error {{expected ')'}} expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp for schedule (auto,  // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
@@ -48,19 +58,37 @@ T tmain(T argc, S **argv) {
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp for schedule (static, N) // expected-error {{argument to 'schedule' clause must be a strictly positive integer value}}
   for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic: static) // expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic: auto) // expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic: runtime) // expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (monotonic, nonmonotonic: auto) // expected-error {{modifier 'nonmonotonic' cannot be used along with modifier 'monotonic'}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic, monotonic: auto) // expected-error {{modifier 'monotonic' cannot be used along with modifier 'nonmonotonic'}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic, nonmonotonic: auto) // expected-error {{modifier 'nonmonotonic' cannot be used along with modifier 'nonmonotonic'}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (monotonic, monotonic: auto) // expected-error {{modifier 'monotonic' cannot be used along with modifier 'monotonic'}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for schedule (nonmonotonic: guided) ordered // expected-error {{'schedule' clause with 'nonmonotonic' modifier cannot be specified if an 'ordered' clause is specified}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for ordered(1) schedule(nonmonotonic: dynamic) // expected-error {{'schedule' clause with 'nonmonotonic' modifier cannot be specified if an 'ordered' clause is specified}}
+  for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   return argc;
 }
 
 int main(int argc, char **argv) {
   #pragma omp for schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
-  #pragma omp for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
-  #pragma omp for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
   #pragma omp for schedule (auto // 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];
-  #pragma omp for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
   #pragma omp for schedule (auto,  // 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];

Modified: cfe/trunk/test/OpenMP/for_simd_schedule_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_simd_schedule_messages.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_simd_schedule_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_simd_schedule_messages.cpp Mon Dec 28 01:25:51 2015
@@ -13,13 +13,13 @@ template <class T, typename S, int N, in
 T tmain(T argc, S **argv) {
   #pragma omp for simd schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp for simd schedule (auto // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp for simd schedule (auto,  // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
@@ -54,13 +54,13 @@ T tmain(T argc, S **argv) {
 int main(int argc, char **argv) {
   #pragma omp for simd schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
-  #pragma omp for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
-  #pragma omp for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
   #pragma omp for simd schedule (auto // 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];
-  #pragma omp for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
   #pragma omp for simd schedule (auto,  // 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];

Modified: cfe/trunk/test/OpenMP/parallel_for_schedule_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_schedule_messages.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_schedule_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_schedule_messages.cpp Mon Dec 28 01:25:51 2015
@@ -13,13 +13,13 @@ template <class T, typename S, int N, in
 T tmain(T argc, S **argv) {
   #pragma omp parallel for schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp parallel for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp parallel for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp parallel for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp parallel for schedule (auto // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp parallel for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp parallel for schedule (auto,  // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
@@ -54,13 +54,13 @@ T tmain(T argc, S **argv) {
 int main(int argc, char **argv) {
   #pragma omp parallel for schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
-  #pragma omp parallel for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
-  #pragma omp parallel for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp parallel for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
   #pragma omp parallel for schedule (auto // 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];
-  #pragma omp parallel for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
   #pragma omp parallel for schedule (auto,  // 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];

Modified: cfe/trunk/test/OpenMP/parallel_for_simd_schedule_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_simd_schedule_messages.cpp?rev=256487&r1=256486&r2=256487&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_simd_schedule_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_simd_schedule_messages.cpp Mon Dec 28 01:25:51 2015
@@ -13,13 +13,13 @@ template <class T, typename S, int N, in
 T tmain(T argc, S **argv) {
   #pragma omp parallel for simd schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp parallel for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp parallel for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp parallel for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp parallel for simd schedule (auto // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp parallel for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp parallel for simd schedule (auto,  // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
@@ -54,13 +54,13 @@ T tmain(T argc, S **argv) {
 int main(int argc, char **argv) {
   #pragma omp parallel for simd schedule // expected-error {{expected '(' after 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
-  #pragma omp parallel for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for simd schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
-  #pragma omp parallel for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
+  #pragma omp parallel for simd schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
   #pragma omp parallel for simd schedule (auto // 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];
-  #pragma omp parallel for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel for simd schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} 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];
   #pragma omp parallel for simd schedule (auto,  // 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];




More information about the cfe-commits mailing list