[Openmp-commits] [openmp] [OpenMP] Add Fortran support routines for dyn_groupprivate (OpenMP 6.1) (PR #211630)

Michael Klemm via Openmp-commits openmp-commits at lists.llvm.org
Wed Sep 30 10:57:24 PDT 2026


https://github.com/mjklemm updated https://github.com/llvm/llvm-project/pull/211630

>From ed57d5421ad8ab73f89cbcf498be076dbd612bf3 Mon Sep 17 00:00:00 2001
From: Michael Klemm <michael.klemm at amd.com>
Date: Thu, 23 Jul 2026 15:28:59 +0200
Subject: [PATCH 1/6] [OpenMP] Add Fortran routine declarations for device
 dynamic memory

---
 openmp/module/omp_lib.F90.var | 48 +++++++++++++++++++++++++++++++++++
 openmp/module/omp_lib.h.var   | 45 ++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/openmp/module/omp_lib.F90.var b/openmp/module/omp_lib.F90.var
index a41b2faad9d3d..0b04190e2e6b7 100644
--- a/openmp/module/omp_lib.F90.var
+++ b/openmp/module/omp_lib.F90.var
@@ -36,6 +36,7 @@
         integer, parameter, public :: omp_control_tool_result_kind = omp_integer_kind
         integer, parameter, public :: omp_allocator_handle_kind = c_intptr_t
         integer, parameter, public :: omp_memspace_handle_kind = c_intptr_t
+        integer, parameter, public :: omp_access_kind = omp_integer_kind
         integer, parameter, public :: omp_alloctrait_key_kind = omp_integer_kind
         integer, parameter, public :: omp_alloctrait_val_kind = c_intptr_t
         integer, parameter, public :: omp_interop_kind = c_intptr_t
@@ -82,6 +83,7 @@
         public :: omp_control_tool_result_kind
         public :: omp_allocator_handle_kind
         public :: omp_memspace_handle_kind
+        public :: omp_access_kind
         public :: omp_alloctrait_key_kind
         public :: omp_alloctrait_val_kind
         public :: omp_interop_kind
@@ -207,6 +209,9 @@
         integer (kind=omp_memspace_handle_kind), parameter, public :: llvm_omp_target_shared_mem_space = 101
         integer (kind=omp_memspace_handle_kind), parameter, public :: llvm_omp_target_device_mem_space = 102
 
+        integer (kind=omp_access_kind), parameter, public :: omp_access_cgroup = 0
+        integer (kind=omp_access_kind), parameter, public :: omp_access_pteam = 1
+
         integer (kind=omp_pause_resource_kind), parameter, public :: omp_pause_resume = 0
         integer (kind=omp_pause_resource_kind), parameter, public :: omp_pause_soft = 1
         integer (kind=omp_pause_resource_kind), parameter, public :: omp_pause_hard = 2
@@ -933,6 +938,44 @@
             integer, intent(in) :: resources(*)
           end function omp_get_submemspace
 
+          function omp_get_dyn_gprivate_ptr(offset, access_group)
+            use omp_lib_kinds
+            use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+            type (c_ptr) omp_get_dyn_gprivate_ptr
+            integer (kind=c_size_t), value, optional :: offset
+            integer (kind=omp_access_kind), value, optional :: access_group
+          end function omp_get_dyn_gprivate_ptr
+
+          function omp_get_dyn_gprivate_nofb_ptr(offset, access_group)
+            use omp_lib_kinds
+            use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+            type (c_ptr) omp_get_dyn_gprivate_nofb_ptr
+            integer (kind=c_size_t), value, optional :: offset
+            integer (kind=omp_access_kind), value, optional :: access_group
+          end function omp_get_dyn_gprivate_nofb_ptr
+
+          function omp_get_dyn_gprivate_size(access_group)
+            use omp_lib_kinds
+            use, intrinsic :: iso_c_binding, only : c_size_t
+            integer (kind=c_size_t) omp_get_dyn_gprivate_size
+            integer (kind=omp_access_kind), value, optional :: access_group
+          end function omp_get_dyn_gprivate_size
+
+          function omp_get_dyn_gprivate_memspace(access_group)
+            use omp_lib_kinds
+            integer (kind=omp_memspace_handle_kind)                           &
+                omp_get_dyn_gprivate_memspace
+            integer (kind=omp_access_kind), value, optional :: access_group
+          end function omp_get_dyn_gprivate_memspace
+
+          function omp_get_gprivate_limit(device_num, access_group)
+            use omp_lib_kinds
+            use, intrinsic :: iso_c_binding, only : c_size_t, c_int
+            integer (kind=c_size_t) omp_get_gprivate_limit
+            integer (kind=c_int), value :: device_num
+            integer (kind=omp_access_kind), value, optional :: access_group
+          end function omp_get_gprivate_limit
+
 !         ***
 !         *** kmp_* entry points
 !         ***
@@ -1269,6 +1312,11 @@
         public :: kmp_set_warnings_on
         public :: kmp_set_warnings_off
         public :: kmp_get_cancellation_status
+        public :: omp_get_dyn_gprivate_ptr
+        public :: omp_get_dyn_gprivate_nofb_ptr
+        public :: omp_get_dyn_gprivate_size
+        public :: omp_get_dyn_gprivate_memspace
+        public :: omp_get_gprivate_limit
         public :: omp_get_num_interop_properties
         public :: omp_get_interop_int
         public :: omp_get_interop_ptr
diff --git a/openmp/module/omp_lib.h.var b/openmp/module/omp_lib.h.var
index 5e1996e31fe0a..de00b05cb2cf1 100644
--- a/openmp/module/omp_lib.h.var
+++ b/openmp/module/omp_lib.h.var
@@ -42,6 +42,8 @@
       parameter(omp_allocator_handle_kind=int_ptr_kind())
       integer omp_memspace_handle_kind
       parameter(omp_memspace_handle_kind=int_ptr_kind())
+      integer omp_access_kind
+      parameter(omp_access_kind=omp_integer_kind)
       integer omp_alloctrait_key_kind
       parameter(omp_alloctrait_key_kind=omp_integer_kind)
       integer omp_alloctrait_val_kind
@@ -273,6 +275,11 @@
       integer(omp_memspace_handle_kind)llvm_omp_target_device_mem_space
       parameter(llvm_omp_target_device_mem_space=102)
 
+      integer(kind=omp_access_kind)omp_access_cgroup
+      parameter(omp_access_cgroup=0)
+      integer(kind=omp_access_kind)omp_access_pteam
+      parameter(omp_access_pteam=1)
+
       integer(kind=omp_pause_resource_kind)omp_pause_resume
       parameter(omp_pause_resume=0)
       integer(kind=omp_pause_resource_kind)omp_pause_soft
@@ -1025,6 +1032,44 @@
           integer, intent(in) :: resources(*)
         end function omp_get_submemspace
 
+        function omp_get_dyn_gprivate_ptr(offset, access_group)
+          use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+          import
+          type (c_ptr) omp_get_dyn_gprivate_ptr
+          integer (kind=c_size_t), value, optional :: offset
+          integer(omp_access_kind), value, optional :: access_group
+        end function omp_get_dyn_gprivate_ptr
+
+        function omp_get_dyn_gprivate_nofb_ptr(offset, access_group)
+          use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
+          import
+          type (c_ptr) omp_get_dyn_gprivate_nofb_ptr
+          integer (kind=c_size_t), value, optional :: offset
+          integer(omp_access_kind), value, optional :: access_group
+        end function omp_get_dyn_gprivate_nofb_ptr
+
+        function omp_get_dyn_gprivate_size(access_group)
+          use, intrinsic :: iso_c_binding, only : c_size_t
+          import
+          integer (kind=c_size_t) omp_get_dyn_gprivate_size
+          integer(omp_access_kind), value, optional :: access_group
+        end function omp_get_dyn_gprivate_size
+
+        function omp_get_dyn_gprivate_memspace(access_group)
+          import
+          integer(omp_memspace_handle_kind)
+     &      omp_get_dyn_gprivate_memspace
+          integer(omp_access_kind), value, optional :: access_group
+        end function omp_get_dyn_gprivate_memspace
+
+        function omp_get_gprivate_limit(device_num, access_group)
+          use, intrinsic :: iso_c_binding, only : c_size_t, c_int
+          import
+          integer (kind=c_size_t) omp_get_gprivate_limit
+          integer (kind=c_int), value :: device_num
+          integer(omp_access_kind), value, optional :: access_group
+        end function omp_get_gprivate_limit
+
 
 !       ***
 !       *** kmp_* entry points

>From 9987ed0891e09cfac539ac70b0555feab65f8e8a Mon Sep 17 00:00:00 2001
From: Michael Klemm <michael.klemm at amd.com>
Date: Thu, 23 Jul 2026 17:34:57 +0200
Subject: [PATCH 2/6] Add stub implementation

---
 openmp/runtime/src/kmp.h           |  5 +++++
 openmp/runtime/src/kmp_ftn_entry.h | 24 ++++++++++++++++++++++++
 openmp/runtime/src/kmp_ftn_os.h    | 20 ++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index 818e07c2bb23f..32c22177e7b05 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -1086,6 +1086,11 @@ extern omp_allocator_handle_t const llvm_omp_target_device_mem_alloc;
 extern omp_allocator_handle_t const kmp_max_mem_alloc;
 extern omp_allocator_handle_t __kmp_def_allocator;
 
+typedef enum omp_access_t {
+  omp_access_cgroup = 0,
+  omp_access_pteam = 1
+} omp_access_t;
+
 // end of duplicate type definitions from omp.h
 #endif
 
diff --git a/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h
index 1c8e568b78407..eebd08502728a 100644
--- a/openmp/runtime/src/kmp_ftn_entry.h
+++ b/openmp/runtime/src/kmp_ftn_entry.h
@@ -551,6 +551,30 @@ FTN_GET_SUBMEMSPACE(omp_memspace_handle_t KMP_DEREF memspace,
 #endif
 }
 
+// The C (KMP_FTN_PLAIN) versions of the dynamic groupprivate information
+// routines are defined in kmp_csupport.cpp, so only the Fortran entry points
+// are generated here. The offset and access_group arguments are optional in
+// Fortran and are passed as null pointers when omitted. These stubs report that
+// no dynamic groupprivate block exists.
+#if KMP_FTN_ENTRIES != KMP_FTN_PLAIN
+void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_PTR(size_t *, omp_access_t *) {
+  return NULL;
+}
+
+void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_NOFB_PTR(size_t *, omp_access_t *) {
+  return NULL;
+}
+
+size_t FTN_STDCALL FTN_GET_DYN_GPRIVATE_SIZE(omp_access_t *) { return 0; }
+
+omp_memspace_handle_t FTN_STDCALL
+FTN_GET_DYN_GPRIVATE_MEMSPACE(omp_access_t *) {
+  return omp_null_mem_space;
+}
+
+size_t FTN_STDCALL FTN_GET_GPRIVATE_LIMIT(int *, omp_access_t *) { return 0; }
+#endif // KMP_FTN_ENTRIES != KMP_FTN_PLAIN
+
 /* OpenMP 5.0 affinity format support */
 #ifndef KMP_STUB
 static void __kmp_fortran_strncpy_truncate(char *buffer, size_t buf_size,
diff --git a/openmp/runtime/src/kmp_ftn_os.h b/openmp/runtime/src/kmp_ftn_os.h
index c439a058f22b4..1e981b44031fb 100644
--- a/openmp/runtime/src/kmp_ftn_os.h
+++ b/openmp/runtime/src/kmp_ftn_os.h
@@ -139,6 +139,11 @@
 #define FTN_GET_DEVICES_ALL_ALLOCATOR omp_get_devices_all_allocator
 #define FTN_GET_MEMSPACE_NUM_RESOURCES omp_get_memspace_num_resources
 #define FTN_GET_SUBMEMSPACE omp_get_submemspace
+#define FTN_GET_DYN_GPRIVATE_PTR omp_get_dyn_gprivate_ptr
+#define FTN_GET_DYN_GPRIVATE_NOFB_PTR omp_get_dyn_gprivate_nofb_ptr
+#define FTN_GET_DYN_GPRIVATE_SIZE omp_get_dyn_gprivate_size
+#define FTN_GET_DYN_GPRIVATE_MEMSPACE omp_get_dyn_gprivate_memspace
+#define FTN_GET_GPRIVATE_LIMIT omp_get_gprivate_limit
 #define FTN_GET_DEVICE_NUM omp_get_device_num
 #define FTN_GET_UID_FROM_DEVICE omp_get_uid_from_device
 #define FTN_GET_DEVICE_FROM_UID omp_get_device_from_uid
@@ -288,6 +293,11 @@
 #define FTN_GET_DEVICES_ALL_ALLOCATOR omp_get_devices_all_allocator_
 #define FTN_GET_MEMSPACE_NUM_RESOURCES omp_get_memspace_num_resources_
 #define FTN_GET_SUBMEMSPACE omp_get_submemspace_
+#define FTN_GET_DYN_GPRIVATE_PTR omp_get_dyn_gprivate_ptr_
+#define FTN_GET_DYN_GPRIVATE_NOFB_PTR omp_get_dyn_gprivate_nofb_ptr_
+#define FTN_GET_DYN_GPRIVATE_SIZE omp_get_dyn_gprivate_size_
+#define FTN_GET_DYN_GPRIVATE_MEMSPACE omp_get_dyn_gprivate_memspace_
+#define FTN_GET_GPRIVATE_LIMIT omp_get_gprivate_limit_
 #define FTN_ALLOC omp_alloc_
 #define FTN_FREE omp_free_
 #define FTN_GET_DEVICE_NUM omp_get_device_num_
@@ -439,6 +449,11 @@
 #define FTN_GET_DEVICES_ALL_ALLOCATOR OMP_GET_DEVICES_ALL_ALLOCATOR
 #define FTN_GET_MEMSPACE_NUM_RESOURCES OMP_GET_MEMSPACE_NUM_RESOURCES
 #define FTN_GET_SUBMEMSPACE OMP_GET_SUBMEMSPACE
+#define FTN_GET_DYN_GPRIVATE_PTR OMP_GET_DYN_GPRIVATE_PTR
+#define FTN_GET_DYN_GPRIVATE_NOFB_PTR OMP_GET_DYN_GPRIVATE_NOFB_PTR
+#define FTN_GET_DYN_GPRIVATE_SIZE OMP_GET_DYN_GPRIVATE_SIZE
+#define FTN_GET_DYN_GPRIVATE_MEMSPACE OMP_GET_DYN_GPRIVATE_MEMSPACE
+#define FTN_GET_GPRIVATE_LIMIT OMP_GET_GPRIVATE_LIMIT
 #define FTN_GET_DEVICE_NUM OMP_GET_DEVICE_NUM
 #define FTN_GET_UID_FROM_DEVICE OMP_GET_UID_FROM_DEVICE
 #define FTN_GET_DEVICE_FROM_UID OMP_GET_DEVICE_FROM_UID
@@ -588,6 +603,11 @@
 #define FTN_GET_DEVICES_ALL_ALLOCATOR OMP_GET_DEVICES_ALL_ALLOCATOR_
 #define FTN_GET_MEMSPACE_NUM_RESOURCES OMP_GET_MEMSPACE_NUM_RESOURCES_
 #define FTN_GET_SUBMEMSPACE OMP_GET_SUBMEMSPACE_
+#define FTN_GET_DYN_GPRIVATE_PTR OMP_GET_DYN_GPRIVATE_PTR_
+#define FTN_GET_DYN_GPRIVATE_NOFB_PTR OMP_GET_DYN_GPRIVATE_NOFB_PTR_
+#define FTN_GET_DYN_GPRIVATE_SIZE OMP_GET_DYN_GPRIVATE_SIZE_
+#define FTN_GET_DYN_GPRIVATE_MEMSPACE OMP_GET_DYN_GPRIVATE_MEMSPACE_
+#define FTN_GET_GPRIVATE_LIMIT OMP_GET_GPRIVATE_LIMIT_
 #define FTN_ALLOC OMP_ALLOC_
 #define FTN_FREE OMP_FREE_
 #define FTN_GET_DEVICE_NUM OMP_GET_DEVICE_NUM_

>From 9793e51bd2aaa2de278df8046dee668490836f28 Mon Sep 17 00:00:00 2001
From: Michael Klemm <michael.klemm at amd.com>
Date: Thu, 23 Jul 2026 18:44:56 +0200
Subject: [PATCH 3/6] Add implementation for dyn_groupprivate routines

---
 openmp/runtime/src/kmp_ftn_entry.h | 81 +++++++++++++++++++++++++++---
 1 file changed, 74 insertions(+), 7 deletions(-)

diff --git a/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h
index eebd08502728a..0f32f920ed65e 100644
--- a/openmp/runtime/src/kmp_ftn_entry.h
+++ b/openmp/runtime/src/kmp_ftn_entry.h
@@ -554,25 +554,92 @@ FTN_GET_SUBMEMSPACE(omp_memspace_handle_t KMP_DEREF memspace,
 // The C (KMP_FTN_PLAIN) versions of the dynamic groupprivate information
 // routines are defined in kmp_csupport.cpp, so only the Fortran entry points
 // are generated here. The offset and access_group arguments are optional in
-// Fortran and are passed as null pointers when omitted. These stubs report that
-// no dynamic groupprivate block exists.
+// Fortran and are passed as null pointers when omitted; the defaults are a zero
+// offset and omp_access_cgroup.
+//
+// The dynamic-groupprivate-information routines report on the dynamic
+// groupprivate block that is instantiated by a dyn_groupprivate clause. When an
+// offload runtime is loaded it provides a device-aware definition; forward to
+// it so that Fortran code observes the same block as C/C++. When no offload
+// runtime is available the lookup resolves to the host entry in
+// kmp_csupport.cpp, which reports that no block exists (a null pointer, a size
+// of zero and a null memory space).
 #if KMP_FTN_ENTRIES != KMP_FTN_PLAIN
-void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_PTR(size_t *, omp_access_t *) {
+void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_PTR(size_t *offset,
+                                           omp_access_t *access_group) {
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
+  return NULL;
+#else
+  void *(*fptr)(size_t, omp_access_t);
+  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_ptr"))) {
+    size_t off = offset ? *offset : 0;
+    omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
+    return (*fptr)(off, ag);
+  }
   return NULL;
+#endif
 }
 
-void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_NOFB_PTR(size_t *, omp_access_t *) {
+void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_NOFB_PTR(size_t *offset,
+                                                omp_access_t *access_group) {
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
   return NULL;
+#else
+  void *(*fptr)(size_t, omp_access_t);
+  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_nofb_ptr"))) {
+    size_t off = offset ? *offset : 0;
+    omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
+    return (*fptr)(off, ag);
+  }
+  return NULL;
+#endif
 }
 
-size_t FTN_STDCALL FTN_GET_DYN_GPRIVATE_SIZE(omp_access_t *) { return 0; }
+size_t FTN_STDCALL FTN_GET_DYN_GPRIVATE_SIZE(omp_access_t *access_group) {
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
+  return 0;
+#else
+  size_t (*fptr)(omp_access_t);
+  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_size"))) {
+    omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
+    return (*fptr)(ag);
+  }
+  return 0;
+#endif
+}
 
 omp_memspace_handle_t FTN_STDCALL
-FTN_GET_DYN_GPRIVATE_MEMSPACE(omp_access_t *) {
+FTN_GET_DYN_GPRIVATE_MEMSPACE(omp_access_t *access_group) {
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
   return omp_null_mem_space;
+#else
+  omp_memspace_handle_t (*fptr)(omp_access_t);
+  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_memspace"))) {
+    omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
+    return (*fptr)(ag);
+  }
+  return omp_null_mem_space;
+#endif
 }
 
-size_t FTN_STDCALL FTN_GET_GPRIVATE_LIMIT(int *, omp_access_t *) { return 0; }
+// The groupprivate limit is a per-device property. libomptarget, if loaded,
+// provides a device-aware omp_get_gprivate_limit; forward to it so that Fortran
+// code observes the same limits as C/C++. When no offload runtime is available
+// there are no non-host devices and the host reports no limit, so return zero.
+size_t FTN_STDCALL FTN_GET_GPRIVATE_LIMIT(int *device_num,
+                                          omp_access_t *access_group) {
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
+  return 0;
+#else
+  size_t (*fptr)(int, omp_access_t);
+  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_gprivate_limit"))) {
+    int dev = device_num ? *device_num : 0;
+    omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
+    return (*fptr)(dev, ag);
+  }
+  return 0;
+#endif
+}
 #endif // KMP_FTN_ENTRIES != KMP_FTN_PLAIN
 
 /* OpenMP 5.0 affinity format support */

>From 4eb4a3a32c2a54407f676918bc4df822ccef6714 Mon Sep 17 00:00:00 2001
From: Michael Klemm <michael.klemm at amd.com>
Date: Thu, 23 Jul 2026 19:55:46 +0200
Subject: [PATCH 4/6] Add test

---
 .../test/api/omp61_dyn_gprivate_routines.f90  | 69 +++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90

diff --git a/openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90 b/openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90
new file mode 100644
index 0000000000000..8db7eb65e60d9
--- /dev/null
+++ b/openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90
@@ -0,0 +1,69 @@
+! RUN: %flang %flags %openmp_flags %s -o %t.exe
+! RUN: %t.exe | FileCheck %s
+
+! REQUIRES: linux
+
+! Test the Fortran interfaces of the OpenMP dynamic-groupprivate-information
+! routines and omp_get_gprivate_limit (TR15 Sec. 34.13).
+!
+! This exercises the interfaces, including the optional offset and access_group
+! arguments, and checks the values reported by the host runtime. When no dynamic
+! groupprivate block exists and no offload runtime is loaded, the routines report
+! a null pointer, a size of zero, a null memory space and a zero limit.
+
+program omp61_dyn_gprivate_routines
+  use omp_lib
+  use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t, c_int, c_associated
+  implicit none
+
+  type(c_ptr) :: p
+  integer(c_size_t) :: sz
+  integer(omp_memspace_handle_kind) :: ms
+  logical :: ok
+
+  ok = .true.
+
+  ! omp_get_dyn_gprivate_ptr: no block => null pointer. Cover default args,
+  ! explicit offset, explicit access_group, and the offset-omitted-via-keyword
+  ! form.
+  p = omp_get_dyn_gprivate_ptr()
+  if (c_associated(p)) ok = .false.
+  p = omp_get_dyn_gprivate_ptr(0_c_size_t)
+  if (c_associated(p)) ok = .false.
+  p = omp_get_dyn_gprivate_ptr(0_c_size_t, omp_access_cgroup)
+  if (c_associated(p)) ok = .false.
+  p = omp_get_dyn_gprivate_ptr(access_group=omp_access_cgroup)
+  if (c_associated(p)) ok = .false.
+
+  ! omp_get_dyn_gprivate_nofb_ptr: no block => null pointer.
+  p = omp_get_dyn_gprivate_nofb_ptr()
+  if (c_associated(p)) ok = .false.
+  p = omp_get_dyn_gprivate_nofb_ptr(0_c_size_t, omp_access_cgroup)
+  if (c_associated(p)) ok = .false.
+
+  ! omp_get_dyn_gprivate_size: no block => zero.
+  sz = omp_get_dyn_gprivate_size()
+  if (sz /= 0_c_size_t) ok = .false.
+  sz = omp_get_dyn_gprivate_size(omp_access_cgroup)
+  if (sz /= 0_c_size_t) ok = .false.
+
+  ! omp_get_dyn_gprivate_memspace: no block => omp_null_mem_space.
+  ms = omp_get_dyn_gprivate_memspace()
+  if (ms /= omp_null_mem_space) ok = .false.
+  ms = omp_get_dyn_gprivate_memspace(omp_access_cgroup)
+  if (ms /= omp_null_mem_space) ok = .false.
+
+  ! omp_get_gprivate_limit: the host reports no groupprivate limit.
+  sz = omp_get_gprivate_limit(0_c_int)
+  if (sz /= 0_c_size_t) ok = .false.
+  sz = omp_get_gprivate_limit(0_c_int, omp_access_cgroup)
+  if (sz /= 0_c_size_t) ok = .false.
+
+  if (ok) then
+    print *, "PASS"
+  else
+    print *, "FAIL"
+  end if
+
+! CHECK: PASS
+end program omp61_dyn_gprivate_routines
\ No newline at end of file

>From 24294cc8de75efa2ff761953147eddaa95f4e343 Mon Sep 17 00:00:00 2001
From: Michael Klemm <michael.klemm at amd.com>
Date: Wed, 30 Sep 2026 19:23:53 +0200
Subject: [PATCH 5/6] Correct dlsym logic.

---
 openmp/runtime/src/kmp_ftn_entry.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h
index 0f32f920ed65e..ae83689cecd3c 100644
--- a/openmp/runtime/src/kmp_ftn_entry.h
+++ b/openmp/runtime/src/kmp_ftn_entry.h
@@ -571,7 +571,7 @@ void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_PTR(size_t *offset,
   return NULL;
 #else
   void *(*fptr)(size_t, omp_access_t);
-  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_ptr"))) {
+  if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_dyn_gprivate_ptr"))) {
     size_t off = offset ? *offset : 0;
     omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
     return (*fptr)(off, ag);
@@ -586,7 +586,7 @@ void *FTN_STDCALL FTN_GET_DYN_GPRIVATE_NOFB_PTR(size_t *offset,
   return NULL;
 #else
   void *(*fptr)(size_t, omp_access_t);
-  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_nofb_ptr"))) {
+  if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_dyn_gprivate_nofb_ptr"))) {
     size_t off = offset ? *offset : 0;
     omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
     return (*fptr)(off, ag);
@@ -600,7 +600,7 @@ size_t FTN_STDCALL FTN_GET_DYN_GPRIVATE_SIZE(omp_access_t *access_group) {
   return 0;
 #else
   size_t (*fptr)(omp_access_t);
-  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_size"))) {
+  if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_dyn_gprivate_size"))) {
     omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
     return (*fptr)(ag);
   }
@@ -614,7 +614,7 @@ FTN_GET_DYN_GPRIVATE_MEMSPACE(omp_access_t *access_group) {
   return omp_null_mem_space;
 #else
   omp_memspace_handle_t (*fptr)(omp_access_t);
-  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_dyn_gprivate_memspace"))) {
+  if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_dyn_gprivate_memspace"))) {
     omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
     return (*fptr)(ag);
   }
@@ -632,7 +632,7 @@ size_t FTN_STDCALL FTN_GET_GPRIVATE_LIMIT(int *device_num,
   return 0;
 #else
   size_t (*fptr)(int, omp_access_t);
-  if ((*(void **)(&fptr) = KMP_DLSYM("omp_get_gprivate_limit"))) {
+  if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_gprivate_limit"))) {
     int dev = device_num ? *device_num : 0;
     omp_access_t ag = access_group ? *access_group : omp_access_cgroup;
     return (*fptr)(dev, ag);

>From bd5743b673f82a796f95dde8126112d4c799befc Mon Sep 17 00:00:00 2001
From: Michael Klemm <michael.klemm at amd.com>
Date: Wed, 30 Sep 2026 19:56:49 +0200
Subject: [PATCH 6/6] Fix newline

---
 openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90 | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90 b/openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90
index 8db7eb65e60d9..6998de2a58372 100644
--- a/openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90
+++ b/openmp/runtime/test/api/omp61_dyn_gprivate_routines.f90
@@ -66,4 +66,5 @@ program omp61_dyn_gprivate_routines
   end if
 
 ! CHECK: PASS
-end program omp61_dyn_gprivate_routines
\ No newline at end of file
+end program omp61_dyn_gprivate_routines
+



More information about the Openmp-commits mailing list