328 lines
11 KiB
Fortran
328 lines
11 KiB
Fortran
|
! RUN: %python %S/test_errors.py %s %flang_fc1
|
||
|
! Pointer assignment constraints 10.2.2.2 (see also assign02.f90)
|
||
|
|
||
|
module m
|
||
|
interface
|
||
|
subroutine s(i)
|
||
|
integer i
|
||
|
end
|
||
|
end interface
|
||
|
type :: t
|
||
|
procedure(s), pointer, nopass :: p
|
||
|
real, pointer :: q
|
||
|
end type
|
||
|
contains
|
||
|
! C1027
|
||
|
subroutine s1
|
||
|
type(t), allocatable :: a(:)
|
||
|
type(t), allocatable :: b[:]
|
||
|
a(1)%p => s
|
||
|
!ERROR: The left-hand side of a pointer assignment is not definable
|
||
|
!BECAUSE: Procedure pointer 'p' may not be a coindexed object
|
||
|
b[1]%p => s
|
||
|
end
|
||
|
! C1028
|
||
|
subroutine s2
|
||
|
type(t) :: a
|
||
|
a%p => s
|
||
|
!ERROR: In assignment to object pointer 'q', the target 's' is a procedure designator
|
||
|
a%q => s
|
||
|
end
|
||
|
! C1029
|
||
|
subroutine s3
|
||
|
type(t) :: a
|
||
|
a%p => f() ! OK: pointer-valued function
|
||
|
!ERROR: Subroutine pointer 'p' may not be associated with function designator 'f'
|
||
|
a%p => f
|
||
|
contains
|
||
|
function f()
|
||
|
procedure(s), pointer :: f
|
||
|
f => s
|
||
|
end
|
||
|
end
|
||
|
|
||
|
! C1030 and 10.2.2.4 - procedure names as target of procedure pointer
|
||
|
subroutine s4(s_dummy)
|
||
|
procedure(s) :: s_dummy
|
||
|
procedure(s), pointer :: p, q
|
||
|
procedure(), pointer :: r
|
||
|
integer :: i
|
||
|
external :: s_external
|
||
|
p => s_dummy
|
||
|
p => s_internal
|
||
|
p => s_module
|
||
|
q => p
|
||
|
r => s_external
|
||
|
contains
|
||
|
subroutine s_internal(i)
|
||
|
integer i
|
||
|
end
|
||
|
end
|
||
|
subroutine s_module(i)
|
||
|
integer i
|
||
|
end
|
||
|
|
||
|
! 10.2.2.4(3)
|
||
|
subroutine s5
|
||
|
procedure(f_impure1), pointer :: p_impure
|
||
|
procedure(f_pure1), pointer :: p_pure
|
||
|
!ERROR: Procedure pointer 'p_elemental' may not be ELEMENTAL
|
||
|
procedure(f_elemental1), pointer :: p_elemental
|
||
|
procedure(s_impure1), pointer :: sp_impure
|
||
|
procedure(s_pure1), pointer :: sp_pure
|
||
|
!ERROR: Procedure pointer 'sp_elemental' may not be ELEMENTAL
|
||
|
procedure(s_elemental1), pointer :: sp_elemental
|
||
|
|
||
|
p_impure => f_impure1 ! OK, same characteristics
|
||
|
p_impure => f_pure1 ! OK, target may be pure when pointer is not
|
||
|
!ERROR: Procedure pointer 'p_impure' associated with incompatible procedure designator 'f_elemental1': incompatible procedure attributes: Elemental
|
||
|
p_impure => f_elemental1
|
||
|
!ERROR: Procedure pointer 'p_impure' associated with incompatible procedure designator 'f_impureelemental1': incompatible procedure attributes: Elemental
|
||
|
p_impure => f_ImpureElemental1 ! OK, target may be elemental
|
||
|
|
||
|
sp_impure => s_impure1 ! OK, same characteristics
|
||
|
sp_impure => s_pure1 ! OK, target may be pure when pointer is not
|
||
|
!ERROR: Procedure pointer 'sp_impure' associated with incompatible procedure designator 's_elemental1': incompatible procedure attributes: Elemental
|
||
|
sp_impure => s_elemental1
|
||
|
|
||
|
!ERROR: PURE procedure pointer 'p_pure' may not be associated with non-PURE procedure designator 'f_impure1'
|
||
|
p_pure => f_impure1
|
||
|
p_pure => f_pure1 ! OK, same characteristics
|
||
|
!ERROR: Procedure pointer 'p_pure' associated with incompatible procedure designator 'f_elemental1': incompatible procedure attributes: Elemental
|
||
|
p_pure => f_elemental1
|
||
|
!ERROR: PURE procedure pointer 'p_pure' may not be associated with non-PURE procedure designator 'f_impureelemental1'
|
||
|
p_pure => f_impureElemental1
|
||
|
|
||
|
!ERROR: PURE procedure pointer 'sp_pure' may not be associated with non-PURE procedure designator 's_impure1'
|
||
|
sp_pure => s_impure1
|
||
|
sp_pure => s_pure1 ! OK, same characteristics
|
||
|
!ERROR: Procedure pointer 'sp_pure' associated with incompatible procedure designator 's_elemental1': incompatible procedure attributes: Elemental
|
||
|
sp_pure => s_elemental1 ! OK, target may be elemental when pointer is not
|
||
|
|
||
|
!ERROR: Procedure pointer 'p_impure' associated with incompatible procedure designator 'f_impure2': incompatible dummy argument #1: incompatible dummy data object intents
|
||
|
p_impure => f_impure2
|
||
|
!ERROR: Function pointer 'p_pure' associated with incompatible function designator 'f_pure2': function results have distinct types: INTEGER(4) vs REAL(4)
|
||
|
p_pure => f_pure2
|
||
|
!ERROR: Function pointer 'p_pure' associated with incompatible function designator 'ccos': function results have distinct types: INTEGER(4) vs COMPLEX(4)
|
||
|
p_pure => ccos
|
||
|
!ERROR: Procedure pointer 'p_impure' associated with incompatible procedure designator 'f_elemental2': incompatible procedure attributes: Elemental
|
||
|
p_impure => f_elemental2
|
||
|
|
||
|
!ERROR: Procedure pointer 'sp_impure' associated with incompatible procedure designator 's_impure2': incompatible procedure attributes: BindC
|
||
|
sp_impure => s_impure2
|
||
|
!ERROR: Procedure pointer 'sp_impure' associated with incompatible procedure designator 's_pure2': incompatible dummy argument #1: incompatible dummy data object intents
|
||
|
sp_impure => s_pure2
|
||
|
!ERROR: Procedure pointer 'sp_pure' associated with incompatible procedure designator 's_elemental2': incompatible procedure attributes: Elemental
|
||
|
sp_pure => s_elemental2
|
||
|
|
||
|
!ERROR: Function pointer 'p_impure' may not be associated with subroutine designator 's_impure1'
|
||
|
p_impure => s_impure1
|
||
|
|
||
|
!ERROR: Subroutine pointer 'sp_impure' may not be associated with function designator 'f_impure1'
|
||
|
sp_impure => f_impure1
|
||
|
|
||
|
contains
|
||
|
integer function f_impure1(n)
|
||
|
real, intent(in) :: n
|
||
|
f_impure = n
|
||
|
end
|
||
|
pure integer function f_pure1(n)
|
||
|
real, intent(in) :: n
|
||
|
f_pure = n
|
||
|
end
|
||
|
elemental integer function f_elemental1(n)
|
||
|
real, intent(in) :: n
|
||
|
f_elemental = n
|
||
|
end
|
||
|
impure elemental integer function f_impureElemental1(n)
|
||
|
real, intent(in) :: n
|
||
|
f_impureElemental = n
|
||
|
end
|
||
|
|
||
|
integer function f_impure2(n)
|
||
|
real, intent(inout) :: n
|
||
|
f_impure = n
|
||
|
end
|
||
|
pure real function f_pure2(n)
|
||
|
real, intent(in) :: n
|
||
|
f_pure = n
|
||
|
end
|
||
|
elemental integer function f_elemental2(n)
|
||
|
real, value :: n
|
||
|
f_elemental = n
|
||
|
end
|
||
|
|
||
|
subroutine s_impure1(n)
|
||
|
integer, intent(inout) :: n
|
||
|
n = n + 1
|
||
|
end
|
||
|
pure subroutine s_pure1(n)
|
||
|
integer, intent(inout) :: n
|
||
|
n = n + 1
|
||
|
end
|
||
|
elemental subroutine s_elemental1(n)
|
||
|
integer, intent(inout) :: n
|
||
|
n = n + 1
|
||
|
end
|
||
|
|
||
|
subroutine s_impure2(n) bind(c)
|
||
|
integer, intent(inout) :: n
|
||
|
n = n + 1
|
||
|
end subroutine s_impure2
|
||
|
pure subroutine s_pure2(n)
|
||
|
integer, intent(out) :: n
|
||
|
n = 1
|
||
|
end subroutine s_pure2
|
||
|
elemental subroutine s_elemental2(m,n)
|
||
|
integer, intent(inout) :: m, n
|
||
|
n = m + n
|
||
|
end subroutine s_elemental2
|
||
|
end
|
||
|
|
||
|
! 10.2.2.4(4)
|
||
|
subroutine s6
|
||
|
procedure(s), pointer :: p, q
|
||
|
procedure(), pointer :: r
|
||
|
external :: s_external
|
||
|
p => s_external ! OK for a pointer with an explicit interface to be associated with a procedure with an implicit interface
|
||
|
r => s_module ! OK for a pointer with implicit interface to be associated with a procedure with an explicit interface. See 10.2.2.4 (3)
|
||
|
end
|
||
|
|
||
|
! 10.2.2.4(5)
|
||
|
subroutine s7
|
||
|
procedure(real) :: f_external
|
||
|
external :: s_external
|
||
|
procedure(), pointer :: p_s
|
||
|
procedure(real), pointer :: p_f
|
||
|
p_f => f_external
|
||
|
p_s => s_external
|
||
|
!Ok: p_s has no interface
|
||
|
p_s => f_external
|
||
|
!Ok: s_external has no interface
|
||
|
p_f => s_external
|
||
|
end
|
||
|
|
||
|
! C1017: bounds-spec
|
||
|
subroutine s8
|
||
|
real, target :: x(10, 10)
|
||
|
real, pointer :: p(:, :)
|
||
|
p(2:,3:) => x
|
||
|
!ERROR: Pointer 'p' has rank 2 but the number of bounds specified is 1
|
||
|
p(2:) => x
|
||
|
end
|
||
|
|
||
|
! bounds-remapping
|
||
|
subroutine s9
|
||
|
real, target :: x(10, 10), y(100)
|
||
|
real, pointer :: p(:, :)
|
||
|
! C1018
|
||
|
!ERROR: Pointer 'p' has rank 2 but the number of bounds specified is 1
|
||
|
p(1:100) => x
|
||
|
! 10.2.2.3(9)
|
||
|
!ERROR: Pointer bounds remapping target must have rank 1 or be simply contiguous
|
||
|
p(1:5,1:5) => x(1:10,::2)
|
||
|
! 10.2.2.3(9)
|
||
|
!ERROR: Pointer bounds require 25 elements but target has only 20
|
||
|
p(1:5,1:5) => x(:,1:2)
|
||
|
!OK - rhs has rank 1 and enough elements
|
||
|
p(1:5,1:5) => y(1:100:2)
|
||
|
!OK - same, but from function result
|
||
|
p(1:5,1:5) => f()
|
||
|
contains
|
||
|
function f()
|
||
|
real, pointer :: f(:)
|
||
|
f => y
|
||
|
end function
|
||
|
end
|
||
|
|
||
|
subroutine s10
|
||
|
integer, pointer :: p(:)
|
||
|
type :: t
|
||
|
integer :: a(4, 4)
|
||
|
integer :: b
|
||
|
end type
|
||
|
type(t), target :: x
|
||
|
type(t), target :: y(10,10)
|
||
|
integer :: v(10)
|
||
|
p(1:16) => x%a
|
||
|
p(1:8) => x%a(:,3:4)
|
||
|
p(1:1) => x%b ! We treat scalars as simply contiguous
|
||
|
p(1:1) => x%a(1,1)
|
||
|
p(1:1) => y(1,1)%a(1,1)
|
||
|
p(1:1) => y(:,1)%a(1,1) ! Rank 1 RHS
|
||
|
!ERROR: Pointer bounds remapping target must have rank 1 or be simply contiguous
|
||
|
p(1:4) => x%a(::2,::2)
|
||
|
!ERROR: Pointer bounds remapping target must have rank 1 or be simply contiguous
|
||
|
p(1:100) => y(:,:)%b
|
||
|
!ERROR: Pointer bounds remapping target must have rank 1 or be simply contiguous
|
||
|
p(1:100) => y(:,:)%a(1,1)
|
||
|
!ERROR: Pointer bounds remapping target must have rank 1 or be simply contiguous
|
||
|
!ERROR: An array section with a vector subscript may not be a pointer target
|
||
|
p(1:4) => x%a(:,v)
|
||
|
end
|
||
|
|
||
|
subroutine s11
|
||
|
complex, target :: x(10,10)
|
||
|
complex, pointer :: p(:)
|
||
|
real, pointer :: q(:)
|
||
|
p(1:100) => x(:,:)
|
||
|
q(1:10) => x(1,:)%im
|
||
|
!ERROR: Pointer bounds remapping target must have rank 1 or be simply contiguous
|
||
|
q(1:100) => x(:,:)%re
|
||
|
end
|
||
|
|
||
|
! Check is_contiguous, which is usually the same as when pointer bounds
|
||
|
! remapping is used.
|
||
|
subroutine s12
|
||
|
integer, pointer :: p(:)
|
||
|
integer, pointer, contiguous :: pc(:)
|
||
|
type :: t
|
||
|
integer :: a(4, 4)
|
||
|
integer :: b
|
||
|
end type
|
||
|
type(t), target :: x
|
||
|
type(t), target :: y(10,10)
|
||
|
integer :: v(10)
|
||
|
logical(kind=merge(1,-1,is_contiguous(x%a(:,:)))) :: l1 ! known true
|
||
|
logical(kind=merge(1,-1,is_contiguous(y(1,1)%a(1,1)))) :: l2 ! known true
|
||
|
!ERROR: Must be a constant value
|
||
|
logical(kind=merge(-1,-2,is_contiguous(y(:,1)%a(1,1)))) :: l3 ! unknown
|
||
|
!ERROR: Must be a constant value
|
||
|
logical(kind=merge(-1,-2,is_contiguous(y(:,1)%a(1,1)))) :: l4 ! unknown
|
||
|
logical(kind=merge(-1,1,is_contiguous(x%a(:,v)))) :: l5 ! known false
|
||
|
!ERROR: Must be a constant value
|
||
|
logical(kind=merge(-1,-2,is_contiguous(y(v,1)%a(1,1)))) :: l6 ! unknown
|
||
|
!ERROR: Must be a constant value
|
||
|
logical(kind=merge(-1,-2,is_contiguous(p(:)))) :: l7 ! unknown
|
||
|
logical(kind=merge(1,-1,is_contiguous(pc(:)))) :: l8 ! known true
|
||
|
logical(kind=merge(-1,1,is_contiguous(pc(1:10:2)))) :: l9 ! known false
|
||
|
logical(kind=merge(-1,1,is_contiguous(pc(10:1:-1)))) :: l10 ! known false
|
||
|
logical(kind=merge(1,-1,is_contiguous(pc(1:10:1)))) :: l11 ! known true
|
||
|
logical(kind=merge(-1,1,is_contiguous(pc(10:1:-1)))) :: l12 ! known false
|
||
|
!ERROR: Must be a constant value
|
||
|
logical(kind=merge(-1,1,is_contiguous(pc(::-1)))) :: l13 ! unknown (could be empty)
|
||
|
logical(kind=merge(1,-1,is_contiguous(y(1,1)%a(::-1,1)))) :: l14 ! known true (empty)
|
||
|
logical(kind=merge(1,-1,is_contiguous(y(1,1)%a(1,::-1)))) :: l15 ! known true (empty)
|
||
|
end
|
||
|
subroutine test3(b)
|
||
|
integer, intent(inout) :: b(..)
|
||
|
!ERROR: Must be a constant value
|
||
|
integer, parameter :: i = rank(b)
|
||
|
end subroutine
|
||
|
|
||
|
subroutine s13
|
||
|
external :: s_external
|
||
|
procedure(), pointer :: ptr
|
||
|
!Ok - don't emit an error about incompatible Subroutine attribute
|
||
|
ptr => s_external
|
||
|
call ptr
|
||
|
end subroutine
|
||
|
|
||
|
subroutine s14
|
||
|
procedure(real), pointer :: ptr
|
||
|
sf(x) = x + 1.
|
||
|
!ERROR: Statement function 'sf' may not be the target of a pointer assignment
|
||
|
ptr => sf
|
||
|
end subroutine
|
||
|
end
|