[llvm] 56c1660 - [OpenMP] Initial parsing/sema for 'strict' modifier with 'num_tasks' clause

Mike Rice via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 18 16:27:14 PST 2022


Author: Fazlay Rabbi
Date: 2022-11-18T16:26:47-08:00
New Revision: 56c166017055595a9f26933e85bfd89e30c528d0

URL: https://github.com/llvm/llvm-project/commit/56c166017055595a9f26933e85bfd89e30c528d0
DIFF: https://github.com/llvm/llvm-project/commit/56c166017055595a9f26933e85bfd89e30c528d0.diff

LOG: [OpenMP] Initial parsing/sema for 'strict' modifier with 'num_tasks' clause

This patch gives basic parsing and semantic analysis support for 'strict'
modifier with 'num_tasks' clause of 'taskloop' construct introduced in
OpenMP 5.1 (section 2.12.2)

Differential Revision: https://reviews.llvm.org/D138328

Added: 
    

Modified: 
    clang/include/clang/AST/OpenMPClause.h
    clang/include/clang/Basic/OpenMPKinds.def
    clang/include/clang/Basic/OpenMPKinds.h
    clang/include/clang/Sema/Sema.h
    clang/lib/AST/OpenMPClause.cpp
    clang/lib/Basic/OpenMPKinds.cpp
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/test/OpenMP/taskloop_strict_modifier_ast_print.cpp
    clang/test/OpenMP/taskloop_strict_modifier_messages.cpp
    llvm/include/llvm/Frontend/OpenMP/OMP.td

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 1c9f62355e4ee..21d9f740eddf1 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -6486,26 +6486,43 @@ class OMPNumTasksClause : public OMPClause, public OMPClauseWithPreInit {
   /// Location of '('.
   SourceLocation LParenLoc;
 
+  /// Modifiers for 'num_tasks' clause.
+  OpenMPNumTasksClauseModifier Modifier = OMPC_NUMTASKS_unknown;
+
+  /// Location of the modifier.
+  SourceLocation ModifierLoc;
+
   /// Safe iteration space distance.
   Stmt *NumTasks = nullptr;
 
   /// Set safelen.
   void setNumTasks(Expr *Size) { NumTasks = Size; }
 
+  /// Sets modifier.
+  void setModifier(OpenMPNumTasksClauseModifier M) { Modifier = M; }
+
+  /// Sets modifier location.
+  void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
+
 public:
   /// Build 'num_tasks' clause.
   ///
+  /// \param Modifier Clause modifier.
   /// \param Size Expression associated with this clause.
   /// \param HelperSize Helper grainsize for the construct.
   /// \param CaptureRegion Innermost OpenMP region where expressions in this
   /// clause must be captured.
   /// \param StartLoc Starting location of the clause.
   /// \param EndLoc Ending location of the clause.
-  OMPNumTasksClause(Expr *Size, Stmt *HelperSize,
-                    OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
-                    SourceLocation LParenLoc, SourceLocation EndLoc)
+  /// \param ModifierLoc Modifier location.
+  /// \param LParenLoc Location of '('.
+  OMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *Size,
+                    Stmt *HelperSize, OpenMPDirectiveKind CaptureRegion,
+                    SourceLocation StartLoc, SourceLocation LParenLoc,
+                    SourceLocation ModifierLoc, SourceLocation EndLoc)
       : OMPClause(llvm::omp::OMPC_num_tasks, StartLoc, EndLoc),
-        OMPClauseWithPreInit(this), LParenLoc(LParenLoc), NumTasks(Size) {
+        OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Modifier(Modifier),
+        ModifierLoc(ModifierLoc), NumTasks(Size) {
     setPreInitStmt(HelperSize, CaptureRegion);
   }
 
@@ -6524,6 +6541,12 @@ class OMPNumTasksClause : public OMPClause, public OMPClauseWithPreInit {
   /// Return safe iteration space distance.
   Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); }
 
