[flang-commits] [flang] af61d08 - [flang] Handle forward reference to shadowing derived type from IMPLICIT (#87280)

via flang-commits flang-commits at lists.llvm.org
Mon Apr 8 11:54:40 PDT 2024


Author: Peter Klausler
Date: 2024-04-08T11:54:37-07:00
New Revision: af61d08280a90becb5a710a812f0d3d6485737a8

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

LOG: [flang] Handle forward reference to shadowing derived type from IMPLICIT (#87280)

A derived type name in an IMPLICIT statement might be a host association
or it might be a forward reference to a local derived type, which may be
shadowing a host-associated name. Add a scan over the specification part
in search of derived type definitions to determine the right
interpretation.

Fixes https://github.com/llvm/llvm-project/issues/87215.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index f2db329e30be78..b04de2648017e7 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1635,6 +1635,8 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
   void FinishDerivedTypeInstantiation(Scope &);
   void ResolveExecutionParts(const ProgramTree &);
   void UseCUDABuiltinNames();
+  void HandleDerivedTypesInImplicitStmts(const parser::ImplicitPart &,
+      const std::list<parser::DeclarationConstruct> &);
 };
 
 // ImplicitRules implementation
@@ -2035,6 +2037,7 @@ bool ImplicitRulesVisitor::Pre(const parser::ImplicitSpec &) {
 }
 
 void ImplicitRulesVisitor::Post(const parser::ImplicitSpec &) {
+  set_allowForwardReferenceToDerivedType(false);
   EndDeclTypeSpec();
 }
 
@@ -8329,6 +8332,67 @@ static bool NeedsExplicitType(const Symbol &symbol) {
   }
 }
 
+void ResolveNamesVisitor::HandleDerivedTypesInImplicitStmts(
+    const parser::ImplicitPart &implicitPart,
+    const std::list<parser::DeclarationConstruct> &decls) {
+  // Detect derived type definitions and create symbols for them now if
+  // they appear in IMPLICIT statements so that these forward-looking
+  // references will not be ambiguous with host associations.
+  std::set<SourceName> implicitDerivedTypes;
+  for (const auto &ipStmt : implicitPart.v) {
+    if (const auto *impl{std::get_if<
+            parser::Statement<common::Indirection<parser::ImplicitStmt>>>(
+            &ipStmt.u)}) {
+      if (const auto *specs{std::get_if<std::list<parser::ImplicitSpec>>(
+              &impl->statement.value().u)}) {
+        for (const auto &spec : *specs) {
+          const auto &declTypeSpec{
+              std::get<parser::DeclarationTypeSpec>(spec.t)};
+          if (const auto *dtSpec{common::visit(
+                  common::visitors{
+                      [](const parser::DeclarationTypeSpec::Type &x) {
+                        return &x.derived;
+                      },
+                      [](const parser::DeclarationTypeSpec::Class &x) {
+                        return &x.derived;
+                      },
+                      [](const auto &) -> const parser::DerivedTypeSpec * {
+                        return nullptr;
+                      }},
+                  declTypeSpec.u)}) {
+            implicitDerivedTypes.emplace(
+                std::get<parser::Name>(dtSpec->t).source);
+          }
+        }
+      }
+    }
+  }
+  if (!implicitDerivedTypes.empty()) {
+    for (const auto &decl : decls) {
+      if (const auto *spec{
+              std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
+        if (const auto *dtDef{
+                std::get_if<common::Indirection<parser::DerivedTypeDef>>(
+                    &spec->u)}) {
+          const parser::DerivedTypeStmt &dtStmt{
+              std::get<parser::Statement<parser::DerivedTypeStmt>>(
+                  dtDef->value().t)
+                  .statement};
+          const parser::Name &name{std::get<parser::Name>(dtStmt.t)};
+          if (implicitDerivedTypes.find(name.source) !=
+                  implicitDerivedTypes.end() &&
+              !FindInScope(name)) {
+            DerivedTypeDetails details;
+            details.set_isForwardReferenced(true);
+            Resolve(name, MakeSymbol(name, std::move(details)));
+            implicitDerivedTypes.erase(name.source);
+          }
+        }
+      }
+    }
+  }
+}
+
 bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
   const auto &[accDecls, ompDecls, compilerDirectives, useStmts, importStmts,
       implicitPart, decls] = x.t;
@@ -8347,6 +8411,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
   ClearUseOnly();
   ClearModuleUses();
   Walk(importStmts);
+  HandleDerivedTypesInImplicitStmts(implicitPart, decls);
   Walk(implicitPart);
   for (const auto &decl : decls) {
     if (const auto *spec{

diff  --git a/flang/test/Semantics/resolve29.f90 b/flang/test/Semantics/resolve29.f90
index 3e6a8a0ba69763..c6a9b036c5828d 100644
--- a/flang/test/Semantics/resolve29.f90
+++ b/flang/test/Semantics/resolve29.f90
@@ -3,6 +3,7 @@ module m1
   type t1
   end type
   type t3
+    integer t3c
   end type
   interface
     subroutine s1(x)
@@ -64,6 +65,17 @@ subroutine s9()
     end type
     type(t2) x
   end
+  subroutine s10()
+    !Forward shadowing derived type in IMPLICIT
+    !(supported by all other compilers)
+    implicit type(t1) (c) ! forward shadow
+    implicit type(t3) (d) ! host associated
+    type t1
+      integer a
+    end type
+    c%a = 1
+    d%t3c = 2
+  end
 end module
 module m2
   integer, parameter :: ck = kind('a')


        


More information about the flang-commits mailing list