Skip to content

Commit f4fc959

Browse files
authored
[flang] Catch impossible but necessary TBP override (#86558)
An apparent attempt to override a type-bound procedure is not allowed to be interpreted as on override when the procedure is PRIVATE and the override attempt appears in another module. However, if the TBP that would have been overridden is a DEFERRED procedure in an abstract base type, the override must take place. PRIVATE DEFERRED procedures must therefore have all of their overrides appear in the same module as the abstract base type.
1 parent f050a09 commit f4fc959

File tree

4 files changed

+46
-5
lines changed

4 files changed

+46
-5
lines changed

flang/include/flang/Semantics/tools.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ const Symbol *FindPointerComponent(const Symbol &);
5353
const Symbol *FindInterface(const Symbol &);
5454
const Symbol *FindSubprogram(const Symbol &);
5555
const Symbol *FindFunctionResult(const Symbol &);
56-
const Symbol *FindOverriddenBinding(const Symbol &);
56+
const Symbol *FindOverriddenBinding(
57+
const Symbol &, bool &isInaccessibleDeferred);
5758
const Symbol *FindGlobal(const Symbol &);
5859

5960
const DeclTypeSpec *FindParentTypeSpec(const DerivedTypeSpec &);

flang/lib/Semantics/check-declarations.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2346,7 +2346,14 @@ void CheckHelper::CheckProcBinding(
23462346
"Intrinsic procedure '%s' is not a specific intrinsic permitted for use in the definition of binding '%s'"_err_en_US,
23472347
binding.symbol().name(), symbol.name());
23482348
}
2349-
if (const Symbol *overridden{FindOverriddenBinding(symbol)}) {
2349+
bool isInaccessibleDeferred{false};
2350+
if (const Symbol *
2351+
overridden{FindOverriddenBinding(symbol, isInaccessibleDeferred)}) {
2352+
if (isInaccessibleDeferred) {
2353+
SayWithDeclaration(*overridden,
2354+
"Override of PRIVATE DEFERRED '%s' must appear in its module"_err_en_US,
2355+
symbol.name());
2356+
}
23502357
if (overridden->attrs().test(Attr::NON_OVERRIDABLE)) {
23512358
SayWithDeclaration(*overridden,
23522359
"Override of NON_OVERRIDABLE '%s' is not permitted"_err_en_US,

flang/lib/Semantics/tools.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,9 @@ const Symbol *FindSubprogram(const Symbol &symbol) {
528528
symbol.details());
529529
}
530530

531-
const Symbol *FindOverriddenBinding(const Symbol &symbol) {
531+
const Symbol *FindOverriddenBinding(
532+
const Symbol &symbol, bool &isInaccessibleDeferred) {
533+
isInaccessibleDeferred = false;
532534
if (symbol.has<ProcBindingDetails>()) {
533535
if (const DeclTypeSpec * parentType{FindParentTypeSpec(symbol.owner())}) {
534536
if (const DerivedTypeSpec * parentDerived{parentType->AsDerived()}) {
@@ -537,8 +539,11 @@ const Symbol *FindOverriddenBinding(const Symbol &symbol) {
537539
overridden{parentScope->FindComponent(symbol.name())}) {
538540
// 7.5.7.3 p1: only accessible bindings are overridden
539541
if (!overridden->attrs().test(Attr::PRIVATE) ||
540-
(FindModuleContaining(overridden->owner()) ==
541-
FindModuleContaining(symbol.owner()))) {
542+
FindModuleContaining(overridden->owner()) ==
543+
FindModuleContaining(symbol.owner())) {
544+
return overridden;
545+
} else if (overridden->attrs().test(Attr::DEFERRED)) {
546+
isInaccessibleDeferred = true;
542547
return overridden;
543548
}
544549
}

flang/test/Semantics/deferred01.f90

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
! Deferred TBPs must be overridden, but when they are private, those
3+
! overrides must appear in the same module.
4+
module m1
5+
type, abstract :: absBase
6+
contains
7+
procedure(deferredInterface), deferred, private :: deferredTbp
8+
end type
9+
abstract interface
10+
subroutine deferredInterface(x)
11+
import absBase
12+
class(absBase), intent(in) :: x
13+
end
14+
end interface
15+
end
16+
17+
module m2
18+
use m1
19+
type, extends(absBase) :: ext
20+
contains
21+
!ERROR: Override of PRIVATE DEFERRED 'deferredtbp' must appear in its module
22+
procedure :: deferredTbp => implTbp
23+
end type
24+
contains
25+
subroutine implTbp(x)
26+
class(ext), intent(in) :: x
27+
end
28+
end

0 commit comments

Comments
 (0)