]> granicus.if.org Git - clang/commitdiff
[OPENMP] Added initial checking of nesting of OpenMP regions.
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 24 Jun 2014 04:39:47 +0000 (04:39 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 24 Jun 2014 04:39:47 +0000 (04:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211566 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOpenMP.cpp
test/OpenMP/nesting_of_regions.cpp [new file with mode: 0644]

index 035a7377e18b472b0ecdbce8627befbb483f113f..98745ca9b8be5fca018e72f1095d0bb6a3714164 100644 (file)
@@ -7096,6 +7096,11 @@ def err_omp_reduction_in_task : Error<
   "reduction variables may not be accessed in an explicit task">;
 def err_omp_reduction_id_not_compatible : Error<
   "variable of type %0 is not valid for specified reduction operation">;
+def err_omp_prohibited_region : Error<
+  "region cannot be%select{| closely}0 nested inside '%1' region"
+  "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?}2">;
+def err_omp_prohibited_region_simd : Error<
+  "OpenMP constructs may not be nested inside a simd region">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {
index de3f860bdce45cfbd94eb4f851530ae9ddbae3da..561251c25655178fde6f622b4eb27379dc06b907 100644 (file)
@@ -152,6 +152,12 @@ public:
   OpenMPDirectiveKind getCurrentDirective() const {
     return Stack.back().Directive;
   }
+  /// \brief Returns parent directive.
+  OpenMPDirectiveKind getParentDirective() const {
+    if (Stack.size() > 2)
+      return Stack[Stack.size() - 2].Directive;
+    return OMPD_unknown;
+  }
 
   /// \brief Set default data sharing attribute to none.
   void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }
@@ -912,6 +918,41 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,
   }
 }
 
+bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
+                           OpenMPDirectiveKind CurrentRegion,
+                           SourceLocation StartLoc) {
+  if (Stack->getCurScope()) {
+    auto ParentRegion = Stack->getParentDirective();
+    bool NestingProhibited = false;
+    bool CloseNesting = true;
+    bool ShouldBeInParallelRegion = false;
+    if (isOpenMPSimdDirective(ParentRegion)) {
+      // OpenMP [2.16, Nesting of Regions]
+      // OpenMP constructs may not be nested inside a simd region.
+      SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd);
+      return true;
+    }
+    if (isOpenMPWorksharingDirective(CurrentRegion) &&
+        !isOpenMPParallelDirective(CurrentRegion) &&
+        !isOpenMPSimdDirective(CurrentRegion)) {
+      // OpenMP [2.16, Nesting of Regions]
+      // A worksharing region may not be closely nested inside a worksharing,
+      // explicit task, critical, ordered, atomic, or master region.
+      // TODO
+      NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) &&
+                          !isOpenMPSimdDirective(ParentRegion);
+      ShouldBeInParallelRegion = true;
+    }
+    if (NestingProhibited) {
+      SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
+          << CloseNesting << getOpenMPDirectiveName(ParentRegion) << true
+          << getOpenMPDirectiveName(CurrentRegion) << ShouldBeInParallelRegion;
+      return true;
+    }
+  }
+  return false;
+}
+
 StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
                                                 ArrayRef<OMPClause *> Clauses,
                                                 Stmt *AStmt,
@@ -920,6 +961,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
   assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
 
   StmtResult Res = StmtError();
+  if (CheckNestingOfRegions(*this, DSAStack, Kind, StartLoc))
+    return StmtError();
 
   // Check default data sharing attributes for referenced variables.
   DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
@@ -2246,7 +2289,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
       //  in a firstprivate clause on a worksharing construct if any of the
       //  worksharing regions arising from the worksharing construct ever bind
       //  to any of the parallel regions arising from the parallel construct.
-      if (isOpenMPWorksharingDirective(CurrDir)) {
+      if (isOpenMPWorksharingDirective(CurrDir) &&
+          !isOpenMPParallelDirective(CurrDir)) {
         DVar = DSAStack->getImplicitDSA(VD);
         if (DVar.CKind != OMPC_shared) {
           Diag(ELoc, diag::err_omp_required_access)
@@ -2357,7 +2401,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
     // lastprivate clause on a worksharing construct if any of the corresponding
     // worksharing regions ever binds to any of the corresponding parallel
     // regions.
-    if (isOpenMPWorksharingDirective(CurrDir)) {
+    if (isOpenMPWorksharingDirective(CurrDir) &&
+        !isOpenMPParallelDirective(CurrDir)) {
       DVar = DSAStack->getImplicitDSA(VD);
       if (DVar.CKind != OMPC_shared) {
         Diag(ELoc, diag::err_omp_required_access)
@@ -2748,7 +2793,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
     //  construct must be shared in the parallel regions to which any of the
     //  worksharing regions arising from the worksharing construct bind.
     OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
-    if (isOpenMPWorksharingDirective(CurrDir)) {
+    if (isOpenMPWorksharingDirective(CurrDir) &&
+        !isOpenMPParallelDirective(CurrDir)) {
       DVar = DSAStack->getImplicitDSA(VD);
       if (DVar.CKind != OMPC_shared) {
         Diag(ELoc, diag::err_omp_required_access)
diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp
new file mode 100644 (file)
index 0000000..a1f416f
--- /dev/null
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp=libiomp5 -verify %s
+
+template <class T>
+void foo() {
+#pragma omp parallel
+#pragma omp for
+  for (int i = 0; i < 10; ++i);
+#pragma omp parallel
+#pragma omp simd
+  for (int i = 0; i < 10; ++i);
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp simd
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp parallel
+  for (int i = 0; i < 10; ++i);
+  }
+}
+
+void foo() {
+#pragma omp parallel
+#pragma omp for
+  for (int i = 0; i < 10; ++i);
+#pragma omp parallel
+#pragma omp simd
+  for (int i = 0; i < 10; ++i);
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp simd
+  for (int i = 0; i < 10; ++i);
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp parallel
+  for (int i = 0; i < 10; ++i);
+  }
+  return foo<int>();
+}
+