[flang-commits] [flang] e162dc6 - [flang] Fix symbol table bugs with ENTRY statements

peter klausler via flang-commits flang-commits at lists.llvm.org
Fri May 21 17:45:48 PDT 2021


Author: peter klausler
Date: 2021-05-21T17:45:37-07:00
New Revision: e162dc6f281e817e6dd000be71bfaf6bad358d79

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

LOG: [flang] Fix symbol table bugs with ENTRY statements

Dummy arguments of ENTRY statements in execution parts were
not being created as objects, nor were they being implicitly
typed.

When the symbol corresponding to an alternate ENTRY point
already exists (by that name) due to having been referenced
in an earlier call, name resolution used to delete the extant
symbol.  This isn't the right thing to do -- the extant
symbol will be pointed to by parser::Name nodes in the parse
tree while no longer being part of any Scope.

Differential Review: https://reviews.llvm.org/D102948

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 0aca2cddb953f..2820ab62922e8 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -746,6 +746,9 @@ class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {
     std::optional<SourceName> source;
   } funcInfo_;
 
+  // Edits an existing symbol created for earlier calls to a subprogram or ENTRY
+  // so that it can be replaced by a later definition.
+  bool HandlePreviousCalls(const parser::Name &, Symbol &, Symbol::Flag);
   // Create a subprogram symbol in the current scope and push a new scope.
   void CheckExtantProc(const parser::Name &, Symbol::Flag);
   Symbol &PushSubprogramScope(const parser::Name &, Symbol::Flag);
@@ -3079,8 +3082,11 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
                       dummy->name(), "Previous declaration of '%s'"_en_US);
                 }},
             dummy->details());
+      } else if (inExecutionPart_) {
+        dummy = &MakeSymbol(*dummyName, ObjectEntityDetails{true});
+        ApplyImplicitRules(*dummy);
       } else {
-        dummy = &MakeSymbol(*dummyName, EntityDetails(true));
+        dummy = &MakeSymbol(*dummyName, EntityDetails{true});
       }
       entryDetails.add_dummyArg(*dummy);
     } else {
@@ -3096,20 +3102,11 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
   Symbol::Flag subpFlag{
       inFunction ? Symbol::Flag::Function : Symbol::Flag::Subroutine};
   Scope &outer{inclusiveScope.parent()}; // global or module scope
+  if (outer.IsModule() && !attrs.test(Attr::PRIVATE)) {
+    attrs.set(Attr::PUBLIC);
+  }
   if (Symbol * extant{FindSymbol(outer, name)}) {
-    if (extant->has<ProcEntityDetails>()) {
-      if (!extant->test(subpFlag)) {
-        Say2(name,
-            subpFlag == Symbol::Flag::Function
-                ? "'%s' was previously called as a subroutine"_err_en_US
-                : "'%s' was previously called as a function"_err_en_US,
-            *extant, "Previous call of '%s'"_en_US);
-      }
-      if (extant->attrs().test(Attr::PRIVATE)) {
-        attrs.set(Attr::PRIVATE);
-      }
-      outer.erase(extant->name());
-    } else {
+    if (!HandlePreviousCalls(name, *extant, subpFlag)) {
       if (outer.IsGlobal()) {
         Say2(name, "'%s' is already defined as a global identifier"_err_en_US,
             *extant, "Previous definition of '%s'"_en_US);
@@ -3119,14 +3116,8 @@ void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
       return;
     }
   }
-  if (outer.IsModule() && !attrs.test(Attr::PRIVATE)) {
-    attrs.set(Attr::PUBLIC);
-  }
   Symbol &entrySymbol{MakeSymbol(outer, name.source, attrs)};
   entrySymbol.set_details(std::move(entryDetails));
-  if (outer.IsGlobal()) {
-    MakeExternal(entrySymbol);
-  }
   SetBindNameOn(entrySymbol);
   entrySymbol.set(subpFlag);
   Resolve(name, entrySymbol);
@@ -3186,24 +3177,37 @@ bool SubprogramVisitor::BeginSubprogram(
 
 void SubprogramVisitor::EndSubprogram() { PopScope(); }
 
+bool SubprogramVisitor::HandlePreviousCalls(
+    const parser::Name &name, Symbol &symbol, Symbol::Flag subpFlag) {
+  if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}; proc &&
+      !proc->isDummy() &&
+      !symbol.attrs().HasAny(Attrs{Attr::INTRINSIC, Attr::POINTER})) {
+    // There's a symbol created for previous calls to this subprogram or
+    // ENTRY's name.  We have to replace that symbol in situ to avoid the
+    // obligation to rewrite symbol pointers in the parse tree.
+    if (!symbol.test(subpFlag)) {
+      Say2(name,
+          subpFlag == Symbol::Flag::Function
+              ? "'%s' was previously called as a subroutine"_err_en_US
+              : "'%s' was previously called as a function"_err_en_US,
+          symbol, "Previous call of '%s'"_en_US);
+    }
+    EntityDetails entity;
+    if (proc->type()) {
+      entity.set_type(*proc->type());
+    }
+    symbol.details() = std::move(entity);
+    return true;
+  } else {
+    return symbol.has<UnknownDetails>() || symbol.has<SubprogramNameDetails>();
+  }
+}
+
 void SubprogramVisitor::CheckExtantProc(
     const parser::Name &name, Symbol::Flag subpFlag) {
   if (auto *prev{FindSymbol(name)}) {
-    if (prev->attrs().test(Attr::EXTERNAL) && prev->has<ProcEntityDetails>()) {
-      // this subprogram was previously called, now being declared
-      if (!prev->test(subpFlag)) {
-        Say2(name,
-            subpFlag == Symbol::Flag::Function
-                ? "'%s' was previously called as a subroutine"_err_en_US
-                : "'%s' was previously called as a function"_err_en_US,
-            *prev, "Previous call of '%s'"_en_US);
-      }
-      EraseSymbol(name);
-    } else if (const auto *details{prev->detailsIf<EntityDetails>()}) {
-      if (!details->isDummy()) {
-        Say2(name, "Procedure '%s' was previously declared"_err_en_US, *prev,
-            "Previous declaration of '%s'"_en_US);
-      }
+    if (!IsDummy(*prev) && !HandlePreviousCalls(name, *prev, subpFlag)) {
+      SayAlreadyDeclared(name, *prev);
     }
   }
 }

diff  --git a/flang/test/Semantics/resolve18.f90 b/flang/test/Semantics/resolve18.f90
index 45980361ae566..76632b9d53596 100644
--- a/flang/test/Semantics/resolve18.f90
+++ b/flang/test/Semantics/resolve18.f90
@@ -98,7 +98,7 @@ subroutine s5
 module m6
   real :: f6
   interface g6
-  !ERROR: Procedure 'f6' was previously declared
+  !ERROR: 'f6' is already declared in this scoping unit
     real function f6()
     end function f6
   end interface g6
@@ -107,7 +107,7 @@ end module m6
 module m7
   integer :: f7
   interface g7
-    !ERROR: Procedure 'f7' was previously declared
+    !ERROR: 'f7' is already declared in this scoping unit
     real function f7()
     end function f7
   end interface g7
@@ -116,7 +116,7 @@ end module m7
 module m8
   real :: f8
   interface g8
-    !ERROR: Procedure 'f8' was previously declared
+    !ERROR: 'f8' is already declared in this scoping unit
     subroutine f8()
     end subroutine f8
   end interface g8


        


More information about the flang-commits mailing list