[flang] Fix bug in .mod file for some subprogram attributes
authorTim Keith <tkeith@nvidia.com>
Tue, 20 Aug 2019 21:49:37 +0000 (14:49 -0700)
committerTim Keith <tkeith@nvidia.com>
Fri, 23 Aug 2019 14:14:55 +0000 (07:14 -0700)
Some attributes for subprograms can be in the subprogram prefix but
others cannot. For the latter, emit a separate attribute statement
to specify them. We were already doing that for PRIVATE but not for
OPTIONAL. Those may be the only two attributes this can apply to.

Fixes flang-compiler/f18#659.

Original-commit: flang-compiler/f18@ae67e087800c5aecb8cb2d2aea16d19b8cc8ccf2
Reviewed-on: https://github.com/flang-compiler/f18/pull/675
Tree-same-pre-rewrite: false

flang/lib/semantics/mod-file.cc
flang/test/semantics/modfile01.f90

index 7dffe82..7845b24 100644 (file)
@@ -274,6 +274,10 @@ void ModFileWriter::PutDerivedType(const Symbol &typeSymbol) {
   decls_ << "end type\n";
 }
 
+// Attributes that may be in a subprogram prefix
+static const Attrs subprogramPrefixAttrs{Attr::ELEMENTAL, Attr::IMPURE,
+    Attr::MODULE, Attr::NON_RECURSIVE, Attr::PURE, Attr::RECURSIVE};
+
 void ModFileWriter::PutSubprogram(const Symbol &symbol) {
   auto attrs{symbol.attrs()};
   auto &details{symbol.get<SubprogramDetails>()};
@@ -283,17 +287,22 @@ void ModFileWriter::PutSubprogram(const Symbol &symbol) {
     bindAttrs.set(Attr::BIND_C, true);
     attrs.set(Attr::BIND_C, false);
   }
-  if (attrs.test(Attr::PRIVATE)) {
-    PutAttr(decls_, Attr::PRIVATE) << "::";
+  Attrs prefixAttrs{subprogramPrefixAttrs};
+  prefixAttrs &= attrs;
+  // emit any non-prefix attributes in an attribute statement
+  attrs &= ~subprogramPrefixAttrs;
+  std::stringstream ss;
+  PutAttrs(ss, attrs);
+  if (!ss.str().empty()) {
+    decls_ << ss.str().substr(1) << "::";
     PutLower(decls_, symbol) << "\n";
-    attrs.set(Attr::PRIVATE, false);
   }
   bool isInterface{details.isInterface()};
   std::ostream &os{isInterface ? decls_ : contains_};
   if (isInterface) {
     os << "interface\n";
   }
-  PutAttrs(os, attrs, std::nullopt, ""s, " "s);
+  PutAttrs(os, prefixAttrs, std::nullopt, ""s, " "s);
   os << (details.isFunction() ? "function " : "subroutine ");
   PutLower(os, symbol) << '(';
   int n = 0;
index 8de9f1b..4b4be59 100644 (file)
@@ -80,3 +80,29 @@ end
 !  real(4)::f2
 ! end
 !end
+
+! Test optional dummy procedure
+module m4
+contains
+  subroutine s(f)
+    interface
+      logical recursive function f()
+        implicit none
+      end function
+    end interface
+    optional f
+  end
+end
+
+!Expect: m4.mod
+!module m4
+!contains
+! subroutine s(f)
+!  optional::f
+!  interface
+!   recursive function f()
+!    logical(4)::f
+!   end
+!  end interface
+! end
+!end