Skip to content

Commit 11d07d9

Browse files
authored
[flang] Handle separate module procedures with INTERFACE dummy arguments (#67608)
The code that duplicates the interface of a separate module procedure into its definition doesn't allow for a dummy procedure with an explicit INTERFACE declaration. Extend the code to handle this case. Fixes #66631.
1 parent 28a686a commit 11d07d9

File tree

2 files changed

+80
-16
lines changed

2 files changed

+80
-16
lines changed

flang/lib/Semantics/resolve-names-utils.cpp

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ class SymbolMapper : public evaluate::AnyTraverse<SymbolMapper, bool> {
779779
return false;
780780
}
781781
void MapSymbolExprs(Symbol &);
782+
Symbol *CopySymbol(const Symbol *);
782783

783784
private:
784785
void MapParamValue(ParamValue &param) const { (*this)(param.GetExplicit()); }
@@ -797,16 +798,44 @@ class SymbolMapper : public evaluate::AnyTraverse<SymbolMapper, bool> {
797798
SymbolAndTypeMappings &map_;
798799
};
799800

800-
void SymbolMapper::MapSymbolExprs(Symbol &symbol) {
801-
if (auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
802-
if (const DeclTypeSpec *type{object->type()}) {
803-
if (const DeclTypeSpec *newType{MapType(*type)}) {
804-
object->ReplaceType(*newType);
801+
Symbol *SymbolMapper::CopySymbol(const Symbol *symbol) {
802+
if (symbol) {
803+
if (auto *subp{symbol->detailsIf<SubprogramDetails>()}) {
804+
if (subp->isInterface()) {
805+
if (auto pair{scope_.try_emplace(symbol->name(), symbol->attrs())};
806+
pair.second) {
807+
Symbol &copy{*pair.first->second};
808+
map_.symbolMap[symbol] = &copy;
809+
copy.set(symbol->test(Symbol::Flag::Subroutine)
810+
? Symbol::Flag::Subroutine
811+
: Symbol::Flag::Function);
812+
Scope &newScope{scope_.MakeScope(Scope::Kind::Subprogram, &copy)};
813+
copy.set_scope(&newScope);
814+
copy.set_details(SubprogramDetails{});
815+
auto &newSubp{copy.get<SubprogramDetails>()};
816+
newSubp.set_isInterface(true);
817+
newSubp.set_isDummy(subp->isDummy());
818+
newSubp.set_defaultIgnoreTKR(subp->defaultIgnoreTKR());
819+
MapSubprogramToNewSymbols(*symbol, copy, newScope, &map_);
820+
return &copy;
821+
}
805822
}
823+
} else if (Symbol * copy{scope_.CopySymbol(*symbol)}) {
824+
map_.symbolMap[symbol] = copy;
825+
return copy;
806826
}
807827
}
828+
return nullptr;
829+
}
830+
831+
void SymbolMapper::MapSymbolExprs(Symbol &symbol) {
808832
common::visit(
809833
common::visitors{[&](ObjectEntityDetails &object) {
834+
if (const DeclTypeSpec * type{object.type()}) {
835+
if (const DeclTypeSpec * newType{MapType(*type)}) {
836+
object.ReplaceType(*newType);
837+
}
838+
}
810839
for (ShapeSpec &spec : object.shape()) {
811840
MapShapeSpec(spec);
812841
}
@@ -892,13 +921,7 @@ const Symbol *SymbolMapper::MapInterface(const Symbol *interface) {
892921
return interface;
893922
} else if (const auto *subp{interface->detailsIf<SubprogramDetails>()};
894923
subp && subp->isInterface()) {
895-
if (Symbol *newSymbol{scope_.CopySymbol(*interface)}) {
896-
newSymbol->get<SubprogramDetails>().set_isInterface(true);
897-
map_.symbolMap[interface] = newSymbol;
898-
Scope &newScope{scope_.MakeScope(Scope::Kind::Subprogram, newSymbol)};
899-
MapSubprogramToNewSymbols(*interface, *newSymbol, newScope, &map_);
900-
return newSymbol;
901-
}
924+
return CopySymbol(interface);
902925
}
903926
}
904927
return nullptr;
@@ -913,23 +936,24 @@ void MapSubprogramToNewSymbols(const Symbol &oldSymbol, Symbol &newSymbol,
913936
mappings->symbolMap[&oldSymbol] = &newSymbol;
914937
const auto &oldDetails{oldSymbol.get<SubprogramDetails>()};
915938
auto &newDetails{newSymbol.get<SubprogramDetails>()};
939+
SymbolMapper mapper{newScope, *mappings};
916940
for (const Symbol *dummyArg : oldDetails.dummyArgs()) {
917941
if (!dummyArg) {
918942
newDetails.add_alternateReturn();
919-
} else if (Symbol *copy{newScope.CopySymbol(*dummyArg)}) {
943+
} else if (Symbol * copy{mapper.CopySymbol(dummyArg)}) {
920944
copy->set(Symbol::Flag::Implicit, false);
921945
newDetails.add_dummyArg(*copy);
922946
mappings->symbolMap[dummyArg] = copy;
923947
}
924948
}
925949
if (oldDetails.isFunction()) {
926950
newScope.erase(newSymbol.name());
927-
if (Symbol *copy{newScope.CopySymbol(oldDetails.result())}) {
951+
const Symbol &result{oldDetails.result()};
952+
if (Symbol * copy{mapper.CopySymbol(&result)}) {
928953
newDetails.set_result(*copy);
929-
mappings->symbolMap[&oldDetails.result()] = copy;
954+
mappings->symbolMap[&result] = copy;
930955
}
931956
}
932-
SymbolMapper mapper{newScope, *mappings};
933957
for (auto &[_, ref] : newScope) {
934958
mapper.MapSymbolExprs(*ref);
935959
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
! RUN: %python %S/test_symbols.py %s %flang_fc1
2+
! Ensure that SMPs work with dummy procedures declared as interfaces
3+
!DEF: /m Module
4+
module m
5+
implicit none
6+
interface
7+
!DEF: /m/smp MODULE, PUBLIC, PURE (Function) Subprogram REAL(4)
8+
!DEF: /m/smp/f EXTERNAL, PURE (Function) Subprogram REAL(4)
9+
!DEF: /m/smp/x INTENT(IN) ObjectEntity REAL(4)
10+
!DEF: /m/smp/res (Implicit) ObjectEntity REAL(4)
11+
pure module function smp(f, x) result(res)
12+
interface
13+
!REF: /m/smp/f
14+
!DEF: /m/smp/f/x INTENT(IN) ObjectEntity REAL(4)
15+
!DEF: /m/smp/f/r ObjectEntity REAL(4)
16+
pure function f(x) result(r)
17+
!REF: /m/smp/f/x
18+
real, intent(in) :: x
19+
!REF: /m/smp/f/r
20+
real r
21+
end function
22+
end interface
23+
!REF: /m/smp/x
24+
real, intent(in) :: x
25+
end function
26+
end interface
27+
end module
28+
!REF: /m
29+
!DEF: /m/sm Module
30+
submodule (m)sm
31+
implicit none
32+
contains
33+
!DEF: /m/sm/smp MODULE, PUBLIC, PURE (Function) Subprogram REAL(4)
34+
module procedure smp
35+
!DEF: /m/sm/smp/res (Implicit) ObjectEntity REAL(4)
36+
!DEF: /m/sm/smp/f EXTERNAL, PURE (Function) Subprogram REAL(4)
37+
!DEF: /m/sm/smp/x INTENT(IN) ObjectEntity REAL(4)
38+
res = f(x)
39+
end procedure
40+
end submodule

0 commit comments

Comments
 (0)