From bcd0bf9284db0d5d4697611ff9bf3243504aab07 Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Thu, 8 Dec 2022 13:45:57 -0800 Subject: [PATCH] [flang] Enforce 15.4.2.2(4)(c) - explicit interface required When a function has an implicit interface its result type may not have a deferred type parameter. Differential Revision: https://reviews.llvm.org/D140132 --- flang/lib/Semantics/check-declarations.cpp | 6 +++-- flang/test/Semantics/resolve69.f90 | 43 ++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 2913b7a..0aca16d 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -2378,11 +2378,13 @@ void CheckHelper::CheckDefinedIoProc(const Symbol &symbol, } void CheckHelper::CheckSymbolType(const Symbol &symbol) { - if (!IsAllocatableOrPointer(symbol)) { // C702 + if (!IsAllocatable(symbol) && + (!IsPointer(symbol) || + (IsProcedure(symbol) && !symbol.HasExplicitInterface()))) { // C702 if (auto dyType{evaluate::DynamicType::From(symbol)}) { if (dyType->HasDeferredTypeParameter()) { messages_.Say( - "'%s' has a type %s with a deferred type parameter but is neither an allocatable or a pointer"_err_en_US, + "'%s' has a type %s with a deferred type parameter but is neither an allocatable nor an object pointer"_err_en_US, symbol.name(), dyType->AsFortran()); } } diff --git a/flang/test/Semantics/resolve69.f90 b/flang/test/Semantics/resolve69.f90 index 4db277d..e5bdac5 100644 --- a/flang/test/Semantics/resolve69.f90 +++ b/flang/test/Semantics/resolve69.f90 @@ -3,36 +3,40 @@ subroutine s1() ! C701 (R701) The type-param-value for a kind type parameter shall be a ! constant expression. ! - ! C702 (R701) A colon shall not be used as a type-param-value except in the + ! C702 (R701) A colon shall not be used as a type-param-value except in the ! declaration of an entity that has the POINTER or ALLOCATABLE attribute. ! - ! C704 (R703) In a declaration-type-spec, every type-param-value that is + ! C704 (R703) In a declaration-type-spec, every type-param-value that is ! not a colon or an asterisk shall be a specification expression. ! Section 10.1.11 defines specification expressions ! + ! 15.4.2.2(4)(c) A procedure must have an explicit interface if it has a + ! result that has a nonassumed type parameter value that is not a constant + ! expression. + ! integer, parameter :: constVal = 1 integer :: nonConstVal = 1 !ERROR: Invalid specification expression: reference to local entity 'nonconstval' character(nonConstVal) :: colonString1 character(len=20, kind=constVal + 1) :: constKindString character(len=:, kind=constVal + 1), pointer :: constKindString1 -!ERROR: 'constkindstring2' has a type CHARACTER(KIND=2,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'constkindstring2' has a type CHARACTER(KIND=2,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(len=:, kind=constVal + 1) :: constKindString2 !ERROR: Must be a constant value character(len=20, kind=nonConstVal) :: nonConstKindString -!ERROR: 'deferredstring' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'deferredstring' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(len=:) :: deferredString -!ERROR: 'colonstring2' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'colonstring2' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(:) :: colonString2 !OK because of the allocatable attribute character(:), allocatable :: colonString3 -!ERROR: 'foo1' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'foo1' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(:), external :: foo1 -!ERROR: 'foo2' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'foo2' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer procedure(character(:)) :: foo2 interface function foo3() -!ERROR: 'foo3' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'foo3' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(:) foo3 end function end interface @@ -57,30 +61,30 @@ subroutine s1() !ERROR: Invalid specification expression: reference to local entity 'nonconstval' type (derived(3, nonConstVal)) :: nonConstDerivedLen -!ERROR: 'colonderivedlen' has a type derived(typekind=3_4,typelen=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'colonderivedlen' has a type derived(typekind=3_4,typelen=:) with a deferred type parameter but is neither an allocatable nor an object pointer type (derived(3, :)) :: colonDerivedLen -!ERROR: 'colonderivedlen1' has a type derived(typekind=:,typelen=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'colonderivedlen1' has a type derived(typekind=:,typelen=:) with a deferred type parameter but is neither an allocatable nor an object pointer type (derived( :, :)) :: colonDerivedLen1 type (derived( :, :)), pointer :: colonDerivedLen2 type (derived(4, :)), pointer :: colonDerivedLen3 end subroutine s1 !C702 -!ERROR: 'f1' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'f1' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(:) function f1 end function function f2 -!ERROR: 'f2' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'f2' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(:) f2 end function function f3() result(res) -!ERROR: 'res' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'res' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer character(:) res end function -!ERROR: 'f4' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable or a pointer +!ERROR: 'f4' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer function f4 implicit character(:)(f) end function @@ -107,3 +111,14 @@ subroutine outer real inner2(n) end function inner2 end subroutine outer + +subroutine s2(dp,dpp) + !ERROR: 'dp' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer + procedure(character(:)) :: dp + !ERROR: 'dpp' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer + procedure(character(:)), pointer :: dpp + !ERROR: 'pp' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer + procedure(character(:)), pointer :: pp + !ERROR: 'xp' has a type CHARACTER(KIND=1,LEN=:) with a deferred type parameter but is neither an allocatable nor an object pointer + procedure(character(:)) :: xp +end subroutine -- 2.7.4