[flang-commits] [flang] 4c9d549 - [flang] Special handling of ENTRY BIND(C, NAME=...)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Sep 23 11:17:41 PDT 2022


Author: Peter Klausler
Date: 2022-09-23T11:01:17-07:00
New Revision: 4c9d54982c85afde04e93b4f4d3ff648e48331db

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

LOG: [flang] Special handling of ENTRY BIND(C,NAME=...)

We apply special symbol table scoping to top-level subroutine
and function names that have interoperable binding names, so
that it's possible to define the same subroutine/function name
more than once at the top level so long as their binding names
are distinct.  But we don't use those scoping techniques for
ENTRY statement symbols with interoperable binding names,
which can lead to bogus semantic errors when the same ENTRY
name is defined multiple times with distinct binding names.

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

Added: 
    flang/test/Semantics/symbol24.f90

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 01f06a752a2d..f4430d97a000 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -831,7 +831,8 @@ class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {
   bool BeginMpSubprogram(const parser::Name &);
   void PushBlockDataScope(const parser::Name &);
   void EndSubprogram(std::optional<parser::CharBlock> stmtSource = std::nullopt,
-      const std::optional<parser::LanguageBindingSpec> * = nullptr);
+      const std::optional<parser::LanguageBindingSpec> * = nullptr,
+      const ProgramTree::EntryStmtList * = nullptr);
 
 protected:
   // Set when we see a stmt function that is really an array element assignment
@@ -849,6 +850,9 @@ class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {
   SubprogramDetails &PostSubprogramStmt(const parser::Name &);
   void CreateEntry(const parser::EntryStmt &stmt, Symbol &subprogram);
   void PostEntryStmt(const parser::EntryStmt &stmt);
+  void HandleLanguageBinding(Symbol *,
+      std::optional<parser::CharBlock> stmtSource,
+      const std::optional<parser::LanguageBindingSpec> *);
 };
 
 class DeclarationVisitor : public ArraySpecVisitor,
@@ -3457,20 +3461,24 @@ void SubprogramVisitor::CreateEntry(
           ? Symbol::Flag::Function
           : Symbol::Flag::Subroutine};
   Attrs attrs;
