Hi Tobias,

I notice that your scalar allocation does not use reallocation at all.
There is something not quite right there.

However, this just demonstrates one of the gotchas associated with
pointers, especially where the target is allocatable, and has nothing
to do with reallocation on assignment. Try this case, which does not
use class assignment.

implicit none (type, external)
integer, pointer :: ptr(:)
class(*), target, allocatable :: alloc(:)
allocate(integer :: alloc(1))
select type(alloc)
   type is(integer)
     alloc = 67
     ptr => alloc
end select
call assign(alloc)
!print *, ptr  ! This causes an invalid read of size 4
!if (ptr(1) /= 5) error stop 1
select type(alloc)
   type is(integer)
    print *, alloc
    if (associated (ptr, alloc)) then
      print *, ptr
    else
      print *, "ptr is no longer associated with assoc"
    end if
    !if (ptr(1) /= 5) error stop 2
end select
deallocate(alloc)
contains
subroutine assign(x)
   class(*), allocatable :: x(:)
   if (allocated(x)) deallocate(x)
   allocate (x, source = [5])
end subroutine assign
end

[pault@pc30 pr83118]$  ./a.out
           5
           5

Interestingly, under valgrind the result is:
           5
 ptr is no longer associated with assoc

Cheers

Paul


On Mon, 18 Nov 2019 at 10:24, Tobias Burnus <tob...@codesourcery.com> wrote:
>
> On 11/17/19 7:34 PM, Paul Richard Thomas wrote:
> […]
> Sorry for not yet reviewing the code, but the following caught my eye:
> >      (gfc_alloc_allocatable_for_assignment): […]
> >      Force reallocation of unlimited
> >      polymorphic lhs's. […]
> > […]
> > !   /* If the lhs is deferred length or unlimited polymorphic, assume that
> > !      the element size changes and force a reallocation.  */
> > !   if (expr1->ts.deferred || UNLIMITED_POLY (expr1))
> I wonder whether this assumption breaks code, which relies on a pointer
> address not changing, cf. test case below.
>
> I think the standard does not state explicitly that no reallocation
> happens, but I think it can be deduced. In any case, the reallocation is
> only supposed to happen for (F2018, 10.2.1.3p1):
> "If the variable is an allocated allocatable variable, it is deallocated
> ifexpr is an array of different shape, any corresponding length type
> parameter values of the variable andexprdiffer, or the variable is
> polymorphic and the dynamic type or any corresponding kind type
> parameter values of the variable andexpr differ."
>
> Cheers,
>
> Tobias
>
> implicit none (type, external)
> integer, pointer :: ptr
> class(*), target, allocatable :: alloc
> allocate(integer :: alloc)
> select type(alloc)
>    type is(integer)
>      alloc = 67
>      ptr => alloc
> end select
> call assign(alloc)
> !print *, ptr
> if (ptr /= 5) error stop 1
> select type(alloc)
>    type is(integer)
>     !print *, alloc
>     if (ptr /= 5) error stop 2
> end select
> contains
> subroutine assign(x)
>    class(*), allocatable :: x
>    x = 5
> end subroutine assign
> end
>


-- 
"If you can't explain it simply, you don't understand it well enough"
- Albert Einstein

Reply via email to