Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

associate (point) to allocatable components of derived type

377 views
Skip to first unread message

Stefano Zaghi

unread,
Mar 13, 2018, 11:22:13 AM3/13/18
to
Probably, this topic has been discussed many times, but I cannot figure out now if the following program is legal or not

---program---
module structured_objects
implicit none
private
public :: first_object
public :: second_object
public :: third_object

type :: third_object
integer, allocatable :: q(:)
endtype third_object

type :: second_object
type(third_object), allocatable :: third(:,:,:)
endtype second_object

type :: first_object
type(second_object), allocatable :: second
endtype first_object
endmodule structured_objects

program test_slice
use structured_objects
implicit none

type(first_object), target :: first
integer, pointer :: q(:,:,:)
integer :: i, j, k

allocate(first%second)
allocate(first%second%third(-1:5,-2:3,2:6))
do k=lbound(first%second%third, dim=3), ubound(first%second%third, dim=3)
do j=lbound(first%second%third, dim=2), ubound(first%second%third, dim=2)
do i=lbound(first%second%third, dim=1), ubound(first%second%third, dim=1)
allocate(first%second%third(i,j,k)%q(7))
enddo
enddo
enddo

associate(t=>first%second%third)
print*, 'original'
print*, lbound(t, dim=1), ubound(t, dim=1)
print*, lbound(t, dim=2), ubound(t, dim=2)
print*, lbound(t, dim=3), ubound(t, dim=3)
print*, 'reordered'
q(-1:,-1:,-1:) => t%q(1)
print*, lbound(q, dim=1), ubound(q, dim=1)
print*, lbound(q, dim=2), ubound(q, dim=2)
print*, lbound(q, dim=3), ubound(q, dim=3)
endassociate
endprogram test_slice
---end program---

Intel Fortran (18.0.0 20170811) compiles it without issues and upon execution gives the expected results

---intel output---
original
-1 5
-2 3
2 6
reordered
-1 5
-1 4
-1 3
---end intel output---

On the contrary, GNU Fortran (both 7.2.1 20171224 and 8.0.1 20180308) refuses to compile it:

---GNU Fortran output---
test_slice.f90:45:6:

q(-1:,-1:,-1:) => t%q(1)
1
Error: Different ranks in pointer assignment at (1)
---end GNU Fortran output---

Is the program valid (standard conforming)? If it is not valid, how can I "easily" "access" to an allocatable component of a structured type?

Thank you in advance for any suggestions.

My best regards.

FortranFan

unread,
Mar 13, 2018, 12:26:51 PM3/13/18
to
On Tuesday, March 13, 2018 at 11:22:13 AM UTC-4, Stefano Zaghi wrote:

> ..
> ---GNU Fortran output---
> test_slice.f90:45:6:
>
> q(-1:,-1:,-1:) => t%q(1)
> 1
> Error: Different ranks in pointer assignment at (1) ..

Hello Stefano,

I think your code is legal and the issue is a bug with the ASSOCIATE construct in gfortran.

Your code can be simplifies to the following standard-conforming case that also fails with gfortran:

--- begin snippet ---
integer, parameter :: n = 2
type :: t
integer :: q(n)
end type
type(t), target :: foo(n,n,n)
integer, pointer :: q(:,:,:)
q(-1:,-1:,-1:) => foo%q(1) !<--- A
associate ( bar => foo )
q(-1:,-1:,-1:) => bar%q(1) !<--- B
end associate
end
--- end snippet ---

p.f90:9:6:
q(-1:,-1:,-1:) => bar%q(1) !<--- B
1
Error: Different ranks in pointer assignment at (1)

Note the instructions marked A and B are equivalent and Intel Fortran accepts both and handles them as expected. However gfortran fails with B.

If my assessment above is confirmed to be valid, hopefully you can find some GNU volunteer can fix the problem for you.

Good luck,




Stefano Zaghi

unread,
Mar 13, 2018, 1:42:40 PM3/13/18
to
Dear FortranFan,

