Skip to content

Commit c541d10

Browse files
committed
[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.
1 parent 69cb99f commit c541d10

File tree

2 files changed

+27
-16
lines changed

2 files changed

+27
-16
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class DistinguishabilityHelper {
192192

193193
private:
194194
void SayNotDistinguishable(const Scope &, const SourceName &, GenericKind,
195-
const Symbol &, const Symbol &, bool isError);
195+
const Symbol &, const Symbol &, bool isHardConflict);
196196
void AttachDeclaration(parser::Message &, const Scope &, const Symbol &);
197197

198198
SemanticsContext &context_;
@@ -3512,6 +3512,11 @@ void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
35123512
}
35133513

35143514
void DistinguishabilityHelper::Check(const Scope &scope) {
3515+
if (FindModuleFileContaining(scope)) {
3516+
// Distinguishability was checked when the module was created;
3517+
// don't let optional warnings then become errors now.
3518+
return;
3519+
}
35153520
for (const auto &[name, info] : nameToSpecifics_) {
35163521
for (auto iter1{info.begin()}; iter1 != info.end(); ++iter1) {
35173522
const auto &[ultimate, procInfo]{*iter1};
@@ -3533,15 +3538,19 @@ void DistinguishabilityHelper::Check(const Scope &scope) {
35333538

35343539
void DistinguishabilityHelper::SayNotDistinguishable(const Scope &scope,
35353540
const SourceName &name, GenericKind kind, const Symbol &proc1,
3536-
const Symbol &proc2, bool isError) {
3537-
if (!isError &&
3538-
!context_.ShouldWarn(
3539-
common::LanguageFeature::IndistinguishableSpecifics)) {
3540-
// The rules for distinguishing specific procedures (F'2023 15.4.3.4.5)
3541-
// are inadequate for some real-world cases like pFUnit.
3542-
// When there are optional dummy arguments or unlimited polymorphic
3543-
// dummy data object arguments, the best that we can do is emit an optional
3544-
// portability warning.
3541+
const Symbol &proc2, bool isHardConflict) {
3542+
bool isUseAssociated{!scope.sourceRange().Contains(name)};
3543+
// The rules for distinguishing specific procedures (F'2023 15.4.3.4.5)
3544+
// are inadequate for some real-world cases like pFUnit.
3545+
// When there are optional dummy arguments or unlimited polymorphic
3546+
// dummy data object arguments, the best that we can do is emit an optional
3547+
// portability warning. Also, generics created by USE association
3548+
// merging shouldn't receive hard errors for ambiguity.
3549+
bool isWarning{!isHardConflict || isUseAssociated};
3550+
if (isWarning &&
3551+
(!context_.ShouldWarn(
3552+
common::LanguageFeature::IndistinguishableSpecifics) ||
3553+
FindModuleFileContaining(scope))) {
35453554
return;
35463555
}
35473556
std::string name1{proc1.name().ToString()};
@@ -3556,17 +3565,19 @@ void DistinguishabilityHelper::SayNotDistinguishable(const Scope &scope,
35563565
}
35573566
}
35583567
parser::Message *msg;
3559-
if (scope.sourceRange().Contains(name)) {
3568+
if (!isUseAssociated) {
3569+
CHECK(isWarning == !isHardConflict);
35603570
msg = &context_.Say(name,
3561-
isError
3571+
isHardConflict
35623572
? "Generic '%s' may not have specific procedures '%s' and '%s' as their interfaces are not distinguishable"_err_en_US
35633573
: "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,
35643574
MakeOpName(name), name1, name2);
35653575
} else {
3576+
CHECK(isWarning);
35663577
msg = &context_.Say(*GetTopLevelUnitContaining(proc1).GetName(),
3567-
isError
3568-
? "USE-associated generic '%s' may not have specific procedures '%s' and '%s' as their interfaces are not distinguishable"_err_en_US
3569-
: "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,
3578+
isHardConflict
3579+
? "USE-associated generic '%s' should not have specific procedures '%s' and '%s' as their interfaces are not distinguishable"_warn_en_US
3580+
: "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,
35703581
MakeOpName(name), name1, name2);
35713582
}
35723583
AttachDeclaration(*msg, scope, proc1);

flang/test/Semantics/resolve17.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ subroutine g()
180180
end
181181
end module
182182
subroutine s9
183-
!ERROR: USE-associated generic 'g' may not have specific procedures 'g' and 'g' as their interfaces are not distinguishable
183+
!PORTABILITY: USE-associated generic 'g' should not have specific procedures 'g' and 'g' as their interfaces are not distinguishable
184184
use m9a
185185
use m9b
186186
end

0 commit comments

Comments
 (0)