-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Further refine errors vs warnings for ambiguous generics #80161
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
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesEnsure 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. Full diff: https://github.com/llvm/llvm-project/pull/80161.diff 2 Files Affected:
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 8af9dc11f822e..f701444e9ccd1 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_;
@@ -3512,6 +3512,13 @@ void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
}
void DistinguishabilityHelper::Check(const Scope &scope) {
+#if 0
+ if (FindModuleFileContaining(scope)) {
+ // Distinguishability was checked when the module was created;
+ // don't let optional warnings then become errors now.
+ return;
+ }
+#endif
for (const auto &[name, info] : nameToSpecifics_) {
for (auto iter1{info.begin()}; iter1 != info.end(); ++iter1) {
const auto &[ultimate, procInfo]{*iter1};
@@ -3533,15 +3540,19 @@ 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, generics created by USE association
+ // merging shouldn't receive hard errors for ambiguity.
+ bool isWarning{!isHardConflict || isUseAssociated};
+ if (isWarning &&
+ (!context_.ShouldWarn(
+ common::LanguageFeature::IndistinguishableSpecifics) ||
+ FindModuleFileContaining(scope))) {
return;
}
std::string name1{proc1.name().ToString()};
@@ -3556,17 +3567,19 @@ 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 {
+ CHECK(isWarning);
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
+ ? "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' 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
|
c541d10
to
87b94ad
Compare
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.
The changes looks good to me, but one thing is not clear to me: what happens when a call to a generic is later resolved and falls in these ambiguous cases? It will be an error at that point, right?
Yes, certainly. This patch is for the ambiguity checker that looks at declarations. For declarations in modules, this checking might help the programmer of a module guarantee that their clients will never get the per-reference ambiguity error; but a module that gets warnings about ambiguities might have clients that get errors. |
Thanks for the explanation! |
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.
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.