diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index c88e20965c1eb..6671151777af4 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -271,13 +271,6 @@ void ModFileWriter::PutSymbol( } } else { PutGeneric(symbol); - if (x.specific() && &x.specific()->owner() == &symbol.owner()) { - PutSymbol(typeBindings, *x.specific()); - } - if (x.derivedType() && - &x.derivedType()->owner() == &symbol.owner()) { - PutSymbol(typeBindings, *x.derivedType()); - } } }, [&](const UseDetails &) { PutUse(symbol); }, @@ -583,21 +576,8 @@ void ModFileWriter::PutUseExtraAttr( } } -// When a generic interface has the same name as a derived type -// in the same scope, the generic shadows the derived type. -// If the derived type were declared first, emit the generic -// interface at the position of derived type's declaration. -// (ReplaceName() is not used for this purpose because doing so -// would confusingly position error messages pertaining to the generic -// interface upon the derived type's declaration.) static inline SourceName NameInModuleFile(const Symbol &symbol) { - if (const auto *generic{symbol.detailsIf()}) { - if (const auto *derivedTypeOverload{generic->derivedType()}) { - if (derivedTypeOverload->name().begin() < symbol.name().begin()) { - return derivedTypeOverload->name(); - } - } - } else if (const auto *use{symbol.detailsIf()}) { + if (const auto *use{symbol.detailsIf()}) { if (use->symbol().attrs().test(Attr::PRIVATE)) { // Avoid the use in sorting of names created to access private // specific procedures as a result of generic resolution; @@ -609,10 +589,10 @@ static inline SourceName NameInModuleFile(const Symbol &symbol) { } // Collect the symbols of this scope sorted by their original order, not name. -// Namelists are an exception: they are sorted after other symbols. +// Generics and namelists are exceptions: they are sorted after other symbols. void CollectSymbols( const Scope &scope, SymbolVector &sorted, SymbolVector &uses) { - SymbolVector namelist; + SymbolVector namelist, generics; std::size_t commonSize{scope.commonBlocks().size()}; auto symbols{scope.GetSymbols()}; sorted.reserve(symbols.size() + commonSize); @@ -620,6 +600,15 @@ void CollectSymbols( if (!symbol->test(Symbol::Flag::ParentComp)) { if (symbol->has()) { namelist.push_back(symbol); + } else if (const auto *generic{symbol->detailsIf()}) { + if (generic->specific() && + &generic->specific()->owner() == &symbol->owner()) { + sorted.push_back(*generic->specific()); + } else if (generic->derivedType() && + &generic->derivedType()->owner() == &symbol->owner()) { + sorted.push_back(*generic->derivedType()); + } + generics.push_back(symbol); } else { sorted.push_back(symbol); } @@ -630,9 +619,12 @@ void CollectSymbols( } // Sort most symbols by name: use of Symbol::ReplaceName ensures the source // location of a symbol's name is the first "real" use. - std::sort(sorted.begin(), sorted.end(), [](SymbolRef x, SymbolRef y) { - return NameInModuleFile(x).begin() < NameInModuleFile(y).begin(); - }); + auto sorter{[](SymbolRef x, SymbolRef y) { + return NameInModuleFile(*x).begin() < NameInModuleFile(*y).begin(); + }}; + std::sort(sorted.begin(), sorted.end(), sorter); + std::sort(generics.begin(), generics.end(), sorter); + sorted.insert(sorted.end(), generics.begin(), generics.end()); sorted.insert(sorted.end(), namelist.begin(), namelist.end()); for (const auto &pair : scope.commonBlocks()) { sorted.push_back(*pair.second); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index c22386ab83d9a..1c568e159e9ac 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -843,11 +843,13 @@ class InterfaceVisitor : public virtual ScopeHandler { using ProcedureKind = parser::ProcedureStmt::Kind; // mapping of generic to its specific proc names and kinds - std::multimap> - specificProcs_; + using SpecificProcMapType = + std::multimap>; + SpecificProcMapType specificProcs_; void AddSpecificProcs(const std::list &, ProcedureKind); - void ResolveSpecificsInGeneric(Symbol &generic); + void ResolveSpecificsInGeneric(Symbol &, bool isEndOfSpecificationPart); + void ResolveNewSpecifics(); }; class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor { @@ -3258,6 +3260,7 @@ bool InterfaceVisitor::Pre(const parser::InterfaceStmt &x) { void InterfaceVisitor::Post(const parser::InterfaceStmt &) { EndAttrs(); } void InterfaceVisitor::Post(const parser::EndInterfaceStmt &) { + ResolveNewSpecifics(); genericInfo_.pop(); } @@ -3277,11 +3280,11 @@ bool InterfaceVisitor::Pre(const parser::GenericSpec &x) { bool InterfaceVisitor::Pre(const parser::ProcedureStmt &x) { if (!isGeneric()) { Say("A PROCEDURE statement is only allowed in a generic interface block"_err_en_US); - return false; + } else { + auto kind{std::get(x.t)}; + const auto &names{std::get>(x.t)}; + AddSpecificProcs(names, kind); } - auto kind{std::get(x.t)}; - const auto &names{std::get>(x.t)}; - AddSpecificProcs(names, kind); return false; } @@ -3295,6 +3298,7 @@ void InterfaceVisitor::Post(const parser::GenericStmt &x) { } const auto &names{std::get>(x.t)}; AddSpecificProcs(names, ProcedureKind::Procedure); + ResolveNewSpecifics(); genericInfo_.pop(); } @@ -3318,36 +3322,48 @@ void InterfaceVisitor::AddSpecificProcs( // By now we should have seen all specific procedures referenced by name in // this generic interface. Resolve those names to symbols. -void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) { +void InterfaceVisitor::ResolveSpecificsInGeneric( + Symbol &generic, bool isEndOfSpecificationPart) { auto &details{generic.get()}; UnorderedSymbolSet symbolsSeen; for (const Symbol &symbol : details.specificProcs()) { symbolsSeen.insert(symbol.GetUltimate()); } auto range{specificProcs_.equal_range(&generic)}; + SpecificProcMapType retain; for (auto it{range.first}; it != range.second; ++it) { const parser::Name *name{it->second.first}; auto kind{it->second.second}; - const auto *symbol{FindSymbol(*name)}; - if (!symbol) { - Say(*name, "Procedure '%s' not found"_err_en_US); + const Symbol *symbol{FindSymbol(*name)}; + if (!isEndOfSpecificationPart && symbol && + &symbol->owner() != &generic.owner()) { + // Don't mistakenly use a name from the enclosing scope while there's + // still a chance that it could be overridden by a later declaration in + // this scope. + retain.emplace(&generic, std::make_pair(name, kind)); continue; } - // Subtlety: when *symbol is a use- or host-association, the specific - // procedure that is recorded in the GenericDetails below must be *symbol, - // not the specific procedure shadowed by a generic, because that specific - // procedure may be a symbol from another module and its name unavailable to - // emit to a module file. - const Symbol &bypassed{BypassGeneric(*symbol)}; - const Symbol &specific{ - symbol == &symbol->GetUltimate() ? bypassed : *symbol}; - const Symbol &ultimate{bypassed.GetUltimate()}; - ProcedureDefinitionClass defClass{ClassifyProcedure(ultimate)}; + ProcedureDefinitionClass defClass{ProcedureDefinitionClass::None}; + const Symbol *specific{symbol}; + const Symbol *ultimate{nullptr}; + if (symbol) { + // Subtlety: when *symbol is a use- or host-association, the specific + // procedure that is recorded in the GenericDetails below must be *symbol, + // not the specific procedure shadowed by a generic, because that specific + // procedure may be a symbol from another module and its name unavailable + // to emit to a module file. + const Symbol &bypassed{BypassGeneric(*symbol)}; + if (symbol == &symbol->GetUltimate()) { + specific = &bypassed; + } + ultimate = &bypassed.GetUltimate(); + defClass = ClassifyProcedure(*ultimate); + } + std::optional error; if (defClass == ProcedureDefinitionClass::Module) { // ok } else if (kind == ProcedureKind::ModuleProcedure) { - Say(*name, "'%s' is not a module procedure"_err_en_US); - continue; + error = "'%s' is not a module procedure"_err_en_US; } else { switch (defClass) { case ProcedureDefinitionClass::Intrinsic: @@ -3357,47 +3373,58 @@ void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) { case ProcedureDefinitionClass::Pointer: break; case ProcedureDefinitionClass::None: - Say(*name, "'%s' is not a procedure"_err_en_US); - continue; + error = "'%s' is not a procedure"_err_en_US; + break; default: - Say(*name, - "'%s' is not a procedure that can appear in a generic interface"_err_en_US); - continue; + error = + "'%s' is not a procedure that can appear in a generic interface"_err_en_US; + break; } } - if (symbolsSeen.insert(ultimate).second /*true if added*/) { + if (error) { + if (isEndOfSpecificationPart) { + Say(*name, std::move(*error)); + } else { + // possible forward reference, catch it later + retain.emplace(&generic, std::make_pair(name, kind)); + } + } else if (!ultimate) { + } else if (symbolsSeen.insert(*ultimate).second /*true if added*/) { // When a specific procedure is a USE association, that association // is saved in the generic's specifics, not its ultimate symbol, // so that module file output of interfaces can distinguish them. - details.AddSpecificProc(specific, name->source); - } else if (&specific == &ultimate) { + details.AddSpecificProc(*specific, name->source); + } else if (specific == ultimate) { Say(name->source, "Procedure '%s' is already specified in generic '%s'"_err_en_US, name->source, MakeOpName(generic.name())); } else { Say(name->source, "Procedure '%s' from module '%s' is already specified in generic '%s'"_err_en_US, - ultimate.name(), ultimate.owner().GetName().value(), + ultimate->name(), ultimate->owner().GetName().value(), MakeOpName(generic.name())); } } specificProcs_.erase(range.first, range.second); + specificProcs_.merge(std::move(retain)); +} + +void InterfaceVisitor::ResolveNewSpecifics() { + if (Symbol * generic{genericInfo_.top().symbol}; + generic && generic->has()) { + ResolveSpecificsInGeneric(*generic, false); + } } // Mixed interfaces are allowed by the standard. // If there is a derived type with the same name, they must all be functions. void InterfaceVisitor::CheckGenericProcedures(Symbol &generic) { - ResolveSpecificsInGeneric(generic); + ResolveSpecificsInGeneric(generic, true); auto &details{generic.get()}; if (auto *proc{details.CheckSpecific()}) { - auto msg{ - "'%s' should not be the name of both a generic interface and a" - " procedure unless it is a specific procedure of the generic"_warn_en_US}; - if (proc->name().begin() > generic.name().begin()) { - Say(proc->name(), std::move(msg)); - } else { - Say(generic.name(), std::move(msg)); - } + Say(proc->name().begin() > generic.name().begin() ? proc->name() + : generic.name(), + "'%s' should not be the name of both a generic interface and a procedure unless it is a specific procedure of the generic"_warn_en_US); } auto &specifics{details.specificProcs()}; if (specifics.empty()) { diff --git a/flang/test/Semantics/modfile07.f90 b/flang/test/Semantics/modfile07.f90 index 48df7243e308c..90c35a9a69377 100644 --- a/flang/test/Semantics/modfile07.f90 +++ b/flang/test/Semantics/modfile07.f90 @@ -53,10 +53,6 @@ integer function s4(x,y) end !Expect: m1.mod !module m1 -! interface foo -! procedure::s1 -! procedure::s2 -! end interface ! interface ! function s1(x,y) ! real(4),intent(in)::x @@ -71,16 +67,6 @@ integer function s4(x,y) ! complex(4)::s2 ! end ! end interface -! interface operator(+) -! procedure::s1 -! procedure::s2 -! end interface -! interface operator(/=) -! procedure::f1 -! procedure::f2 -! procedure::f3 -! end interface -! private::operator(/=) ! interface ! function f1(x,y) ! real(4),intent(in)::x @@ -102,6 +88,20 @@ integer function s4(x,y) ! logical(4)::f3 ! end ! end interface +! interface foo +! procedure::s1 +! procedure::s2 +! end interface +! interface operator(+) +! procedure::s1 +! procedure::s2 +! end interface +! interface operator(/=) +! procedure::f1 +! procedure::f2 +! procedure::f3 +! end interface +! private::operator(/=) ! interface bar ! procedure::s1 ! procedure::s2 @@ -191,11 +191,11 @@ module m2b end !Expect: m2b.mod !module m2b -! interface foo -! end interface ! type::foo ! real(4)::x ! end type +! interface foo +! end interface ! interface bar ! end interface ! private::bar @@ -218,9 +218,6 @@ subroutine x() end !Expect: m3.mod !module m3 -! interface g -! procedure::s1 -! end interface ! interface ! subroutine s1(f) ! interface @@ -234,6 +231,9 @@ subroutine x() ! end interface ! end ! end interface +! interface g +! procedure::s1 +! end interface !end module m4 @@ -250,10 +250,6 @@ subroutine s4 end !Expect: m4.mod !module m4 -! interface foo -! procedure::foo -! procedure::f -! end interface ! interface ! function foo() ! integer(4)::foo @@ -265,6 +261,10 @@ subroutine s4 ! integer(4)::f ! end ! end interface +! interface foo +! procedure::foo +! procedure::f +! end interface !end ! Compile contents of m4.mod and verify it gets the same thing again. @@ -287,10 +287,6 @@ function f(x) end !Expect: m5.mod !module m5 -! interface foo -! procedure::foo -! procedure::f -! end interface ! interface ! function foo() ! integer(4)::foo @@ -302,6 +298,10 @@ function f(x) ! integer(4)::f ! end ! end interface +! interface foo +! procedure::foo +! procedure::f +! end interface !end module m6a @@ -313,9 +313,6 @@ logical function lt(x, y) end !Expect: m6a.mod !module m6a -! interface operator(<) -! procedure::lt -! end interface ! interface ! function lt(x,y) ! logical(4),intent(in)::x @@ -323,6 +320,9 @@ logical function lt(x, y) ! logical(4)::lt ! end ! end interface +! interface operator(<) +! procedure::lt +! end interface !end module m6b @@ -345,10 +345,10 @@ subroutine s(x) end !Expect: m7a.mod !module m7a +! private :: s ! interface g_integer ! procedure :: s ! end interface -! private :: s !contains ! subroutine s(x) ! integer(4) :: x @@ -367,10 +367,10 @@ subroutine s(x) end !Expect: m7b.mod !module m7b +! private :: s ! interface g_real ! procedure :: s ! end interface -! private :: s !contains ! subroutine s(x) ! real(4) :: x @@ -401,10 +401,10 @@ subroutine test() !module m7c ! use m7a, only: g => g_integer ! use m7b, only: g => g_real +! private :: s ! interface g ! procedure :: s ! end interface -! private :: s !contains ! subroutine s(x) ! complex(4) :: x @@ -427,10 +427,10 @@ subroutine s(x) end !Expect: m8a.mod !module m8a +! private :: s ! interface g ! procedure :: s ! end interface -! private :: s !contains ! subroutine s(x) ! integer(4) :: x @@ -449,10 +449,10 @@ subroutine s(x) end !Expect: m8b.mod !module m8b +! private :: s ! interface g ! procedure :: s ! end interface -! private :: s !contains ! subroutine s(x) ! real(4) :: x @@ -483,10 +483,10 @@ subroutine test() !module m8c ! use m8a, only: g ! use m8b, only: g +! private :: s ! interface g ! procedure :: s ! end interface -! private :: s !contains ! subroutine s(x) ! complex(4) :: x @@ -509,10 +509,10 @@ subroutine s(x) end !Expect: m9a.mod !module m9a +! private :: s ! interface g ! procedure :: s ! end interface -! private :: s !contains ! subroutine s(x) ! integer(4) :: x @@ -537,10 +537,10 @@ subroutine test() !Expect: m9b.mod !module m9b ! use m9a,only:g +! private::s ! interface g ! procedure::s ! end interface -! private::s !contains ! subroutine s(x) ! real(4)::x @@ -624,3 +624,37 @@ module m11b ! procedure::s1 ! end interface !end + +module m12 + interface generic + module procedure specific + end interface + interface + module subroutine s(a1,a2) + character(*) a1 + character(generic(a1)) a2 + end + end interface + contains + pure integer function specific(x) + character(*), intent(in) :: x + specific = len(x) + end +end +!Expect: m12.mod +!module m12 +! interface +! module subroutine s(a1,a2) +! character(*,1)::a1 +! character(specific(a1),1)::a2 +! end +! end interface +! interface generic +! procedure::specific +! end interface +!contains +! pure function specific(x) +! character(*,1),intent(in)::x +! integer(4)::specific +! end +!end diff --git a/flang/test/Semantics/modfile32.f90 b/flang/test/Semantics/modfile32.f90 index f85eb0fa26f7f..2878614b90416 100644 --- a/flang/test/Semantics/modfile32.f90 +++ b/flang/test/Semantics/modfile32.f90 @@ -33,11 +33,6 @@ subroutine s4(x, y, z, w, u) end !Expect: m1.mod !module m1 -! interface f -! procedure :: f1 -! procedure :: f2 -! procedure :: f3 -! end interface ! interface ! pure function f1(x) ! real(4), intent(in) :: x @@ -60,6 +55,11 @@ subroutine s4(x, y, z, w, u) ! integer(8) :: f3 ! end ! end interface +! interface f +! procedure :: f1 +! procedure :: f2 +! procedure :: f3 +! end interface !contains ! subroutine s1(x, z) ! real(4) :: x @@ -114,11 +114,6 @@ subroutine s3(x, y) end !Expect: m2.mod !module m2 -! interface f -! procedure :: f_real4 -! procedure :: f_real8 -! procedure :: f_integer -! end interface ! interface ! pure function f_real4(x) ! real(4), intent(in) :: x @@ -137,6 +132,11 @@ subroutine s3(x, y) ! integer(8) :: f_integer ! end ! end interface +! interface f +! procedure :: f_real4 +! procedure :: f_real8 +! procedure :: f_integer +! end interface !contains ! subroutine s1(x, y) ! real(4) :: x @@ -243,10 +243,6 @@ subroutine s2(x, y) end !Expect: m4.mod !module m4 -! interface operator(.foo.) -! procedure :: f_real -! procedure :: f_integer -! end interface ! interface ! pure function f_real(x) ! real(4), intent(in) :: x @@ -259,6 +255,10 @@ subroutine s2(x, y) ! integer(8) :: f_integer ! end ! end interface +! interface operator(.foo.) +! procedure :: f_real +! procedure :: f_integer +! end interface !contains ! subroutine s1(x, y) ! real(4) :: x @@ -294,10 +294,6 @@ subroutine s2(x, y) end !Expect: m5.mod !module m5 -! interface operator(.foo.) -! procedure :: f1 -! procedure :: f2 -! end interface ! interface ! pure function f1(x, y) ! real(4), intent(in) :: x @@ -312,6 +308,10 @@ subroutine s2(x, y) ! integer(8) :: f2 ! end ! end interface +! interface operator(.foo.) +! procedure :: f1 +! procedure :: f2 +! end interface !contains ! subroutine s1(x, y) ! complex(4) :: x diff --git a/flang/test/Semantics/modfile33.f90 b/flang/test/Semantics/modfile33.f90 index 6aad8b2937b61..98d6da402cbeb 100644 --- a/flang/test/Semantics/modfile33.f90 +++ b/flang/test/Semantics/modfile33.f90 @@ -63,11 +63,6 @@ subroutine s4(x, y, z) ! sequence ! logical(4) :: x ! end type -! interface operator(+) -! procedure :: add_ll -! procedure :: add_li -! procedure :: add_tt -! end interface ! interface ! pure function add_ll(x, y) ! logical(4), intent(in) :: x @@ -90,10 +85,6 @@ subroutine s4(x, y, z) ! integer(8) :: add_tt ! end ! end interface -! interface operator(/) -! procedure :: div_tz -! procedure :: div_ct -! end interface ! interface ! pure function div_tz(x, y) ! import :: t @@ -110,6 +101,15 @@ subroutine s4(x, y, z) ! integer(8) :: div_ct ! end ! end interface +! interface operator(+) +! procedure :: add_ll +! procedure :: add_li +! procedure :: add_tt +! end interface +! interface operator(/) +! procedure :: div_tz +! procedure :: div_ct +! end interface !contains ! subroutine s1(x, y, z) ! logical(4) :: x @@ -199,11 +199,6 @@ subroutine s5(x, y, z) ! sequence ! logical(4) :: x ! end type -! interface operator( .and.) -! procedure :: and_ti -! procedure :: and_li -! procedure :: and_tt -! end interface ! interface ! pure function and_ti(x, y) ! import :: t @@ -227,10 +222,6 @@ subroutine s5(x, y, z) ! integer(8) :: and_tt ! end ! end interface -! interface operator(.x.) -! procedure :: neqv_tt -! procedure :: neqv_rr -! end interface ! interface ! pure function neqv_tt(x, y) ! import :: t @@ -246,6 +237,15 @@ subroutine s5(x, y, z) ! integer(8) :: neqv_rr ! end ! end interface +! interface operator( .and.) +! procedure :: and_ti +! procedure :: and_li +! procedure :: and_tt +! end interface +! interface operator(.x.) +! procedure :: neqv_tt +! procedure :: neqv_rr +! end interface !contains ! subroutine s1(x, y, z) ! type(t) :: x @@ -323,11 +323,6 @@ subroutine s3(x, y, z) ! sequence ! logical(4) :: x ! end type -! interface operator(<>) -! procedure :: ne_it -! procedure :: ne_tt -! procedure :: ne_ci -! end interface ! interface ! pure function ne_it(x, y) ! import :: t @@ -351,6 +346,11 @@ subroutine s3(x, y, z) ! integer(8) :: ne_ci ! end ! end interface +! interface operator(<>) +! procedure :: ne_it +! procedure :: ne_tt +! procedure :: ne_ci +! end interface !contains ! subroutine s1(x, y, z) ! integer(4) :: x @@ -403,10 +403,6 @@ subroutine s2(x, y, z) ! sequence ! logical(4) :: x ! end type -! interface operator(//) -! procedure :: concat_12 -! procedure :: concat_int_real -! end interface ! interface ! pure function concat_12(x, y) ! character(*, 1), intent(in) :: x @@ -421,6 +417,10 @@ subroutine s2(x, y, z) ! integer(8) :: concat_int_real ! end ! end interface +! interface operator(//) +! procedure :: concat_12 +! procedure :: concat_int_real +! end interface !contains ! subroutine s1(x, y, z) ! character(*, 1) :: x @@ -480,18 +480,12 @@ subroutine s4(x, y) !module m5 ! type :: t ! end type -! interface operator(+) -! procedure :: plus_l -! end interface ! interface ! pure function plus_l(x) ! logical(4), intent(in) :: x ! integer(8) :: plus_l ! end ! end interface -! interface operator(-) -! procedure :: minus_t -! end interface ! interface ! pure function minus_t(x) ! import :: t @@ -499,10 +493,6 @@ subroutine s4(x, y) ! integer(8) :: minus_t ! end ! end interface -! interface operator( .not.) -! procedure :: not_t -! procedure :: not_real -! end interface ! interface ! pure function not_t(x) ! import :: t @@ -516,6 +506,16 @@ subroutine s4(x, y) ! integer(8) :: not_real ! end ! end interface +! interface operator(+) +! procedure :: plus_l +! end interface +! interface operator(-) +! procedure :: minus_t +! end interface +! interface operator( .not.) +! procedure :: not_t +! procedure :: not_real +! end interface !contains ! subroutine s1(x, y) ! logical(4) :: x @@ -556,9 +556,6 @@ subroutine s1(n, x, y, z, a, b) !Expect: m6.mod !module m6 -! interface operator(+) -! procedure :: add -! end interface ! interface ! pure function add(x, y) ! real(4), intent(in) :: x(:, :) @@ -566,6 +563,9 @@ subroutine s1(n, x, y, z, a, b) ! integer(8) :: add ! end ! end interface +! interface operator(+) +! procedure :: add +! end interface !contains ! subroutine s1(n, x, y, z, a, b) ! integer(8) :: n @@ -610,10 +610,6 @@ subroutine s2(x, y, z) ! integer(4), kind :: k ! real(int(int(k,kind=4),kind=8))::a ! end type -! interface operator(+) -! procedure :: f1 -! procedure :: f2 -! end interface ! interface ! pure function f1(x, y) ! import :: t @@ -630,6 +626,10 @@ subroutine s2(x, y, z) ! integer(8) :: f2 ! end ! end interface +! interface operator(+) +! procedure :: f1 +! procedure :: f2 +! end interface !contains ! subroutine s1(x, y, z) ! type(t(k=4_4)) :: x diff --git a/flang/test/Semantics/modfile38.f90 b/flang/test/Semantics/modfile38.f90 index d2646b6ca6154..2631357c07597 100644 --- a/flang/test/Semantics/modfile38.f90 +++ b/flang/test/Semantics/modfile38.f90 @@ -20,14 +20,14 @@ type(t) function f !Expect: m.mod !module m -!interface t -!procedure::f -!end interface !type::t !end type !type::t2 !type(t)::c !end type +!interface t +!procedure::f +!end interface !contains !function f() !type(t)::f diff --git a/flang/test/Semantics/modfile39.f90 b/flang/test/Semantics/modfile39.f90 index fbbd6ae4ce299..f3b63da140014 100644 --- a/flang/test/Semantics/modfile39.f90 +++ b/flang/test/Semantics/modfile39.f90 @@ -15,10 +15,10 @@ pure integer function priv(n) end module !Expect: m1.mod !module m1 +!private::priv !interface gen !procedure::priv !end interface -!private::priv !contains !pure function priv(n) !integer(4),intent(in)::n diff --git a/flang/test/Semantics/modfile44.f90 b/flang/test/Semantics/modfile44.f90 index d0402b5678808..23d93b18a5a1f 100644 --- a/flang/test/Semantics/modfile44.f90 +++ b/flang/test/Semantics/modfile44.f90 @@ -19,12 +19,12 @@ function xzy(j) result(res) !Expect: m1.mod !module m1 -!interface xyz -!procedure::xzy -!end interface !type::xyz !integer(4)::n !end type +!interface xyz +!procedure::xzy +!end interface !contains !function xzy(j) result(res) !integer(4),intent(in)::j diff --git a/flang/test/Semantics/resolve15.f90 b/flang/test/Semantics/resolve15.f90 index 29fcf6f7ee153..a030d15323d41 100644 --- a/flang/test/Semantics/resolve15.f90 +++ b/flang/test/Semantics/resolve15.f90 @@ -4,7 +4,7 @@ module m interface i !ERROR: 'var' is not a procedure procedure :: sub, var - !ERROR: Procedure 'bad' not found + !ERROR: 'bad' is not a procedure procedure :: bad end interface interface operator(.foo.) @@ -12,7 +12,7 @@ module m procedure :: var !ERROR: OPERATOR(.foo.) procedure 'sub' must be a function procedure :: sub - !ERROR: Procedure 'bad' not found + !ERROR: 'bad' is not a procedure procedure :: bad end interface contains diff --git a/flang/test/Semantics/resolve25.f90 b/flang/test/Semantics/resolve25.f90 index 9e717d50cd9a6..9311fb34b4fae 100644 --- a/flang/test/Semantics/resolve25.f90 +++ b/flang/test/Semantics/resolve25.f90 @@ -6,7 +6,7 @@ real function s1(x) end !ERROR: 's2' is not a module procedure module procedure s2 - !ERROR: Procedure 's3' not found + !ERROR: 's3' is not a procedure procedure s3 !ERROR: Procedure 's1' is already specified in generic 'foo' procedure s1 diff --git a/flang/test/Semantics/resolve77.f90 b/flang/test/Semantics/resolve77.f90 index 1f5e4d4d80719..1a76e70090816 100644 --- a/flang/test/Semantics/resolve77.f90 +++ b/flang/test/Semantics/resolve77.f90 @@ -10,7 +10,7 @@ module m end interface !ERROR: Automatic data object 'a' may not appear in the specification part of a module real :: a(if1(1)) - !ERROR: No specific function of generic 'ifn2' matches the actual arguments + !ERROR: Automatic data object 'b' may not appear in the specification part of a module real :: b(ifn2(1)) contains subroutine t1(n)