Skip to content

Commit ecf264d

Browse files
authored
[flang] Fix spurious error message due to inaccessible generic binding (#122810)
Generic operator/assignment checks for distinguishable specific procedures must ignore inaccessible generic bindings. Fixes #122764.
1 parent 9629f2c commit ecf264d

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

flang/include/flang/Semantics/tools.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ inline bool NeedCUDAAlloc(const Symbol &sym) {
241241
const Scope *FindCUDADeviceContext(const Scope *);
242242
std::optional<common::CUDADataAttr> GetCUDADataAttr(const Symbol *);
243243

244+
bool IsAccessible(const Symbol &, const Scope &);
245+
244246
// Return an error if a symbol is not accessible from a scope
245247
std::optional<parser::MessageFormattedText> CheckAccessibleSymbol(
246248
const Scope &, const Symbol &);

flang/lib/Semantics/check-declarations.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,6 +2742,9 @@ void CheckHelper::CheckBlockData(const Scope &scope) {
27422742
void CheckHelper::CheckGenericOps(const Scope &scope) {
27432743
DistinguishabilityHelper helper{context_};
27442744
auto addSpecifics{[&](const Symbol &generic) {
2745+
if (!IsAccessible(generic, scope)) {
2746+
return;
2747+
}
27452748
const auto *details{generic.GetUltimate().detailsIf<GenericDetails>()};
27462749
if (!details) {
27472750
// Not a generic; ensure characteristics are defined if a function.

flang/lib/Semantics/tools.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -550,9 +550,7 @@ const Symbol *FindOverriddenBinding(
550550
if (const Symbol *
551551
overridden{parentScope->FindComponent(symbol.name())}) {
552552
// 7.5.7.3 p1: only accessible bindings are overridden
553-
if (!overridden->attrs().test(Attr::PRIVATE) ||
554-
FindModuleContaining(overridden->owner()) ==
555-
FindModuleContaining(symbol.owner())) {
553+
if (IsAccessible(*overridden, symbol.owner())) {
556554
return overridden;
557555
} else if (overridden->attrs().test(Attr::DEFERRED)) {
558556
isInaccessibleDeferred = true;
@@ -1126,23 +1124,31 @@ std::optional<common::CUDADataAttr> GetCUDADataAttr(const Symbol *symbol) {
11261124
return object ? object->cudaDataAttr() : std::nullopt;
11271125
}
11281126

1127+
bool IsAccessible(const Symbol &original, const Scope &scope) {
1128+
const Symbol &ultimate{original.GetUltimate()};
1129+
if (ultimate.attrs().test(Attr::PRIVATE)) {
1130+
const Scope *module{FindModuleContaining(ultimate.owner())};
1131+
return !module || module->Contains(scope);
1132+
} else {
1133+
return true;
1134+
}
1135+
}
1136+
11291137
std::optional<parser::MessageFormattedText> CheckAccessibleSymbol(
11301138
const Scope &scope, const Symbol &symbol) {
1131-
if (symbol.attrs().test(Attr::PRIVATE)) {
1132-
if (FindModuleFileContaining(scope)) {
1133-
// Don't enforce component accessibility checks in module files;
1134-
// there may be forward-substituted named constants of derived type
1135-
// whose structure constructors reference private components.
1136-
} else if (const Scope *
1137-
moduleScope{FindModuleContaining(symbol.owner())}) {
1138-
if (!moduleScope->Contains(scope)) {
1139-
return parser::MessageFormattedText{
1140-
"PRIVATE name '%s' is only accessible within module '%s'"_err_en_US,
1141-
symbol.name(), moduleScope->GetName().value()};
1142-
}
1143-
}
1139+
if (IsAccessible(symbol, scope)) {
1140+
return std::nullopt;
1141+
} else if (FindModuleFileContaining(scope)) {
1142+
// Don't enforce component accessibility checks in module files;
1143+
// there may be forward-substituted named constants of derived type
1144+
// whose structure constructors reference private components.
1145+
return std::nullopt;
1146+
} else {
1147+
return parser::MessageFormattedText{
1148+
"PRIVATE name '%s' is only accessible within module '%s'"_err_en_US,
1149+
symbol.name(),
1150+
DEREF(FindModuleContaining(symbol.owner())).GetName().value()};
11441151
}
1145-
return std::nullopt;
11461152
}
11471153

11481154
SymbolVector OrderParameterNames(const Symbol &typeSymbol) {

flang/test/Semantics/generic12.f90

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
module m
3+
type t
4+
contains
5+
procedure :: tweedledee
6+
generic :: operator(.ga.) => tweedledee
7+
generic, private :: operator(.gb.) => tweedledee
8+
end type
9+
interface operator(.gc.)
10+
module procedure tweedledum
11+
end interface
12+
contains
13+
integer function tweedledee(x,y)
14+
class(t), intent(in) :: x, y
15+
tweedledee = 1
16+
end
17+
integer function tweedledum(x,y)
18+
class(t), intent(in) :: x, y
19+
tweedledum = 2
20+
end
21+
end
22+
23+
module badDueToAccessibility
24+
!ERROR: Generic 'OPERATOR(.ga.)' may not have specific procedures 'tweedledum' and 't%tweedledee' as their interfaces are not distinguishable
25+
use m, operator(.ga.) => operator(.gc.)
26+
end
27+
28+
module goodDueToInaccessibility
29+
use m, operator(.gb.) => operator(.gc.)
30+
end

0 commit comments

Comments
 (0)