https://gcc.gnu.org/g:2f8f383036d28226723a2e08d105e94c6b2d74d6

commit r17-5648-g2f8f383036d28226723a2e08d105e94c6b2d74d6
Author: Tobias Burnus <[email protected]>
Date:   Tue Oct 27 19:06:25 2026 +0100

    libgomp: Add omp_get_gprivate_limit API routine
    
    This API routine returns the maximally possible limit of for groupprivate
    variables, be it via the directive or using the dyn_groupprivate clause.
    
    GCC still has to support dyn_groupprivate, however, 'groupprivate' is
    supported on some offload devices. Note that for simplicity, the added API
    routines currently always return 0.
    
    For some reasons, there is a 'omp_access_pteam' named constant, even if
    it is nowhere specified for what it can be used. The API routines
    and the 'dyn_groupprivate' clause technically accept other values, but,
    effectively, only 'omp_access_cgroup' is specified.
    
    gcc/fortran/ChangeLog:
    
            * intrinsic.texi (OpenMP intrinsic modules): Update list of
            kind value and parameters.
    
    gcc/ChangeLog:
    
            * omp-general.cc (omp_runtime_api_procname): Add
            omp_get_gprivate_limit.
    
    libgomp/ChangeLog:
    
            * fortran.c (omp_get_gprivate_limit_): Add.
            * libgomp-plugin.h (GOMP_OFFLOAD_get_gprivate_limit): Add.
            * libgomp.h (struct gomp_device_descr): Add get_gprivate_limit_func.
            * libgomp.map: Add omp_get_gprivate_limit_.
            * libgomp.texi (omp_get_gprivate_limit): Document new routine.
            * omp.h.in (omp_access_t, omp_get_gprivate_limit): Add.
            * omp_lib.f90.in (omp_access_kind, omp_get_gprivate_limit): Add.
            * omp_lib.h.in (omp_access_kind, omp_get_gprivate_limit): Add.
            * plugin/plugin-gcn.c (GOMP_OFFLOAD_get_gprivate_limit): Add.
            * plugin/plugin-nvptx.c (GOMP_OFFLOAD_get_gprivate_limit): Add.
            * target.c (omp_get_gprivate_limit): Add.
            * testsuite/libgomp.c-c++-common/gprivate-1.c: New test.
            * testsuite/libgomp.fortran/gprivate-1.f90: New test.

Diff:
---
 gcc/fortran/intrinsic.texi                         | 72 +++++++++++++++++++++-
 gcc/omp-general.cc                                 |  1 +
 libgomp/fortran.c                                  |  9 +++
 libgomp/libgomp-plugin.h                           |  1 +
 libgomp/libgomp.h                                  |  1 +
 libgomp/libgomp.map                                |  2 +
 libgomp/libgomp.texi                               | 45 +++++++++++++-
 libgomp/omp.h.in                                   |  9 +++
 libgomp/omp_lib.f90.in                             | 13 ++++
 libgomp/omp_lib.h.in                               | 16 +++++
 libgomp/plugin/plugin-gcn.c                        | 12 ++++
 libgomp/plugin/plugin-nvptx.c                      | 12 ++++
 libgomp/target.c                                   | 23 +++++++
 .../testsuite/libgomp.c-c++-common/gprivate-1.c    | 49 +++++++++++++++
 libgomp/testsuite/libgomp.fortran/gprivate-1.f90   | 54 ++++++++++++++++
 15 files changed, 317 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index bce59971e4bc..53c6baed0b6d 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -16410,15 +16410,23 @@ OpenMP Application Program Interface v6.0}.
 named constants:
 
 @table @asis
+@item @code{omp_access_kind}
 @item @code{omp_allocator_handle_kind}
 @item @code{omp_alloctrait_key_kind}
 @item @code{omp_alloctrait_val_kind}
+@item @code{omp_control_tool_kind}
+@item @code{omp_control_tool_result_kind}
 @item @code{omp_depend_kind}
+@item @code{omp_event_handle_kind}
+@item @code{omp_interop_fr_kind}
+@item @code{omp_interop_kind}
+@item @code{omp_interop_property_kind}
+@item @code{omp_interop_rc_kind}
 @item @code{omp_lock_kind}
 @item @code{omp_lock_hint_kind}
+@item @code{omp_memspace_handle_kind}
 @item @code{omp_nest_lock_kind}
 @item @code{omp_pause_resource_kind}
-@item @code{omp_memspace_handle_kind}
 @item @code{omp_proc_bind_kind}
 @item @code{omp_sched_kind}
 @item @code{omp_sync_hint_kind}
