Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29418 Discussions

Changing variable type within in SELECT TYPE statement

Jacob_Williams
New Contributor III
691 Views

I came across something interesting (see simple example below). Clearly, what I'm doing is wrong, but I was wondering if the compiler shouldn't complain more about it. I'm basically changing the type of a polymorphic variable within a select type construct. When I then try to access a variable that should no longer be there, it doesn't complain, but instead gives me the value of the variable in the new type.

module test_module

 implicit none

 type,abstract :: blah
 end type

 type,extends(blah) :: int_blah
  integer :: i = 999
 end type int_blah

 type,extends(blah) :: real_blah
  integer :: r = 888.0
 end type real_blah

 type :: segment
  class(blah),allocatable :: b
 contains
  procedure :: change_b
 end type segment

 contains

 subroutine change_b(me,i)
  !! change the type of me%b
  implicit none
  class(segment),intent(inout) :: me
  integer,intent(in) :: i

  if (allocated(me%b)) deallocate(me%b)
  select case(i)
  case(1)  !to int
   allocate(int_blah :: me%b)
  case(2)  !to real
   allocate(real_blah :: me%b)
  end select
 end subroutine change_b

end module test_module

program test

 use test_module

 implicit none

 type(segment) :: seg

 allocate(int_blah :: seg%b)

 select type (b => seg%b)
 class is (int_blah)

  write(*,*) 'b%i:',b%i

  !change to real:
  call seg%change_b(2)

  !b is now real_blah
  !but, this prints 888.0...
  write(*,*) 'b%i:',b%i

 end select

 !just to make sure it worked:
 select type (b => seg%b)
 class is (int_blah)
  write(*,*) 'b is int:',b%i
 class is (real_blah)
  write(*,*) 'b is real:',b%r
 end select

end program test

The output is:

 b%i:         999
 b%i:         888
 b is real:         888

 

0 Kudos
2 Replies
Arjen_Markus
Honored Contributor II
691 Views

I am not sure that the compiler can detect this change. It is akin to:

real, dimension(:), pointer :: p
real, dimension(:), allocatable, target :: array

allocate( array(10) )
p => array
deallocate( array )

write(*,*) p

Such dangling pointers are difficult if not impossible to detect completely reliably (like the classic halting problem).

Most probably the fact that the data structure is so small makes the program print the old value. But that is just a "lucky" coincidence.

0 Kudos
Steven_L_Intel1
Employee
691 Views

I agree with Arjen.

0 Kudos
Reply