During a recent discussion I stumbled about the behavior of the associated() intrinsic when checking whether two pointers point to the same zero-sized array target, which surprised me at first glance.
program test
implicit none
integer, pointer :: a(:), b(:)
allocate(a(0))
b => a
print *, "associated(a)", associated(a)
print *, "associated(b)", associated(b)
print *, "associated(a, b)", associated(a, b)
end program test
```
Apparently, if the target is zero-sized, associated(a, b)returns .false. even if the two pointers point to the same (zero-sized) target.
I understand, that this behavior is fully standard conforming, as 16.9.20 says
Case (vi):
If TARGET is present and is an array target, the result is true if and only if POINTER is associated
with a target that has the same shape as TARGET, is neither of size zero nor an array whose elements
are zero-sized storage sequences, and occupies the same storage units as TARGET in array element
order.
But does anyone have some insights about the motivation for this behavior? What are the situations, where this behavior is more intuitive/desired than associated(a, b) just delivering .true. whenever the two pointers point to the same object, regardless of its storage size?
I think your example, with both arguments being pointers, is rather covered by Case (viii) of that section:
Case (viii): If TARGET is present and is an array pointer, the result is true if and only if POINTER and TARGET are both associated, have the same shape, are neither of size zero nor arrays whose elements are zero-sized storage sequences, and occupy the same storage units in array element order.
I do not know of the motivation behind all of those conditions. I think in principle the result could have been defined either way. If it had been defined the other way, namely allowing zero-sized pointer arrays to be associated with each other, then the associated metadata would have needed to be extended somehow to keep track of which ones were associated and which ones were not. Maybe that leads to incompatible or inconsistent situations, or maybe it was just too much effort to place on the compiler for any possible benefits. As it is written, the metadata does not need to store that additional information, and the result of ASSOCIATED can be determined rather easily, just by looking at the two zero-size arguments.
The single-argument case, which returns .true. in the zero-length situation, does require a bit in the metadata that keeps track of whether the pointer has been associated, but it is not required to keep track of its defined/undefined status – that status is rather the responsibility of the programmer.
I would also note that all eight of those cases include the phrase “if and only if”, so there is no ambiguity in the text for any of these cases as to what a compiler is supposed to do. This is in contrast to the analogous wording in the allocate-on-assignment situation in section 10.2.1.3 which only includes the word “if” and is therefore ambiguous in some situations.
If I have two objects that are identical in other ways except that they might point to different data, I probably check that by looking at the addresses of the data. If the arrays are of zero size they do not point to any data, hence I cannot tell them apart. I would have to have them point to a unique name or add an additional value to the metadata to be able to tell one from the other. So you are requiring that pointers and targets retain a unique name and that target name be part of the metadata for a pointer; whereas the simpler and more robust approach is probably to use the data address.
If that were not the case you would not need a boolean test to tell if something was associated, you could just ask the “name” of the target. But think of the bookkeeping involved and the issues with the scope of the “names”.
Haven’t thought to long about it, but it might be something along those lines.
If the question being asked is “do we point to the same data?” it is easy to answer by looking at the location of the data. Otherwise, can pointer A even target B? Are they compatible types, etc? The test for telling if two objects are the “same” when they have no data associated becomes much more nebulous.