mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 03:46:46 +00:00

Name resolutions defers all resolution and checking of specific procedures in non-type-bound generic interfaces to the end of the specification part. This prevents expression analysis of references to generic functions in specification expressions in interfaces from resolving. Example (now a new test case in modfile07.f90): ``` module m12 interface generic module procedure specific end interface interface module subroutine s(a1,a2) character(*) a1 character(generic(a1)) a2 ! <-- end end interface contains pure integer function specific(x) character(*), intent(in) :: x specific = len(x) end end ``` The solution is to partially resolve specific procedures as they are defined for each generic, when they can be resolved, with the final pass at the end of the specification part to finish up any forward references and emit the necessary error messages. Making this fix caused some issues in module file output, which have all been resolved by making this simplifying change: generics are now all emitted to module file specification parts as their own group of declarations at the end of the specification part, followed only by namelists and COMMON blocks. Differential Revision: https://reviews.llvm.org/D157346
645 lines
13 KiB
Fortran
645 lines
13 KiB
Fortran
! RUN: %python %S/test_modfile.py %s %flang_fc1 -flogical-abbreviations -fxor-operator
|
|
|
|
! Resolution of user-defined operators in expressions.
|
|
! Test by using generic function in a specification expression that needs
|
|
! to be written to a .mod file.
|
|
|
|
! Numeric operators
|
|
module m1
|
|
type :: t
|
|
sequence
|
|
logical :: x
|
|
end type
|
|
interface operator(+)
|
|
pure integer(8) function add_ll(x, y)
|
|
logical, intent(in) :: x, y
|
|
end
|
|
pure integer(8) function add_li(x, y)
|
|
logical, intent(in) :: x
|
|
integer, intent(in) :: y
|
|
end
|
|
pure integer(8) function add_tt(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x, y
|
|
end
|
|
end interface
|
|
interface operator(/)
|
|
pure integer(8) function div_tz(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x
|
|
complex, intent(in) :: y
|
|
end
|
|
pure integer(8) function div_ct(x, y)
|
|
import :: t
|
|
character(10), intent(in) :: x
|
|
type(t), intent(in) :: y
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y, z)
|
|
logical :: x, y
|
|
real :: z(x + y) ! resolves to add_ll
|
|
end
|
|
subroutine s2(x, y, z)
|
|
logical :: x
|
|
integer :: y
|
|
real :: z(x + y) ! resolves to add_li
|
|
end
|
|
subroutine s3(x, y, z)
|
|
type(t) :: x
|
|
complex :: y
|
|
real :: z(x / y) ! resolves to div_tz
|
|
end
|
|
subroutine s4(x, y, z)
|
|
character(10) :: x
|
|
type(t) :: y
|
|
real :: z(x / y) ! resolves to div_ct
|
|
end
|
|
end
|
|
|
|
!Expect: m1.mod
|
|
!module m1
|
|
! type :: t
|
|
! sequence
|
|
! logical(4) :: x
|
|
! end type
|
|
! interface
|
|
! pure function add_ll(x, y)
|
|
! logical(4), intent(in) :: x
|
|
! logical(4), intent(in) :: y
|
|
! integer(8) :: add_ll
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function add_li(x, y)
|
|
! logical(4), intent(in) :: x
|
|
! integer(4), intent(in) :: y
|
|
! integer(8) :: add_li
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function add_tt(x, y)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! type(t), intent(in) :: y
|
|
! integer(8) :: add_tt
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function div_tz(x, y)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! complex(4), intent(in) :: y
|
|
! integer(8) :: div_tz
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function div_ct(x, y)
|
|
! import :: t
|
|
! character(10_4, 1), intent(in) :: x
|
|
! type(t), intent(in) :: y
|
|
! integer(8) :: div_ct
|
|
! end
|
|
! end interface
|
|
! interface operator(+)
|
|
! procedure :: add_ll
|
|
! procedure :: add_li
|
|
! procedure :: add_tt
|
|
! end interface
|
|
! interface operator(/)
|
|
! procedure :: div_tz
|
|
! procedure :: div_ct
|
|
! end interface
|
|
!contains
|
|
! subroutine s1(x, y, z)
|
|
! logical(4) :: x
|
|
! logical(4) :: y
|
|
! real(4) :: z(1_8:add_ll(x, y))
|
|
! end
|
|
! subroutine s2(x, y, z)
|
|
! logical(4) :: x
|
|
! integer(4) :: y
|
|
! real(4) :: z(1_8:add_li(x, y))
|
|
! end
|
|
! subroutine s3(x, y, z)
|
|
! type(t) :: x
|
|
! complex(4) :: y
|
|
! real(4) :: z(1_8:div_tz(x, y))
|
|
! end
|
|
! subroutine s4(x, y, z)
|
|
! character(10_4, 1) :: x
|
|
! type(t) :: y
|
|
! real(4) :: z(1_8:div_ct(x, y))
|
|
! end
|
|
!end
|
|
|
|
! Logical operators
|
|
module m2
|
|
type :: t
|
|
sequence
|
|
logical :: x
|
|
end type
|
|
interface operator(.And.)
|
|
pure integer(8) function and_ti(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x
|
|
integer, intent(in) :: y
|
|
end
|
|
pure integer(8) function and_li(x, y)
|
|
logical, intent(in) :: x
|
|
integer, intent(in) :: y
|
|
end
|
|
end interface
|
|
! Alternative spelling of .AND.
|
|
interface operator(.a.)
|
|
pure integer(8) function and_tt(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x, y
|
|
end
|
|
end interface
|
|
interface operator(.x.)
|
|
pure integer(8) function neqv_tt(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x, y
|
|
end
|
|
end interface
|
|
interface operator(.neqv.)
|
|
pure integer(8) function neqv_rr(x, y)
|
|
real, intent(in) :: x, y
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y, z)
|
|
type(t) :: x
|
|
integer :: y
|
|
real :: z(x .and. y) ! resolves to and_ti
|
|
end
|
|
subroutine s2(x, y, z)
|
|
logical :: x
|
|
integer :: y
|
|
real :: z(x .a. y) ! resolves to and_li
|
|
end
|
|
subroutine s3(x, y, z)
|
|
type(t) :: x, y
|
|
real :: z(x .and. y) ! resolves to and_tt
|
|
end
|
|
subroutine s4(x, y, z)
|
|
type(t) :: x, y
|
|
real :: z(x .neqv. y) ! resolves to neqv_tt
|
|
end
|
|
subroutine s5(x, y, z)
|
|
real :: x, y
|
|
real :: z(x .xor. y) ! resolves to neqv_rr
|
|
end
|
|
end
|
|
|
|
!Expect: m2.mod
|
|
!module m2
|
|
! type :: t
|
|
! sequence
|
|
! logical(4) :: x
|
|
! end type
|
|
! interface
|
|
! pure function and_ti(x, y)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! integer(4), intent(in) :: y
|
|
! integer(8) :: and_ti
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function and_li(x, y)
|
|
! logical(4), intent(in) :: x
|
|
! integer(4), intent(in) :: y
|
|
! integer(8) :: and_li
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function and_tt(x, y)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! type(t), intent(in) :: y
|
|
! integer(8) :: and_tt
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function neqv_tt(x, y)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! type(t), intent(in) :: y
|
|
! integer(8) :: neqv_tt
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function neqv_rr(x, y)
|
|
! real(4), intent(in) :: x
|
|
! real(4), intent(in) :: y
|
|
! integer(8) :: neqv_rr
|
|
! end
|
|
! end interface
|
|
! interface operator( .and.)
|
|
! procedure :: and_ti
|
|
! procedure :: and_li
|
|
! procedure :: and_tt
|
|
! end interface
|
|
! interface operator(.x.)
|
|
! procedure :: neqv_tt
|
|
! procedure :: neqv_rr
|
|
! end interface
|
|
!contains
|
|
! subroutine s1(x, y, z)
|
|
! type(t) :: x
|
|
! integer(4) :: y
|
|
! real(4) :: z(1_8:and_ti(x, y))
|
|
! end
|
|
! subroutine s2(x, y, z)
|
|
! logical(4) :: x
|
|
! integer(4) :: y
|
|
! real(4) :: z(1_8:and_li(x, y))
|
|
! end
|
|
! subroutine s3(x, y, z)
|
|
! type(t) :: x
|
|
! type(t) :: y
|
|
! real(4) :: z(1_8:and_tt(x, y))
|
|
! end
|
|
! subroutine s4(x, y, z)
|
|
! type(t) :: x
|
|
! type(t) :: y
|
|
! real(4) :: z(1_8:neqv_tt(x, y))
|
|
! end
|
|
! subroutine s5(x, y, z)
|
|
! real(4) :: x
|
|
! real(4) :: y
|
|
! real(4) :: z(1_8:neqv_rr(x, y))
|
|
! end
|
|
!end
|
|
|
|
! Relational operators
|
|
module m3
|
|
type :: t
|
|
sequence
|
|
logical :: x
|
|
end type
|
|
interface operator(<>)
|
|
pure integer(8) function ne_it(x, y)
|
|
import :: t
|
|
integer, intent(in) :: x
|
|
type(t), intent(in) :: y
|
|
end
|
|
end interface
|
|
interface operator(/=)
|
|
pure integer(8) function ne_tt(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x, y
|
|
end
|
|
end interface
|
|
interface operator(.ne.)
|
|
pure integer(8) function ne_ci(x, y)
|
|
character(len=*), intent(in) :: x
|
|
integer, intent(in) :: y
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y, z)
|
|
integer :: x
|
|
type(t) :: y
|
|
real :: z(x /= y) ! resolves to ne_it
|
|
end
|
|
subroutine s2(x, y, z)
|
|
type(t) :: x
|
|
type(t) :: y
|
|
real :: z(x .ne. y) ! resolves to ne_tt
|
|
end
|
|
subroutine s3(x, y, z)
|
|
character(len=*) :: x
|
|
integer :: y
|
|
real :: z(x <> y) ! resolves to ne_ci
|
|
end
|
|
end
|
|
|
|
!Expect: m3.mod
|
|
!module m3
|
|
! type :: t
|
|
! sequence
|
|
! logical(4) :: x
|
|
! end type
|
|
! interface
|
|
! pure function ne_it(x, y)
|
|
! import :: t
|
|
! integer(4), intent(in) :: x
|
|
! type(t), intent(in) :: y
|
|
! integer(8) :: ne_it
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function ne_tt(x, y)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! type(t), intent(in) :: y
|
|
! integer(8) :: ne_tt
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function ne_ci(x, y)
|
|
! character(*, 1), intent(in) :: x
|
|
! integer(4), intent(in) :: y
|
|
! integer(8) :: ne_ci
|
|
! end
|
|
! end interface
|
|
! interface operator(<>)
|
|
! procedure :: ne_it
|
|
! procedure :: ne_tt
|
|
! procedure :: ne_ci
|
|
! end interface
|
|
!contains
|
|
! subroutine s1(x, y, z)
|
|
! integer(4) :: x
|
|
! type(t) :: y
|
|
! real(4) :: z(1_8:ne_it(x, y))
|
|
! end
|
|
! subroutine s2(x, y, z)
|
|
! type(t) :: x
|
|
! type(t) :: y
|
|
! real(4) :: z(1_8:ne_tt(x, y))
|
|
! end
|
|
! subroutine s3(x, y, z)
|
|
! character(*, 1) :: x
|
|
! integer(4) :: y
|
|
! real(4) :: z(1_8:ne_ci(x, y))
|
|
! end
|
|
!end
|
|
|
|
! Concatenation
|
|
module m4
|
|
type :: t
|
|
sequence
|
|
logical :: x
|
|
end type
|
|
interface operator(//)
|
|
pure integer(8) function concat_12(x, y)
|
|
character(len=*,kind=1), intent(in) :: x
|
|
character(len=*,kind=2), intent(in) :: y
|
|
end
|
|
pure integer(8) function concat_int_real(x, y)
|
|
integer, intent(in) :: x
|
|
real, intent(in) :: y
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y, z)
|
|
character(len=*,kind=1) :: x
|
|
character(len=*,kind=2) :: y
|
|
real :: z(x // y) ! resolves to concat_12
|
|
end
|
|
subroutine s2(x, y, z)
|
|
integer :: x
|
|
real :: y
|
|
real :: z(x // y) ! resolves to concat_int_real
|
|
end
|
|
end
|
|
!Expect: m4.mod
|
|
!module m4
|
|
! type :: t
|
|
! sequence
|
|
! logical(4) :: x
|
|
! end type
|
|
! interface
|
|
! pure function concat_12(x, y)
|
|
! character(*, 1), intent(in) :: x
|
|
! character(*, 2), intent(in) :: y
|
|
! integer(8) :: concat_12
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function concat_int_real(x, y)
|
|
! integer(4), intent(in) :: x
|
|
! real(4), intent(in) :: y
|
|
! integer(8) :: concat_int_real
|
|
! end
|
|
! end interface
|
|
! interface operator(//)
|
|
! procedure :: concat_12
|
|
! procedure :: concat_int_real
|
|
! end interface
|
|
!contains
|
|
! subroutine s1(x, y, z)
|
|
! character(*, 1) :: x
|
|
! character(*, 2) :: y
|
|
! real(4) :: z(1_8:concat_12(x, y))
|
|
! end
|
|
! subroutine s2(x, y, z)
|
|
! integer(4) :: x
|
|
! real(4) :: y
|
|
! real(4) :: z(1_8:concat_int_real(x, y))
|
|
! end
|
|
!end
|
|
|
|
! Unary operators
|
|
module m5
|
|
type :: t
|
|
end type
|
|
interface operator(+)
|
|
pure integer(8) function plus_l(x)
|
|
logical, intent(in) :: x
|
|
end
|
|
end interface
|
|
interface operator(-)
|
|
pure integer(8) function minus_t(x)
|
|
import :: t
|
|
type(t), intent(in) :: x
|
|
end
|
|
end interface
|
|
interface operator(.not.)
|
|
pure integer(8) function not_t(x)
|
|
import :: t
|
|
type(t), intent(in) :: x
|
|
end
|
|
pure integer(8) function not_real(x)
|
|
real, intent(in) :: x
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y)
|
|
logical :: x
|
|
real :: y(+x) ! resolves_to plus_l
|
|
end
|
|
subroutine s2(x, y)
|
|
type(t) :: x
|
|
real :: y(-x) ! resolves_to minus_t
|
|
end
|
|
subroutine s3(x, y)
|
|
type(t) :: x
|
|
real :: y(.not. x) ! resolves to not_t
|
|
end
|
|
subroutine s4(x, y)
|
|
real :: y(.not. x) ! resolves to not_real
|
|
end
|
|
end
|
|
|
|
!Expect: m5.mod
|
|
!module m5
|
|
! type :: t
|
|
! end type
|
|
! interface
|
|
! pure function plus_l(x)
|
|
! logical(4), intent(in) :: x
|
|
! integer(8) :: plus_l
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function minus_t(x)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! integer(8) :: minus_t
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function not_t(x)
|
|
! import :: t
|
|
! type(t), intent(in) :: x
|
|
! integer(8) :: not_t
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function not_real(x)
|
|
! real(4), intent(in) :: x
|
|
! integer(8) :: not_real
|
|
! end
|
|
! end interface
|
|
! interface operator(+)
|
|
! procedure :: plus_l
|
|
! end interface
|
|
! interface operator(-)
|
|
! procedure :: minus_t
|
|
! end interface
|
|
! interface operator( .not.)
|
|
! procedure :: not_t
|
|
! procedure :: not_real
|
|
! end interface
|
|
!contains
|
|
! subroutine s1(x, y)
|
|
! logical(4) :: x
|
|
! real(4) :: y(1_8:plus_l(x))
|
|
! end
|
|
! subroutine s2(x, y)
|
|
! type(t) :: x
|
|
! real(4) :: y(1_8:minus_t(x))
|
|
! end
|
|
! subroutine s3(x, y)
|
|
! type(t) :: x
|
|
! real(4) :: y(1_8:not_t(x))
|
|
! end
|
|
! subroutine s4(x, y)
|
|
! real(4) :: x
|
|
! real(4) :: y(1_8:not_real(x))
|
|
! end
|
|
!end
|
|
|
|
! Resolved based on shape
|
|
module m6
|
|
interface operator(+)
|
|
pure integer(8) function add(x, y)
|
|
real, intent(in) :: x(:, :)
|
|
real, intent(in) :: y(:, :, :)
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(n, x, y, z, a, b)
|
|
integer(8) :: n
|
|
real :: x
|
|
real :: y(4, n)
|
|
real :: z(2, 2, 2)
|
|
real :: a(size(x+y)) ! intrinsic +
|
|
real :: b(y+z) ! resolves to add
|
|
end
|
|
end
|
|
|
|
!Expect: m6.mod
|
|
!module m6
|
|
! interface
|
|
! pure function add(x, y)
|
|
! real(4), intent(in) :: x(:, :)
|
|
! real(4), intent(in) :: y(:, :, :)
|
|
! integer(8) :: add
|
|
! end
|
|
! end interface
|
|
! interface operator(+)
|
|
! procedure :: add
|
|
! end interface
|
|
!contains
|
|
! subroutine s1(n, x, y, z, a, b)
|
|
! integer(8) :: n
|
|
! real(4) :: x
|
|
! real(4) :: y(1_8:4_8, 1_8:n)
|
|
! real(4) :: z(1_8:2_8, 1_8:2_8, 1_8:2_8)
|
|
! real(4) :: a(1_8:int(int(4_8*size(y,dim=2,kind=8),kind=4),kind=8))
|
|
! real(4) :: b(1_8:add(y, z))
|
|
! end
|
|
!end
|
|
|
|
! Parameterized derived type
|
|
module m7
|
|
type :: t(k)
|
|
integer, kind :: k
|
|
real(k) :: a
|
|
end type
|
|
interface operator(+)
|
|
pure integer(8) function f1(x, y)
|
|
import :: t
|
|
type(t(4)), intent(in) :: x, y
|
|
end
|
|
pure integer(8) function f2(x, y)
|
|
import :: t
|
|
type(t(8)), intent(in) :: x, y
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y, z)
|
|
type(t(4)) :: x, y
|
|
real :: z(x + y) ! resolves to f1
|
|
end
|
|
subroutine s2(x, y, z)
|
|
type(t(8)) :: x, y
|
|
real :: z(x + y) ! resolves to f2
|
|
end
|
|
end
|
|
|
|
!Expect: m7.mod
|
|
!module m7
|
|
! type :: t(k)
|
|
! integer(4), kind :: k
|
|
! real(int(int(k,kind=4),kind=8))::a
|
|
! end type
|
|
! interface
|
|
! pure function f1(x, y)
|
|
! import :: t
|
|
! type(t(k=4_4)), intent(in) :: x
|
|
! type(t(k=4_4)), intent(in) :: y
|
|
! integer(8) :: f1
|
|
! end
|
|
! end interface
|
|
! interface
|
|
! pure function f2(x, y)
|
|
! import :: t
|
|
! type(t(k=8_4)), intent(in) :: x
|
|
! type(t(k=8_4)), intent(in) :: y
|
|
! integer(8) :: f2
|
|
! end
|
|
! end interface
|
|
! interface operator(+)
|
|
! procedure :: f1
|
|
! procedure :: f2
|
|
! end interface
|
|
!contains
|
|
! subroutine s1(x, y, z)
|
|
! type(t(k=4_4)) :: x
|
|
! type(t(k=4_4)) :: y
|
|
! real(4) :: z(1_8:f1(x, y))
|
|
! end
|
|
! subroutine s2(x, y, z)
|
|
! type(t(k=8_4)) :: x
|
|
! type(t(k=8_4)) :: y
|
|
! real(4) :: z(1_8:f2(x, y))
|
|
! end
|
|
!end
|