From 723add0b8d211a9ca41c486fbe319fd3717080ce Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Thu, 1 Aug 2019 13:06:25 -0700 Subject: [PATCH] [flang] Fix merging of use associated generics When we use-associate a generic interface name and then add more procedures to the generic, we create a new symbol for the merged generic. That symbol has to include a pointer to the derived type or procedure with the same name, just as the original generic did. To achieve that, change `AddSpecificProcsFrom` to also copy those fields from the original symbol and change its name to `CopyFrom` to reflect its new purpose. Also, change it to take `GenericDetails` instead of `Symbol` as its argument so we can't call it on the wrong kind of symbol. Original-commit: flang-compiler/f18@1e22970e4352775df8a32e018435743786a66280 Reviewed-on: https://github.com/flang-compiler/f18/pull/614 --- flang/lib/semantics/resolve-names.cc | 10 +++++----- flang/lib/semantics/symbol.cc | 12 ++++++++++-- flang/lib/semantics/symbol.h | 5 +++-- flang/test/semantics/resolve18.f90 | 22 ++++++++++++++++++++++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc index ff95734..81fad11 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -1984,7 +1984,7 @@ void ModuleVisitor::AddUse( // new generic in this scope auto genericDetails{ultimate.get()}; genericDetails.set_useDetails(*useDetails); - genericDetails.AddSpecificProcsFrom(useSymbol); + genericDetails.CopyFrom(useSymbol.get()); EraseSymbol(localSymbol); MakeSymbol( localSymbol.name(), ultimate.attrs(), std::move(genericDetails)); @@ -1995,8 +1995,8 @@ void ModuleVisitor::AddUse( auto *genericDetails{localSymbol.detailsIf()}; if (genericDetails && genericDetails->useDetails().has_value()) { // localSymbol came from merging two use-associated generics - if (useSymbol.has()) { - genericDetails->AddSpecificProcsFrom(useSymbol); + if (auto *useDetails{useSymbol.detailsIf()}) { + genericDetails->CopyFrom(*useDetails); } else { ConvertToUseError(localSymbol, location, *useModuleScope_); } @@ -5051,8 +5051,8 @@ void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) { return; // already have generic, add to it } Symbol &ultimate{existing->GetUltimate()}; - if (ultimate.has()) { - genericDetails.AddSpecificProcsFrom(ultimate); + if (auto *ultimateDetails{ultimate.detailsIf()}) { + genericDetails.CopyFrom(*ultimateDetails); } else if (ultimate.has() || ultimate.has()) { genericDetails.set_specific(ultimate); diff --git a/flang/lib/semantics/symbol.cc b/flang/lib/semantics/symbol.cc index e27aba3..997d9a8 100644 --- a/flang/lib/semantics/symbol.cc +++ b/flang/lib/semantics/symbol.cc @@ -182,8 +182,16 @@ Symbol *GenericDetails::CheckSpecific() { } } -void GenericDetails::AddSpecificProcsFrom(const Symbol &generic) { - const auto &procs{generic.get().specificProcs()}; +void GenericDetails::CopyFrom(const GenericDetails &from) { + if (from.specific_) { + CHECK(!specific_); + specific_ = from.specific_; + } + if (from.derivedType_) { + CHECK(!derivedType_); + derivedType_ = from.derivedType_; + } + auto &procs{from.specificProcs_}; specificProcs_.insert(specificProcs_.end(), procs.begin(), procs.end()); } diff --git a/flang/lib/semantics/symbol.h b/flang/lib/semantics/symbol.h index 9056876..045182c 100644 --- a/flang/lib/semantics/symbol.h +++ b/flang/lib/semantics/symbol.h @@ -393,14 +393,12 @@ class GenericDetails { public: GenericDetails() {} GenericDetails(const SymbolVector &specificProcs); - GenericDetails(Symbol *specific) : specific_{specific} {} GenericKind kind() const { return kind_; } void set_kind(GenericKind kind) { kind_ = kind; } const SymbolVector &specificProcs() const { return specificProcs_; } void add_specificProc(const Symbol &proc) { specificProcs_.push_back(&proc); } - void AddSpecificProcsFrom(const Symbol &generic); // specific and derivedType indicate a specific procedure or derived type // with the same name as this generic. Only one of them may be set. @@ -411,6 +409,9 @@ public: const Symbol *derivedType() const { return derivedType_; } void set_derivedType(Symbol &derivedType); + // Copy in specificProcs, specific, and derivedType from another generic + void CopyFrom(const GenericDetails &); + // Check that specific is one of the specificProcs. If not, return the // specific as a raw pointer. const Symbol *CheckSpecific() const; diff --git a/flang/test/semantics/resolve18.f90 b/flang/test/semantics/resolve18.f90 index 10e7ff7..208b374 100644 --- a/flang/test/semantics/resolve18.f90 +++ b/flang/test/semantics/resolve18.f90 @@ -76,3 +76,25 @@ contains function foo(x) end end + +! Use associating a name that is a generic and a derived type +module m5a + interface g + end interface + type g + end type +end module +module m5b + use m5a + interface g + procedure f + end interface + type(g) :: x +contains + function f(i) + end function +end module +subroutine s5 + use m5b + type(g) :: y +end -- 2.7.4