From a27d3852095a461b739da534ddc9abfb625f2e06 Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Tue, 9 Jun 2020 14:14:01 -0700 Subject: [PATCH] [flang] Fix bug resolving type in type definition When we encountered a type name in a derived type definition, we were sometimes finding a component of that name rather than the type from the enclosing scope. Fix this by introducing `NonDerivedTypeScope()` to start the search in the right scope. Differential Revision: https://reviews.llvm.org/D81493 --- flang/lib/Semantics/resolve-names.cpp | 14 +++++++++----- flang/test/Semantics/resolve92.f90 | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 flang/test/Semantics/resolve92.f90 diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 5626163144d3..218dcc07b270 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -455,6 +455,8 @@ public: // TODO: Will return the scope of a FORALL or implied DO loop; is this ok? // If not, should call FindProgramUnitContaining() instead. Scope &InclusiveScope(); + // The enclosing scope, skipping derived types. + Scope &NonDerivedTypeScope(); // Create a new scope and push it on the scope stack. void PushScope(Scope::Kind kind, Symbol *symbol); @@ -1999,6 +2001,10 @@ Scope &ScopeHandler::InclusiveScope() { DIE("inclusive scope not found"); } +Scope &ScopeHandler::NonDerivedTypeScope() { + return currScope_->IsDerivedType() ? currScope_->parent() : *currScope_; +} + void ScopeHandler::PushScope(Scope::Kind kind, Symbol *symbol) { PushScope(currScope().MakeScope(kind, symbol)); } @@ -3294,9 +3300,7 @@ void DeclarationVisitor::Post(const parser::EnumDef &) { bool DeclarationVisitor::Pre(const parser::AccessSpec &x) { Attr attr{AccessSpecToAttr(x)}; - const Scope &scope{ - currScope().IsDerivedType() ? currScope().parent() : currScope()}; - if (!scope.IsModule()) { // C817 + if (!NonDerivedTypeScope().IsModule()) { // C817 Say(currStmtSource().value(), "%s attribute may only appear in the specification part of a module"_err_en_US, EnumToString(attr)); @@ -4725,7 +4729,7 @@ void DeclarationVisitor::SetType( std::optional DeclarationVisitor::ResolveDerivedType( const parser::Name &name) { - Symbol *symbol{FindSymbol(name)}; + Symbol *symbol{FindSymbol(NonDerivedTypeScope(), name)}; if (!symbol || symbol->has()) { if (allowForwardReferenceToDerivedType()) { if (!symbol) { @@ -5769,7 +5773,7 @@ void ResolveNamesVisitor::HandleCall( void ResolveNamesVisitor::HandleProcedureName( Symbol::Flag flag, const parser::Name &name) { CHECK(flag == Symbol::Flag::Function || flag == Symbol::Flag::Subroutine); - auto *symbol{FindSymbol(name)}; + auto *symbol{FindSymbol(NonDerivedTypeScope(), name)}; if (!symbol) { if (context().intrinsics().IsIntrinsic(name.source.ToString())) { symbol = diff --git a/flang/test/Semantics/resolve92.f90 b/flang/test/Semantics/resolve92.f90 new file mode 100644 index 000000000000..24d86c34a5d2 --- /dev/null +++ b/flang/test/Semantics/resolve92.f90 @@ -0,0 +1,26 @@ +! RUN: %S/test_errors.sh %s %t %f18 + +module m1 + implicit none + type t + integer :: n + end type + type t2 + ! t and t2 must be resolved to types in m, not components in t2 + type(t) :: t(10) = t(1) + type(t) :: x = t(1) + integer :: t2 + type(t2), pointer :: p + end type +end + +module m2 + type :: t(t) + integer, kind :: t + integer(t) :: n + end type + type :: t2(t) + integer, kind :: t + type(t(t)) :: x = t(t)(t) + end type +end