-  if (Symbol * extant{FindSymbol(outer, entryName)}) {
-    if (!HandlePreviousCalls(entryName, *extant, subpFlag)) {
-      if (outer.IsTopLevel()) {
-        Say2(entryName,
-            "'%s' is already defined as a global identifier"_err_en_US, *extant,
-            "Previous definition of '%s'"_en_US);
-      } else {
-        SayAlreadyDeclared(entryName, *extant);
+  const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)};
+  bool hasGlobalBindingName{outer.IsGlobal() && suffix && suffix->binding &&
+      suffix->binding->v.has_value()};
+  if (!hasGlobalBindingName) {
+    if (Symbol * extant{FindSymbol(outer, entryName)}) {
+      if (!HandlePreviousCalls(entryName, *extant, subpFlag)) {
+        if (outer.IsTopLevel()) {
+          Say2(entryName,
+              "'%s' is already defined as a global identifier"_err_en_US,
+              *extant, "Previous definition of '%s'"_en_US);
+        } else {
+          SayAlreadyDeclared(entryName, *extant);
+        }
+        return;
       }
-      return;
+      attrs = extant->attrs();
     }
-    attrs = extant->attrs();
   }
-  const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)};
   bool badResultName{false};
   std::optional<SourceName> distinctResultName;
   if (suffix && suffix->resultName &&
@@ -3496,17 +3504,27 @@ void SubprogramVisitor::CreateEntry(
   if (outer.IsModule() && !attrs.test(Attr::PRIVATE)) {
     attrs.set(Attr::PUBLIC);
   }
-  Symbol *entrySymbol{FindInScope(outer, entryName.source)};
-  if (entrySymbol) {
-    if (auto *generic{entrySymbol->detailsIf<GenericDetails>()}) {
-      if (auto *specific{generic->specific()}) {
-        // Forward reference to ENTRY from a generic interface
-        entrySymbol = specific;
-        entrySymbol->attrs() |= attrs;
+  Symbol *entrySymbol{nullptr};
+  if (hasGlobalBindingName) {
+    // Hide the entry's symbol in a new anonymous global scope so
+    // that its name doesn't clash with anything.
+    Symbol &symbol{MakeSymbol(outer, context().GetTempName(outer), Attrs{})};
+    symbol.set_details(MiscDetails{MiscDetails::Kind::ScopeName});
+    Scope &hidden{outer.MakeScope(Scope::Kind::Global, &symbol)};
+    entrySymbol = &MakeSymbol(hidden, entryName.source, attrs);
+  } else {
+    entrySymbol = FindInScope(outer, entryName.source);
+    if (entrySymbol) {
+      if (auto *generic{entrySymbol->detailsIf<GenericDetails>()}) {
+        if (auto *specific{generic->specific()}) {
+          // Forward reference to ENTRY from a generic interface
+          entrySymbol = specific;
+          entrySymbol->attrs() |= attrs;
+        }
       }
+    } else {
+      entrySymbol = &MakeSymbol(outer, entryName.source, attrs);
     }
-  } else {
-    entrySymbol = &MakeSymbol(outer, entryName.source, attrs);
   }
   SubprogramDetails entryDetails;
   entryDetails.set_entryScope(currScope());
@@ -3696,21 +3714,38 @@ bool SubprogramVisitor::BeginSubprogram(const parser::Name &name,
   return true;
 }
 
-void SubprogramVisitor::EndSubprogram(
+void SubprogramVisitor::HandleLanguageBinding(Symbol *symbol,
     std::optional<parser::CharBlock> stmtSource,
     const std::optional<parser::LanguageBindingSpec> *binding) {
-  if (binding && *binding && currScope().symbol()) {
+  if (binding && *binding && symbol) {
     // Finally process the BIND(C,NAME=name) now that symbols in the name
-    // expression will resolve local names.
+    // expression will resolve to local names if needed.
     auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};
     auto originalStmtSource{messageHandler().currStmtSource()};
     messageHandler().set_currStmtSource(stmtSource);
     BeginAttrs();
     Walk(**binding);
-    SetBindNameOn(*currScope().symbol());
-    currScope().symbol()->attrs() |= EndAttrs();
+    SetBindNameOn(*symbol);
+    symbol->attrs() |= EndAttrs();
     messageHandler().set_currStmtSource(originalStmtSource);
   }
+}
+
+void SubprogramVisitor::EndSubprogram(
+    std::optional<parser::CharBlock> stmtSource,
+    const std::optional<parser::LanguageBindingSpec> *binding,
+    const ProgramTree::EntryStmtList *entryStmts) {
+  HandleLanguageBinding(currScope().symbol(), stmtSource, binding);
+  if (entryStmts) {
+    for (const auto &ref : *entryStmts) {
+      const parser::EntryStmt &entryStmt{*ref};
+      if (const auto &suffix{
+              std::get<std::optional<parser::Suffix>>(entryStmt.t)}) {
+        const auto &name{std::get<parser::Name>(entryStmt.t)};
+        HandleLanguageBinding(name.symbol, name.source, &suffix->binding);
+      }
+    }
+  }
   PopScope();
 }
 
@@ -7607,7 +7642,7 @@ void ResolveNamesVisitor::EndScopeForNode(const ProgramTree &node) {
           [](const auto *) {},
       },
       node.stmt());
-  EndSubprogram(stmtSource, binding);
+  EndSubprogram(stmtSource, binding, &node.entryStmts());
 }
 
 // Some analyses and checks, such as the processing of initializers of

diff  --git a/flang/test/Semantics/symbol24.f90 b/flang/test/Semantics/symbol24.f90
new file mode 100644
index 000000000000..e1173f38649d
--- /dev/null
+++ b/flang/test/Semantics/symbol24.f90
@@ -0,0 +1,20 @@
+! RUN: %python %S/test_symbols.py %s %flang_fc1
+! Ensure that global ENTRY symbols with global bindings
+! are hidden in distinct global scopes, and nothing
+! clashes so long as binding names are distinct.
+
+!DEF: /s1 (Subroutine) Subprogram
+subroutine s1
+ !DEF: /foo (Subroutine) Subprogram
+ entry foo()
+end subroutine
+!DEF: /s2 (Subroutine) Subprogram
+subroutine s2
+ !DEF: /foo BIND(C) (Subroutine) Subprogram
+ entry foo() bind(c, name="foo1")
+end subroutine
+!DEF: /s3 (Subroutine) Subprogram
+subroutine s3
+ !DEF: /foo BIND(C) (Subroutine) Subprogram
+ entry foo() bind(c, name="foo2")
+end subroutine


        


More information about the flang-commits mailing list