When a procedure name was used on the RHS of an assignment we were not reporting the error. When one was used in an expression the error message wasn't very good (e.g. "Operands of + must be numeric; have INTEGER(4) and untyped"). Detect these cases in ArgumentAnalyzer and emit better messages, depending on whether the named procedure is a function or subroutine. Procedure names may appear as actual arguments to function and subroutine calls so don't report errors in those cases. That is the same case where assumed type arguments are allowed, so rename `isAssumedType_` to `isProcedureCall_` and use that to decide if it is an error. Differential Revision: https://reviews.llvm.org/D86107
263 lines
7.1 KiB
Fortran
263 lines
7.1 KiB
Fortran
! RUN: %S/test_errors.sh %s %t %f18
|
|
! Invalid operand types when user-defined operator is available
|
|
module m1
|
|
type :: t
|
|
end type
|
|
interface operator(==)
|
|
logical function eq_tt(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x, y
|
|
end
|
|
end interface
|
|
interface operator(+)
|
|
logical function add_tr(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x
|
|
real, intent(in) :: y
|
|
end
|
|
logical function plus_t(x)
|
|
import :: t
|
|
type(t), intent(in) :: x
|
|
end
|
|
logical function add_12(x, y)
|
|
real, intent(in) :: x(:), y(:,:)
|
|
end
|
|
end interface
|
|
interface operator(.and.)
|
|
logical function and_tr(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x
|
|
real, intent(in) :: y
|
|
end
|
|
end interface
|
|
interface operator(//)
|
|
logical function concat_tt(x, y)
|
|
import :: t
|
|
type(t), intent(in) :: x, y
|
|
end
|
|
end interface
|
|
interface operator(.not.)
|
|
logical function not_r(x)
|
|
real, intent(in) :: x
|
|
end
|
|
end interface
|
|
type(t) :: x, y
|
|
real :: r
|
|
logical :: l
|
|
integer :: iVar
|
|
complex :: cvar
|
|
character :: charVar
|
|
contains
|
|
subroutine test_relational()
|
|
l = x == y !OK
|
|
l = x .eq. y !OK
|
|
l = x .eq. y !OK
|
|
l = iVar == z'fe' !OK
|
|
l = z'fe' == iVar !OK
|
|
l = r == z'fe' !OK
|
|
l = z'fe' == r !OK
|
|
l = cVar == z'fe' !OK
|
|
l = z'fe' == cVar !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types CHARACTER(KIND=1) and INTEGER(4)
|
|
l = charVar == z'fe'
|
|
!ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types INTEGER(4) and CHARACTER(KIND=1)
|
|
l = z'fe' == charVar
|
|
!ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types LOGICAL(4) and INTEGER(4)
|
|
l = l == z'fe' !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types INTEGER(4) and LOGICAL(4)
|
|
l = z'fe' == l !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(==) matches operand types TYPE(t) and REAL(4)
|
|
l = x == r
|
|
|
|
lVar = z'a' == b'1010' !OK
|
|
end
|
|
subroutine test_numeric()
|
|
l = x + r !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(+) matches operand types REAL(4) and TYPE(t)
|
|
l = r + x
|
|
end
|
|
subroutine test_logical()
|
|
l = x .and. r !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(.AND.) matches operand types REAL(4) and TYPE(t)
|
|
l = r .and. x
|
|
end
|
|
subroutine test_unary()
|
|
l = +x !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(+) matches operand type LOGICAL(4)
|
|
l = +l
|
|
l = .not. r !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(.NOT.) matches operand type TYPE(t)
|
|
l = .not. x
|
|
end
|
|
subroutine test_concat()
|
|
l = x // y !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(//) matches operand types TYPE(t) and REAL(4)
|
|
l = x // r
|
|
end
|
|
subroutine test_conformability(x, y)
|
|
real :: x(10), y(10,10)
|
|
l = x + y !OK
|
|
!ERROR: No intrinsic or user-defined OPERATOR(+) matches rank 2 array of REAL(4) and rank 1 array of REAL(4)
|
|
l = y + x
|
|
end
|
|
end
|
|
|
|
! Invalid operand types when user-defined operator is not available
|
|
module m2
|
|
intrinsic :: sin
|
|
type :: t
|
|
end type
|
|
type(t) :: x, y
|
|
real :: r
|
|
logical :: l
|
|
contains
|
|
subroutine test_relational()
|
|
!ERROR: Operands of .EQ. must have comparable types; have TYPE(t) and REAL(4)
|
|
l = x == r
|
|
!ERROR: Subroutine name is not allowed here
|
|
l = r == test_numeric
|
|
!ERROR: Function call must have argument list
|
|
l = r == sin
|
|
end
|
|
subroutine test_numeric()
|
|
!ERROR: Operands of + must be numeric; have REAL(4) and TYPE(t)
|
|
l = r + x
|
|
end
|
|
subroutine test_logical()
|
|
!ERROR: Operands of .AND. must be LOGICAL; have REAL(4) and TYPE(t)
|
|
l = r .and. x
|
|
end
|
|
subroutine test_unary()
|
|
!ERROR: Operand of unary + must be numeric; have LOGICAL(4)
|
|
l = +l
|
|
!ERROR: Operand of .NOT. must be LOGICAL; have TYPE(t)
|
|
l = .not. x
|
|
end
|
|
subroutine test_concat(a, b)
|
|
character(4,kind=1) :: a
|
|
character(4,kind=2) :: b
|
|
character(4) :: c
|
|
!ERROR: Operands of // must be CHARACTER with the same kind; have CHARACTER(KIND=1) and CHARACTER(KIND=2)
|
|
c = a // b
|
|
!ERROR: Operands of // must be CHARACTER with the same kind; have TYPE(t) and REAL(4)
|
|
l = x // r
|
|
end
|
|
subroutine test_conformability(x, y)
|
|
real :: x(10), y(10,10)
|
|
!ERROR: Operands of + are not conformable; have rank 2 and rank 1
|
|
l = y + x
|
|
end
|
|
end
|
|
|
|
! Invalid untyped operands: user-defined operator doesn't affect errors
|
|
module m3
|
|
interface operator(+)
|
|
logical function add(x, y)
|
|
logical, intent(in) :: x
|
|
integer, value :: y
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y)
|
|
logical :: x
|
|
integer :: y
|
|
logical :: l
|
|
complex :: z
|
|
y = y + z'1' !OK
|
|
!ERROR: Operands of + must be numeric; have untyped and COMPLEX(4)
|
|
z = z'1' + z
|
|
y = +z'1' !OK
|
|
!ERROR: Operand of unary - must be numeric; have untyped
|
|
y = -z'1'
|
|
!ERROR: Operands of + must be numeric; have LOGICAL(4) and untyped
|
|
y = x + z'1'
|
|
!ERROR: Operands of .NE. must have comparable types; have LOGICAL(4) and untyped
|
|
l = x /= null()
|
|
end
|
|
end
|
|
|
|
! Test alternate operators. They aren't enabled by default so should be
|
|
! treated as defined operators, not intrinsic ones.
|
|
module m4
|
|
contains
|
|
subroutine s1(x, y, z)
|
|
logical :: x
|
|
real :: y, z
|
|
!ERROR: No operator .A. defined for REAL(4) and REAL(4)
|
|
x = y .a. z
|
|
!ERROR: No operator .O. defined for REAL(4) and REAL(4)
|
|
x = y .o. z
|
|
!ERROR: No operator .N. defined for REAL(4)
|
|
x = .n. y
|
|
!ERROR: No operator .XOR. defined for REAL(4) and REAL(4)
|
|
x = y .xor. z
|
|
!ERROR: No operator .X. defined for REAL(4)
|
|
x = .x. y
|
|
end
|
|
end
|
|
|
|
! Like m4 in resolve63 but compiled with different options.
|
|
! .A. is a defined operator.
|
|
module m5
|
|
interface operator(.A.)
|
|
logical function f1(x, y)
|
|
integer, intent(in) :: x, y
|
|
end
|
|
end interface
|
|
interface operator(.and.)
|
|
logical function f2(x, y)
|
|
real, intent(in) :: x, y
|
|
end
|
|
end interface
|
|
contains
|
|
subroutine s1(x, y, z)
|
|
logical :: x
|
|
complex :: y, z
|
|
!ERROR: No intrinsic or user-defined OPERATOR(.AND.) matches operand types COMPLEX(4) and COMPLEX(4)
|
|
x = y .and. z
|
|
!ERROR: No intrinsic or user-defined .A. matches operand types COMPLEX(4) and COMPLEX(4)
|
|
x = y .a. z
|
|
end
|
|
end
|
|
|
|
! Type-bound operators
|
|
module m6
|
|
type :: t1
|
|
contains
|
|
procedure, pass(x) :: p1 => f1
|
|
generic :: operator(+) => p1
|
|
end type
|
|
type, extends(t1) :: t2
|
|
contains
|
|
procedure, pass(y) :: p2 => f2
|
|
generic :: operator(+) => p2
|
|
end type
|
|
type :: t3
|
|
contains
|
|
procedure, nopass :: p1 => f1
|
|
!ERROR: OPERATOR(+) procedure 'p1' may not have NOPASS attribute
|
|
generic :: operator(+) => p1
|
|
end type
|
|
contains
|
|
integer function f1(x, y)
|
|
class(t1), intent(in) :: x
|
|
integer, intent(in) :: y
|
|
end
|
|
integer function f2(x, y)
|
|
class(t1), intent(in) :: x
|
|
class(t2), intent(in) :: y
|
|
end
|
|
subroutine test(x, y, z)
|
|
class(t1) :: x
|
|
class(t2) :: y
|
|
integer :: i
|
|
i = x + y
|
|
i = x + i
|
|
i = y + i
|
|
!ERROR: No intrinsic or user-defined OPERATOR(+) matches operand types TYPE(t2) and TYPE(t1)
|
|
i = y + x
|
|
!ERROR: No intrinsic or user-defined OPERATOR(+) matches operand types INTEGER(4) and TYPE(t1)
|
|
i = i + x
|
|
end
|
|
end
|