+  /// Gets modifier.
+  OpenMPNumTasksClauseModifier getModifier() const { return Modifier; }
+
+  /// Gets modifier location.
+  SourceLocation getModifierLoc() const { return ModifierLoc; }
+
   child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
 
   const_child_range children() const {

diff  --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index 339139abe2a49..a084e9686f5ee 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -74,6 +74,9 @@
 #ifndef OPENMP_GRAINSIZE_MODIFIER
 #define OPENMP_GRAINSIZE_MODIFIER(Name)
 #endif
+#ifndef OPENMP_NUMTASKS_MODIFIER
+#define OPENMP_NUMTASKS_MODIFIER(Name)
+#endif
 
 // Static attributes for 'schedule' clause.
 OPENMP_SCHEDULE_KIND(static)
@@ -187,6 +190,10 @@ OPENMP_BIND_KIND(thread)
 // Modifiers for the 'grainsize' clause.
 OPENMP_GRAINSIZE_MODIFIER(strict)
 
+// Modifiers for the 'num_tasks' clause.
+OPENMP_NUMTASKS_MODIFIER(strict)
+
+#undef OPENMP_NUMTASKS_MODIFIER
 #undef OPENMP_GRAINSIZE_MODIFIER
 #undef OPENMP_BIND_KIND
 #undef OPENMP_ADJUST_ARGS_KIND

diff  --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index da13756b93a47..814c245e8b5b4 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -201,6 +201,12 @@ enum OpenMPGrainsizeClauseModifier {
   OMPC_GRAINSIZE_unknown
 };
 
+enum OpenMPNumTasksClauseModifier {
+#define OPENMP_NUMTASKS_MODIFIER(Name) OMPC_NUMTASKS_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+  OMPC_NUMTASKS_unknown
+};
+
 /// Contains 'interop' data for 'append_args' and 'init' clauses.
 class Expr;
 struct OMPInteropInfo final {

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4628ffe606c6a..82d5ae169c7b3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11685,8 +11685,10 @@ class Sema final {
                                         SourceLocation ModifierLoc,
                                         SourceLocation EndLoc);
   /// Called on well-formed 'num_tasks' clause.
-  OMPClause *ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
+  OMPClause *ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier,
+                                       Expr *NumTasks, SourceLocation StartLoc,
                                        SourceLocation LParenLoc,
+                                       SourceLocation ModifierLoc,
                                        SourceLocation EndLoc);
   /// Called on well-formed 'hint' clause.
   OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,

diff  --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 07022a7e1faa9..1bf14806ce836 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1931,6 +1931,11 @@ void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) {
 
 void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) {
   OS << "num_tasks(";
+  OpenMPNumTasksClauseModifier Modifier = Node->getModifier();
+  if (Modifier != OMPC_NUMTASKS_unknown) {
+    OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier)
+       << ": ";
+  }
   Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0);
   OS << ")";
 }

diff  --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 2a46b462cf0f3..81d68a4c1f459 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -158,6 +158,15 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
       return OMPC_GRAINSIZE_unknown;
     return Type;
   }
+  case OMPC_num_tasks: {
+    unsigned Type = llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_NUMTASKS_MODIFIER(Name) .Case(#Name, OMPC_NUMTASKS_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+                        .Default(OMPC_NUMTASKS_unknown);
+    if (LangOpts.OpenMP < 51)
+      return OMPC_NUMTASKS_unknown;
+    return Type;
+  }
   case OMPC_unknown:
   case OMPC_threadprivate:
   case OMPC_if:
@@ -198,7 +207,6 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_nogroup:
-  case OMPC_num_tasks:
   case OMPC_hint:
   case OMPC_uniform:
   case OMPC_use_device_ptr:
@@ -454,6 +462,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
 #include "clang/Basic/OpenMPKinds.def"
     }
     llvm_unreachable("Invalid OpenMP 'grainsize' clause modifier");
