1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
|
! { dg-do run }
! { dg-additional-options "-fdump-tree-original" }
!
! PR fortran/97592 - fix argument passing to CONTIGUOUS,TARGET dummy
!
! { dg-final { scan-tree-dump-times "_gfortran_internal_pack \\(&b_2d" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_internal_pack \\(&p1" 3 "original" } }
!
! N.B.: there is no reliable count of _gfortran_internal_pack on temporaries parm.*
program pr97592
implicit none
integer :: i, k
integer, target :: a(10)
integer, pointer :: p1(:), p2(:), tgt(:), expect(:)
integer, pointer, contiguous :: cp(:)
integer, allocatable, target :: b(:)
!----------------------
! Code from original PR
!----------------------
call RemappingTest ()
!---------------------
! Additional 1-d tests
!---------------------
a = [(i, i=1,size(a))]
b = a
! Set p1 to an actually contiguous pointer
p1(13:) => a(3::2)
print *, lbound (p1), ubound (p1), is_contiguous (p1)
! non-contiguous pointer actual argument
expect => p1
call chk_cont (p1)
expect => p1
call chk_tgt_cont (p1)
expect => p1
call chk_ptr (p1, p2)
if (any (p2 /= p1)) stop 1
expect => p1
call chk_tgt (p1, p2)
if (any (p2 /= p1)) stop 2
! non-contiguous target actual argument
expect => b(3::2)
call chk_tgt_cont (b(3::2))
expect => b(3::2)
call chk_tgt (b(3::2), p2)
if (any (p2 /= p1)) stop 3
expect => b(3::2)
call chk_ptr (b(3::2), p2)
if (any (p2 /= p1)) stop 4
! Set p1 to an actually contiguous pointer
cp(17:) => a(3:9:1)
p1 => cp
print *, lbound (cp), ubound (cp), is_contiguous (cp)
print *, lbound (p1), ubound (p1), is_contiguous (p1)
expect => p1
call chk_tgt (p1, p2)
if (any (p2 /= cp)) stop 31
expect => cp
call chk_tgt (cp, p2)
if (any (p2 /= cp)) stop 32
expect => cp
call chk_tgt_cont (cp, p2)
if (any (p2 /= cp)) stop 33
expect => cp
call chk_tgt_expl (cp, p2, size (cp))
if (any (p2 /= cp)) stop 34
! See F2018:15.5.2.4 and F2018:C.10.4
expect => p1
call chk_tgt_cont (p1, p2)
! print *, p2
if (any (p2 /= cp)) stop 35
expect => p1
call chk_tgt_expl (p1, p2, size (p1))
if (any (p2 /= cp)) stop 36
expect => cp
call chk_ptr_cont (cp, p2)
if (any (p2 /= cp)) stop 37
! Pass array section which is actually contigous
k = 1
expect => cp(::k)
call chk_ptr (cp(::k), p2)
if (any (p2 /= cp(::k))) stop 38
expect => p1(::k)
call chk_tgt_cont (p1(::k), p2)
if (any (p2 /= p1(::k))) stop 39
expect => p1(::k)
call chk_tgt (p1(::k), p2)
if (any (p2 /= p1(::k))) stop 40
expect => p1(::k)
call chk_tgt_expl (p1(::k), p2, size (p1(::k)))
if (any (p2 /= p1(::k))) stop 41
expect => b(3::k)
call chk_tgt_cont (b(3::k), p2)
if (any (p2 /= b(3::k))) stop 42
expect => b(3::k)
call chk_tgt (b(3::k), p2)
if (any (p2 /= b(3::k))) stop 43
expect => b(3::k)
call chk_tgt_expl (b(3::k), p2, size (b(3::k)))
if (any (p2 /= b(3::k))) stop 44
if (any (a /= [(i, i=1,size(a))])) stop 66
if (any (a /= b)) stop 77
deallocate (b)
contains
! Contiguous pointer dummy
subroutine chk_ptr_cont (x, y)
integer, contiguous, pointer, intent(in) :: x(:)
integer, pointer, optional :: y(:)
print *, lbound (x), ubound (x)
if (present (y)) y => x(:)
if (associated (expect)) then
if (size (x) /= size (expect)) stop 10
if (any (x /= expect)) stop 11
if (lbound(expect,1) /= 1 .and. &
lbound(expect,1) /= lbound (x,1)) stop 20
end if
end
! Pointer dummy
subroutine chk_ptr (x, y)
integer, pointer, intent(in) :: x(:)
integer, pointer, optional :: y(:)
print *, lbound (x), ubound (x)
if (present (y)) y => x(:)
if (associated (expect)) then
if (size (x) /= size (expect)) stop 12
if (any (x /= expect)) stop 13
if (lbound(expect,1) /= 1 .and. &
lbound(expect,1) /= lbound (x,1)) stop 22
end if
end
! Dummy with target attribute
subroutine chk_tgt_cont (x, y)
integer, contiguous, target, intent(in) :: x(:)
integer, pointer, optional :: y(:)
if (present (y)) y => x(:)
if (associated (expect)) then
if (size (x) /= size (expect)) stop 14
if (any (x /= expect)) stop 15
end if
end
subroutine chk_tgt (x, y)
integer, target, intent(in) :: x(:)
integer, pointer, optional :: y(:)
if (present (y)) y => x(:)
if (associated (expect)) then
if (size (x) /= size (expect)) stop 16
if (any (x /= expect)) stop 17
end if
end
! Explicit-shape dummy with target attribute
subroutine chk_tgt_expl (x, y, n)
integer, intent(in) :: n
integer, target, intent(in) :: x(n)
integer, pointer, optional :: y(:)
if (present (y)) y => x(:)
if (associated (expect)) then
if (size (x) /= size (expect)) stop 18
if (any (x /= expect)) stop 19
end if
end
! Dummy without pointer or target attribute
subroutine chk_cont (x)
integer, contiguous, intent(in) :: x(:)
if (associated (expect)) then
if (size (x) /= size (expect)) stop 23
if (any (x /= expect)) stop 24
end if
end
!------------------------------------------------------------------------
subroutine RemappingTest ()
real, pointer :: B_2D(:,:)
real, pointer :: B_3D(:,:,:) => NULL()
integer, parameter :: n1=4, n2=4, n3=3
!-- Prepare B_2D
allocate (B_2D(n1*n2, n3))
B_2D = - huge (1.0)
if (.not. is_contiguous (B_2D)) stop 101
!-- Point B_3D to Storage
call SetPointer (B_2D, n1, n2, n3, B_3D)
!print *,"is_contiguous (B_3D) =", is_contiguous (B_3D)
if (.not. is_contiguous (B_3D)) stop 102
!-- Set B_3D
B_3D = 2.0
!-- See if the result is reflected in Storage
if (any (B_2D /= 2.0)) then
print *, "B_2D = ", B_2D !-- expect 2.0 for all elements
stop 103
end if
print *,"RemappingTest passed"
end
subroutine SetPointer (C_2D, n1, n2, n3, C_3D)
integer, intent(in) :: n1, n2, n3
real, target, contiguous :: C_2D(:,:)
real, pointer :: C_3D(:,:,:)
intent(in) :: C_2D
C_3D(1:n1,1:n2,1:n3) => C_2D
end
end
|