[flang-commits] [flang] 7c71ce9 - [flang] Defer NAMELIST group item name resolution

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Apr 14 17:50:11 PDT 2022


Author: Peter Klausler
Date: 2022-04-14T17:50:03-07:00
New Revision: 7c71ce97e7be0a00322459527564ad1194e1e4b5

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

LOG: [flang] Defer NAMELIST group item name resolution

Items in NAMELIST groups might be host-associated implicitly-typed
variables, but name resolution can't know that when the NAMELIST
appears in a specification part and the host's execution part has
not yet been analyzed.  So defer NAMELIST group item name resolution
to the end of the execution part.  This is safe because nothing
else in name resolution depends on whether a variable is in a
NAMELIST group or not.

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 15cc77328b34e..2e693f82220a9 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -667,9 +667,26 @@ class ScopeHandler : public ImplicitRulesVisitor {
     } saveInfo;
   } specPartState_;
 
+  // Some declaration processing can and should be deferred to
+  // ResolveExecutionParts() to avoid prematurely creating implicitly-typed
+  // local symbols that should be host associations.
+  struct DeferredDeclarationState {
+    // The content of each namelist group
+    std::list<const parser::NamelistStmt::Group *> namelistGroups;
+  };
+  DeferredDeclarationState *GetDeferredDeclarationState(bool add = false) {
+    if (!add && deferred_.find(&currScope()) == deferred_.end()) {
+      return nullptr;
+    } else {
+      return &deferred_.emplace(&currScope(), DeferredDeclarationState{})
+                  .first->second;
+    }
+  }
+
 private:
   Scope *currScope_{nullptr};
   FuncResultStack funcResultStack_{*this};
+  std::map<Scope *, DeferredDeclarationState> deferred_;
 };
 
 class ModuleVisitor : public virtual ScopeHandler {
@@ -960,6 +977,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
   void CheckEquivalenceSets();
   bool CheckNotInBlock(const char *);
   bool NameIsKnownOrIntrinsic(const parser::Name &);
+  void FinishNamelists();
 
   // Each of these returns a pointer to a resolved Name (i.e. with symbol)
   // or nullptr in case of error.
@@ -4986,30 +5004,41 @@ bool DeclarationVisitor::Pre(const parser::NamelistStmt::Group &x) {
   if (!CheckNotInBlock("NAMELIST")) { // C1107
     return false;
   }
-
-  NamelistDetails details;
-  for (const auto &name : std::get<std::list<parser::Name>>(x.t)) {
-    auto *symbol{FindSymbol(name)};
-    if (!symbol) {
-      symbol = &MakeSymbol(name, ObjectEntityDetails{});
-      ApplyImplicitRules(*symbol);
-    } else if (!ConvertToObjectEntity(*symbol)) {
-      SayWithDecl(name, *symbol, "'%s' is not a variable"_err_en_US);
-    }
-    symbol->GetUltimate().set(Symbol::Flag::InNamelist);
-    details.add_object(*symbol);
-  }
-
   const auto &groupName{std::get<parser::Name>(x.t)};
   auto *groupSymbol{FindInScope(groupName)};
   if (!groupSymbol || !groupSymbol->has<NamelistDetails>()) {
-    groupSymbol = &MakeSymbol(groupName, std::move(details));
+    groupSymbol = &MakeSymbol(groupName, NamelistDetails{});
     groupSymbol->ReplaceName(groupName.source);
   }
-  groupSymbol->get<NamelistDetails>().add_objects(details.objects());
+  // Name resolution of group items is deferred to FinishNamelists()
+  // so that host association is handled correctly.
+  GetDeferredDeclarationState(true)->namelistGroups.emplace_back(&x);
   return false;
 }
 
+void DeclarationVisitor::FinishNamelists() {
+  if (auto *deferred{GetDeferredDeclarationState()}) {
+    for (const parser::NamelistStmt::Group *group : deferred->namelistGroups) {
+      if (auto *groupSymbol{FindInScope(std::get<parser::Name>(group->t))}) {
+        if (auto *details{groupSymbol->detailsIf<NamelistDetails>()}) {
+          for (const auto &name : std::get<std::list<parser::Name>>(group->t)) {
+            auto *symbol{FindSymbol(name)};
+            if (!symbol) {
+              symbol = &MakeSymbol(name, ObjectEntityDetails{});
+              ApplyImplicitRules(*symbol);
+            } else if (!ConvertToObjectEntity(*symbol)) {
+              SayWithDecl(name, *symbol, "'%s' is not a variable"_err_en_US);
+            }
+            symbol->GetUltimate().set(Symbol::Flag::InNamelist);
+            details->add_object(*symbol);
+          }
+        }
+      }
+    }
+    deferred->namelistGroups.clear();
+  }
+}
+
 bool DeclarationVisitor::Pre(const parser::IoControlSpec &x) {
   if (const auto *name{std::get_if<parser::Name>(&x.u)}) {
     auto *symbol{FindSymbol(*name)};
@@ -7447,6 +7476,7 @@ void ResolveNamesVisitor::ResolveExecutionParts(const ProgramTree &node) {
   if (const auto *exec{node.exec()}) {
     Walk(*exec);
   }
+  FinishNamelists();
   PopScope(); // converts unclassified entities into objects
   for (const auto &child : node.children()) {
     ResolveExecutionParts(child);

diff  --git a/flang/test/Semantics/call19.f90 b/flang/test/Semantics/call19.f90
index 753ff95d280df..3cca46c93ce0b 100644
--- a/flang/test/Semantics/call19.f90
+++ b/flang/test/Semantics/call19.f90
@@ -10,6 +10,7 @@ module m
     integer, len :: len
   end type
   type(pdt(1,2)) :: x
+  !ERROR: 'i' is not a variable
   namelist /nml/i
  contains
   subroutine s(d)

diff  --git a/flang/test/Semantics/resolve40.f90 b/flang/test/Semantics/resolve40.f90
index 331c5ebd02c0e..310b3c3872a0f 100644
--- a/flang/test/Semantics/resolve40.f90
+++ b/flang/test/Semantics/resolve40.f90
@@ -40,7 +40,6 @@ subroutine s4b
 
 subroutine s5
   namelist /nl/x
-  !ERROR: The type of 'x' has already been implicitly declared
   integer x
 end
 
@@ -57,8 +56,8 @@ integer function f()
 
 subroutine s7
   real x
+  !ERROR: 'x' is not a variable
   namelist /nl/ x
-  !ERROR: EXTERNAL attribute not allowed on 'x'
   external x
 end
 


        


More information about the flang-commits mailing list