+  case OMPC_num_tasks:
+    switch (Type) {
+    case OMPC_NUMTASKS_unknown:
+      return "unknown";
+#define OPENMP_NUMTASKS_MODIFIER(Name)                                         \
+  case OMPC_NUMTASKS_##Name:                                                   \
+    return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+    }
+    llvm_unreachable("Invalid OpenMP 'num_tasks' clause modifier");
   case OMPC_unknown:
   case OMPC_threadprivate:
   case OMPC_if:
@@ -494,7 +512,6 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_nogroup:
-  case OMPC_num_tasks:
   case OMPC_hint:
   case OMPC_uniform:
   case OMPC_use_device_ptr:

diff  --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 820dd179610b6..e8b60ce81fcbb 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3226,7 +3226,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
     if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
         PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
       Clause = ParseOpenMPClause(CKind, WrongDirective);
-    else if (CKind == OMPC_grainsize)
+    else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
       Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
     else
       Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
@@ -3900,6 +3900,33 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
       Arg.push_back(OMPC_GRAINSIZE_unknown);
       KLoc.emplace_back();
     }
+  } else if (Kind == OMPC_num_tasks) {
+    // Parse optional <num_tasks modifier> ':'
+    OpenMPNumTasksClauseModifier Modifier =
+        static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
+            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
+            getLangOpts()));
+    if (getLangOpts().OpenMP >= 51) {
+      if (NextToken().is(tok::colon)) {
+        Arg.push_back(Modifier);
+        KLoc.push_back(Tok.getLocation());
+        // Parse modifier
+        ConsumeAnyToken();
+        // Parse ':'
+        ConsumeAnyToken();
+      } else {
+        if (Modifier == OMPC_NUMTASKS_strict) {
+          Diag(Tok, diag::err_modifier_expected_colon) << "strict";
+          // Parse modifier
+          ConsumeAnyToken();
+        }
+        Arg.push_back(OMPC_NUMTASKS_unknown);
+        KLoc.emplace_back();
+      }
+    } else {
+      Arg.push_back(OMPC_NUMTASKS_unknown);
+      KLoc.emplace_back();
+    }
   } else {
     assert(Kind == OMPC_if);
     KLoc.push_back(Tok.getLocation());
@@ -3923,7 +3950,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
   bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
                           (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
                           Kind == OMPC_if || Kind == OMPC_device ||
-                          Kind == OMPC_grainsize;
+                          Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
   if (NeedAnExpression) {
     SourceLocation ELoc = Tok.getLocation();
     ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index a67983da2b66e..e150b0d65ad34 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -15110,9 +15110,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
   case OMPC_priority:
     Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
     break;
-  case OMPC_num_tasks:
-    Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc);
-    break;
   case OMPC_hint:
     Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
     break;
@@ -15138,6 +15135,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
     Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
     break;
   case OMPC_grainsize:
+  case OMPC_num_tasks:
   case OMPC_device:
   case OMPC_if:
   case OMPC_default:
@@ -16884,6 +16882,13 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
         static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
     break;
+  case OMPC_num_tasks:
+    assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
+           "Modifier for num_tasks clause and its location are expected.");
+    Res = ActOnOpenMPNumTasksClause(
+        static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
+        StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
+    break;
   case OMPC_final:
   case OMPC_num_threads:
   case OMPC_safelen:
@@ -16930,7 +16935,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_nogroup:
-  case OMPC_num_tasks:
   case OMPC_hint:
   case OMPC_unknown:
   case OMPC_uniform:
@@ -22393,10 +22397,21 @@ OMPClause *Sema::ActOnOpenMPGrainsizeClause(
                          StartLoc, LParenLoc, ModifierLoc, EndLoc);
 }
 
-OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
-                                           SourceLocation StartLoc,
-                                           SourceLocation LParenLoc,
-                                           SourceLocation EndLoc) {
+OMPClause *Sema::ActOnOpenMPNumTasksClause(
+    OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
+    SourceLocation StartLoc, SourceLocation LParenLoc,
+    SourceLocation ModifierLoc, SourceLocation EndLoc) {
+  assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
+         "Unexpected num_tasks modifier in OpenMP < 51.");
+
+  if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
+    std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
+                                                 OMPC_NUMTASKS_unknown);
+    Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
+        << Values << getOpenMPClauseName(OMPC_num_tasks);
+    return nullptr;
+  }
+
   Expr *ValExpr = NumTasks;
   Stmt *HelperValStmt = nullptr;
   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
