diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp --- a/flang/lib/Semantics/runtime-type-info.cpp +++ b/flang/lib/Semantics/runtime-type-info.cpp @@ -555,44 +555,47 @@ static_cast( procPtrComponents.size())})); // Compile the "vtable" of type-bound procedure bindings - std::vector bindings{ - DescribeBindings(dtScope, scope)}; - AddValue(dtValues, derivedTypeSchema_, "binding"s, - SaveDerivedPointerTarget(scope, SaveObjectName(".v."s + distinctName), - std::move(bindings), - evaluate::ConstantSubscripts{ - static_cast(bindings.size())})); - // Describe "special" bindings to defined assignments, FINAL subroutines, - // and user-defined derived type I/O subroutines. - const DerivedTypeDetails &dtDetails{dtSymbol->get()}; - for (const auto &pair : dtDetails.finals()) { - DescribeSpecialProc( - specials, *pair.second, false /*!isAssignment*/, true, std::nullopt); - } - IncorporateDefinedIoGenericInterfaces( - specials, GenericKind::DefinedIo::ReadFormatted, &scope); - IncorporateDefinedIoGenericInterfaces( - specials, GenericKind::DefinedIo::ReadUnformatted, &scope); - IncorporateDefinedIoGenericInterfaces( - specials, GenericKind::DefinedIo::WriteFormatted, &scope); - IncorporateDefinedIoGenericInterfaces( - specials, GenericKind::DefinedIo::WriteUnformatted, &scope); - // Pack the special procedure bindings in ascending order of their "which" - // code values, and compile a little-endian bit-set of those codes for - // use in O(1) look-up at run time. - std::vector sortedSpecials; std::uint32_t specialBitSet{0}; - for (auto &pair : specials) { - auto bit{std::uint32_t{1} << pair.first}; - CHECK(!(specialBitSet & bit)); - specialBitSet |= bit; - sortedSpecials.emplace_back(std::move(pair.second)); + bool isAbstractType{dtSymbol->attrs().test(Attr::ABSTRACT)}; + if (!isAbstractType) { + std::vector bindings{ + DescribeBindings(dtScope, scope)}; + AddValue(dtValues, derivedTypeSchema_, "binding"s, + SaveDerivedPointerTarget(scope, SaveObjectName(".v."s + distinctName), + std::move(bindings), + evaluate::ConstantSubscripts{ + static_cast(bindings.size())})); + // Describe "special" bindings to defined assignments, FINAL subroutines, + // and user-defined derived type I/O subroutines. + const DerivedTypeDetails &dtDetails{dtSymbol->get()}; + for (const auto &pair : dtDetails.finals()) { + DescribeSpecialProc(specials, *pair.second, false /*!isAssignment*/, + true, std::nullopt); + } + IncorporateDefinedIoGenericInterfaces( + specials, GenericKind::DefinedIo::ReadFormatted, &scope); + IncorporateDefinedIoGenericInterfaces( + specials, GenericKind::DefinedIo::ReadUnformatted, &scope); + IncorporateDefinedIoGenericInterfaces( + specials, GenericKind::DefinedIo::WriteFormatted, &scope); + IncorporateDefinedIoGenericInterfaces( + specials, GenericKind::DefinedIo::WriteUnformatted, &scope); + // Pack the special procedure bindings in ascending order of their "which" + // code values, and compile a little-endian bit-set of those codes for + // use in O(1) look-up at run time. + std::vector sortedSpecials; + for (auto &pair : specials) { + auto bit{std::uint32_t{1} << pair.first}; + CHECK(!(specialBitSet & bit)); + specialBitSet |= bit; + sortedSpecials.emplace_back(std::move(pair.second)); + } + AddValue(dtValues, derivedTypeSchema_, "special"s, + SaveDerivedPointerTarget(scope, SaveObjectName(".s."s + distinctName), + std::move(sortedSpecials), + evaluate::ConstantSubscripts{ + static_cast(specials.size())})); } - AddValue(dtValues, derivedTypeSchema_, "special"s, - SaveDerivedPointerTarget(scope, SaveObjectName(".s."s + distinctName), - std::move(sortedSpecials), - evaluate::ConstantSubscripts{ - static_cast(specials.size())})); AddValue(dtValues, derivedTypeSchema_, "specialbitset"s, IntExpr<4>(specialBitSet)); // Note the presence/absence of a parent component @@ -602,14 +605,16 @@ // instances without any initialized components, analyze the type // and set a flag if there's nothing to do for it at run time. AddValue(dtValues, derivedTypeSchema_, "noinitializationneeded"s, - IntExpr<1>( - derivedTypeSpec && !derivedTypeSpec->HasDefaultInitialization())); + IntExpr<1>(isAbstractType || + (derivedTypeSpec && !derivedTypeSpec->HasDefaultInitialization()))); // Similarly, a flag to short-circuit destruction when not needed. AddValue(dtValues, derivedTypeSchema_, "nodestructionneeded"s, - IntExpr<1>(derivedTypeSpec && !derivedTypeSpec->HasDestruction())); + IntExpr<1>(isAbstractType || + (derivedTypeSpec && !derivedTypeSpec->HasDestruction()))); // Similarly, a flag to short-circuit finalization when not needed. AddValue(dtValues, derivedTypeSchema_, "nofinalizationneeded"s, - IntExpr<1>(derivedTypeSpec && !IsFinalizable(*derivedTypeSpec))); + IntExpr<1>(isAbstractType || + (derivedTypeSpec && !IsFinalizable(*derivedTypeSpec)))); } dtObject.get().set_init(MaybeExpr{ StructureExpr(Structure(derivedTypeSchema_, std::move(dtValues)))});