[flang] Implicitly convert result of statement function
authorTim Keith <tkeith@nvidia.com>
Fri, 24 Jul 2020 00:15:33 +0000 (17:15 -0700)
committerTim Keith <tkeith@nvidia.com>
Fri, 24 Jul 2020 00:15:35 +0000 (17:15 -0700)
The result of a statement function may require an implicit conversion
to match its result type. Add that to the expression that represents
the statement function body in SubprogramDetails.

Extract the analysis of that expression into a separate function.

Dump the statement function expression as part of the dump of
SubprogramDetails.

Differential Revision: https://reviews.llvm.org/D84452

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

index 73d111ca3c0932432d3eb6c9f0bf11ad7e3f69dd..7189b48482654ac527427968d23220605d92209f 100644 (file)
@@ -1438,6 +1438,7 @@ private:
   void PreSpecificationConstruct(const parser::SpecificationConstruct &);
   void CreateGeneric(const parser::GenericSpec &);
   void FinishSpecificationPart(const std::list<parser::DeclarationConstruct> &);
+  void AnalyzeStmtFunctionStmt(const parser::StmtFunctionStmt &);
   void CheckImports();
   void CheckImport(const SourceName &, const SourceName &);
   void HandleCall(Symbol::Flag, const parser::Call &);
@@ -6101,23 +6102,11 @@ void ResolveNamesVisitor::FinishSpecificationPart(
     }
   }
   currScope().InstantiateDerivedTypes(context());
-  // Analyze the bodies of statement functions now that the symbol in this
-  // specification part have been fully declared and implicitly typed.
   for (const auto &decl : decls) {
     if (const auto *statement{std::get_if<
             parser::Statement<common::Indirection<parser::StmtFunctionStmt>>>(
             &decl.u)}) {
-      const parser::StmtFunctionStmt &stmtFunc{statement->statement.value()};
-      if (Symbol * symbol{std::get<parser::Name>(stmtFunc.t).symbol}) {
-        if (auto *details{symbol->detailsIf<SubprogramDetails>()}) {
-          if (auto expr{AnalyzeExpr(context(),
-                  std::get<parser::Scalar<parser::Expr>>(stmtFunc.t))}) {
-            details->set_stmtFunction(std::move(*expr));
-          } else {
-            context().SetError(*symbol);
-          }
-        }
-      }
+      AnalyzeStmtFunctionStmt(statement->statement.value());
     }
   }
   // TODO: what about instantiations in BLOCK?
@@ -6126,6 +6115,33 @@ void ResolveNamesVisitor::FinishSpecificationPart(
   CheckEquivalenceSets();
 }
 
+// Analyze the bodies of statement functions now that the symbols in this
+// specification part have been fully declared and implicitly typed.
+void ResolveNamesVisitor::AnalyzeStmtFunctionStmt(
+    const parser::StmtFunctionStmt &stmtFunc) {
+  Symbol *symbol{std::get<parser::Name>(stmtFunc.t).symbol};
+  if (!symbol || !symbol->has<SubprogramDetails>()) {
+    return;
+  }
+  auto &details{symbol->get<SubprogramDetails>()};
+  auto expr{AnalyzeExpr(
+      context(), std::get<parser::Scalar<parser::Expr>>(stmtFunc.t))};
+  if (!expr) {
+    context().SetError(*symbol);
+    return;
+  }
+  if (auto type{evaluate::DynamicType::From(*symbol)}) {
+    auto converted{ConvertToType(*type, std::move(*expr))};
+    if (!converted) {
+      context().SetError(*symbol);
+      return;
+    }
+    details.set_stmtFunction(std::move(*converted));
+  } else {
+    details.set_stmtFunction(std::move(*expr));
+  }
+}
+
 void ResolveNamesVisitor::CheckImports() {
   auto &scope{currScope()};
   switch (scope.GetImportKind()) {
index a7e2696518ffe08250adcf177c4d7b930d2d0af7..e0d80ec6d1c8b4cd0201f97a356807bf7ae9ea40 100644 (file)
@@ -111,6 +111,9 @@ llvm::raw_ostream &operator<<(
     }
   }
   os << (sep == '(' ? "()" : ")");
+  if (x.stmtFunction_) {
+    os << " -> " << x.stmtFunction_->AsFortran();
+  }
   return os;
 }