@@ -22410,8 +22425,9 @@ OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
           DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
     return nullptr;
 
-  return new (Context) OMPNumTasksClause(ValExpr, HelperValStmt, CaptureRegion,
-                                         StartLoc, LParenLoc, EndLoc);
+  return new (Context)
+      OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
+                        StartLoc, LParenLoc, ModifierLoc, EndLoc);
 }
 
 OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index ee633289db3b9..a917007ee82cf 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2064,11 +2064,13 @@ class TreeTransform {
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide 
diff erent behavior.
-  OMPClause *RebuildOMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
+  OMPClause *RebuildOMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier,
+                                      Expr *NumTasks, SourceLocation StartLoc,
                                       SourceLocation LParenLoc,
+                                      SourceLocation ModifierLoc,
                                       SourceLocation EndLoc) {
-    return getSema().ActOnOpenMPNumTasksClause(NumTasks, StartLoc, LParenLoc,
-                                               EndLoc);
+    return getSema().ActOnOpenMPNumTasksClause(Modifier, NumTasks, StartLoc,
+                                               LParenLoc, ModifierLoc, EndLoc);
   }
 
   /// Build a new OpenMP 'hint' clause.
@@ -10363,7 +10365,8 @@ TreeTransform<Derived>::TransformOMPNumTasksClause(OMPNumTasksClause *C) {
   if (E.isInvalid())
     return nullptr;
   return getDerived().RebuildOMPNumTasksClause(
-      E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+      C->getModifier(), E.get(), C->getBeginLoc(), C->getLParenLoc(),
+      C->getModifierLoc(), C->getEndLoc());
 }
 
 template <typename Derived>

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 83e539d14d887..7dc935a68c083 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10792,7 +10792,9 @@ void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
 
 void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
   VisitOMPClauseWithPreInit(C);
+  C->setModifier(Record.readEnum<OpenMPNumTasksClauseModifier>());
   C->setNumTasks(Record.readSubExpr());
+  C->setModifierLoc(Record.readSourceLocation());
   C->setLParenLoc(Record.readSourceLocation());
 }
 

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 2567cb3803835..329407a30f5f9 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6798,7 +6798,9 @@ void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
 
 void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
   VisitOMPClauseWithPreInit(C);
+  Record.writeEnum(C->getModifier());
   Record.AddStmt(C->getNumTasks());
+  Record.AddSourceLocation(C->getModifierLoc());
   Record.AddSourceLocation(C->getLParenLoc());
 }
 

diff  --git a/clang/test/OpenMP/taskloop_strict_modifier_ast_print.cpp b/clang/test/OpenMP/taskloop_strict_modifier_ast_print.cpp
index 3f2494e16588a..84538582108c4 100644
--- a/clang/test/OpenMP/taskloop_strict_modifier_ast_print.cpp
+++ b/clang/test/OpenMP/taskloop_strict_modifier_ast_print.cpp
@@ -56,6 +56,46 @@ T tmain(T argc) {
   // CHECK-NEXT: #pragma omp cancel taskgroup
   // CHECK-NEXT: #pragma omp cancellation point taskgroup
   // CHECK-NEXT: foo();
+
+#pragma omp taskgroup
+#pragma omp taskloop num_tasks(strict: N)
+  // CHECK: #pragma omp taskgroup
+  // CHECK-NEXT: #pragma omp taskloop num_tasks(strict: N)
+  for (int i = 0; i < 2; ++i)
+    a = 2;
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp parallel
+#pragma omp taskloop num_tasks(strict: N)
+  for (int i = 0; i < 2; ++i)
+    for (int j = 0; j < 2; ++j)
+      for (int j = 0; j < 2; ++j)
+        for (int j = 0; j < 2; ++j)
+          for (int j = 0; j < 2; ++j)
+  for (int i = 0; i < 2; ++i)
+    for (int j = 0; j < 2; ++j)
+      for (int j = 0; j < 2; ++j)
+        for (int j = 0; j < 2; ++j)
+          for (int j = 0; j < 2; ++j) {
+#pragma omp cancel taskgroup
+#pragma omp cancellation point taskgroup
+            foo();
+          }
+  // CHECK-NEXT: #pragma omp parallel
+  // CHECK-NEXT: #pragma omp taskloop num_tasks(strict: N)
+  // CHECK-NEXT: for (int i = 0; i < 2; ++i)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int i = 0; i < 2; ++i)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j) {
+  // CHECK-NEXT: #pragma omp cancel taskgroup
+  // CHECK-NEXT: #pragma omp cancellation point taskgroup
+  // CHECK-NEXT: foo();
   return T();
 }
 
