-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Fix spurious error message due to inaccessible generic binding #122810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Generic operator/assignment checks for distinguishable specific procedures must ignore inaccessible generic bindings. Fixes llvm#122764.
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesGeneric operator/assignment checks for distinguishable specific procedures must ignore inaccessible generic bindings. Fixes #122764. Full diff: https://github.com/llvm/llvm-project/pull/122810.diff 4 Files Affected:
diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index 96d4dbb2acaa11..1ec78acbd73c2d 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -240,6 +240,8 @@ inline bool NeedCUDAAlloc(const Symbol &sym) {
const Scope *FindCUDADeviceContext(const Scope *);
std::optional<common::CUDADataAttr> GetCUDADataAttr(const Symbol *);
+bool IsAccessible(const Symbol &, const Scope &);
+
// Return an error if a symbol is not accessible from a scope
std::optional<parser::MessageFormattedText> CheckAccessibleSymbol(
const Scope &, const Symbol &);
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 99c6e16c4260f1..a7e6cf32e85eea 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -2742,6 +2742,9 @@ void CheckHelper::CheckBlockData(const Scope &scope) {
void CheckHelper::CheckGenericOps(const Scope &scope) {
DistinguishabilityHelper helper{context_};
auto addSpecifics{[&](const Symbol &generic) {
+ if (!IsAccessible(generic, scope)) {
+ return;
+ }
const auto *details{generic.GetUltimate().detailsIf<GenericDetails>()};
if (!details) {
// Not a generic; ensure characteristics are defined if a function.
diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index 9e180605c1b3bd..627d8b35353f54 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -544,9 +544,7 @@ const Symbol *FindOverriddenBinding(
if (const Symbol *
overridden{parentScope->FindComponent(symbol.name())}) {
// 7.5.7.3 p1: only accessible bindings are overridden
- if (!overridden->attrs().test(Attr::PRIVATE) ||
- FindModuleContaining(overridden->owner()) ==
- FindModuleContaining(symbol.owner())) {
+ if (IsAccessible(*overridden, symbol.owner())) {
return overridden;
} else if (overridden->attrs().test(Attr::DEFERRED)) {
isInaccessibleDeferred = true;
@@ -1120,23 +1118,31 @@ std::optional<common::CUDADataAttr> GetCUDADataAttr(const Symbol *symbol) {
return object ? object->cudaDataAttr() : std::nullopt;
}
+bool IsAccessible(const Symbol &original, const Scope &scope) {
+ const Symbol &ultimate{original.GetUltimate()};
+ if (ultimate.attrs().test(Attr::PRIVATE)) {
+ const Scope *module{FindModuleContaining(ultimate.owner())};
+ return !module || module->Contains(scope);
+ } else {
+ return true;
+ }
+}
+
std::optional<parser::MessageFormattedText> CheckAccessibleSymbol(
const Scope &scope, const Symbol &symbol) {
- if (symbol.attrs().test(Attr::PRIVATE)) {
- if (FindModuleFileContaining(scope)) {
- // Don't enforce component accessibility checks in module files;
- // there may be forward-substituted named constants of derived type
- // whose structure constructors reference private components.
- } else if (const Scope *
- moduleScope{FindModuleContaining(symbol.owner())}) {
- if (!moduleScope->Contains(scope)) {
- return parser::MessageFormattedText{
- "PRIVATE name '%s' is only accessible within module '%s'"_err_en_US,
- symbol.name(), moduleScope->GetName().value()};
- }
- }
+ if (IsAccessible(symbol, scope)) {
+ return std::nullopt;
+ } else if (FindModuleFileContaining(scope)) {
+ // Don't enforce component accessibility checks in module files;
+ // there may be forward-substituted named constants of derived type
+ // whose structure constructors reference private components.
+ return std::nullopt;
+ } else {
+ return parser::MessageFormattedText{
+ "PRIVATE name '%s' is only accessible within module '%s'"_err_en_US,
+ symbol.name(),
+ DEREF(FindModuleContaining(symbol.owner())).GetName().value()};
}
- return std::nullopt;
}
SymbolVector OrderParameterNames(const Symbol &typeSymbol) {
diff --git a/flang/test/Semantics/generic12.f90 b/flang/test/Semantics/generic12.f90
new file mode 100644
index 00000000000000..1ac76c13b7a2b0
--- /dev/null
+++ b/flang/test/Semantics/generic12.f90
@@ -0,0 +1,30 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+module m
+ type t
+ contains
+ procedure :: tweedledee
+ generic :: operator(.ga.) => tweedledee
+ generic, private :: operator(.gb.) => tweedledee
+ end type
+ interface operator(.gc.)
+ module procedure tweedledum
+ end interface
+ contains
+ integer function tweedledee(x,y)
+ class(t), intent(in) :: x, y
+ tweedledee = 1
+ end
+ integer function tweedledum(x,y)
+ class(t), intent(in) :: x, y
+ tweedledum = 2
+ end
+end
+
+module badDueToAccessibility
+ !ERROR: Generic 'OPERATOR(.ga.)' may not have specific procedures 'tweedledum' and 't%tweedledee' as their interfaces are not distinguishable
+ use m, operator(.ga.) => operator(.gc.)
+end
+
+module goodDueToInaccessibility
+ use m, operator(.gb.) => operator(.gc.)
+end
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Thanks for the quick fix!
Generic operator/assignment checks for distinguishable specific procedures must ignore inaccessible generic bindings.
Fixes #122764.