thank you very much for your help, it is really appreciated.

You replay, assuming you are right, eliminates my doubts about the pointer association "reordering". However, I have still doubts about the associate "bit".

Please, consider this new (cumbersome) example:

---new associate example---
module structured_objects
implicit none
private
public :: first_object
public :: second_object
public :: third_object

type :: third_object
integer, allocatable :: q(:)
endtype third_object

type :: second_object
type(third_object), allocatable :: third(:,:,:)
endtype second_object

type :: first_object
type(second_object), allocatable :: second
endtype first_object
endmodule structured_objects

program test_slice
use structured_objects
implicit none

type(first_object), target :: first
integer :: i, j, k

allocate(first%second)
allocate(first%second%third(2,3,4))
do k=lbound(first%second%third, dim=3), ubound(first%second%third, dim=3)
do j=lbound(first%second%third, dim=2), ubound(first%second%third, dim=2)
do i=lbound(first%second%third, dim=1), ubound(first%second%third, dim=1)
allocate(first%second%third(i,j,k)%q(7))
enddo
enddo
enddo

associate(q=>first%second%third%q(3))
print*, lbound(q, dim=1), ubound(q, dim=1)
print*, lbound(q, dim=2), ubound(q, dim=2)
print*, lbound(q, dim=3), ubound(q, dim=3)
endassociate
endprogram test_slice
---end new associate example---

Now, no pointer associations are involved, only associate construct.

Intel compiler still accepts it and run as expected:

---intel output---

1 2
1 3
1 4

---end intel output---

whereas GNU Fortran rejects it saying:

---gnu fortran output---
test_slice.f90:38:16:

associate(q=>first%second%third%q(3))
1
Error: Component to the right of a part reference with nonzero rank must not have the ALLOCATABLE attribute at (1)


---end gnu fortran output---

Is this new example legal or not?

If others will confirm that the first example (in your reduced version) is legal, I'll try fill a GNU Fortran bug (although bugzilla is not very friendly with my gmail account...).

Thank you again.

Cheers.

FortranFan

unread,
Mar 13, 2018, 4:12:51 PM3/13/18
to
On Tuesday, March 13, 2018 at 1:42:40 PM UTC-4, Stefano Zaghi wrote:

> ..
>
> whereas GNU Fortran rejects it saying:
>
> ---gnu fortran output---
> test_slice.f90:38:16:
>
> associate(q=>first%second%third%q(3))
> 1
> Error: Component to the right of a part reference with nonzero rank must not have the ALLOCATABLE attribute at (1)
>
>
> ---end gnu fortran output---
>
> Is this new example legal or not? ..


Hi Stefano,

I think your new example is *not* standard-conforming. Per 10-007r1 toward Fortran 2008 standard, there is constraint C618 that says in section 6.4.2 Structure components:

16 C618 (R611) There shall not be more than one part-ref with nonzero rank. A part-name to the right of a
17 part-ref with nonzero rank shall not have the ALLOCATABLE or POINTER attribute.

I think the above selector prevents you from employing "q => first%second%third%q(3)" in structure component context, whether it be an ASSOCIATE construct or a pointer association.

Here's a simple example that I think is handled correctly by gfortran but not by Intel Fortran:

--- begin snippet ---
type t
integer, allocatable :: q(:)
end type
type u
type(t), allocatable :: x(:,:,:)
end type
integer, pointer :: q(:,:,:)
type(u), target :: foo
q(-1:,-1:,-1:) => foo%x%q(1)
associate ( y => foo%x%q(1) )
end associate
end
--- begin snippet ---

p.f90:9:21:
q(-1:,-1:,-1:) => foo%x%q(1)
1
Error: Component to the right of a part reference with nonzero rank must not have the ALLOCATABLE attribute at (1)
p.f90:10:20:
associate ( y => foo%x%q(1) )

Stefano Zaghi

unread,
Mar 13, 2018, 4:48:48 PM3/13/18
to
Dear FortranFan,