@@ -136,6 +176,77 @@ int main(int argc, char **argv) {
    // CHECK-NEXT: for (int i = 0; i < 10; ++i)
    // CHECK-NEXT: foo();
 
+#pragma omp taskloop num_tasks(strict: argc)
+  for (int i = 0; i < 10; ++i)
+    foo();
+  // CHECK: #pragma omp taskloop num_tasks(strict: argc)
+  // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+  // CHECK-NEXT: foo();
+
+#pragma omp parallel
+#pragma omp masked taskloop num_tasks(strict: argc)
+  for (int i = 0; i < 10; ++i)
+    foo();
+  // CHECK: #pragma omp parallel
+  // CHECK-NEXT: #pragma omp masked taskloop num_tasks(strict: argc)
+  // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+  // CHECK-NEXT: foo();
+
+#pragma omp parallel
+#pragma omp masked taskloop simd num_tasks(strict: argc)
+   for (int i = 0; i < 10; ++i)
+     foo();
+   // CHECK: #pragma omp parallel
+   // CHECK-NEXT: #pragma omp masked taskloop simd num_tasks(strict: argc)
+   // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+   // CHECK-NEXT: foo();
+
+#pragma omp parallel masked taskloop num_tasks(strict: argc)
+  for (int i = 0; i < 10; ++i)
+    foo();
+  // CHECK-NEXT: #pragma omp parallel masked taskloop num_tasks(strict: argc)
+  // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+  // CHECK-NEXT: foo();
+
+#pragma omp parallel masked taskloop simd num_tasks(strict: argc)
+   for (int i = 0; i < 10; ++i)
+     foo();
+   // CHECK-NEXT: #pragma omp parallel masked taskloop simd num_tasks(strict: argc)
+   // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+   // CHECK-NEXT: foo();
+
+#pragma omp parallel
+#pragma omp master taskloop num_tasks(strict: argc)
+  for (int i = 0; i < 10; ++i)
+    foo();
+  // CHECK: #pragma omp parallel
+  // CHECK-NEXT: #pragma omp master taskloop num_tasks(strict: argc)
+  // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+  // CHECK-NEXT: foo();
+
+#pragma omp parallel
+#pragma omp master taskloop simd num_tasks(strict: argc)
+   for (int i = 0; i < 10; ++i)
+     foo();
+   // CHECK: #pragma omp parallel
+   // CHECK-NEXT: #pragma omp master taskloop simd num_tasks(strict: argc)
+   // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+   // CHECK-NEXT: foo();
+
+#pragma omp parallel master taskloop num_tasks(strict: argc)
+  for (int i = 0; i < 10; ++i)
+    foo();
+  // CHECK-NEXT: #pragma omp parallel master taskloop num_tasks(strict: argc)
+  // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+  // CHECK-NEXT: foo();
+
+#pragma omp parallel master taskloop simd num_tasks(strict: argc)
+   for (int i = 0; i < 10; ++i)
+     foo();
+   // CHECK-NEXT: #pragma omp parallel master taskloop simd num_tasks(strict: argc)
+   // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+   // CHECK-NEXT: foo();
+
   return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0]));
 }
 

