[flang-commits] [flang] f45b413 - [flang] Defer stmt function body analysis until specification part complete

peter klausler via flang-commits flang-commits at lists.llvm.org
Mon Jun 29 12:33:55 PDT 2020


Author: peter klausler
Date: 2020-06-29T12:32:19-07:00
New Revision: f45b41348ba49c4a76baab1e3e302ef8e2bb992b

URL: https://github.com/llvm/llvm-project/commit/f45b41348ba49c4a76baab1e3e302ef8e2bb992b
DIFF: https://github.com/llvm/llvm-project/commit/f45b41348ba49c4a76baab1e3e302ef8e2bb992b.diff

LOG: [flang] Defer stmt function body analysis until specification part complete

Expression analysis was being invoked on the bodies of statement functions
as they were being encountered during name resolution.  This led to failures
on some FCVS tests in cases where those expressions contained implicitly
typed objects.  Defer the analysis of statemet function bodies to the end
of the specification part, at which time the symbols of the enclosing scope
will have been typed.

Reviewed By: tskeith

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

Added: 
    

Modified: 
    flang/lib/Semantics/resolve-names.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 2b257fce9fd6..277f5f77d1b3 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1436,7 +1436,7 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
 
   void PreSpecificationConstruct(const parser::SpecificationConstruct &);
   void CreateGeneric(const parser::GenericSpec &);
-  void FinishSpecificationPart();
+  void FinishSpecificationPart(const std::list<parser::DeclarationConstruct> &);
   void CheckImports();
   void CheckImport(const SourceName &, const SourceName &);
   void HandleCall(Symbol::Flag, const parser::Call &);
@@ -2714,11 +2714,9 @@ bool SubprogramVisitor::HandleStmtFunction(const parser::StmtFunctionStmt &x) {
   details.set_result(result);
   const auto &parsedExpr{std::get<parser::Scalar<parser::Expr>>(x.t)};
   Walk(parsedExpr);
-  if (auto expr{AnalyzeExpr(context(), parsedExpr)}) {
-    details.set_stmtFunction(std::move(*expr));
-  } else {
-    context().SetError(symbol);
-  }
+  // The analysis of the expression that constitutes the body of the
+  // statement function is deferred to FinishSpecificationPart() so that
+  // all declarations and implicit typing are complete.
   PopScope();
   return true;
 }
@@ -6011,7 +6009,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
     }
   }
   Walk(decls);
-  FinishSpecificationPart();
+  FinishSpecificationPart(decls);
   return false;
 }
 
@@ -6068,7 +6066,8 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) {
   info.Resolve(&MakeSymbol(symbolName, Attrs{}, std::move(genericDetails)));
 }
 
-void ResolveNamesVisitor::FinishSpecificationPart() {
+void ResolveNamesVisitor::FinishSpecificationPart(
+    const std::list<parser::DeclarationConstruct> &decls) {
   badStmtFuncFound_ = false;
   CheckImports();
   bool inModule{currScope().kind() == Scope::Kind::Module};
@@ -6089,6 +6088,25 @@ 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);
+          }
+        }
+      }
+    }
+  }
   // TODO: what about instantiations in BLOCK?
   CheckSaveStmts();
   CheckCommonBlocks();
@@ -6278,8 +6296,8 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
       node.stmt());
   Walk(node.spec());
   // If this is a function, convert result to an object. This is to prevent the
-  // result to be converted later to a function symbol if it is called inside
-  // the function.
+  // result from being converted later to a function symbol if it is called
+  // inside the function.
   // If the result is function pointer, then ConvertToObjectEntity will not
   // convert the result to an object, and calling the symbol inside the function
   // will result in calls to the result pointer.


        


More information about the flang-commits mailing list