Skip to content

Commit 4328571

Browse files
committed
[flang] More careful handling of PROCEDURE() components
Derived type components declared as PROCEDURE() -- without an explicit interface or result type, and also necessarily a NOPASS POINTER -- should not be allowed to be called as functions, and should elicit an optional warning or error if called as subroutines. This form of declaration is neither a function nor a subroutine, although many compilers interpret it as a subroutine. The compiler was previously treating such components in the same way as non-component PROCEDURE() entities are handled; in particular, they were implicitly typed.
1 parent 616f3b5 commit 4328571

File tree

4 files changed

+63
-12
lines changed

4 files changed

+63
-12
lines changed

flang/docs/Extensions.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,17 @@ print *, [(j,j=1,10)]
939939
This design allows format-driven input with `DT` editing to retain
940940
control over advancement in child input, while otherwise allowing it.
941941

942+
* Many compilers interpret `PROCEDURE()` as meaning a subroutine,
943+
but it does not do so; it defines an entity that is not declared
944+
to be either a subroutine or a function.
945+
If it is referenced, its references must be consistent.
946+
If it is never referenced, it may be associated with any
947+
procedure.
948+
949+
* A `PROCEDURE()` component (necessarily also a pointer) without an
950+
explicit interface or result type cannot be called as a function,
951+
and will elicit an optional warning when called as a subroutine.
952+
942953
## De Facto Standard Features
943954

944955
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the

flang/include/flang/Support/Fortran-features.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
5656
IgnoreIrrelevantAttributes, Unsigned, AmbiguousStructureConstructor,
5757
ContiguousOkForSeqAssociation, ForwardRefExplicitTypeDummy,
5858
InaccessibleDeferredOverride, CudaWarpMatchFunction, DoConcurrentOffload,
59-
TransferBOZ, Coarray)
59+
TransferBOZ, Coarray, CallImplicitProcComponent)
6060

6161
// Portability and suspicious usage warnings
6262
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

flang/lib/Semantics/resolve-names.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9456,13 +9456,35 @@ bool ResolveNamesVisitor::SetProcFlag(
94569456
SayWithDecl(name, symbol,
94579457
"Implicit declaration of function '%s' has a different result type than in previous declaration"_err_en_US);
94589458
return false;
9459-
} else if (symbol.has<ProcEntityDetails>()) {
9460-
symbol.set(flag); // in case it hasn't been set yet
9461-
if (flag == Symbol::Flag::Function) {
9462-
ApplyImplicitRules(symbol);
9463-
}
9464-
if (symbol.attrs().test(Attr::INTRINSIC)) {
9465-
AcquireIntrinsicProcedureFlags(symbol);
9459+
} else if (const auto *procDetails{symbol.detailsIf<ProcEntityDetails>()}) {
9460+
if (symbol.owner().IsDerivedType()) { // procedure pointer component
9461+
bool isFunction{IsFunction(symbol)};
9462+
const Symbol *explicitInterface{procDetails->procInterface()};
9463+
if (flag == Symbol::Flag::Function) {
9464+
if (!isFunction) {
9465+
SayWithDecl(name, symbol,
9466+
"Procedure pointer component '%s' was not declared to be a function"_err_en_US);
9467+
}
9468+
} else if (isFunction ||
9469+
(!explicitInterface &&
9470+
!context().IsEnabled(
9471+
common::LanguageFeature::CallImplicitProcComponent))) {
9472+
SayWithDecl(name, symbol,
9473+
"Procedure pointer component '%s' was not declared to be a subroutine"_err_en_US);
9474+
} else if (!explicitInterface &&
9475+
context().ShouldWarn(
9476+
common::LanguageFeature::CallImplicitProcComponent)) {
9477+
SayWithDecl(name, symbol,
9478+
"Procedure pointer component '%s' should have been declared to be a subroutine"_warn_en_US);
9479+
}
9480+
} else {
9481+
symbol.set(flag); // in case it hasn't been set yet
9482+
if (flag == Symbol::Flag::Function) {
9483+
ApplyImplicitRules(symbol);
9484+
}
9485+
if (symbol.attrs().test(Attr::INTRINSIC)) {
9486+
AcquireIntrinsicProcedureFlags(symbol);
9487+
}
94669488
}
94679489
} else if (symbol.GetType() && flag == Symbol::Flag::Subroutine) {
94689490
SayWithDecl(

flang/test/Semantics/resolve09.f90

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
22
integer :: y
33
procedure() :: a
44
procedure(real) :: b
@@ -136,16 +136,34 @@ function b8()
136136
end
137137

138138
subroutine s9
139+
abstract interface
140+
subroutine subr
141+
end
142+
real function realfunc()
143+
end
144+
end interface
139145
type t
140146
procedure(), nopass, pointer :: p1, p2
147+
procedure(subr), nopass, pointer :: psub
148+
procedure(realfunc), nopass, pointer :: pfunc
141149
end type
142150
type(t) x
151+
!ERROR: Function result characteristics are not known
152+
!ERROR: Procedure pointer component 'p1' was not declared to be a function
143153
print *, x%p1()
144-
call x%p2
145-
!ERROR: Cannot call function 'p1' like a subroutine
154+
!ERROR: Procedure pointer component 'p1' should have been declared to be a subroutine
146155
call x%p1
147-
!ERROR: Cannot call subroutine 'p2' like a function
156+
!ERROR: Procedure pointer component 'p2' should have been declared to be a subroutine
157+
call x%p2
158+
!ERROR: Function result characteristics are not known
159+
!ERROR: Procedure pointer component 'p2' was not declared to be a function
148160
print *, x%p2()
161+
!ERROR: Cannot call subroutine 'psub' like a function
162+
print *, x%psub()
163+
print *, x%pfunc() ! ok
164+
call x%psub ! ok
165+
!ERROR: Cannot call function 'pfunc' like a subroutine
166+
call x%pfunc
149167
end subroutine
150168

151169
subroutine s10

0 commit comments

Comments
 (0)