@@ -16543,6 +16551,8 @@ The following scalar integer named constants are of the 
kind
 @item @code{omp_cgroup_mem_alloc}
 @item @code{omp_pteam_mem_alloc}
 @item @code{omp_thread_mem_alloc}
+@item @code{ompx_gnu_pinned_mem_alloc} (GCC specific)
+@item @code{ompx_gnu_managed_mem_alloc} (GCC specific)
 @end table
 
 The following scalar integer named constants are of the kind
@@ -16554,6 +16564,66 @@ The following scalar integer named constants are of 
the kind
 @item @code{omp_const_mem_space}
 @item @code{omp_high_bw_mem_space}
 @item @code{omp_low_lat_mem_space}
+@item @code{ompx_gnu_managed_mem_space} (GCC specific)
+@end table
+
+The following scalar integer named constant is of the kind
+@code{omp_interop_kind}:
+
+@table @asis
+@item @code{omp_interop_none}
+@end table
+
+The following scalar integer named constants are of the kind
+@code{omp_interop_fr_kind}:
+
+@table @asis
+@item @code{omp_ifr_cuda}
+@item @code{omp_ifr_cuda_driver}
+@item @code{omp_ifr_opencl}
+@item @code{omp_ifr_sycl}
+@item @code{omp_ifr_hip}
+@item @code{omp_ifr_level_zero}
+@item @code{omp_ifr_hsa}
+@item @code{omp_ifr_last}
+@end table
+
+The following scalar integer named constants are of the kind
+@code{omp_interop_property_kind}:
+
+@table @asis
+@item @code{omp_ipr_fr_id}
+@item @code{omp_ipr_fr_name}
+@item @code{omp_ipr_vendor}
+@item @code{omp_ipr_vendor_name}
+@item @code{omp_ipr_device_num}
+@item @code{omp_ipr_platform}
+@item @code{omp_ipr_device}
+@item @code{omp_ipr_device_context}
+@item @code{omp_ipr_targetsync}
+@item @code{omp_ipr_first}
+@end table
+
+The following scalar integer named constants are of the kind
+@code{omp_interop_rc_kind}:
+
+@table @asis
+@item @code{omp_irc_no_value}
+@item @code{omp_irc_success}
+@item @code{omp_irc_empty}
+@item @code{omp_irc_out_of_range}
+@item @code{omp_irc_type_int}
+@item @code{omp_irc_type_ptr}
+@item @code{omp_irc_type_str}
+@item @code{omp_irc_other}
+@end table
+
+The following scalar integer named constants are of the kind
+@code{omp_access_kind}:
+
+@table @asis
+@item @code{omp_access_cgroup}
+@item @code{omp_access_pteam}
 @end table
 
 The following scalar integer named constants are of the kind
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index 5d0bd02f3a3e..9162972dc88d 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -4021,6 +4021,7 @@ omp_runtime_api_procname (const char *name)
       "get_device_from_uid",
       "get_device_num",
       "get_dynamic",
+      "get_gprivate_limit",
       "get_initial_device",
       "get_interop_name",
       "get_interop_rc_desc",
diff --git a/libgomp/fortran.c b/libgomp/fortran.c
index a28b86ae666e..3af77c6c7ba8 100644
--- a/libgomp/fortran.c
+++ b/libgomp/fortran.c
@@ -104,6 +104,7 @@ ialias_redirect (omp_get_interop_name)
 ialias_redirect (omp_get_interop_type_desc)
 ialias_redirect (omp_get_interop_rc_desc)
 ialias_redirect (omp_control_tool)
+ialias_redirect (omp_get_gprivate_limit)
 ialias_redirect (omp_get_supported_active_team_dims)
 ialias_redirect (omp_get_supported_active_league_dims)
 #endif
@@ -875,6 +876,14 @@ omp_get_supported_active_league_dims_ (int *device_num, 
int *native_support)
   return omp_get_supported_active_league_dims (*device_num, *native_support);
 }
 