I guessed that the last example was not legal, thank you for your insight. I was in doubt due to the fact that Intel accepts it.

So my last question (just for a minute :-)) is: how can I "deal" with "q" component in my last example? Is there a legal way to "obtain" a rank-3 array of %q(3) component avoiding a copy of the data?

Cheers

FortranFan

unread,
Mar 13, 2018, 5:57:11 PM3/13/18
to
On Tuesday, March 13, 2018 at 4:48:48 PM UTC-4, Stefano Zaghi wrote:

> .. Is there a legal way to "obtain" a rank-3 array of %q(3) component avoiding a copy of the data? ..


With the constraint of no data copies, I'm unable to think of any option but other readers here will have good ideas to suggest to you. All I can suggest is get attention of some GNU volunteers to take a close look at the standard vis-a-vis gfortran.

spectrum

unread,
Mar 13, 2018, 7:50:57 PM3/13/18
to
In the first example, this part

> associate( t => first% second% third )
> ...
> q( -1:, -1:, -1: ) => t % q( 1 )
> ...
> endassociate

seems equivalent to

q( -1:, -1:, -1: ) => first % second % third % q( 1 )

but isn't this illegal because q is an allocatable array component?

--------------

https://stackoverflow.com/questions/27183800/error-the-part-name-to-the-right-of-a-part-ref-with-nonzero-rank-has-the-alloca?noredirect=1&lq=1

From the first answer (by @VladimirF):

> each %weight is stored elsewhere and you don't have any simple formula to
> compute where is each %weight(i).

From the second answer (by @IanH):

> In the allocatable component case some components in some elements might not
> be allocated and where they are allocated the component might have different
> bounds, making a "regular" reference to the data in the component across the
> elements of the array conceptually difficult.

The situation seems the same as "jagged" or "rugged" arrays, so making it
impossible to get a "rectangular" reference to a set of elements. But does this
not apply if the associate construct do something special (?) or is there
any exception if "q" is allocated with equal size?

--------------

Btw, for the first code, PGI fortran 2017.4 gives

original
-1 5
-2 3
2 6
reordered
-1 5
-1 4
-1 3

which is the same as Intel Fortran. But if I print "q" (after assigning some
value for check),

do k = lbound(first%second%third, dim=3), ubound(first%second%third, dim=3)
do j = lbound(first%second%third, dim=2), ubound(first%second%third, dim=2)
do i = lbound(first%second%third, dim=1), ubound(first%second%third, dim=1)

allocate(first%second%third(i,j,k)%q(7))

first%second%third(i,j,k)%q(:) = 100 ! <-- assign dummy values

enddo
enddo
enddo
...
associate( t => first % second % third )
...
q( -1:, -1:, -1: ) => t % q( 1 )
...

print *, "minval( q ) = ", minval( q ) !<-- check (1)
print *, "q = ", q ! <-- check (2)

endassociate

I get:

original
-1 5
-2 3
2 6
reordered
-1 5
-1 4
-1 3
minval( q ) = 0
q = 100 100 0 100 8
1078656 100 0 100 100 0
100 0 100 0 100 0
1079712 100 0 100 100 0
100 0 1080416 100 0 100
....

In the second example, PGI fortran gives

1 2
1 3
1 4

which again agrees with Intel, but if I do some calculation with q, it results
in segmentation fault (not surprisingly):

associate( q => first % second % third % q( 3 ) )
print*, lbound(q, dim=1), ubound(q, dim=1)
print*, lbound(q, dim=2), ubound(q, dim=2)
print*, lbound(q, dim=3), ubound(q, dim=3)

print *, minval( q ) !<--- do some calculation

endassociate

=>

1 2
1 3
1 4
Segmentation fault: 11

-------------

I have no Intel Fortran in hand so cannot try it (my workstation recently crushed!!)
but the above are the results on my Mac with gfortran-7.3 and PGI (at hand).

Ian Harvey

