Files
clang-p2996/flang/test/Semantics/null01.f90
Peter Klausler 79a25e11fe [flang] Further work on NULL(MOLD=allocatable) (#129345)
Refine handling of NULL(...) in semantics to properly distinguish
NULL(), NULL(objectPointer), NULL(procPointer), and NULL(allocatable)
from each other in relevant contexts.

Add IsNullAllocatable() and IsNullPointerOrAllocatable() utility
functions. IsNullAllocatable() is true only for NULL(allocatable); it is
false for a bare NULL(), which can be detected independently with
IsBareNullPointer().

IsNullPointer() now returns false for NULL(allocatable).

ALLOCATED(NULL(allocatable)) now works, and folds to .FALSE.

These utilities were modified to accept const pointer arguments rather
than const references; I usually prefer this style when the result
should clearly be false for a null argument (in the C sense), and it
helped me find all of their use sites in the code.
2025-03-03 14:46:35 -08:00

170 lines
5.9 KiB
Fortran

! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
! NULL() intrinsic function error tests
subroutine test
interface
subroutine s0
end subroutine
subroutine s1(j)
integer, intent(in) :: j
end subroutine
subroutine canbenull(x, y)
integer, intent(in), optional :: x
real, intent(in), pointer :: y
end
subroutine optionalAllocatable(x)
integer, intent(in), allocatable, optional :: x
end
function f0()
real :: f0
end function
function f1(x)
real :: f1
real, intent(inout) :: x
end function
function f2(p)
import s0
real :: f1
procedure(s0), pointer, intent(inout) :: p
end function
function f3()
import s1
procedure(s1), pointer :: f3
end function
end interface
external implicit
type :: dt0
integer, pointer :: ip0
integer :: n = 666
end type dt0
type :: dt1
integer, pointer :: ip1(:)
end type dt1
type :: dt2
procedure(s0), pointer, nopass :: pps0
end type dt2
type :: dt3
procedure(s1), pointer, nopass :: pps1
end type dt3
type :: dt4
real, allocatable :: ra0
end type dt4
type, extends(dt4) :: dt5
end type dt5
integer :: j
type(dt0) :: dt0x
type(dt1) :: dt1x
type(dt2) :: dt2x
type(dt3) :: dt3x
type(dt4) :: dt4x
integer, pointer :: ip0, ip1(:), ip2(:,:)
integer, allocatable :: ia0, ia1(:), ia2(:,:)
real, pointer :: rp0, rp1(:)
integer, parameter :: ip0r = rank(null(mold=ip0))
integer, parameter :: ip1r = rank(null(mold=ip1))
integer, parameter :: ip2r = rank(null(mold=ip2))
integer, parameter :: eight = ip0r + ip1r + ip2r + 5
real(kind=eight) :: r8check
logical, pointer :: lp
type(dt4), pointer :: dt4p
type(dt5), pointer :: dt5p
ip0 => null() ! ok
ip0 => null(null()) ! ok
ip0 => null(null(null())) ! ok
ip1 => null() ! ok
ip1 => null(null()) ! ok
ip1 => null(null(null())) ! ok
ip2 => null() ! ok
ip2 => null(null()) ! ok
ip2 => null(null(null())) ! ok
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
ip0 => null(mold=1)
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
ip0 => null(null(mold=1))
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
ip0 => null(mold=j)
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
ip0 => null(mold=null(mold=j))
dt0x = dt0(null())
dt0x = dt0(ip0=null())
dt0x = dt0(ip0=null(ip0))
dt0x = dt0(ip0=null(mold=ip0))
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
dt0x = dt0(ip0=null(mold=rp0))
!ERROR: A NULL pointer may not be used as the value for component 'n'
dt0x = dt0(null(), null())
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
dt1x = dt1(ip1=null(mold=rp1))
dt2x = dt2(pps0=null())
dt2x = dt2(pps0=null(mold=dt2x%pps0))
!ERROR: Procedure pointer 'pps0' associated with result of reference to function 'null' that is an incompatible procedure pointer: distinct numbers of dummy arguments
dt2x = dt2(pps0=null(mold=dt3x%pps1))
!ERROR: Procedure pointer 'pps1' associated with result of reference to function 'null' that is an incompatible procedure pointer: distinct numbers of dummy arguments
dt3x = dt3(pps1=null(mold=dt2x%pps0))
dt3x = dt3(pps1=null(mold=dt3x%pps1))
dt4x = dt4(null()) ! ok
!PORTABILITY: NULL() with arguments is not standard conforming as the value for allocatable component 'ra0'
dt4x = dt4(null(rp0))
!PORTABILITY: NULL() with arguments is not standard conforming as the value for allocatable component 'ra0'
!ERROR: Rank-1 array value is not compatible with scalar component 'ra0'
dt4x = dt4(null(rp1))
!ERROR: A NULL procedure pointer may not be used as the value for component 'ra0'
dt4x = dt4(null(dt2x%pps0))
call canbenull(null(), null()) ! fine
call canbenull(null(mold=ip0), null(mold=rp0)) ! fine
!ERROR: ALLOCATABLE dummy argument 'x=' must be associated with an ALLOCATABLE actual argument
call optionalAllocatable(null(mold=ip0))
call optionalAllocatable(null(mold=ia0)) ! fine
call optionalAllocatable(null()) ! fine
!ERROR: Null pointer argument requires an explicit interface
call implicit(null())
!ERROR: Null pointer argument requires an explicit interface
call implicit(null(mold=ip0))
!ERROR: A NULL() pointer is not allowed for 'x=' intrinsic argument
print *, sin(null(rp0))
!ERROR: A NULL() pointer is not allowed for 'x=' intrinsic argument
print *, kind(null())
print *, kind(null(rp0)) ! ok
!ERROR: A NULL() pointer is not allowed for 'a=' intrinsic argument
print *, extends_type_of(null(), null())
print *, extends_type_of(null(dt5p), null(dt4p)) ! ok
!ERROR: A NULL() pointer is not allowed for 'a=' intrinsic argument
print *, same_type_as(null(), null())
print *, same_type_as(null(dt5p), null(dt4p)) ! ok
!ERROR: A NULL() pointer is not allowed for 'source=' intrinsic argument
print *, transfer(null(rp0),ip0)
!WARNING: Source of TRANSFER contains allocatable or pointer component %ra0
print *, transfer(dt4(null()),[0])
!ERROR: NULL() may not be used as an expression in this context
select case(null(ip0))
end select
!ERROR: NULL() may not be used as an expression in this context
if (null(lp)) then
end if
end subroutine test
module m
type :: pdt(n)
integer, len :: n
end type
contains
subroutine s1(x)
character(*), pointer, intent(in) :: x
end
subroutine s2(x)
type(pdt(*)), pointer, intent(in) :: x
end
subroutine s3(ar)
real, pointer :: ar(..)
end
subroutine test(ar)
real, pointer :: ar(..)
!ERROR: Actual argument associated with dummy argument 'x=' is a NULL() pointer without a MOLD= to provide a character length
call s1(null())
!ERROR: Actual argument associated with dummy argument 'x=' is a NULL() pointer without a MOLD= to provide a value for the assumed type parameter 'n'
call s2(null())
!ERROR: MOLD= argument to NULL() must not be assumed-rank
call s3(null(ar))
end
end