Hi!

Currently if a target* pragma appears within a target region, GCC successfully
compiles such code (with a warning).  But the binary fails at run-time, since it
tries to call GOMP_target* functions on target.

The spec says: "If a target, target update, or target data construct appears
within a target region then the behavior is unspecified."

I see 2 options to make the behavior more user-friendly:
1. To return an error at compile-time.
2. To check at run-time in libgomp whether GOMP_target* is called on target, and
perform target-fallback if so.

If we will select option #1, the patch is ready.


diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index eaad52a..ae8b90a 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2682,8 +2682,14 @@ check_omp_nesting_restrictions (gimple stmt, omp_context 
*ctx)
        }
       break;
     case GIMPLE_OMP_TARGET:
-      for (; ctx != NULL; ctx = ctx->outer)
-       if (is_targetreg_ctx (ctx))
+      {
+       bool target_p = false;
+       if (cgraph_node::get (current_function_decl)->offloadable)
+         target_p = true;
+       for (; ctx != NULL && !target_p; ctx = ctx->outer)
+         if (is_targetreg_ctx (ctx))
+           target_p = true;
+       if (target_p)
          {
            const char *name;
            switch (gimple_omp_target_kind (stmt))
@@ -2693,9 +2699,11 @@ check_omp_nesting_restrictions (gimple stmt, omp_context 
*ctx)
              case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
              default: gcc_unreachable ();
              }
-           warning_at (gimple_location (stmt), 0,
-                       "%s construct inside of target region", name);
+           error_at (gimple_location (stmt),
+                     "%s construct inside of target region", name);
+           return false;
          }
+      }
       break;
     default:
       break;
diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-error-1.c 
b/gcc/testsuite/c-c++-common/gomp/nesting-error-1.c
new file mode 100644
index 0000000..ff6a75e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/nesting-error-1.c
@@ -0,0 +1,23 @@
+extern int i;
+
+void
+f_omp_target (void)
+{
+#pragma omp target
+  {
+#pragma omp target /* { dg-error "target construct inside of target region" } 
*/
+    ;
+#pragma omp target data /* { dg-error "target data construct inside of target 
region" } */
+    ;
+#pragma omp target update to(i) /* { dg-error "target update construct inside 
of target region" } */
+
+#pragma omp parallel
+    {
+#pragma omp target /* { dg-error "target construct inside of target region" } 
*/
+      ;
+#pragma omp target data /* { dg-error "target data construct inside of target 
region" } */
+      ;
+#pragma omp target update to(i) /* { dg-error "target update construct inside 
of target region" } */
+    }
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c 
b/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c
deleted file mode 100644
index c39dd49..0000000
--- a/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c
+++ /dev/null
@@ -1,23 +0,0 @@
-extern int i;
-
-void
-f_omp_target (void)
-{
-#pragma omp target
-  {
-#pragma omp target /* { dg-warning "target construct inside of target region" 
} */
-    ;
-#pragma omp target data /* { dg-warning "target data construct inside of 
target region" } */
-    ;
-#pragma omp target update to(i) /* { dg-warning "target update construct 
inside of target region" } */
-
-#pragma omp parallel
-    {
-#pragma omp target /* { dg-warning "target construct inside of target region" 
} */
-      ;
-#pragma omp target data /* { dg-warning "target data construct inside of 
target region" } */
-      ;
-#pragma omp target update to(i) /* { dg-warning "target update construct 
inside of target region" } */
-    }
-  }
-}
diff --git a/gcc/testsuite/gfortran.dg/gomp/target3.f90 
b/gcc/testsuite/gfortran.dg/gomp/target3.f90
index 53a9682..e451548 100644
--- a/gcc/testsuite/gfortran.dg/gomp/target3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/target3.f90
@@ -4,9 +4,18 @@
 subroutine foo (r)
   integer :: i, r
   !$omp target
-  !$omp target teams distribute parallel do reduction (+: r) ! { dg-warning 
"target construct inside of target region" }
+  !$omp target teams distribute parallel do reduction (+: r) ! { dg-error 
"target construct inside of target region" }
     do i = 1, 10
       r = r + 1
     end do
   !$omp end target
 end subroutine
+
+subroutine bar (r)
+  !$omp declare target
+  integer :: i, r
+  !$omp target teams distribute parallel do reduction (+: r) ! { dg-error 
"target construct inside of target region" }
+    do i = 1, 10
+      r = r + 1
+    end do
+end subroutine


  -- Ilya

Reply via email to