[flang-commits] [flang] 8c407f4 - [flang] Allow ENTRY function result symbol usage before the ENTRY

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon May 9 19:12:33 PDT 2022


Author: Peter Klausler
Date: 2022-05-09T19:12:23-07:00
New Revision: 8c407f4a1121ac3eaf46ca6e92f0976c196ce35b

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

LOG: [flang] Allow ENTRY function result symbol usage before the ENTRY

In a function, ENTRY E without an explicit RESULT() creates a
function result entity also named E that is storage associated with
the enclosing function's result.  f18 was emitting an incorrect error
message if that function result E was referenced without any
declaration prior to its ENTRY statement when it should have been
implicitly declared instead.

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

Added: 
    

Modified: 
    flang/lib/Semantics/resolve-names.cpp
    flang/test/Semantics/entry01.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 114b64508c76..062c016cc738 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -821,7 +821,8 @@ class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {
 
   bool BeginSubprogram(const parser::Name &, Symbol::Flag,
       bool hasModulePrefix = false,
-      const parser::LanguageBindingSpec * = nullptr);
+      const parser::LanguageBindingSpec * = nullptr,
+      const ProgramTree::EntryStmtList * = nullptr);
   bool BeginMpSubprogram(const parser::Name &);
   void PushBlockDataScope(const parser::Name &);
   void EndSubprogram();
@@ -3373,12 +3374,16 @@ void SubprogramVisitor::PostEntryStmt(const parser::EntryStmt &stmt) {
   entryDetails.set_entryScope(inclusiveScope);
   if (inFunction) {
     // Create the entity to hold the function result, if necessary.
-    Symbol *resultSymbol{nullptr};
     auto &effectiveResultName{*(resultName ? resultName : &name)};
-    resultSymbol = FindInScope(currScope(), effectiveResultName);
+    Symbol *resultSymbol{FindInScope(currScope(), effectiveResultName)};
     if (resultSymbol) { // C1574
       common::visit(
-          common::visitors{[](EntityDetails &x) { x.set_funcResult(true); },
+          common::visitors{[resultSymbol](UnknownDetails &) {
+                             EntityDetails entity;
+                             entity.set_funcResult(true);
+                             resultSymbol->set_details(std::move(entity));
+                           },
+              [](EntityDetails &x) { x.set_funcResult(true); },
               [](ObjectEntityDetails &x) { x.set_funcResult(true); },
               [](ProcEntityDetails &x) { x.set_funcResult(true); },
               [&](const auto &) {
@@ -3388,6 +3393,11 @@ void SubprogramVisitor::PostEntryStmt(const parser::EntryStmt &stmt) {
                 context().SetError(*resultSymbol);
               }},
           resultSymbol->details());
+      // The Function flag will have been set if the ENTRY's symbol was created
+      // as a placeholder in BeginSubprogram.  This prevents misuse of the ENTRY
+      // as a subroutine.  Clear it now because it's inappropriate for a
+      // function result.
+      resultSymbol->set(Symbol::Flag::Function, false);
     } else if (!inSpecificationPart_) {
       ObjectEntityDetails entity;
       entity.set_funcResult(true);
@@ -3509,7 +3519,8 @@ bool SubprogramVisitor::BeginMpSubprogram(const parser::Name &name) {
 // A subprogram or interface declared with SUBROUTINE or FUNCTION
 bool SubprogramVisitor::BeginSubprogram(const parser::Name &name,
     Symbol::Flag subpFlag, bool hasModulePrefix,
-    const parser::LanguageBindingSpec *bindingSpec) {
+    const parser::LanguageBindingSpec *bindingSpec,
+    const ProgramTree::EntryStmtList *entryStmts) {
   if (hasModulePrefix && currScope().IsGlobal()) { // C1547
     Say(name,
         "'%s' is a MODULE procedure which must be declared within a "
@@ -3546,6 +3557,21 @@ bool SubprogramVisitor::BeginSubprogram(const parser::Name &name,
   }
   if (IsFunction(currScope())) {
     funcResultStack().Push();
+    if (entryStmts) {
+      // It's possible to refer to the function result variable of an ENTRY
+      // statement that lacks an explicit RESULT in code that appears before the
+      // ENTRY. Create a placeholder symbol now for that case so that the name
+      // doesn't resolve instead to the ENTRY's symbol in the scope around the
+      // function.
+      for (const auto &ref : *entryStmts) {
+        const auto &suffix{std::get<std::optional<parser::Suffix>>(ref->t)};
+        if (!(suffix && suffix->resultName)) {
+          Symbol &symbol{MakeSymbol(std::get<parser::Name>(ref->t).source,
+              Attrs{}, UnknownDetails{})};
+          symbol.set(Symbol::Flag::Function);
+        }
+      }
+    }
   }
   return true;
 }
@@ -7364,7 +7390,7 @@ bool ResolveNamesVisitor::BeginScopeForNode(const ProgramTree &node) {
   case ProgramTree::Kind::Function:
   case ProgramTree::Kind::Subroutine:
     return BeginSubprogram(node.name(), node.GetSubpFlag(),
-        node.HasModulePrefix(), node.bindingSpec());
+        node.HasModulePrefix(), node.bindingSpec(), &node.entryStmts());
   case ProgramTree::Kind::MpSubprogram:
     return BeginMpSubprogram(node.name());
   case ProgramTree::Kind::Module:

diff  --git a/flang/test/Semantics/entry01.f90 b/flang/test/Semantics/entry01.f90
index 2a95d6cc5906..44065e36100d 100644
--- a/flang/test/Semantics/entry01.f90
+++ b/flang/test/Semantics/entry01.f90
@@ -108,8 +108,8 @@ function ifunc()
   entry ibadt4() result(alloc)
   !ERROR: Result of ENTRY is not compatible with result of containing function
   entry ibadt5() result(ptr)
+  !ERROR: Cannot call function 'isubr' like a subroutine
   call isubr
-  !ERROR: 'isubr' was previously called as a subroutine
   entry isubr()
   continue ! force transition to execution part
   entry implicit()
@@ -204,3 +204,11 @@ function inone
   !ERROR: No explicit type declared for 'implicitbad2'
   entry implicitbad2
 end
+
+module m5
+ contains
+  real function setBefore
+    ent = 1.0
+    entry ent
+  end function
+end module


        


More information about the flang-commits mailing list