Skip to content

Commit

Permalink
[flang] Fix bugs in .mod file for abstract interface
Browse files Browse the repository at this point in the history
When an abstract interface is defined, add the ABSTRACT attribute to
subprogram symbols that define the interface body. Make use of that
when writing .mod files to include "abstract" on the interface statement.

Also, fix a problem with the order of symbols in a .mod file. Sometimes
a name is mentioned before the "real" declaration, e.g. in an access
statement. We want the order to be based on the real definitions. In
these cases we replace the symbol name with an identical name with a
different source location. Then by sorting based on the source location
we get symbols in the right order.

Differential Revision: https://reviews.llvm.org/D93572
  • Loading branch information
tskeith committed Dec 28, 2020
1 parent 496fb70 commit d55627d
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 4 deletions.
11 changes: 10 additions & 1 deletion flang/lib/Semantics/mod-file.cpp
Expand Up @@ -319,6 +319,10 @@ void ModFileWriter::PutSubprogram(const Symbol &symbol) {
bindAttrs.set(Attr::BIND_C, true);
attrs.set(Attr::BIND_C, false);
}
bool isAbstract{attrs.test(Attr::ABSTRACT)};
if (isAbstract) {
attrs.set(Attr::ABSTRACT, false);
}
Attrs prefixAttrs{subprogramPrefixAttrs & attrs};
// emit any non-prefix attributes in an attribute statement
attrs &= ~subprogramPrefixAttrs;
Expand All @@ -331,7 +335,7 @@ void ModFileWriter::PutSubprogram(const Symbol &symbol) {
bool isInterface{details.isInterface()};
llvm::raw_ostream &os{isInterface ? decls_ : contains_};
if (isInterface) {
os << "interface\n";
os << (isAbstract ? "abstract " : "") << "interface\n";
}
PutAttrs(os, prefixAttrs, std::nullopt, ""s, " "s);
os << (details.isFunction() ? "function " : "subroutine ");
Expand Down Expand Up @@ -457,6 +461,11 @@ 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 x->name().begin() < y->name().begin();
});
sorted.insert(sorted.end(), namelist.begin(), namelist.end());
for (const auto &pair : scope.commonBlocks()) {
sorted.push_back(*pair.second);
Expand Down
5 changes: 4 additions & 1 deletion flang/lib/Semantics/resolve-names.cpp
Expand Up @@ -3085,11 +3085,14 @@ Symbol &SubprogramVisitor::PushSubprogramScope(
symbol = &MakeSymbol(name, SubprogramDetails{});
}
symbol->set(subpFlag);
symbol->ReplaceName(name.source);
PushScope(Scope::Kind::Subprogram, symbol);
auto &details{symbol->get<SubprogramDetails>()};
if (inInterfaceBlock()) {
details.set_isInterface();
if (!isAbstract()) {
if (isAbstract()) {
symbol->attrs().set(Attr::ABSTRACT);
} else {
MakeExternal(*symbol);
}
if (isGeneric()) {
Expand Down
37 changes: 37 additions & 0 deletions flang/test/Semantics/modfile10.f90
Expand Up @@ -90,3 +90,40 @@ subroutine test
! subroutine test()
! end
!end

! Ensure the type is emitted before its use
module m2
private s
type :: t
contains
procedure :: foo
end type
abstract interface
subroutine s(x)
import
type(t) :: x
end subroutine
end interface
contains
subroutine foo(x)
class(t) :: x
end subroutine
end module
!Expect: m2.mod
!module m2
! type::t
! contains
! procedure::foo
! end type
! private::s
! abstract interface
! subroutine s(x)
! import::t
! type(t)::x
! end
! end interface
!contains
! subroutine foo(x)
! class(t)::x
! end
!end
2 changes: 1 addition & 1 deletion flang/test/Semantics/procinterface01.f90
Expand Up @@ -5,7 +5,7 @@
!DEF: /module1 Module
module module1
abstract interface
!DEF: /module1/abstract1 PUBLIC (Function) Subprogram REAL(4)
!DEF: /module1/abstract1 ABSTRACT, PUBLIC (Function) Subprogram REAL(4)
!DEF: /module1/abstract1/x INTENT(IN) ObjectEntity REAL(4)
real function abstract1(x)
!REF: /module1/abstract1/x
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Semantics/symbol15.f90
Expand Up @@ -5,7 +5,7 @@
module m
implicit none
abstract interface
!DEF: /m/iface PUBLIC (Subroutine) Subprogram
!DEF: /m/iface ABSTRACT, PUBLIC (Subroutine) Subprogram
subroutine iface
end subroutine
end interface
Expand Down

0 comments on commit d55627d

Please sign in to comment.