[flang-commits] [flang] [flang] Further refine errors vs warnings for ambiguous generics (PR #80161)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Feb 2 08:49:47 PST 2024
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/80161
>From 6f5ef8ff0b3bd589550e5e7f1ff38428c3257da0 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Wed, 31 Jan 2024 08:31:01 -0800
Subject: [PATCH] [flang] Further refine errors vs warnings for ambiguous
generics
Ensure that the compiler emits a hard error for a generic interface
with ambiguous specific procedures when it is declared as such, and
the ambiguity doesn't involve optional or unlimited polymorphic dummy
data arguments. But: emit an optional portability warning when the
ambiguity in the generic interface is due to USE association's merging
of multiple generics, as USE association may involve modules not under
control of the programmer; we'll emit a hard error message if any
the actual arguments in a particular reference to the generic procedure
doesn't resolve to exactly one specific procedure. And don't emit
warnings when potential ambiguity due to USE association is taking
place in a module file; the warnings, if any, will have been produced
when the module file was compiled.
---
flang/lib/Semantics/check-declarations.cpp | 44 ++++++++++++++--------
flang/test/Semantics/resolve17.f90 | 2 +-
2 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 816227fb3354f..2db3f9a27d8f4 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -192,7 +192,7 @@ class DistinguishabilityHelper {
private:
void SayNotDistinguishable(const Scope &, const SourceName &, GenericKind,
- const Symbol &, const Symbol &, bool isError);
+ const Symbol &, const Symbol &, bool isHardConflict);
void AttachDeclaration(parser::Message &, const Scope &, const Symbol &);
SemanticsContext &context_;
@@ -3513,6 +3513,11 @@ void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
}
void DistinguishabilityHelper::Check(const Scope &scope) {
+ if (FindModuleFileContaining(scope)) {
+ // Distinguishability was checked when the module was created;
+ // don't let optional warnings then become errors now.
+ return;
+ }
for (const auto &[name, info] : nameToSpecifics_) {
for (auto iter1{info.begin()}; iter1 != info.end(); ++iter1) {
const auto &[ultimate, procInfo]{*iter1};
@@ -3534,15 +3539,21 @@ void DistinguishabilityHelper::Check(const Scope &scope) {
void DistinguishabilityHelper::SayNotDistinguishable(const Scope &scope,
const SourceName &name, GenericKind kind, const Symbol &proc1,
- const Symbol &proc2, bool isError) {
- if (!isError &&
- !context_.ShouldWarn(
- common::LanguageFeature::IndistinguishableSpecifics)) {
- // The rules for distinguishing specific procedures (F'2023 15.4.3.4.5)
- // are inadequate for some real-world cases like pFUnit.
- // When there are optional dummy arguments or unlimited polymorphic
- // dummy data object arguments, the best that we can do is emit an optional
- // portability warning.
+ const Symbol &proc2, bool isHardConflict) {
+ bool isUseAssociated{!scope.sourceRange().Contains(name)};
+ // The rules for distinguishing specific procedures (F'2023 15.4.3.4.5)
+ // are inadequate for some real-world cases like pFUnit.
+ // When there are optional dummy arguments or unlimited polymorphic
+ // dummy data object arguments, the best that we can do is emit an optional
+ // portability warning. Also, named generics created by USE association
+ // merging shouldn't receive hard errors for ambiguity.
+ // (Non-named generics might be defined I/O procedures or defined
+ // assignments that need to be used by the runtime.)
+ bool isWarning{!isHardConflict || (isUseAssociated && kind.IsName())};
+ if (isWarning &&
+ (!context_.ShouldWarn(
+ common::LanguageFeature::IndistinguishableSpecifics) ||
+ FindModuleFileContaining(scope))) {
return;
}
std::string name1{proc1.name().ToString()};
@@ -3557,17 +3568,20 @@ void DistinguishabilityHelper::SayNotDistinguishable(const Scope &scope,
}
}
parser::Message *msg;
- if (scope.sourceRange().Contains(name)) {
+ if (!isUseAssociated) {
+ CHECK(isWarning == !isHardConflict);
msg = &context_.Say(name,
- isError
+ isHardConflict
? "Generic '%s' may not have specific procedures '%s' and '%s' as their interfaces are not distinguishable"_err_en_US
: "Generic '%s' should not have specific procedures '%s' and '%s' as their interfaces are not distinguishable by the rules in the standard"_port_en_US,
MakeOpName(name), name1, name2);
} else {
msg = &context_.Say(*GetTopLevelUnitContaining(proc1).GetName(),
- isError
- ? "USE-associated generic '%s' may not have specific procedures '%s' and '%s' as their interfaces are not distinguishable"_err_en_US
- : "USE-associated generic '%s' should not have specific procedures '%s' and '%s' as their interfaces are not distinguishable by the incomplete rules in the standard"_port_en_US,
+ isHardConflict
+ ? (isWarning
+ ? "USE-associated generic '%s' should not have specific procedures '%s' and '%s' as their interfaces are not distinguishable"_warn_en_US
+ : "USE-associated generic '%s' may not have specific procedures '%s' and '%s' as their interfaces are not distinguishable"_err_en_US)
+ : "USE-associated generic '%s' should not have specific procedures '%s' and '%s' as their interfaces are not distinguishable by the rules in the standard"_port_en_US,
MakeOpName(name), name1, name2);
}
AttachDeclaration(*msg, scope, proc1);
diff --git a/flang/test/Semantics/resolve17.f90 b/flang/test/Semantics/resolve17.f90
index 513676fe670a1..770af756d03bc 100644
--- a/flang/test/Semantics/resolve17.f90
+++ b/flang/test/Semantics/resolve17.f90
@@ -180,7 +180,7 @@ subroutine g()
end
end module
subroutine s9
- !ERROR: USE-associated generic 'g' may not have specific procedures 'g' and 'g' as their interfaces are not distinguishable
+ !PORTABILITY: USE-associated generic 'g' should not have specific procedures 'g' and 'g' as their interfaces are not distinguishable
use m9a
use m9b
end
More information about the flang-commits
mailing list