unread,
Mar 13, 2018, 8:02:20 PM3/13/18
to
You are allocating all the 'q' components to the same size. Consider making the size of that component a type parameter, then it doesn't need to be allocatable.

spectrum

unread,
Mar 13, 2018, 8:05:50 PM3/13/18
to
# Hmm... my use of the word "rugged" may be wrong... (the correct one is "ragged" ?)

https://en.wikipedia.org/wiki/Jagged_array

Stefano Zaghi

unread,
Mar 14, 2018, 12:25:47 AM3/14/18
to
Dear Ian, thank you very much for your suggestion.

Currently, I have kept my self far from parametrized derived type because GNU fortran had not a good support for them. In the last releases something should be changed, thus a test is worth to be done.

Ian, is my first example valid Fortran?

My best regards

Stefano Zaghi

unread,
Mar 14, 2018, 12:26:41 AM3/14/18
to
Dear FortranFan,

Thank you very much for your help.

Cheers

Stefano Zaghi

unread,
Mar 14, 2018, 12:27:44 AM3/14/18
to
Dear spectrum,

Thank you very much for your insight.

I'll read your stack overflow reference.

Cheers

Ian Harvey

unread,
Mar 14, 2018, 6:08:34 AM3/14/18
to
No. It violates the constraint against having an allocatable component
to the right of an part reference that is of non-zero rank, that is
discussed elsethread. The associate name `t` has the same rank as the
selector `first%second%third` - it is rank three. In the component
reference `t%q(1)`, you then have the allocatable component `q` to the
right of that rank three object.

With length type parameters, the relevant fragments of the code would
look like:

type :: third_object(len)
integer, len :: len
integer :: q(len)
endtype third_object

type :: second_object
type(third_object(:)), allocatable :: third(:,:,:)
endtype second_object
...
allocate(first%second)
allocate(third_object(7) :: first%second%third(-1:5,-2:3,2:6))

and the subsequent reference to t%q(1) and the pointer assignment would
be conforming.

>
> My best regards
>

Stefano Zaghi

unread,
Mar 14, 2018, 6:12:41 AM3/14/18
to
Again, thank you very much!

My best regards.

Stefano Zaghi

unread,
Mar 14, 2018, 6:27:22 AM3/14/18
to
Il giorno mercoledì 14 marzo 2018 11:08:34 UTC+1, Ian Harvey ha scritto:
Anyhow, I have just checked and both GNU Fortran 7.2 (stable) and the experimental 8.x branch does not support parametrized derived type "well", in particular it seems that any tentative of "allocatable" PDT will face with a

951: internal compiler error: in gfc_get_derived_type, at fortran/trans-types.c:254

I have to check if this bug is known or not.

My best regards.

FortranFan

unread,
Mar 14, 2018, 9:15:42 AM3/14/18
to
On Wednesday, March 14, 2018 at 6:08:34 AM UTC-4, Ian Harvey wrote:

> ..
>
> No. It violates the constraint against having an allocatable component
> to the right of an part reference that is of non-zero rank, that is
> discussed elsethread. The associate name `t` has the same rank as the
> selector `first%second%third` - it is rank three. In the component
> reference `t%q(1)`, you then have the allocatable component `q` to the
> right of that rank three object. ..


The thought did occur to me yesterday as soon as I noticed the original post but my understanding (likely faulty) is t%q is not allocatable unlike first%second%third(i,j,k)%q.

FortranFan

unread,
Mar 14, 2018, 9:32:16 AM3/14/18
to
On Wednesday, March 14, 2018 at 6:27:22 AM UTC-4, Stefano Zaghi wrote:

> ..
> Anyhow, I have just checked and both GNU Fortran 7.2 (stable) and the experimental 8.x branch does not support parametrized derived type "well" ..

Stefano,

I did consider parameterized derived types (PDTs) yesterday but concluded they will offer you no solace, if anything they might make matters worse.

