OpenMP: Add strictly nested API call check [PR102972]

The teams construct only permits omp_get_num_teams and omp_get_team_num
as API call in strictly nested regions - check for it.

Additionally, for Fortran, using DECL_NAME does not show the mangled
name, hence, DECL_ASSEMBLER_NAME had to be used to.

Finally, 'target device(ancestor:1)' wrongly rejected non-API calls
as well.

	PR middle-end/102972
gcc/ChangeLog:

	* omp-low.c (omp_runtime_api_call): Use DECL_ASSEMBLER_NAME to get
	internal Fortran name; new permit_num_teams arg to permit
	omp_get_num_teams and omp_get_team_num.
	(scan_omp_1_stmt): Update call to it, add missing call for
	reverse offload, and check for strictly nested API calls in teams.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/target-device-ancestor-3.c: Add non-API
	routine test.
	* gfortran.dg/gomp/order-6.f90: Add missing bind(C).
	* c-c++-common/gomp/teams-3.c: New test.
	* gfortran.dg/gomp/teams-3.f90: New test.
	* gfortran.dg/gomp/teams-4.f90: New test.

libgomp/ChangeLog:
	* testsuite/libgomp.c-c++-common/icv-3.c: Nest API calls inside
	parallel construct.
	* testsuite/libgomp.c-c++-common/icv-4.c: Likewise.
	* testsuite/libgomp.c/target-3.c: Likewise.
	* testsuite/libgomp.c/target-5.c: Likewise.
	* testsuite/libgomp.c/target-6.c: Likewise.
	* testsuite/libgomp.c/target-teams-1.c: Likewise.
	* testsuite/libgomp.c/teams-1.c: Likewise.
	* testsuite/libgomp.c/thread-limit-2.c: Likewise.
	* testsuite/libgomp.c/thread-limit-3.c: Likewise.
	* testsuite/libgomp.c/thread-limit-4.c: Likewise.
	* testsuite/libgomp.c/thread-limit-5.c: Likewise.
	* testsuite/libgomp.fortran/icv-3.f90: Likewise.
	* testsuite/libgomp.fortran/icv-4.f90: Likewise.
	* testsuite/libgomp.fortran/teams1.f90: Likewise.

 gcc/omp-low.c                                      |  30 +++++-
 .../c-c++-common/gomp/target-device-ancestor-3.c   |   2 +
 gcc/testsuite/c-c++-common/gomp/teams-3.c          |  64 ++++++++++++
 gcc/testsuite/gfortran.dg/gomp/order-6.f90         |   2 +-
 gcc/testsuite/gfortran.dg/gomp/teams-3.f90         |  65 ++++++++++++
 gcc/testsuite/gfortran.dg/gomp/teams-4.f90         |  47 +++++++++
 libgomp/testsuite/libgomp.c-c++-common/icv-3.c     |   3 +
 libgomp/testsuite/libgomp.c-c++-common/icv-4.c     |   1 +
 libgomp/testsuite/libgomp.c/target-3.c             |   6 +-
 libgomp/testsuite/libgomp.c/target-5.c             |   1 +
 libgomp/testsuite/libgomp.c/target-6.c             |  12 ++-
 libgomp/testsuite/libgomp.c/target-teams-1.c       | 115 +++++++++++++++------
 libgomp/testsuite/libgomp.c/teams-1.c              |   6 +-
 libgomp/testsuite/libgomp.c/thread-limit-2.c       |  21 ++--
 libgomp/testsuite/libgomp.c/thread-limit-3.c       |   1 +
 libgomp/testsuite/libgomp.c/thread-limit-4.c       |  25 +++--
 libgomp/testsuite/libgomp.c/thread-limit-5.c       |   1 +
 libgomp/testsuite/libgomp.fortran/icv-3.f90        |   6 ++
 libgomp/testsuite/libgomp.fortran/icv-4.f90        |   2 +
 libgomp/testsuite/libgomp.fortran/teams1.f90       |  16 +--
 20 files changed, 351 insertions(+), 75 deletions(-)

diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 15e4424b0bc..2f5b5bec48a 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -3911,7 +3911,7 @@ setjmp_or_longjmp_p (const_tree fndecl)
 /* Return true if FNDECL is an omp_* runtime API call.  */
 
 static bool