+size_t
+omp_get_gprivate_limit_ (int device_num, int access_group, bool present_agrp)
+{
+  if (!present_agrp)
+    access_group = omp_access_cgroup;
+  return omp_get_gprivate_limit (device_num, access_group);
+}
+
 void
 omp_display_env_ (const int32_t *verbose)
 {
diff --git a/libgomp/libgomp-plugin.h b/libgomp/libgomp-plugin.h
index a01873131fb1..c67eeec6978f 100644
--- a/libgomp/libgomp-plugin.h
+++ b/libgomp/libgomp-plugin.h
@@ -169,6 +169,7 @@ extern const char *GOMP_OFFLOAD_get_uid (int);
 extern int GOMP_OFFLOAD_get_numa_node (int);
 extern int GOMP_OFFLOAD_supported_teams_dim (int, int);
 extern int GOMP_OFFLOAD_supported_threads_dim (int, int);
+extern size_t GOMP_OFFLOAD_get_gprivate_limit (int, omp_access_t);
 
 extern unsigned int GOMP_OFFLOAD_get_caps (void);
 extern unsigned int GOMP_OFFLOAD_get_dev_caps (int);
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index c4bab1097368..fed3da2e6624 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -1460,6 +1460,7 @@ struct gomp_device_descr
   __typeof (GOMP_OFFLOAD_get_numa_node) *get_numa_node_func;
   __typeof (GOMP_OFFLOAD_supported_teams_dim) *supported_teams_dim_func;
   __typeof (GOMP_OFFLOAD_supported_threads_dim) *supported_threads_dim_func;
+  __typeof (GOMP_OFFLOAD_get_gprivate_limit) *get_gprivate_limit_func;
   __typeof (GOMP_OFFLOAD_get_caps) *get_caps_func;
   __typeof (GOMP_OFFLOAD_get_dev_caps) *get_dev_caps_func;
   __typeof (GOMP_OFFLOAD_get_type) *get_type_func;
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index 00e47d65d4c6..19890c05c76c 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -250,6 +250,8 @@ OMP_6.0 {
 OMP_6.1 {
   global:
        omp_get_device_distances;
+       omp_get_gprivate_limit;
+       omp_get_gprivate_limit_;
        omp_get_num_teams_dim;
        omp_get_num_threads_dim;
        omp_get_supported_active_league_dims;
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index f3f95df0c8b3..d323078494e7 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -3955,7 +3955,7 @@ They have C linkage and do not throw exceptions.
 @c * omp_get_dyn_gprivate_nofb_ptr:: <fixme>/TR15
 @c * omp_get_dyn_gprivate_size:: <fixme>/TR15
 @c * omp_get_dyn_gprivate_memspace:: <fixme>/TR15
-@c * omp_get_gprivate_limit:: <fixme>/TR15
+* omp_get_gprivate_limit:: Absolute limit of groupprivate memory
 @end menu
 
 
@@ -4418,6 +4418,49 @@ was already deallocated or when the used allocator has 
already been destroyed.
 
 
 
+@node omp_get_gprivate_limit
+@subsection @code{omp_get_gprivate_limit} -- Absolute limit of groupprivate 
memory
+@table @asis
+@item @emph{Description}:
+The @code{omp_get_gprivate_limit} routine returns the maximally possible limit
+on groupprivate memory, which consists of memory allocatable via the
+@code{dyn_groupprivate} clause and of variables that appear in the
+@code{groupprivate} directive.  @var{device_num} must be a conforming device
+number and @var{access_group} takes @code{omp_access_cgroup} as argument.  The
+effect of running this routine in a @code{target} region is unspecified.
+
+@item @emph{C}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{size_t omp_get_gprivate_limit(int *dev_num,}
+@item                   @tab @code{  omp_access_t access_group)}
+@end multitable
+
+@item @emph{C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{size_t omp_get_gprivate_limit(int *dev_num,}
+@item                   @tab @code{  omp_access_t access_group = 
omp_access_cgroup)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer (kind=c_size_t) function 
omp_get_gprivate_limit( &}
+@item                   @tab @code{  device_num, access_group)}
+@item                   @tab @code{use, intrinsic :: iso_c_binding, only : 
c_size_t, c_int}
+@item                   @tab @code{integer (kind=c_int), value :: device_num}
+@item                   @tab @code{integer (kind=omp_access_kind), value, 
optional :: access_group}
+@end multitable
+
+@c @item @emph{See also}:
+@c @ref{omp_alloc}, @ref{omp_aligned_alloc}, @ref{omp_calloc},
+@c @ref{omp_aligned_calloc}, @ref{omp_realloc}
+
+@item @emph{Reference}:
+@c TODO: Update once OpenMP 6.1 is released
+@uref{https://www.openmp.org, OpenMP Technical Report 15}, Section 34.13.5
+@end table
+
+
+
 @node Tool Control Routine
 @section Tool Control Routine
 
diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in
index 605ea9bb5a6b..6ffec871fd0e 100644
--- a/libgomp/omp.h.in
+++ b/libgomp/omp.h.in
@@ -115,6 +115,11 @@ typedef __UINTPTR_TYPE__ omp_uintptr_t;
 # define __GOMP_UINTPTR_T_ENUM
 #endif
 
+typedef enum omp_access_t {
+  omp_access_cgroup = 0,
+  omp_access_pteam = 1
+} omp_access_t;
+
 typedef enum omp_memspace_handle_t __GOMP_UINTPTR_T_ENUM
 {
   omp_default_mem_space = 0,
@@ -259,6 +264,7 @@ typedef enum omp_control_tool_result_t {
 #ifdef __cplusplus
 extern "C" {
 # define __GOMP_NOTHROW throw ()
+# define __GOMP_DEFAULT_ACCESS = omp_access_cgroup
 # define __GOMP_DEFAULT_NULL_ALLOCATOR = omp_null_allocator
 # define __GOMP_DEFAULT_NULL = __null
 #else
@@ -343,6 +349,9 @@ extern int omp_is_initial_device (void) __GOMP_NOTHROW;
 extern int omp_get_initial_device (void) __GOMP_NOTHROW;
 extern int omp_get_max_task_priority (void) __GOMP_NOTHROW;
 
+extern __SIZE_TYPE__ omp_get_gprivate_limit (int,
+                      omp_access_t __GOMP_DEFAULT_ACCESS) __GOMP_NOTHROW;
+
 extern void omp_fulfill_event (omp_event_handle_t) __GOMP_NOTHROW;
 
 extern void omp_set_num_teams (int) __GOMP_NOTHROW;
diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in
index 740b5a886410..598ae10fbdf2 100644
--- a/libgomp/omp_lib.f90.in
+++ b/libgomp/omp_lib.f90.in
@@ -34,6 +34,7 @@
         integer, parameter :: omp_sync_hint_kind = 4
         integer, parameter :: omp_lock_hint_kind = omp_sync_hint_kind
         integer, parameter :: omp_pause_resource_kind = 4
+        integer, parameter :: omp_access_kind = c_int
         integer, parameter :: omp_allocator_handle_kind = c_intptr_t
         integer, parameter :: omp_alloctrait_key_kind = c_int
         integer, parameter :: omp_alloctrait_val_kind = c_intptr_t
@@ -219,6 +220,8 @@
         integer (omp_interop_rc_kind), parameter :: omp_irc_type_ptr = -4
         integer (omp_interop_rc_kind), parameter :: omp_irc_type_str = -5
         integer (omp_interop_rc_kind), parameter :: omp_irc_other = -6
+        integer (omp_access_kind), parameter :: omp_access_cgroup = 0
+        integer (omp_access_kind), parameter :: omp_access_pteam = 1
         integer (omp_control_tool_kind), parameter :: omp_control_tool_start = 
1
         integer (omp_control_tool_kind), parameter :: omp_control_tool_pause = 
2
         integer (omp_control_tool_kind), parameter :: omp_control_tool_flush = 
3
@@ -710,6 +713,16 @@
           end function omp_get_teams_thread_limit
         end interface
 
+        interface
+          integer (kind=c_size_t) function omp_get_gprivate_limit (&
+              device_num, access_group)
+            use, intrinsic :: iso_c_binding, only : c_size_t, c_int
+            import :: omp_access_kind
+            integer (kind=c_int), value :: device_num
+            integer (kind=omp_access_kind), value, optional :: access_group
+          end function omp_get_gprivate_limit
+        end interface
+
         interface
           subroutine omp_fulfill_event (event)
             use omp_lib_kinds
diff --git a/libgomp/omp_lib.h.in b/libgomp/omp_lib.h.in
index cce424eaa350..70ebca71a9b7 100644
--- a/libgomp/omp_lib.h.in
+++ b/libgomp/omp_lib.h.in
@@ -89,6 +89,13 @@
       integer omp_event_handle_kind
       integer omp_interop_kind, omp_interop_fr_kind
       integer omp_interop_property_kind, omp_interop_rc_kind
+
+      integer omp_access_kind
+      parameter (omp_access_kind = 4)
+      integer (omp_access_kind) omp_access_cgroup
+      integer (omp_access_kind) omp_access_pteam
+      parameter (omp_access_cgroup = 0)
+      parameter (omp_access_pteam = 1)
       integer omp_control_tool_kind
       integer omp_control_tool_result_kind
       parameter (omp_allocator_handle_kind = @INTPTR_T_KIND@)
@@ -771,6 +778,15 @@
         end function omp_get_supported_threads_dim
       end interface
 
+      interface
+        integer (kind=c_size_t) function omp_get_gprivate_limit (              
 &
+     &      device_num, access_group)
+          use, intrinsic :: iso_c_binding, only : c_size_t, c_int
+          import :: omp_access_kind
+          integer (kind=c_int), value :: device_num
+          integer (kind=omp_access_kind),value,optional :: access_group
+        end function omp_get_gprivate_limit
+      end interface
 
       interface
 !       This function only supports integer(4) for simplicity.
diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c
index 4aad9532183c..9d36178f33f1 100644
--- a/libgomp/plugin/plugin-gcn.c
+++ b/libgomp/plugin/plugin-gcn.c
@@ -3744,6 +3744,18 @@ GOMP_OFFLOAD_supported_threads_dim (int ord, int dim)
   return limit_worker_threads (__INT_MAX__);
 }
 
+/* The maximum amount of memory available in a groupprivate memory space,
+   inclusive of groupprivate variables and any groupprivate copy of an
+   instantiated dynamic groupprivate block. */
+
+size_t
+GOMP_OFFLOAD_get_gprivate_limit (int ord, omp_access_t access)
+{
+  if (access != omp_access_cgroup)
+    return 0;
+  return 0;  /* FIXME. dyn_groupprivate unsupported, but otherwise supported. 
*/
+}
+
 /* Return the specific capabilities the HSA accelerator have.  */
 
 unsigned int
diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c
index 4a559877c9e8..62c43e7bd7a5 100644
--- a/libgomp/plugin/plugin-nvptx.c
+++ b/libgomp/plugin/plugin-nvptx.c
@@ -1428,6 +1428,18 @@ GOMP_OFFLOAD_supported_threads_dim (int ord, int dim)
   return max_warps_block;
 }
 
+/* The maximum amount of memory available in a groupprivate memory space,
+   inclusive of groupprivate variables and any groupprivate copy of an
+   instantiated dynamic groupprivate block. */
+
+size_t
+GOMP_OFFLOAD_get_gprivate_limit (int ord, omp_access_t access)
+{
+  if (access != omp_access_cgroup)
+    return 0;
+  return 0;  /* FIXME. dyn_groupprivate unsupported, but otherwise supported. 
*/
+}
+
 unsigned int
 GOMP_OFFLOAD_get_caps (void)
 {
diff --git a/libgomp/target.c b/libgomp/target.c
index f508040e0cad..f09e4ef38550 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -6387,6 +6387,27 @@ omp_get_device_from_uid (const char *uid)
   return omp_invalid_device;
 }
 
+/* The maximum amount of memory available in a groupprivate memory space,
+   inclusive of groupprivate variables and any groupprivate copy of an
+   instantiated dynamic groupprivate block. */
+
+size_t
+omp_get_gprivate_limit (int device_num, omp_access_t access_group)
+{
+  if (device_num == omp_default_device)
+    device_num = gomp_get_default_device ();
+
+  if (device_num == omp_initial_device
+      || device_num == omp_get_initial_device ())
+    /* FIXME - update once dyn_groupprivate is supported on the host.  */
+    return access_group != omp_access_cgroup ? 0 : 0;
+
+  struct gomp_device_descr *devicep = resolve_device (device_num, false);
+  if (devicep == NULL || !devicep->get_gprivate_limit_func)
+    return 0;
+  return devicep->get_gprivate_limit_func (devicep->target_id, access_group);
+}
+
 /* Return the numa distance between the numa node of the calling host
    thread and each of the NDEV devices in DEVICES.
    Special values:
@@ -6447,6 +6468,7 @@ ialias (omp_get_supported_active_team_dims)
 ialias (omp_get_supported_active_league_dims)
 ialias (omp_get_supported_threads_dim)
 ialias (omp_get_supported_teams_dim)
+ialias (omp_get_gprivate_limit)
 ialias (omp_get_uid_from_device)
 ialias (omp_get_device_from_uid)
 ialias (omp_get_device_distances)
@@ -6497,6 +6519,7 @@ gomp_load_plugin_for_device (struct gomp_device_descr 
*device,
   DLSYM_OPT (get_numa_node, get_numa_node);
   DLSYM_OPT (supported_threads_dim, supported_threads_dim);
   DLSYM_OPT (supported_teams_dim, supported_teams_dim);
+  DLSYM_OPT (get_gprivate_limit, get_gprivate_limit);
   DLSYM (get_caps);
   DLSYM_OPT (get_dev_caps, get_dev_caps);
   DLSYM (get_type);
diff --git a/libgomp/testsuite/libgomp.c-c++-common/gprivate-1.c 
b/libgomp/testsuite/libgomp.c-c++-common/gprivate-1.c
new file mode 100644
index 000000000000..e8ea66324992
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/gprivate-1.c
@@ -0,0 +1,49 @@
+#include <omp.h>
+
+void
+test_it (int dev)
+{
+  // Invalid access argument - expect 0
+  if (omp_get_gprivate_limit (dev, (omp_access_t) -1) != 0)
+    __builtin_abort ();
+
+  // Invalid access argument - expect 0
+  if (omp_get_gprivate_limit (dev, (omp_access_t) 99) != 0)
+    __builtin_abort ();
+
+  // FIXME: cgroup - should be valid in principle:
+  // - offload: groupprivate permitted for offloading,
+  //            even if dyn_groupprivate is not implemented.
+  // - host: dyn_groupprivate implementable, but not implemented.
+  //
+  if (dev == omp_invalid_device
+      && omp_get_gprivate_limit (dev, omp_access_cgroup) != 0)
+    __builtin_abort ();
+  else if (dev != omp_invalid_device  // For now, expect 0
+          && omp_get_gprivate_limit (dev, omp_access_cgroup) != 0)
+    __builtin_abort ();
+
+  // pteam - enum value defined but otherwise not specified at all!
+  // but in principle the limit question could be answered.
+  //
+  // Still, for now assume == 0.
+  if (omp_get_gprivate_limit (dev, omp_access_pteam) != 0)
+    __builtin_abort ();
+
+#if __cplusplus
+  // access is optional and defaults to 'omp_access_cgroup'.
+  if (omp_get_gprivate_limit (dev, omp_access_cgroup)
+      != omp_get_gprivate_limit (dev))
+    __builtin_abort ();
+#endif
+}
+
+int main ()
+{
+ // avoid - will exit after printing: libgomp: omp_invalid_device encountered
+ // test_it (omp_invalid_device);
+ test_it (omp_default_device);
+
+ for (int dev = omp_initial_device; dev <= omp_get_num_devices (); dev++)
+   test_it (dev);
+}
diff --git a/libgomp/testsuite/libgomp.fortran/gprivate-1.f90 
b/libgomp/testsuite/libgomp.fortran/gprivate-1.f90
new file mode 100644
index 000000000000..c171a2422a86
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/gprivate-1.f90
@@ -0,0 +1,54 @@
+module m
+  use omp_lib
+  implicit none (type, external)
+contains
+subroutine test_it (dev)
+  integer, value :: dev
+
+  ! Invalid access argument - expect 0
+  if (omp_get_gprivate_limit (dev, -1_omp_access_kind) /= 0) &
+    stop 1
+
+  ! Invalid access argument - expect 0
+  if (omp_get_gprivate_limit (dev, 99_omp_access_kind) /= 0) &
+    stop 2
+
+  ! FIXME: cgroup - should be valid in principle:
+  ! - offload: groupprivate permitted for offloading,
+  !            even if dyn_groupprivate is not implemented.
+  ! - host: dyn_groupprivate implementable, but not implemented.
+  !
+  if (dev == omp_invalid_device &
+      .and. omp_get_gprivate_limit (dev, omp_access_cgroup) /= 0) then
+    stop 3
+  else if (dev /= omp_invalid_device  &  ! For now, expect 0
+           .and. omp_get_gprivate_limit (dev, omp_access_cgroup) /= 0) then
+    stop 4
+  end if
+
+  ! pteam - enum value defined but otherwise not specified at all!
+  ! but in principle the limit question could be answered.
+  !
+  ! Still, for now assume == 0.
+  if (omp_get_gprivate_limit (dev, omp_access_pteam) /= 0) &
+    stop 5
+
+  ! access is optional and defaults to 'omp_access_cgroup'.
+  if (omp_get_gprivate_limit (dev, omp_access_cgroup) &
+      /= omp_get_gprivate_limit (dev)) &
+    stop 6
+end
+end
+
+program main
+  use m
+  implicit none (type, external)
+  integer :: dev
+  ! avoid - will exit after printing: libgomp: omp_invalid_device encountered
+  ! call test_it (omp_invalid_device)
+  call test_it (omp_default_device)
+
+  do dev = omp_initial_device, omp_get_num_devices ()
+    call test_it (dev)
+  end do
+end

Reply via email to