nncarlson / gfortran.dg

The GFortran testsuite rigged for testing other Fortran compilers

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Invalid nested derived type constructor in extends_2.f03, defined_assignment_5.f90

nncarlson opened this issue · comments

This nested constructor expression from extends_2.f03 is illegal:

59:    new_person = person_record (education (person (name, ss), &
60:                                attainment, institution), &
61:                                personnel_number, department, &
62:                                supervisor)

In the absence of keywords, the component data must appear in component order, but parent types are not part of the order. For example, the components of education are name, ss, attainment, and institution. Thus the first argument to the education constructor, a person object, is being associated with the character name component -- an error. The NAG compiler reports:

$ nagfor -kind=byte extends_2.f03
NAG Fortran Compiler Release 6.1(Tozai) Build 6144
Error: extends_2.f03, line 59: Wrong data type for component NAME in constructor for type EDUCATION

To use the person constructor one must use keywords. See Note 4.59 in F08 or F15. So the correct expression would be

59:    new_person = person_record (education=education (person=person (name, ss), &
60:                                attainment=attainment, institution=institution), &
61:                                personnel_number=personnel_number, department=department, &
62:                                supervisor=supervisor)

(once a keyword argument appears, the following ones must use keywords too)
The corrected code compiles and runs cleanly with NAG 6.1 and Intel 18.1.

This seemed a pretty serious bug, so I reported it as PR84093
It is really tempting to think of this behavior as an extension, however the following example shows it can't be.

type parent
  type(parent), pointer :: next => null()
end type

type, extends(parent) :: child
  integer :: n
end type

type(child) :: c
type(parent), pointer :: p

allocate(p)
allocate(p%next)

c = child(parent=p,n=1)
if (.not.associated(c%next,p%next)) stop 1

c = child(p,1)
if (.not.associated(c%next,p)) stop 2

end

The same type of invalid code is in defined_assignment_5.f90