-omp_runtime_api_call (const_tree fndecl)
+omp_runtime_api_call (tree fndecl, bool permit_num_teams)
 {
   tree declname = DECL_NAME (fndecl);
   if (!declname
@@ -3920,6 +3920,8 @@ omp_runtime_api_call (const_tree fndecl)
       || !TREE_PUBLIC (fndecl))
     return false;
 
+  if (HAS_DECL_ASSEMBLER_NAME_P (fndecl))
+    declname = DECL_ASSEMBLER_NAME (fndecl);
   const char *name = IDENTIFIER_POINTER (declname);
   if (!startswith (name, "omp_"))
     return false;
@@ -4029,7 +4031,17 @@ omp_runtime_api_call (const_tree fndecl)
 		  && (name[4 + len + 1] == '\0'
 		      || (mode > 1
 			  && strcmp (name + 4 + len + 1, "8_") == 0)))))
-	return true;
+	{
+	  /* Only omp_get_num_teams + omp_get_team_num.  */
+	  if (permit_num_teams
+	      && mode == 1
+	      && (strncmp (name + 4, "get_num_teams",
+			   strlen ("get_num_teams")) == 0
+		  || strncmp (name + 4, "get_team_num",
+			      strlen ("get_team_num")) == 0))
+	    return false;
+	  return true;
+	}
     }
   return false;
 }
@@ -4088,16 +4100,26 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 	      omp_context *octx = ctx;
 	      if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN && ctx->outer)
 		octx = ctx->outer;
-	      if (octx->order_concurrent && omp_runtime_api_call (fndecl))
+	      if (octx->order_concurrent
+		  && omp_runtime_api_call (fndecl, false))
 		{
 		  remove = true;
 		  error_at (gimple_location (stmt),
 			    "OpenMP runtime API call %qD in a region with "
 			    "%<order(concurrent)%> clause", fndecl);
 		}
