From 3cdee3522501bbea3141c6e13e015b5e348877bd Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Mon, 2 Jun 2025 12:32:57 -0700 Subject: [PATCH] [flang] Ensure overrides of special procedures When a derived type declares a generic procedure binding of interest to the runtime library, such as for ASSIGNMENT(=), it overrides any binding that might have been present for the parent type. Fixes https://github.com/llvm/llvm-project/issues/142414. --- flang/lib/Semantics/runtime-type-info.cpp | 4 ++-- flang/test/Semantics/typeinfo13.f90 | 26 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 flang/test/Semantics/typeinfo13.f90 diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp index ccc5e37c840a9..26ae81f97895a 100644 --- a/flang/lib/Semantics/runtime-type-info.cpp +++ b/flang/lib/Semantics/runtime-type-info.cpp @@ -1063,7 +1063,7 @@ RuntimeTableBuilder::DescribeSpecialGenerics(const Scope &dtScope, specials = DescribeSpecialGenerics(*parentScope, thisScope, derivedTypeSpec); } - for (auto pair : dtScope) { + for (const auto &pair : dtScope) { const Symbol &symbol{*pair.second}; if (const auto *generic{symbol.detailsIf()}) { DescribeSpecialGeneric(*generic, specials, thisScope, derivedTypeSpec); @@ -1241,7 +1241,7 @@ void RuntimeTableBuilder::DescribeSpecialProc( AddValue(values, specialSchema_, procCompName, SomeExpr{evaluate::ProcedureDesignator{specific}}); // index might already be present in the case of an override - specials.emplace(*index, + specials.insert_or_assign(*index, evaluate::StructureConstructor{ DEREF(specialSchema_.AsDerived()), std::move(values)}); } diff --git a/flang/test/Semantics/typeinfo13.f90 b/flang/test/Semantics/typeinfo13.f90 new file mode 100644 index 0000000000000..cf4abf9e38181 --- /dev/null +++ b/flang/test/Semantics/typeinfo13.f90 @@ -0,0 +1,26 @@ +!RUN: %flang_fc1 -fdebug-dump-symbols %s | FileCheck %s +!Ensure ASSIGNMENT(=) overrides are applied to the special procedures table. +module m + type base + contains + procedure :: baseAssign + generic :: assignment(=) => baseAssign + end type + type, extends(base) :: child + contains + procedure :: override + generic :: assignment(=) => override + end type + contains + impure elemental subroutine baseAssign(to, from) + class(base), intent(out) :: to + type(base), intent(in) :: from + end + impure elemental subroutine override(to, from) + class(child), intent(out) :: to + type(child), intent(in) :: from + end +end + +!CHECK: .s.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=1_1,istypebound=1_1,isargcontiguousset=0_1,proc=override)] +!CHECK: .v.child, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(binding) shape: 0_8:1_8 init:[binding::binding(proc=baseassign,name=.n.baseassign),binding(proc=override,name=.n.override)]