! { dg-do run }
+use iso_c_binding
+use omp_lib
+implicit none
+
type t
integer, pointer :: p(:)
integer, pointer :: p2(:)
type(t) :: var
integer, target :: tgt(5), tgt2(1000)
+logical :: host_accessible, self_mapping
+integer(c_intptr_t) :: ip, ip2
+
+ip = transfer(c_loc(tgt), ip)
+ip2 = transfer(c_loc(tgt2), ip2)
+
var%p => tgt
var%p2 => tgt2
-p = 0
-p2 = 0
+! 'map(var)' shall never do any pointer attachment - even if the pointer
+! variables are mapped to the device.
+!
+! There are three case:
+!
+! 1. Host fallback or self mapping: In the target region, the values are modified on the host
+! 2. Host memory inaccessible: var's pointers point to the host version (inaccessible);
+! tgt and tgt2 are mapped from/to the device but are inaccessible via var's pointers.
+! 3. No selfmapping but variables are accessible on the host:
+! Modifying var%p and var%p2 changes the value on the host - but copying back tgt and
+! tgt2 will set the value prior to the copy in.
-!$omp target map(tgt, tgt2(4:6), var)
- var%p(1) = 5
- var%p2(5) = 7
+! NOTE: Due to PR libgomp/113216, omp_target_is_accessible will report .false. on Nvptx
+! even if host access to the device is possible. - This will reduce the test coverage
+! but will not cause a fail.
+
+host_accessible = omp_target_is_accessible(c_loc(tgt), c_sizeof(tgt), omp_default_device) /= 0
+!host_accessible = .true. ! set this manually on nvptx with USM support, until fixed
+
+self_mapping = .false.
+!$omp target map(to: self_mapping)
+ self_mapping = .true.
!$omp end target
-if (var%p(1).ne.5) stop 1
-if (var%p2(5).ne.7) stop 2
+print *, (self_mapping ? '' : 'NO '), 'self mapping, ', &
+ (host_accessible ? '' : 'NOT '), 'host accessible'
-end
+var%p = 1
+var%p2 = 2
+
+! The following is slightly tricky as well: As 'tgt' is not used, it is optimized away
+! by during gimplification! - Hence, 'tgt' is also not copied back.
+! For 'tgt2(4:6)', the expression is too complex for the gimplifier - hence, it
+! is copied back ...
+
+!$omp target map(tgt, tgt2(4:6),var) firstprivate(host_accessible, ip, ip2)
+ ! No pointer attachment = points to the host
+ if (ip /= transfer(c_loc(var%p), ip)) stop 1
+ if (ip2 /= transfer(c_loc(var%p2), ip2)) stop 2
+
+ if (lbound(var%p,1) /= 1 .or. ubound(var%p,1) /= 5 .or. .not.associated(var%p)) &
+ stop 3
+ if (lbound(var%p2,1) /= 1 .or. ubound(var%p2,1) /= 1000 .or. .not.associated(var%p2)) &
+ stop 4
+
+ if (omp_is_initial_device() .or. host_accessible) then
+ if (any (var%p /= 1)) stop 5
+ if (any (var%p2 /= 2)) stop 6
+ var%p(1) = 5
+ var%p2(5) = 6
+ var%p2(22) = 7
+ end if
+!$omp end target
-! { dg-shouldfail "" { offload_device_nonshared_as } }
+if (omp_get_default_device() == omp_get_num_devices() &
+ .or. omp_get_default_device() == omp_initial_device &
+ .or. host_accessible) then
+ if (self_mapping) then
+ if (var%p(1) /= 5) stop 7
+ if (var%p2(5) /= 6) stop 8
+ if (var%p2(22) /= 7) stop 9
+ else
+ if (var%p(1) /= 5) stop 10 ! NO copy back - hence, value is 5
+ if (var%p2(5) /= 2) stop 11
+ if (var%p2(22) /= 7) stop 12
+ endif
+ if (any (var%p(2:) /= 1)) stop 13
+ if (any (var%p2(:4) /= 2) &
+ .or. any (var%p2(6:21) /= 2) &
+ .or. any (var%p2(23:) /= 2)) &
+ stop 14
+else
+ if (any(var%p /= 1)) stop 15
+ if (any(var%p2 /= 2)) stop 16
+end if
+
+
+! The same - but now using tgt / tgt2 inside the region
+
+var%p = 1
+var%p2 = 2
+
+!$omp target map(tgt, tgt2(4:6),var) firstprivate(host_accessible, ip, ip2)
+ ! No pointer attachment = points to the host
+ if (ip /= transfer(c_loc(var%p), ip)) stop 17
+ if (ip2 /= transfer(c_loc(var%p2), ip2)) stop 18
+
+ if (omp_is_initial_device() .or. self_mapping) then
+ if (.not. c_associated(c_loc(var%p), c_loc(tgt))) stop 19
+ if (.not. c_associated(c_loc(var%p2), c_loc(tgt2))) stop 20
+ else
+ if (c_associated(c_loc(var%p), c_loc(tgt))) stop 21
+ if (c_associated(c_loc(var%p2), c_loc(tgt2))) stop 22
+ endif
+
+ if (lbound(var%p,1) /= 1 .or. ubound(var%p,1) /= 5 .or. .not.associated(var%p)) &
+ stop 23
+ if (lbound(var%p2,1) /= 1 .or. ubound(var%p2,1) /= 1000 .or. .not.associated(var%p2)) &
+ stop 24
+
+ if (omp_is_initial_device() .or. host_accessible) then
+ if (any (var%p /= 1)) stop 25
+ if (any (var%p2 /= 2)) stop 26
+ var%p(1) = 5
+ var%p2(5) = 6
+ var%p2(22) = 7
+ end if
+!$omp end target
+
+if (omp_get_default_device() == omp_get_num_devices() &
+ .or. omp_get_default_device() == omp_initial_device &
+ .or. host_accessible) then
+ if (self_mapping) then
+ if (var%p(1) /= 5) stop 27
+ if (var%p2(5) /= 6) stop 28
+ if (var%p2(22) /= 7) stop 29
+ else
+ if (var%p(1) /= 1) stop 30 ! NOW tgt is copied back
+ if (var%p2(5) /= 2) stop 31
+ if (var%p2(22) /= 7) stop 32
+ endif
+ if (any (var%p(2:) /= 1)) stop 33
+ if (any (var%p2(:4) /= 2) &
+ .or. any (var%p2(6:21) /= 2) &
+ .or. any (var%p2(23:) /= 2)) &
+ stop 34
+else
+ if (any(var%p /= 1)) stop 35
+ if (any(var%p2 /= 2)) stop 36
+end if
+
+end