+	      if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
+		  && omp_runtime_api_call (fndecl, true))
+		{
+		  remove = true;
+		  error_at (gimple_location (stmt),
+			    "OpenMP runtime API call %qD strictly nested in a "
+			    "%<teams%> region", fndecl);
+		}
 	      if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
 		  && (gimple_omp_target_kind (ctx->stmt)
-		      == GF_OMP_TARGET_KIND_REGION))
+		      == GF_OMP_TARGET_KIND_REGION)
+		  && omp_runtime_api_call (fndecl, false))
 		{
 		  tree tgt_clauses = gimple_omp_target_clauses (ctx->stmt);
 		  tree c = omp_find_clause (tgt_clauses, OMP_CLAUSE_DEVICE);
diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c
index 5e3a478fd5b..ea6e5a0cf6c 100644
--- a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c
+++ b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-3.c
@@ -3,6 +3,7 @@ extern "C" {
 #endif
 
 int omp_get_num_teams (void);
+int bar (void);
 
 #ifdef __cplusplus
 }
@@ -22,6 +23,7 @@ foo (void)
 
   #pragma omp target device (ancestor: 1)
     {
+      a = bar (); /* OK */
       a = omp_get_num_teams (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_teams\[^\n\r]*' in a region with 'device\\(ancestor\\)' clause" }  */
     }
 
diff --git a/gcc/testsuite/c-c++-common/gomp/teams-3.c b/gcc/testsuite/c-c++-common/gomp/teams-3.c
new file mode 100644
index 00000000000..7f8b47f7df0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/teams-3.c
@@ -0,0 +1,64 @@
+/* PR middle-end/102972 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* From omp.h  */
+extern int omp_get_num_teams (void);
+extern void omp_set_num_teams (int);
+extern int omp_get_team_size (int);
+extern int omp_get_team_num (void);
+extern int omp_get_max_teams (void);
+extern void omp_set_teams_thread_limit (int);
+extern int omp_get_teams_thread_limit (void);
+extern int omp_is_initial_device (void);
+extern int omp_get_num_threads (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+void valid ()
+{
+  #pragma omp teams
+  {
+    #pragma omp distribute
+    for (int i = 0; i < 64; i++)
+      ;
+
+    int n = omp_get_num_teams ();
+    if (n >= omp_get_team_num ())
+      __builtin_abort ();
+
+    #pragma omp parallel for
+    for (int i = 0; i < 64; i++)
+      if (!omp_is_initial_device () || omp_get_num_threads () < 0)
+	__builtin_abort ();
+
+    #pragma omp loop
+    for (int i = 0; i < 64; i++)
+      ;
+  }
+}
+
+void invalid_nest ()
+{
+  #pragma omp teams
+  {
+    #pragma distribute parallel for simd
+    for (int i = 0; i < 64; i++)
+      ;
+
+    int n = 0;
+    n += omp_get_team_size (0);  /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_team_size\[^\n\r]*' strictly nested in a 'teams' region" }  */
+    n += omp_get_num_teams ();
+    n += omp_get_team_num ();
+    omp_set_num_teams (n);  /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_set_num_teams\[^\n\r]*' strictly nested in a 'teams' region" }  */
+    n += omp_get_max_teams ();  /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_max_teams\[^\n\r]*' strictly nested in a 'teams' region" }  */
+    n += omp_get_teams_thread_limit ();  /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_teams_thread_limit\[^\n\r]*' strictly nested in a 'teams' region" }  */
+    omp_set_teams_thread_limit (n);  /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_set_teams_thread_limit\[^\n\r]*' strictly nested in a 'teams' region" }  */
+  }
+}
diff --git a/gcc/testsuite/gfortran.dg/gomp/order-6.f90 b/gcc/testsuite/gfortran.dg/gomp/order-6.f90
index c8aeecb6f27..8d7f9c57a98 100644
--- a/gcc/testsuite/gfortran.dg/gomp/order-6.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/order-6.f90
@@ -8,7 +8,7 @@ module m
     end
     integer function omp_get_num_threads ()
     end
-    integer function omp_target_is_present (x, i)
+    integer function omp_target_is_present (x, i) bind(c)
       import :: c_ptr
       type(c_ptr) :: x
       integer, value :: i
diff --git a/gcc/testsuite/gfortran.dg/gomp/teams-3.f90 b/gcc/testsuite/gfortran.dg/gomp/teams-3.f90
new file mode 100644
index 00000000000..fac3393bd9d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/teams-3.f90
@@ -0,0 +1,65 @@
+! PR middle-end/102972
+
+module m
+implicit none (type, external)
+interface
+subroutine omp_set_num_teams (num_teams); integer :: num_teams; end
+subroutine omp_set_teams_thread_limit (thread_limit); integer :: thread_limit; end
+subroutine omp_set_num_teams_8 (num_teams); integer(8) :: num_teams; end
+subroutine omp_set_num_teams_9 (num_teams); integer :: num_teams; end
+subroutine omp_set_teams_thread_limit_8 (thread_limit); integer(8) :: thread_limit; end
+integer function omp_get_num_teams (); end
+integer function omp_get_team_size (level); integer :: level; end
+integer function omp_get_team_num (); end
+integer function omp_get_max_teams (); end
+integer function omp_get_teams_thread_limit (); end
+logical function omp_is_initial_device (); end
+integer function omp_get_num_threads (); end
+end interface
+
+contains
+
+subroutine valid ()
+  integer :: i, n
+  !$omp teams
+    !$omp distribute
+    do i = 1, 64
+    end do
+
+    n = omp_get_num_teams ()
+    if (n >= omp_get_team_num ()) &
+      error stop
+
+    !$omp parallel do
+    do i = 1, 64
+      if (.not.omp_is_initial_device () .or. omp_get_num_threads () < 0) &
+        error stop
+    end do
+
+    !$omp loop
+    do i = 1, 64
+    end do
+  !$omp end teams
+end
+
+subroutine invalid_nest ()
+  integer :: i, n
+  !$omp teams
+    !$omp distribute parallel do simd
+    do i = 1, 64
+    end do
+
+    n = 0
+    n = n + omp_get_team_size (0)  ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_team_size\[^\n\r]*' strictly nested in a 'teams' region" }
+    n = n + omp_get_num_teams ()
+    n = n + omp_get_team_num ()
+    call omp_set_num_teams (n)  ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_set_num_teams\[^\n\r]*' strictly nested in a 'teams' region" }
+    call omp_set_num_teams_8 (4_8)  ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_set_num_teams_8\[^\n\r]*' strictly nested in a 'teams' region" }
+    call omp_set_num_teams_9 (4)  ! OK - but misnamed user function
+    n = n + omp_get_max_teams ()  ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_max_teams\[^\n\r]*' strictly nested in a 'teams' region" }
+    n = n + omp_get_teams_thread_limit ()  ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_teams_thread_limit\[^\n\r]*' strictly nested in a 'teams' region" }
+    call omp_set_teams_thread_limit (n)  ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_set_teams_thread_limit'\[^\n\r]* strictly nested in a 'teams' region" }
+    call omp_set_teams_thread_limit_8 (3_8)  ! { dg-error "OpenMP runtime API call '\[^\n\r]*omp_set_teams_thread_limit_8'\[^\n\r]* strictly nested in a 'teams' region" }
+  !$omp end teams
+end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/teams-4.f90 b/gcc/testsuite/gfortran.dg/gomp/teams-4.f90
new file mode 100644
index 00000000000..422c2c9ef92
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/teams-4.f90
@@ -0,0 +1,47 @@
+! PR middle-end/102972
+
+module m
+implicit none (type, external)
+
+! Note: Those are module functions - not an interface
+! Hence, they are internally manged to contain the module name!
+
+contains
+
+subroutine omp_set_num_teams (num_teams); integer :: num_teams; end
+subroutine omp_set_teams_thread_limit (thread_limit); integer :: thread_limit; end
+subroutine omp_set_num_teams_8 (num_teams); integer(8) :: num_teams; end
+subroutine omp_set_num_teams_9 (num_teams); integer :: num_teams; end
+subroutine omp_set_teams_thread_limit_8 (thread_limit); integer(8) :: thread_limit; end
+integer function omp_get_num_teams (); omp_get_num_teams = 0; end
+integer function omp_get_team_size (level); integer :: level; omp_get_team_size = 0; end
+integer function omp_get_team_num (); omp_get_team_num = 0; end
+integer function omp_get_max_teams (); omp_get_max_teams = 0; end
+integer function omp_get_teams_thread_limit (); omp_get_teams_thread_limit = 0; end
+logical function omp_is_initial_device (); omp_is_initial_device = .true.; end
+integer function omp_get_num_threads (); omp_get_num_threads = 0; end
+end module
+
+subroutine nest_test ()
+  use m
+  implicit none (type, external)
+  
+  integer :: i, n
+  !$omp teams
+    !$omp distribute parallel do simd
+    do i = 1, 64
+    end do
+
+    n = 0
+    n = n + omp_get_team_size (0)
+    n = n + omp_get_num_teams ()
+    n = n + omp_get_team_num ()
+    call omp_set_num_teams (n)
+    call omp_set_num_teams_8 (4_8)
+    call omp_set_num_teams_9 (4)
+    n = n + omp_get_max_teams ()
+    n = n + omp_get_teams_thread_limit ()
+    call omp_set_teams_thread_limit (n)
+    call omp_set_teams_thread_limit_8 (3_8)
+  !$omp end teams
+end
diff --git a/libgomp/testsuite/libgomp.c-c++-common/icv-3.c b/libgomp/testsuite/libgomp.c-c++-common/icv-3.c
index 54cbf99b597..795b98240a3 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/icv-3.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/icv-3.c
@@ -18,6 +18,7 @@ main ()
     abort ();
   #pragma omp teams
   {
+    #pragma omp parallel
     if (omp_get_max_teams () != 7
 	|| omp_get_teams_thread_limit () != 15
 	|| omp_get_num_teams () < 1
@@ -30,6 +31,7 @@ main ()
   }
   #pragma omp teams num_teams(5) thread_limit (13)
   {
+    #pragma omp parallel
     if (omp_get_max_teams () != 7
 	|| omp_get_teams_thread_limit () != 15
 	|| omp_get_num_teams () != 5
@@ -41,6 +43,7 @@ main ()
   }
   #pragma omp teams num_teams(8) thread_limit (16)
   {
+    #pragma omp parallel
     if (omp_get_max_teams () != 7
 	|| omp_get_teams_thread_limit () != 15
 	|| omp_get_num_teams () != 8
diff --git a/libgomp/testsuite/libgomp.c-c++-common/icv-4.c b/libgomp/testsuite/libgomp.c-c++-common/icv-4.c
index 6cb671d8ac7..db6f34dbe68 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/icv-4.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/icv-4.c
@@ -26,6 +26,7 @@ main ()
     omp_set_teams_thread_limit (12);
   #pragma omp teams
   {
+    #pragma omp parallel
     if (omp_get_max_teams () != 6
 	|| omp_get_teams_thread_limit () != 12
 	|| omp_get_num_teams () < 1
diff --git a/libgomp/testsuite/libgomp.c/target-3.c b/libgomp/testsuite/libgomp.c/target-3.c
index 7002cf287f9..2de86fb8fc3 100644
--- a/libgomp/testsuite/libgomp.c/target-3.c
+++ b/libgomp/testsuite/libgomp.c/target-3.c
@@ -11,7 +11,9 @@ main ()
     abort ();
   #pragma omp target if (0)
   #pragma omp teams
-  if (omp_get_level ())
-    abort ();
+  #pragma omp distribute
+  for (int i = 0; i < 1; ++i)
+    if (omp_get_level ())
+      abort ();
   return 0;
 }
diff --git a/libgomp/testsuite/libgomp.c/target-5.c b/libgomp/testsuite/libgomp.c/target-5.c
index 21a69ea6812..82b8637f44b 100644
--- a/libgomp/testsuite/libgomp.c/target-5.c
+++ b/libgomp/testsuite/libgomp.c/target-5.c
@@ -55,6 +55,7 @@ main ()
     abort ();
   #pragma omp target if (0)
   #pragma omp teams
+  #pragma omp parallel
   {
     omp_sched_t s_c;
     int c_c;
diff --git a/libgomp/testsuite/libgomp.c/target-6.c b/libgomp/testsuite/libgomp.c/target-6.c
index 8ffcb5b5b6a..e878fa41bb2 100644
--- a/libgomp/testsuite/libgomp.c/target-6.c
+++ b/libgomp/testsuite/libgomp.c/target-6.c
@@ -47,11 +47,13 @@ main ()
 		{
 		  #pragma omp teams thread_limit (2)
 		    {
-		      if (omp_in_parallel ()
-			  || omp_get_level () != 0
-			  || omp_get_ancestor_thread_num (0) != 0
-			  || omp_get_ancestor_thread_num (1) != -1)
-			abort ();
+		      #pragma omp distribute
+		      for (int i = 0; i < 1; ++i)
+			if (omp_in_parallel ()
+			    || omp_get_level () != 0
+			    || omp_get_ancestor_thread_num (0) != 0
+			    || omp_get_ancestor_thread_num (1) != -1)
+			  abort ();
 		      #pragma omp parallel num_threads (2)
 		      {
 			if (!omp_in_parallel ()
diff --git a/libgomp/testsuite/libgomp.c/target-teams-1.c b/libgomp/testsuite/libgomp.c/target-teams-1.c
index 8f591e02c48..e42a9ed910d 100644
--- a/libgomp/testsuite/libgomp.c/target-teams-1.c
+++ b/libgomp/testsuite/libgomp.c/target-teams-1.c
@@ -35,76 +35,115 @@ foo (int a, int b, long c, long d)
     abort ();
   #pragma omp target map(from: err)
   #pragma omp teams
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1;
+  {
+    err = omp_get_num_teams () < 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1;
+  }
   if (err)
     abort ();
   #pragma omp target teams map(from: err)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1;
+  {
+    err = omp_get_num_teams () < 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1;
+  }
   if (err)
     abort ();
   #pragma omp target map(from: err)
   #pragma omp teams num_teams (4)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > 4;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > 4;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1;
+  }
   if (err)
     abort ();
   #pragma omp target teams num_teams (4) map(from: err)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > 4;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > 4;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1;
+  }
   if (err)
     abort ();
   #pragma omp target map(from: err)
   #pragma omp teams thread_limit (7)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_thread_limit () > 7;
+  {
+    err = omp_get_num_teams () < 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > 7;
+  }
   if (err)
     abort ();
   #pragma omp target teams thread_limit (7) map(from: err)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_thread_limit () > 7;
+  {
+    err = omp_get_num_teams () < 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > 7;
+  }
   if (err)
     abort ();
   #pragma omp target map(from: err)
   #pragma omp teams num_teams (4) thread_limit (8)
   {
     {
-      err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	    || omp_get_num_teams () > 4 || omp_get_thread_limit () > 8;
+      err = omp_get_num_teams () < 1 || omp_get_num_teams () > 4;
     }
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > 8;
   }
   if (err)
     abort ();
   #pragma omp target teams num_teams (4) thread_limit (8) map(from: err)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > 4 || omp_get_thread_limit () > 8;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > 4;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > 8;
+  }
   if (err)
     abort ();
   #pragma omp target map(from: err)
   #pragma omp teams num_teams (a) thread_limit (b)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > a || omp_get_thread_limit () > b;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > a;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > b;
+  }
   if (err)
     abort ();
   #pragma omp target teams num_teams (a) thread_limit (b) map(from: err)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > a || omp_get_thread_limit () > b;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > a;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > b;
+  }
   if (err)
     abort ();
   #pragma omp target map(from: err)
   #pragma omp teams num_teams (c + 1) thread_limit (d - 1)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > c + 1 || omp_get_thread_limit () > d - 1;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > c + 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > d - 1;
+  }
   if (err)
     abort ();
   #pragma omp target teams num_teams (c + 1) thread_limit (d - 1) map(from: err)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > c + 1 || omp_get_thread_limit () > d - 1;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > c + 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > d - 1;
+  }
   if (err)
     abort ();
   #pragma omp target map (always, to: c, d) map(from: err)
   #pragma omp teams num_teams (c + 1) thread_limit (d - 1)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > c + 1 || omp_get_thread_limit () > d - 1;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > c + 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > d - 1;
+  }
   if (err)
     abort ();
   #pragma omp target data map (to: c, d)
@@ -116,8 +155,11 @@ foo (int a, int b, long c, long d)
        their device and original values match is unclear.  */
     #pragma omp target map (to: c, d) map(from: err)
     #pragma omp teams num_teams (c + 1) thread_limit (d - 1)
-    err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	  || omp_get_num_teams () > c + 1 || omp_get_thread_limit () > d - 1;
+    {
+      err = omp_get_num_teams () < 1 || omp_get_num_teams () > c + 1;
+      #pragma omp parallel masked
+      err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > d - 1;
+    }
     if (err)
       abort ();
   }
@@ -125,21 +167,30 @@ foo (int a, int b, long c, long d)
      target involved.  */
   #pragma omp target map(from: err)
   #pragma omp teams num_teams (baz () + 1) thread_limit (baz () - 1)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > baz () + 1 || omp_get_thread_limit () > baz () - 1;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > baz () + 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > baz () - 1;
+  }
   if (err)
     abort ();
   #pragma omp target teams num_teams (baz () + 1) thread_limit (baz () - 1) map(from: err)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > baz () + 1 || omp_get_thread_limit () > baz () - 1;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > baz () + 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > baz () - 1;
+  }
   if (err)
     abort ();
   /* This one can't be optimized, as v might have different value between
      host and target.  */
   #pragma omp target map(from: err)
   #pragma omp teams num_teams (v + 1) thread_limit (v - 1)
-  err = omp_get_num_teams () < 1 || omp_get_thread_limit () < 1
-	|| omp_get_num_teams () > v + 1 || omp_get_thread_limit () > v - 1;
+  {
+    err = omp_get_num_teams () < 1 || omp_get_num_teams () > v + 1;
+    #pragma omp parallel masked
+    err |= omp_get_thread_limit () < 1 || omp_get_thread_limit () > v - 1;
+  }
   if (err)
     abort ();
 }
diff --git a/libgomp/testsuite/libgomp.c/teams-1.c b/libgomp/testsuite/libgomp.c/teams-1.c
index 977e5fc5323..023d30eafe3 100644
--- a/libgomp/testsuite/libgomp.c/teams-1.c
+++ b/libgomp/testsuite/libgomp.c/teams-1.c
@@ -6,15 +6,17 @@
 int
 main ()
 {
+  omp_set_dynamic (0);
+  omp_set_nested (1);
   #pragma omp teams thread_limit (2)
   {
+    #pragma omp distribute
+    for (int i = 0; i < 1; ++i)
     if (omp_in_parallel ()
 	|| omp_get_level () != 0
 	|| omp_get_ancestor_thread_num (0) != 0
 	|| omp_get_ancestor_thread_num (1) != -1)
       abort ();
-    omp_set_dynamic (0);
-    omp_set_nested (1);
     #pragma omp parallel num_threads (2)
     {
       if (!omp_in_parallel ()
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-2.c b/libgomp/testsuite/libgomp.c/thread-limit-2.c
index 2cff1fd48c3..7997a70adc3 100644
--- a/libgomp/testsuite/libgomp.c/thread-limit-2.c
+++ b/libgomp/testsuite/libgomp.c/thread-limit-2.c
@@ -20,25 +20,26 @@ main ()
   if (omp_get_num_threads () > 9)
     abort ();
   #pragma omp target if (0)
-  #pragma omp teams thread_limit (6)
   {
-    if (omp_get_thread_limit () > 6)
-      abort ();
-    if (omp_get_thread_limit () == 6)
+    omp_set_dynamic (0);
+    omp_set_nested (1);
+    #pragma omp teams thread_limit (6)
       {
-	omp_set_dynamic (0);
-	omp_set_nested (1);
 	#pragma omp parallel num_threads (3)
-	if (omp_get_num_threads () != 3)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () != 3))
 	  abort ();
 	#pragma omp parallel num_threads (3)
-	if (omp_get_num_threads () != 3)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () != 3))
 	  abort ();
 	#pragma omp parallel num_threads (8)
-	if (omp_get_num_threads () > 6)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () > 6))
 	  abort ();
 	#pragma omp parallel num_threads (6)
-	if (omp_get_num_threads () != 6)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () != 6))
 	  abort ();
 	int cnt = 0;
 	#pragma omp parallel num_threads (5)
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-3.c b/libgomp/testsuite/libgomp.c/thread-limit-3.c
index af9bd7887ab..500c1fb3c2c 100644
--- a/libgomp/testsuite/libgomp.c/thread-limit-3.c
+++ b/libgomp/testsuite/libgomp.c/thread-limit-3.c
@@ -6,6 +6,7 @@ main ()
 {
   #pragma omp target if (0)
   #pragma omp teams thread_limit (1)
+  #pragma omp parallel
   if (omp_get_thread_limit () != 1)
     abort ();
   return 0;
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-4.c b/libgomp/testsuite/libgomp.c/thread-limit-4.c
index 351423cab94..c6ccc7d6330 100644
--- a/libgomp/testsuite/libgomp.c/thread-limit-4.c
+++ b/libgomp/testsuite/libgomp.c/thread-limit-4.c
@@ -18,25 +18,25 @@ main ()
   #pragma omp parallel num_threads (16)
   if (omp_get_num_threads () > 9)
     abort ();
+  omp_set_dynamic (0);
+  omp_set_nested (1);
   #pragma omp teams thread_limit (6)
-  {
-    if (omp_get_thread_limit () > 6)
-      abort ();
-    if (omp_get_thread_limit () == 6)
-      {
-	omp_set_dynamic (0);
-	omp_set_nested (1);
+    {
 	#pragma omp parallel num_threads (3)
-	if (omp_get_num_threads () != 3)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () != 3))
 	  abort ();
 	#pragma omp parallel num_threads (3)
-	if (omp_get_num_threads () != 3)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () != 3))
 	  abort ();
 	#pragma omp parallel num_threads (8)