Firstly, the letters of the constraint in question (C618 per 10-007r1) may not preclude length-type parameters but the spirit of it should, for the same rationale that tries to guard against the dangers of part-ref on the right with an ALLOCATABLE attribute can come into play, albeit to a lesser extent, with components sized with the length type. However implementations all seem to struggle quite a bit with the use of length type in PDT components more than almost anything else in the standard.

Secondly, gfortran fails and Intel Fortran throws a segmentation fault with an example I had tried yesterday with PDT involving a length-type parameter. So no luck with this option either.

Stefano Zaghi

unread,
Mar 14, 2018, 9:39:01 AM3/14/18
to
Dear FortranFan,

your help is priceless.

I agree, currently PDT is not a "robust" option for me (I have to rely on GNU Fortran in 99% of the development and Intel Compiler for cluster/cross-check runs). Anyhow, I tried to get the attention of Damian in order to understand the (current and future) "level" of support offered by GNU Fortran to PDT.

PDT seems to be "missed chance" by Fortran, at least for who want to use GNU/Intel compilers...

Cheers.

FortranFan

unread,
Mar 14, 2018, 11:51:42 AM3/14/18
to
On Wednesday, March 14, 2018 at 9:39:01 AM UTC-4, Stefano Zaghi wrote:


> .. I have to rely on GNU Fortran in 99% of the development ..


I figured as much. Here's the simple PDT case that I tried yesterday which failed with gfortran:

--- begin snippet ---
type :: t(n)
integer, len :: n
integer :: a(n)
end type
type :: u
type(t(n=:)), allocatable :: x
end type
type(u) :: foo
allocate( t(n=1) :: foo%x )
end
--- end snippet ---

p.f90:9:23:
allocate( t(n=1) :: foo%x )
1
Error: Type of entity at (1) is type incompatible with typespec

FortranFan

unread,
Mar 14, 2018, 1:48:39 PM3/14/18
to
On Wednesday, March 14, 2018 at 9:39:01 AM UTC-4, Stefano Zaghi wrote:

> ..
> I agree, currently PDT is not a "robust" option for me (I have to rely on .. Intel Compiler for cluster/cross-check runs ..

Hi Stefano,

Here's the simple case I'd tried with Intel Fortran and the PDT approach yesterday and which I ruled out due to the unexpected result I got (in addition to segmentation fault if run-time checks are enabled):

--- begin snippet ---
use, intrinsic :: iso_fortran_env, only : compiler_version
integer, parameter :: m = 2
type :: t(n)
integer, len :: n
integer :: q(n)
end type
type :: u
type(t(n=:)), allocatable :: x(:)
end type
type(u), target :: foo
integer, pointer :: q(:)
integer :: i, j
print *, "Compiler Version: ", compiler_version()
allocate( t(n=m) :: foo%x(m) )
do i = 1, m
foo%x(i)%q = [( 10*(i-1)+j, j=1,m )]
end do
q(-1:) => foo%x%q(1)
print *, "q = ", q
print "(*(g0,1x))", "expected: ", (foo%x(i)%q(1), i=1,m)
end
--- end snippet ---

Upon execution,
Compiler Version:
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 18.0.1.156 Build 20171018

q = 1 0
expected: 1 11

Stefano Zaghi

unread,
Mar 14, 2018, 1:52:29 PM3/14/18
to
Argh... I have not understood how "fragile" is also the support of Intel concerning PDT. Muble, muble... no, PDT is not my way (for now).

Thank you very much FortranFan.

Cheers.

FortranFan

unread,
Mar 14, 2018, 2:37:22 PM3/14/18
to
On Wednesday, March 14, 2018 at 1:52:29 PM UTC-4, Stefano Zaghi wrote:

> .. no, PDT is not my way (for now). ..

I'll suggest stressing the "now" part. I personally think PDTs are a super feature and the standard should build on it. I think PDTs are integrally tied to any advances with generic programming with Fortran. Hopefully the implementations will all soon provide robust and efficient support of this facility, Intel is nearly there notwithstanding the problem for the case at hand.

0 new messages