llvm-project/flang/test/Semantics/resolve108.f90
Peter Klausler 93b0638eff [flang] Handle "type(foo) function f" when foo is defined in f
Fortran allows forward references to derived types, including
function results that are typed in a prefix of a FUNCTION statement.
If a type is defined in the body of the function, a reference to
that type from a prefix on the FUNCTION statement must resolve to
the local symbol, even and especially when that type shadows one
from the host scope.

The solution is to defer the processing of that type until the
end of the function's specification part.  But the language doesn't
allow for forward references to other names in the prefix, so defer
the processing of the type only when it is not an intrinsic type.
The data structures in name resolution that track this information
for functions needed to become a stack in order to make this work,
since functions can contain interfaces that are functions.

Differential Revision: https://reviews.llvm.org/D119448
2022-02-10 10:29:36 -08:00

70 lines
1.4 KiB
Fortran

! RUN: %python %S/test_errors.py %s %flang_fc1
! Tests attempts at forward references to local names in a FUNCTION prefix
! This case is not an error, but will elicit bogus errors if the
! result type of the function is badly resolved.
module m1
type t1
sequence
integer not_m
end type
contains
type(t1) function foo(n)
integer, intent(in) :: n
type t1
sequence
integer m
end type
foo%m = n
end function
end module
subroutine s1
use :: m1, only: foo
type t1
sequence
integer m
end type
type(t1) x
x = foo(234)
print *, x
end subroutine
module m2
integer, parameter :: k = kind(1.e0)
contains
real(kind=k) function foo(n)
integer, parameter :: k = kind(1.d0)
integer, intent(in) :: n
foo = n
end function
end module
subroutine s2
use :: m2, only: foo
!If we got the type of foo right, this declaration will fail
!due to an attempted division by zero.
!ERROR: Must be a constant value
integer, parameter :: test = 1 / (kind(foo(1)) - kind(1.e0))
end subroutine
module m3
integer, parameter :: k = kind(1.e0)
contains
real(kind=kind(x)) function foo(x)
!ERROR: The type of 'x' has already been implicitly declared
real(kind=kind(1.0d0)) x
foo = n
end function
end module
module m4
contains
!ERROR: Must be a constant value
real(n) function foo(x)
integer, parameter :: n = kind(foo)
real(n), intent(in) :: x
foo = x
end function
end module