-	if (omp_get_num_threads () > 6)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () > 6))
 	  abort ();
 	#pragma omp parallel num_threads (6)
-	if (omp_get_num_threads () != 6)
+	if (omp_get_thread_limit () > 6
+	    || (omp_get_thread_limit () == 6 && omp_get_num_threads () != 6))
 	  abort ();
 	int cnt = 0;
 	#pragma omp parallel num_threads (5)
@@ -52,7 +52,6 @@ main ()
 	  #pragma omp atomic
 	  --cnt;
 	}
-      }
-  }
+    }
   return 0;
 }
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-5.c b/libgomp/testsuite/libgomp.c/thread-limit-5.c
index d3d22b1e1a6..44eeb7b9dc1 100644
--- a/libgomp/testsuite/libgomp.c/thread-limit-5.c
+++ b/libgomp/testsuite/libgomp.c/thread-limit-5.c
@@ -5,6 +5,7 @@ int
 main ()
 {
   #pragma omp teams thread_limit (1)
+  #pragma omp parallel
   if (omp_get_thread_limit () != 1)
     abort ();
   return 0;
diff --git a/libgomp/testsuite/libgomp.fortran/icv-3.f90 b/libgomp/testsuite/libgomp.fortran/icv-3.f90
index b2ccd776223..645063b954e 100644
--- a/libgomp/testsuite/libgomp.fortran/icv-3.f90
+++ b/libgomp/testsuite/libgomp.fortran/icv-3.f90
@@ -13,6 +13,7 @@ implicit none (type, external)
   if (omp_get_teams_thread_limit () /= 15) &
     error stop 4
   !$omp teams
+   !$omp parallel
     if (omp_get_max_teams () /= 7 &
         .or. omp_get_teams_thread_limit () /= 15 &
         .or. omp_get_num_teams () < 1 &
@@ -22,8 +23,10 @@ implicit none (type, external)
         .or. omp_get_thread_limit () < 1 &
         .or. omp_get_thread_limit () > 15) &
       error stop 5
+   !$omp end parallel
   !$omp end teams
   !$omp teams num_teams(5) thread_limit (13)
+   !$omp parallel
     if (omp_get_max_teams () /= 7 &
         .or. omp_get_teams_thread_limit () /= 15 &
         .or. omp_get_num_teams () /= 5 &
@@ -32,8 +35,10 @@ implicit none (type, external)
         .or. omp_get_thread_limit () < 1 &
         .or. omp_get_thread_limit () > 13) &
       error stop 6
+   !$omp end parallel
   !$omp end teams
   !$omp teams num_teams(8) thread_limit (16)
+   !$omp parallel
     if (omp_get_max_teams () /= 7 &
         .or. omp_get_teams_thread_limit () /= 15 &
         .or. omp_get_num_teams () /= 8 &
@@ -42,6 +47,7 @@ implicit none (type, external)
         .or. omp_get_thread_limit () < 1 &
         .or. omp_get_thread_limit () > 16) &
       error stop 7
+   !$omp end parallel
   !$omp end teams
 contains
   logical function env_exists (name)
diff --git a/libgomp/testsuite/libgomp.fortran/icv-4.f90 b/libgomp/testsuite/libgomp.fortran/icv-4.f90
index f76c96d7d0d..4f888a80852 100644
--- a/libgomp/testsuite/libgomp.fortran/icv-4.f90
+++ b/libgomp/testsuite/libgomp.fortran/icv-4.f90
@@ -16,6 +16,7 @@ implicit none (type, external)
     call omp_set_teams_thread_limit (12)
   end if
   !$omp teams
+   !$omp parallel
     if (omp_get_max_teams () /= 6 &
         .or. omp_get_teams_thread_limit () /= 12 &
         .or. omp_get_num_teams () < 1 &
@@ -25,6 +26,7 @@ implicit none (type, external)
         .or. omp_get_thread_limit () < 1 &
         .or. omp_get_thread_limit () > 12) &
       error stop 3
+   !$omp end parallel
   !$omp end teams
 contains
   logical function env_is_set (name, val)
diff --git a/libgomp/testsuite/libgomp.fortran/teams1.f90 b/libgomp/testsuite/libgomp.fortran/teams1.f90
index 0077a703f74..4906040d019 100644
--- a/libgomp/testsuite/libgomp.fortran/teams1.f90
+++ b/libgomp/testsuite/libgomp.fortran/teams1.f90
@@ -2,13 +2,17 @@
 
 program teams1
   use omp_lib
+  integer :: i
 !$omp teams thread_limit (2)
-  if (omp_in_parallel ()) stop 1
-  if (omp_get_level () .ne. 0) stop 2
-  if (omp_get_ancestor_thread_num (0) .ne. 0) stop 3
-  if (omp_get_ancestor_thread_num (1) .ne. -1) stop 4
-  call omp_set_dynamic (.false.)
-  call omp_set_nested (.true.)
+  !$omp distribute
+  do i = 1, 1
+    if (omp_in_parallel ()) stop 1
+    if (omp_get_level () .ne. 0) stop 2
+    if (omp_get_ancestor_thread_num (0) .ne. 0) stop 3
+    if (omp_get_ancestor_thread_num (1) .ne. -1) stop 4
+    call omp_set_dynamic (.false.)
+    call omp_set_nested (.true.)
+  end do
 !$omp parallel num_threads (2)
   if (.not. omp_in_parallel ()) stop 5
   if (omp_get_level () .ne. 1) stop 6
