! { dg-do run } ! ! Tests the fix for PR81758, in which the vpointer for 'ptr' in ! function 'pointer_value' would be set to the vtable of the component ! 'container' rather than that of the component 'vec_elem'. In this test ! case it is ensured that there is a single typebound procedure for both ! types, so that different values are returned. In the original problem ! completely different procedures were involved so that a segfault resulted. ! ! Reduced from the original code of Dimitry Liakh by ! Paul Thomas ! module types type, public:: gfc_container_t contains procedure, public:: get_value => ContTypeGetValue end type gfc_container_t !Element of a container: type, public:: gfc_cont_elem_t integer :: value_p contains procedure, public:: get_value => ContElemGetValue end type gfc_cont_elem_t !Vector element: type, extends(gfc_cont_elem_t), public:: vector_elem_t end type vector_elem_t !Vector: type, extends(gfc_container_t), public:: vector_t type(vector_elem_t), allocatable, private :: vec_elem end type vector_t type, public :: vector_iter_t class(vector_t), pointer, private :: container => NULL() contains procedure, public:: get_vector_value => vector_Value procedure, public:: get_pointer_value => pointer_value end type contains integer function ContElemGetValue (this) class(gfc_cont_elem_t) :: this ContElemGetValue = this%value_p end function integer function ContTypeGetValue (this) class(gfc_container_t) :: this ContTypeGetValue = 0 end function integer function vector_Value (this) class(vector_iter_t) :: this vector_value = this%container%vec_elem%get_value() end function integer function pointer_value (this) class(vector_iter_t), target :: this class(gfc_cont_elem_t), pointer :: ptr ptr => this%container%vec_elem pointer_value = ptr%get_value() end function subroutine factory (arg) class (vector_iter_t), pointer :: arg allocate (vector_iter_t :: arg) allocate (vector_t :: arg%container) allocate (arg%container%vec_elem) arg%container%vec_elem%value_p = 99 end subroutine end module use types class (vector_iter_t), pointer :: x call factory (x) if (x%get_vector_value() .ne. 99) STOP 1 if (x%get_pointer_value() .ne. 99) STOP 2 end