diff  --git a/clang/test/OpenMP/taskloop_strict_modifier_messages.cpp b/clang/test/OpenMP/taskloop_strict_modifier_messages.cpp
index e9024a0aa523a..423554fb37d07 100644
--- a/clang/test/OpenMP/taskloop_strict_modifier_messages.cpp
+++ b/clang/test/OpenMP/taskloop_strict_modifier_messages.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -verify=expected,omp51 -fopenmp -fopenmp-version=51 -ferror-limit 100 %s -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp51 -fopenmp -fopenmp-version=51 -ferror-limit 150 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 150 %s -Wuninitialized
 
-// RUN: %clang_cc1 -verify=expected,omp51 -fopenmp -fopenmp-version=51 -fopenmp-simd -ferror-limit 100 %s -Wuninitialized
-// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -fopenmp-simd -ferror-limit 100 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp51 -fopenmp -fopenmp-version=51 -fopenmp-simd -ferror-limit 150 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -fopenmp-simd -ferror-limit 150 %s -Wuninitialized
 
 void foo() {
 }
@@ -23,7 +23,15 @@ int tmain(T argc, S **argv) {
   #pragma omp taskloop grainsize(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'grainsize'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
   for (int i = 0; i < 10; ++i)
      foo();
-
+  #pragma omp taskloop num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp taskloop num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp taskloop num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
   return 0;
 }
 
@@ -108,6 +116,83 @@ int main(int argc, char **argv) {
   #pragma omp parallel master taskloop simd grainsize(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'grainsize'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
   for (int i = 0; i < 10; ++i)
      foo();
-
+  #pragma omp masked taskloop num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp masked taskloop num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp masked taskloop num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
+  
+  #pragma omp masked taskloop simd num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp masked taskloop simd num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp masked taskloop simd num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
+  
+  #pragma omp parallel masked taskloop num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel masked taskloop num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel masked taskloop num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
+  
+  #pragma omp parallel masked taskloop simd num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel masked taskloop simd num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel masked taskloop simd num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
+  
+  #pragma omp master taskloop num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp master taskloop num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp master taskloop num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
+  
+  #pragma omp master taskloop simd num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp master taskloop simd num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp master taskloop simd num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
+  #pragma omp parallel master taskloop num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel master taskloop num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel master taskloop num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
+  
+  #pragma omp parallel master taskloop simd num_tasks(strict 10) // omp51-error {{missing ':' after strict modifier}} omp50-error {{use of undeclared identifier 'strict'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel master taskloop simd num_tasks(aa 10) // omp51-error {{use of undeclared identifier 'aa'}} omp51-error {{expected ')'}} omp51-note {{to match this '('}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+    foo();
+  #pragma omp parallel master taskloop simd num_tasks(aa: 10) // omp51-error {{expected 'strict' in OpenMP clause 'num_tasks'}} omp50-error {{use of undeclared identifier 'aa'}} omp50-error {{expected ')'}} omp50-note {{to match this '('}}
+  for (int i = 0; i < 10; ++i)
+     foo();
   return tmain(argc, argv);
 }

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 18a98ba6af749..49faa945b8358 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -246,9 +246,18 @@ def OMPC_GrainSize : Clause<"grainsize"> {
 def OMPC_NoGroup : Clause<"nogroup"> {
   let clangClass = "OMPNogroupClause";
 }
+
+def OMP_NUMTASKS_Strict : ClauseVal<"strict", 1, 1> {}
+def OMP_NUMTASKS_Unknown : ClauseVal<"unkonwn", 2, 0> { let isDefault = 1; }
+
 def OMPC_NumTasks : Clause<"num_tasks"> {
   let clangClass = "OMPNumTasksClause";
   let flangClass = "ScalarIntExpr";
+  let enumClauseValue = "NumTasksType";
+  let allowedClauseValues = [
+    OMP_NUMTASKS_Strict,
+    OMP_NUMTASKS_Unknown
+  ];
 }
 def OMPC_Hint : Clause<"hint"> {
   let clangClass = "OMPHintClause";


        


More information about the llvm-commits mailing list