Author: Tim Keith Date: 2020-12-28T08:50:32-08:00 New Revision: d55627d221be8154cbdf454fa727afcc3f716b08
URL: https://github.com/llvm/llvm-project/commit/d55627d221be8154cbdf454fa727afcc3f716b08 DIFF: https://github.com/llvm/llvm-project/commit/d55627d221be8154cbdf454fa727afcc3f716b08.diff LOG: [flang] Fix bugs in .mod file for abstract interface 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 Added: Modified: flang/lib/Semantics/mod-file.cpp flang/lib/Semantics/resolve-names.cpp flang/test/Semantics/modfile10.f90 flang/test/Semantics/procinterface01.f90 flang/test/Semantics/symbol15.f90 Removed: ################################################################################ diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 99ea65b753a6..f8e5889e4698 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -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; @@ -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 "); @@ -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); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 8d5284131cc0..73c624aefa22 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -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()) { diff --git a/flang/test/Semantics/modfile10.f90 b/flang/test/Semantics/modfile10.f90 index ef10f1f23e8e..996178f5896d 100644 --- a/flang/test/Semantics/modfile10.f90 +++ b/flang/test/Semantics/modfile10.f90 @@ -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 diff --git a/flang/test/Semantics/procinterface01.f90 b/flang/test/Semantics/procinterface01.f90 index a960922d5637..dd9fd3b66041 100644 --- a/flang/test/Semantics/procinterface01.f90 +++ b/flang/test/Semantics/procinterface01.f90 @@ -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 diff --git a/flang/test/Semantics/symbol15.f90 b/flang/test/Semantics/symbol15.f90 index ddd3772252dc..cc230ff1fc03 100644 --- a/flang/test/Semantics/symbol15.f90 +++ b/flang/test/Semantics/symbol15.f90 @@ -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 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits