[flang-commits] [flang] [flang][lowering] Implement component-wise initialization for derived types (PR #187465)
via flang-commits
flang-commits at lists.llvm.org
Wed Apr 15 23:27:30 PDT 2026
https://github.com/refuseno updated https://github.com/llvm/llvm-project/pull/187465
>From d1c9fb4cb033bbc5b9e8e5fb95dfa902b7f79496 Mon Sep 17 00:00:00 2001
From: hechenxi <hechenxi at bosc.ac.cn>
Date: Thu, 19 Mar 2026 16:27:03 +0800
Subject: [PATCH 1/7] component-wise-init
Co-authored-by: ict-ql <168183727+ict-ql at users.noreply.github.com>
Co-authored-by: buggfg <wangyingying at bosc.ac.cn>
---
flang/lib/Lower/ConvertVariable.cpp | 369 +++++++++++++++++++----
flang/test/Lower/component-wise-init.f90 | 94 ++++++
2 files changed, 407 insertions(+), 56 deletions(-)
create mode 100644 flang/test/Lower/component-wise-init.f90
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 0ededb364bfea..16509b855ce9e 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//
-#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/Allocatable.h"
#include "flang/Lower/BoxAnalyzer.h"
@@ -20,6 +19,7 @@
#include "flang/Lower/ConvertExpr.h"
#include "flang/Lower/ConvertExprToHLFIR.h"
#include "flang/Lower/ConvertProcedureDesignator.h"
+#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/Mangler.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/StatementContext.h"
@@ -32,12 +32,15 @@
#include "flang/Optimizer/Builder/IntrinsicCall.h"
#include "flang/Optimizer/Builder/Runtime/Derived.h"
#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/CodeGen/TypeConverter.h"
#include "flang/Optimizer/Dialect/CUF/CUFOps.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/Support/DataLayout.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Support/Utils.h"
@@ -48,6 +51,11 @@
#include "llvm/Support/Debug.h"
#include <optional>
+static llvm::cl::opt<bool> enablePreciseInit(
+ "enable-precise-init",
+ llvm::cl::desc("Enable precise component initialization for derived types"),
+ llvm::cl::init(false));
+
static llvm::cl::opt<bool>
allowAssumedRank("allow-assumed-rank",
llvm::cl::desc("Enable assumed rank lowering"),
@@ -585,15 +593,14 @@ fir::GlobalOp Fortran::lower::defineGlobal(
if (details && details->init()) {
auto sym{*details->init()};
if (sym) // Has a procedure target.
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &b) {
- Fortran::lower::StatementContext stmtCtx(
- /*cleanupProhibited=*/true);
- auto box{Fortran::lower::convertProcedureDesignatorInitialTarget(
- converter, loc, *sym)};
- auto castTo{builder.createConvert(loc, symTy, box)};
- fir::HasValueOp::create(b, loc, castTo);
- });
+ createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
+ Fortran::lower::StatementContext stmtCtx(
+ /*cleanupProhibited=*/true);
+ auto box{Fortran::lower::convertProcedureDesignatorInitialTarget(
+ converter, loc, *sym)};
+ auto castTo{builder.createConvert(loc, symTy, box)};
+ fir::HasValueOp::create(b, loc, castTo);
+ });
else { // Has NULL() target.
createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
auto box{fir::factory::createNullBoxProc(b, loc, symTy)};
@@ -812,6 +819,244 @@ mustBeDefaultInitializedAtRuntime(const Fortran::lower::pft::Variable &var) {
return Fortran::lower::hasDefaultInitialization(sym);
}
+namespace {
+/// Determines if \p sym represents a complex derived type.
+/// A derived type is considered complex if it contains allocatable, pointer,
+/// or procedure pointer components, or nested complex derived types.
+static bool isComplexDerivedType(const Fortran::semantics::Symbol &sym) {
+ const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType();
+ if (!declTy || !declTy->AsDerived())
+ return false;
+ const Fortran::semantics::DerivedTypeSpec &derivedSpec = *declTy->AsDerived();
+ const Fortran::semantics::Scope *scope = derivedSpec.GetScope();
+ if (!scope)
+ return false;
+ const auto &typeDetails =
+ derivedSpec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
+ for (const auto &compName : typeDetails.componentNames()) {
+ auto iter = scope->find(compName);
+ if (iter == scope->cend())
+ continue;
+ const Fortran::semantics::Symbol &compSym = iter->second.get();
+ const auto *objDetails =
+ compSym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
+ const auto *procDetails =
+ compSym.detailsIf<Fortran::semantics::ProcEntityDetails>();
+ if (Fortran::semantics::IsAllocatableOrPointer(compSym)) {
+ return true;
+ } else if (procDetails && procDetails->init().has_value()) {
+ return true;
+ } else if (objDetails && objDetails->init() && compSym.Rank() > 0) {
+ return true;
+ } else if (isComplexDerivedType(compSym)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/// Performs precise, component-wise initialization for \p derivedSpec,
+/// selectively generating IR only for components that require it.
+static void genDerivedTypeComponentInit(
+ Fortran::lower::AbstractConverter &converter, mlir::Location loc,
+ const Fortran::semantics::DerivedTypeSpec &derivedSpec,
+ mlir::Value baseAddr, fir::RecordType recTy) {
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ const Fortran::semantics::Scope *scope = derivedSpec.GetScope();
+ if (!scope)
+ return;
+ const auto &typeDetails =
+ derivedSpec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
+ for (const auto &compName : typeDetails.componentNames()) {
+ auto scopeIter = scope->find(compName);
+ if (scopeIter == scope->cend())
+ continue;
+ const Fortran::semantics::Symbol &compSym = scopeIter->second.get();
+ const auto *objDetails =
+ compSym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
+ const auto *procDetails =
+ compSym.detailsIf<Fortran::semantics::ProcEntityDetails>();
+ // Determine if the component requires initialization.
+ // Dynamic descriptors (pointers/allocatables) and explicitly initialized
+ // entities must be processed.
+ bool needsInit = Fortran::semantics::IsAllocatableOrPointer(compSym) ||
+ (objDetails && objDetails->init()) ||
+ (procDetails && procDetails->init().has_value());
+ if (!needsInit && !Fortran::lower::hasDefaultInitialization(compSym))
+ continue;
+ std::string name = converter.getRecordTypeFieldName(compSym);
+ mlir::Type compFirTy = recTy.getType(name);
+ if (!compFirTy)
+ continue;
+ // Compute the memory coordinate of the current component.
+ auto fieldIdx = builder.create<fir::FieldIndexOp>(
+ loc, fir::FieldType::get(recTy.getContext()), name, recTy,
+ mlir::ValueRange{});
+ auto compAddr =
+ builder.create<fir::CoordinateOp>(loc, builder.getRefType(compFirTy),
+ baseAddr, mlir::ValueRange{fieldIdx});
+
+ // Case A: Standard data components (ObjectEntityDetails).
+ if (objDetails) {
+ if (objDetails->init()) {
+ // Subcase A.1: Component has explicit initialization.
+ if (Fortran::semantics::IsPointer(compSym)) {
+ // Subcase A.1.1: Pointer with explicit target.
+ std::string globalName = fir::NameUniquer::doGenerated(
+ (converter.mangleName(derivedSpec) + fir::kNameSeparator + name +
+ fir::kNameSeparator + "init")
+ .str());
+ fir::GlobalOp global = builder.getNamedGlobal(globalName);
+ if (!global) {
+ global = builder.createGlobal(loc, compFirTy, globalName,
+ builder.createInternalLinkage(),
+ mlir::Attribute{}, true);
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &b) {
+ mlir::Value initBox = Fortran::lower::genInitialDataTarget(
+ converter, loc, compFirTy, *objDetails->init());
+ b.create<fir::HasValueOp>(loc, initBox);
+ });
+ }
+ auto srcAddr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
+ global.getSymbol());
+ mlir::Value loadedBox = builder.create<fir::LoadOp>(loc, srcAddr);
+ builder.create<fir::StoreOp>(loc, loadedBox, compAddr);
+ } else {
+ // Subcase A.1.2: Non-pointer components with explicit initialization.
+ Fortran::lower::StatementContext stmtCtx(/*cleanupProhibited=*/true);
+ if (mlir::isa<fir::SequenceType>(compFirTy)) {
+ std::string globalName = fir::NameUniquer::doGenerated(
+ (converter.mangleName(derivedSpec) + fir::kNameSeparator +
+ name + fir::kNameSeparator + "arr_init")
+ .str());
+ fir::GlobalOp global = builder.getNamedGlobal(globalName);
+ if (!global) {
+ const auto &initExpr = objDetails->init().value();
+ cuf::DataAttributeAttr dataAttr = {};
+ global = Fortran::lower::tryCreatingDenseGlobal(
+ builder, loc, compFirTy, globalName,
+ builder.createInternalLinkage(), /*isConst=*/true, initExpr,
+ dataAttr);
+ }
+ if (global) {
+ auto srcAddr = builder.create<fir::AddrOfOp>(
+ loc, global.resultType(), global.getSymbol());
+ builder.create<fir::CopyOp>(loc, srcAddr, compAddr,
+ /*noOverlap=*/true);
+ } else {
+ Fortran::lower::StatementContext inlineCtx;
+ Fortran::lower::SymMap emptyMap;
+ hlfir::Entity lhs{compAddr};
+ hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR(
+ loc, converter, objDetails->init().value(), emptyMap,
+ inlineCtx);
+ builder.create<hlfir::AssignOp>(loc, rhs, lhs);
+ }
+ } else {
+ // Scalar component: Evaluate the expression and store directly.
+ fir::ExtendedValue exInitVal = genInitializerExprValue(
+ converter, loc, objDetails->init().value(), stmtCtx);
+ mlir::Value initVal = fir::getBase(exInitVal);
+ if (fir::isa_ref_type(initVal.getType()) &&
+ !fir::isa_ref_type(compFirTy))
+ initVal = builder.create<fir::LoadOp>(loc, initVal);
+ mlir::Value castVal =
+ builder.createConvert(loc, compFirTy, initVal);
+ builder.create<fir::StoreOp>(loc, castVal, compAddr);
+ }
+ }
+ } else if (Fortran::semantics::IsAllocatableOrPointer(compSym)) {
+ // Subcase A.2: Pointer or allocatable without initialization.
+ // Create deallocated/disassociated value.
+ std::string globalName = fir::NameUniquer::doGenerated(
+ (converter.mangleName(derivedSpec) + fir::kNameSeparator + name +
+ fir::kNameSeparator + "null_box")
+ .str());
+ fir::GlobalOp global = builder.getNamedGlobal(globalName);
+ if (!global) {
+ global = builder.createGlobal(loc, compFirTy, globalName,
+ builder.createInternalLinkage(),
+ mlir::Attribute{}, true);
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &b) {
+ mlir::Value nullBox = fir::factory::createUnallocatedBox(
+ b, loc, compFirTy, mlir::ValueRange{});
+ b.create<fir::HasValueOp>(loc, nullBox);
+ });
+ }
+ auto srcAddr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
+ global.getSymbol());
+ mlir::Value loadedBox = builder.create<fir::LoadOp>(loc, srcAddr);
+ builder.create<fir::StoreOp>(loc, loadedBox, compAddr);
+ } else if (Fortran::lower::hasDefaultInitialization(compSym)) {
+ // Subcase A.3: Nested derived type requires initialization.
+ // Derived type has no explicit initialization but contains
+ // components requiring initialization.
+ if (mlir::isa<fir::SequenceType>(compFirTy) &&
+ isComplexDerivedType(compSym)) {
+ // Complex derived type arrays.
+ mlir::Value box =
+ builder.createBox(loc, fir::ExtendedValue(compAddr));
+ fir::runtime::genDerivedTypeInitialize(builder, loc, box);
+ } else if (isComplexDerivedType(compSym)) {
+ // Complex derived type scalars.
+ const Fortran::semantics::DeclTypeSpec *compDeclTy =
+ compSym.GetType();
+ auto nestedRecTy = mlir::dyn_cast<fir::RecordType>(compFirTy);
+ genDerivedTypeComponentInit(converter, loc, *compDeclTy->AsDerived(),
+ compAddr, nestedRecTy);
+ } else {
+ // Simple derived type scalars.
+ Fortran::lower::StatementContext stmtCtx;
+ mlir::Value initVal = genDefaultInitializerValue(
+ converter, loc, compSym, compFirTy, stmtCtx);
+ mlir::Value castVal = builder.createConvert(loc, compFirTy, initVal);
+ builder.create<fir::StoreOp>(loc, castVal, compAddr);
+ }
+ }
+ }
+ // Case B: Procedure pointers (ProcEntityDetails).
+ else if (procDetails) {
+ if (procDetails->init().has_value()) {
+ // Has a procedure or NULL() target.
+ std::string globalName = fir::NameUniquer::doGenerated(
+ (converter.mangleName(derivedSpec) + fir::kNameSeparator + name +
+ fir::kNameSeparator + "init")
+ .str());
+ fir::GlobalOp global = builder.getNamedGlobal(globalName);
+ if (!global) {
+ global = builder.createGlobal(loc, compFirTy, globalName,
+ builder.createInternalLinkage(),
+ mlir::Attribute{}, true);
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &b) {
+ mlir::Value procBox;
+ auto targetSym = *procDetails->init();
+ if (targetSym) {
+ procBox =
+ Fortran::lower::convertProcedureDesignatorInitialTarget(
+ converter, loc, *targetSym);
+ procBox = b.createConvert(loc, compFirTy, procBox);
+ } else {
+ procBox = fir::factory::createNullBoxProc(b, loc, compFirTy);
+ }
+ b.create<fir::HasValueOp>(loc, procBox);
+ });
+ }
+ auto srcAddr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
+ global.getSymbol());
+ mlir::Value loadedBox = builder.create<fir::LoadOp>(loc, srcAddr);
+ builder.create<fir::StoreOp>(loc, loadedBox, compAddr);
+ } else {
+ // Has no initialization.
+ continue;
+ }
+ }
+ }
+}
+} // namespace
+
/// Call default initialization runtime routine to initialize \p var.
void Fortran::lower::defaultInitializeAtRuntime(
Fortran::lower::AbstractConverter &converter,
@@ -823,8 +1068,8 @@ void Fortran::lower::defaultInitializeAtRuntime(
// 15.5.2.12 point 3, absent optional dummies are not initialized.
// Creating descriptor/passing null descriptor to the runtime would
// create runtime crashes.
- auto isPresent = fir::IsPresentOp::create(builder, loc, builder.getI1Type(),
- fir::getBase(exv));
+ auto isPresent = builder.create<fir::IsPresentOp>(loc, builder.getI1Type(),
+ fir::getBase(exv));
builder.genIfThen(loc, isPresent)
.genThen([&]() {
auto box = builder.createBox(loc, exv);
@@ -839,56 +1084,68 @@ void Fortran::lower::defaultInitializeAtRuntime(
mlir::Type symTy = converter.genType(sym);
const auto *details =
sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- if (details && !Fortran::semantics::IsPolymorphic(sym) &&
+ bool useFastInit =
+ details && !Fortran::semantics::IsPolymorphic(sym) &&
declTy->category() ==
Fortran::semantics::DeclTypeSpec::Category::TypeDerived &&
!mlir::isa<fir::SequenceType>(symTy) &&
!sym.test(Fortran::semantics::Symbol::Flag::OmpPrivate) &&
!sym.test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate) &&
- !Fortran::semantics::HasCUDAComponent(sym)) {
- std::string globalName = fir::NameUniquer::doGenerated(
- (converter.mangleName(*declTy->AsDerived()) + fir::kNameSeparator +
- fir::kDerivedTypeInitSuffix)
- .str());
- mlir::Location loc = genLocation(converter, sym);
- mlir::StringAttr linkage = builder.createInternalLinkage();
- fir::GlobalOp global = builder.getNamedGlobal(globalName);
- if (!global && details->init()) {
- global = builder.createGlobal(loc, symTy, globalName, linkage,
- mlir::Attribute{},
- /*isConst=*/true,
- /*isTarget=*/false,
- /*dataAttr=*/{});
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &builder) {
- Fortran::lower::StatementContext stmtCtx(
- /*cleanupProhibited=*/true);
- fir::ExtendedValue initVal = genInitializerExprValue(
- converter, loc, details->init().value(), stmtCtx);
- mlir::Value castTo =
- builder.createConvert(loc, symTy, fir::getBase(initVal));
- fir::HasValueOp::create(builder, loc, castTo);
- });
- } else if (!global) {
- global = builder.createGlobal(loc, symTy, globalName, linkage,
- mlir::Attribute{},
- /*isConst=*/true,
- /*isTarget=*/false,
- /*dataAttr=*/{});
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &builder) {
- Fortran::lower::StatementContext stmtCtx(
- /*cleanupProhibited=*/true);
- mlir::Value initVal = genDefaultInitializerValue(
- converter, loc, sym, symTy, stmtCtx);
- mlir::Value castTo = builder.createConvert(loc, symTy, initVal);
- fir::HasValueOp::create(builder, loc, castTo);
- });
+ !Fortran::semantics::HasCUDAComponent(sym);
+ if (useFastInit) {
+ if (enablePreciseInit) {
+ // Precise initialization
+ mlir::Value baseAddr = fir::getBase(exv);
+ const auto &derivedSpec = *sym.GetType()->AsDerived();
+ auto recTy = mlir::cast<fir::RecordType>(
+ fir::unwrapPassByRefType(baseAddr.getType()));
+ genDerivedTypeComponentInit(converter, loc, derivedSpec, baseAddr,
+ recTy);
+ } else {
+ std::string globalName = fir::NameUniquer::doGenerated(
+ (converter.mangleName(*declTy->AsDerived()) + fir::kNameSeparator +
+ fir::kDerivedTypeInitSuffix)
+ .str());
+ mlir::Location loc = genLocation(converter, sym);
+ mlir::StringAttr linkage = builder.createInternalLinkage();
+ fir::GlobalOp global = builder.getNamedGlobal(globalName);
+ if (!global && details->init()) {
+ global = builder.createGlobal(loc, symTy, globalName, linkage,
+ mlir::Attribute{},
+ /*isConst=*/true,
+ /*isTarget=*/false,
+ /*dataAttr=*/{});
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &builder) {
+ Fortran::lower::StatementContext stmtCtx(
+ /*cleanupProhibited=*/true);
+ fir::ExtendedValue initVal = genInitializerExprValue(
+ converter, loc, details->init().value(), stmtCtx);
+ mlir::Value castTo =
+ builder.createConvert(loc, symTy, fir::getBase(initVal));
+ builder.create<fir::HasValueOp>(loc, castTo);
+ });
+ } else if (!global) {
+ global = builder.createGlobal(loc, symTy, globalName, linkage,
+ mlir::Attribute{},
+ /*isConst=*/true,
+ /*isTarget=*/false,
+ /*dataAttr=*/{});
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &builder) {
+ Fortran::lower::StatementContext stmtCtx(
+ /*cleanupProhibited=*/true);
+ mlir::Value initVal = genDefaultInitializerValue(
+ converter, loc, sym, symTy, stmtCtx);
+ mlir::Value castTo = builder.createConvert(loc, symTy, initVal);
+ builder.create<fir::HasValueOp>(loc, castTo);
+ });
+ }
+ auto addrOf = builder.create<fir::AddrOfOp>(loc, global.resultType(),
+ global.getSymbol());
+ builder.create<fir::CopyOp>(loc, addrOf, fir::getBase(exv),
+ /*noOverlap=*/true);
}
- auto addrOf = fir::AddrOfOp::create(builder, loc, global.resultType(),
- global.getSymbol());
- fir::CopyOp::create(builder, loc, addrOf, fir::getBase(exv),
- /*noOverlap=*/true);
} else {
mlir::Value box = builder.createBox(loc, exv);
fir::runtime::genDerivedTypeInitialize(builder, loc, box);
diff --git a/flang/test/Lower/component-wise-init.f90 b/flang/test/Lower/component-wise-init.f90
new file mode 100644
index 0000000000000..2b751e784dc47
--- /dev/null
+++ b/flang/test/Lower/component-wise-init.f90
@@ -0,0 +1,94 @@
+! RUN: bbc -emit-fir -enable-precise-init %s -o - | FileCheck %s
+
+! Test for precise component-wise initialization of derived types
+! to avoid generating large, fully-initialized global templates (sparse initialization).
+
+module my_types
+ type :: InnerType
+ integer :: flag = 42
+ real, pointer :: p
+ real, allocatable :: arr(:)
+ end type InnerType
+
+ type :: OuterType
+ real, pointer :: q
+ integer :: explicit_arr(3) = [10, 20, 30]
+ real(8) :: uninit_buffer(80, 100, 100)
+ type(InnerType) :: nested
+ type(InnerType) :: nested_arr(2)
+ end type OuterType
+end module my_types
+
+subroutine test_complex_init()
+ use my_types
+ type(OuterType) :: my_var
+ call do_something(my_var)
+end subroutine test_complex_init
+
+! ==============================================================================
+! FileCheck Assertions
+! ==============================================================================
+
+! CHECK-LABEL: func.func @_QPtest_complex_init()
+
+! Ensure we allocate the local variable
+! CHECK: %[[MY_VAR:.*]] = fir.alloca !fir.type<_QMmy_typesToutertype{{.*}}>
+
+! ------------------------------------------------------------------------------
+! 1. Check pointer 'q' initialization (First component, offset 0, no coordinate_of needed)
+! ------------------------------------------------------------------------------
+! CHECK: %[[Q_NULL_BOX_ADDR:.*]] = fir.address_of(@_QQ_QMmy_typesToutertype.q.{{(null_box|init)}})
+! CHECK: %[[Q_NULL_BOX:.*]] = fir.load %[[Q_NULL_BOX_ADDR]]
+! CHECK: fir.store %[[Q_NULL_BOX]] to %{{.*}}
+
+! ------------------------------------------------------------------------------
+! 2. Check explicit array initialization
+! ------------------------------------------------------------------------------
+! CHECK: %[[EXPLICIT_ARR_ADDR:.*]] = fir.coordinate_of %{{.*}}, explicit_arr
+! CHECK: %[[EXPLICIT_ARR_INIT:.*]] = fir.address_of(@_QQ_QMmy_typesToutertype.explicit_arr.arr_init)
+! CHECK: fir.copy %[[EXPLICIT_ARR_INIT]] to %[[EXPLICIT_ARR_ADDR]]
+
+! ------------------------------------------------------------------------------
+! 3. Check scalar derived type 'nested' component-wise precise initialization
+! ------------------------------------------------------------------------------
+! CHECK: %[[NESTED_ADDR:.*]] = fir.coordinate_of %{{.*}}, nested
+
+! -> Check 'flag' (integer = 42)
+! CHECK: %[[FLAG_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], flag
+! CHECK: fir.store %c42{{.*}} to %[[FLAG_ADDR]]
+
+! -> Check 'p' (pointer)
+! CHECK: %[[P_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], p
+! CHECK: %[[P_INIT_ADDR:.*]] = fir.address_of(@_QQ_QMmy_typesTinnertype.p.{{(null_box|init)}})
+! CHECK: %[[P_INIT_VAL:.*]] = fir.load %[[P_INIT_ADDR]]
+! CHECK: fir.store %[[P_INIT_VAL]] to %[[P_ADDR]]
+
+! -> Check 'arr' (allocatable)
+! CHECK: %[[ARR_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], arr
+! CHECK: %[[ARR_INIT_ADDR:.*]] = fir.address_of(@_QQ_QMmy_typesTinnertype.arr.null_box)
+! CHECK: %[[ARR_INIT_VAL:.*]] = fir.load %[[ARR_INIT_ADDR]]
+! CHECK: fir.store %[[ARR_INIT_VAL]] to %[[ARR_ADDR]]
+
+! ------------------------------------------------------------------------------
+! 4. Check derived type array 'nested_arr' initialization (Runtime call)
+! ------------------------------------------------------------------------------
+! CHECK: %[[NESTED_ARR_ADDR:.*]] = fir.coordinate_of %{{.*}}, nested_arr
+! CHECK: %[[NESTED_ARR_BOX:.*]] = fir.embox %[[NESTED_ARR_ADDR]]
+! CHECK: %[[NESTED_ARR_PTR:.*]] = fir.convert %[[NESTED_ARR_BOX]]
+! CHECK: fir.call @_FortranAInitialize(%[[NESTED_ARR_PTR]], {{.*}})
+
+
+! ------------------------------------------------------------------------------
+! Global Variables Check
+! ------------------------------------------------------------------------------
+
+! CRITICAL: Ensure NO full derived type initialization templates are generated!
+! We should NOT see fir.global for the entire DerivedInit.
+! CHECK-NOT: fir.global internal @_QQ_QMmy_typesToutertype.DerivedInit
+! CHECK-NOT: fir.global internal @_QQ_QMmy_typesTinnertype.DerivedInit
+
+! Verify the fine-grained component global constants exist
+! CHECK-DAG: fir.global internal @_QQ_QMmy_typesToutertype.explicit_arr.arr_init(dense<[10, 20, 30]> : tensor<3xi32>)
+! CHECK-DAG: fir.global internal @_QQ_QMmy_typesToutertype.q.{{(null_box|init)}}
+! CHECK-DAG: fir.global internal @_QQ_QMmy_typesTinnertype.p.{{(null_box|init)}}
+! CHECK-DAG: fir.global internal @_QQ_QMmy_typesTinnertype.arr.null_box
\ No newline at end of file
>From 2013a119c00f304f8f6dde15129338376e0f59b2 Mon Sep 17 00:00:00 2001
From: hechenxi <hechenxi at bosc.ac.cn>
Date: Fri, 20 Mar 2026 16:08:44 +0800
Subject: [PATCH 2/7] Fix deprecated MLIR builder.create usages
---
flang/lib/Lower/ConvertVariable.cpp | 91 ++++++++++++++---------------
1 file changed, 45 insertions(+), 46 deletions(-)
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 16509b855ce9e..c114643d89e5a 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/Allocatable.h"
#include "flang/Lower/BoxAnalyzer.h"
@@ -19,7 +20,6 @@
#include "flang/Lower/ConvertExpr.h"
#include "flang/Lower/ConvertExprToHLFIR.h"
#include "flang/Lower/ConvertProcedureDesignator.h"
-#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/Mangler.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/StatementContext.h"
@@ -32,7 +32,6 @@
#include "flang/Optimizer/Builder/IntrinsicCall.h"
#include "flang/Optimizer/Builder/Runtime/Derived.h"
#include "flang/Optimizer/Builder/Todo.h"
-#include "flang/Optimizer/CodeGen/TypeConverter.h"
#include "flang/Optimizer/Dialect/CUF/CUFOps.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
@@ -40,7 +39,6 @@
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
-#include "flang/Optimizer/Support/DataLayout.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Support/Utils.h"
@@ -593,14 +591,15 @@ fir::GlobalOp Fortran::lower::defineGlobal(
if (details && details->init()) {
auto sym{*details->init()};
if (sym) // Has a procedure target.
- createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
- Fortran::lower::StatementContext stmtCtx(
- /*cleanupProhibited=*/true);
- auto box{Fortran::lower::convertProcedureDesignatorInitialTarget(
- converter, loc, *sym)};
- auto castTo{builder.createConvert(loc, symTy, box)};
- fir::HasValueOp::create(b, loc, castTo);
- });
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &b) {
+ Fortran::lower::StatementContext stmtCtx(
+ /*cleanupProhibited=*/true);
+ auto box{Fortran::lower::convertProcedureDesignatorInitialTarget(
+ converter, loc, *sym)};
+ auto castTo{builder.createConvert(loc, symTy, box)};
+ fir::HasValueOp::create(b, loc, castTo);
+ });
else { // Has NULL() target.
createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
auto box{fir::factory::createNullBoxProc(b, loc, symTy)};
@@ -889,12 +888,12 @@ static void genDerivedTypeComponentInit(
if (!compFirTy)
continue;
// Compute the memory coordinate of the current component.
- auto fieldIdx = builder.create<fir::FieldIndexOp>(
- loc, fir::FieldType::get(recTy.getContext()), name, recTy,
+ auto fieldIdx = fir::FieldIndexOp::create(
+ builder, loc, fir::FieldType::get(recTy.getContext()), name, recTy,
mlir::ValueRange{});
auto compAddr =
- builder.create<fir::CoordinateOp>(loc, builder.getRefType(compFirTy),
- baseAddr, mlir::ValueRange{fieldIdx});
+ fir::CoordinateOp::create(builder, loc, builder.getRefType(compFirTy),
+ baseAddr, mlir::ValueRange{fieldIdx});
// Case A: Standard data components (ObjectEntityDetails).
if (objDetails) {
@@ -915,13 +914,13 @@ static void genDerivedTypeComponentInit(
builder, global, [&](fir::FirOpBuilder &b) {
mlir::Value initBox = Fortran::lower::genInitialDataTarget(
converter, loc, compFirTy, *objDetails->init());
- b.create<fir::HasValueOp>(loc, initBox);
+ fir::HasValueOp::create(b, loc, initBox);
});
}
- auto srcAddr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
- global.getSymbol());
- mlir::Value loadedBox = builder.create<fir::LoadOp>(loc, srcAddr);
- builder.create<fir::StoreOp>(loc, loadedBox, compAddr);
+ auto srcAddr = fir::AddrOfOp::create(builder, loc, global.resultType(),
+ global.getSymbol());
+ mlir::Value loadedBox = fir::LoadOp::create(builder, loc, srcAddr);
+ fir::StoreOp::create(builder, loc, loadedBox, compAddr);
} else {
// Subcase A.1.2: Non-pointer components with explicit initialization.
Fortran::lower::StatementContext stmtCtx(/*cleanupProhibited=*/true);
@@ -940,10 +939,10 @@ static void genDerivedTypeComponentInit(
dataAttr);
}
if (global) {
- auto srcAddr = builder.create<fir::AddrOfOp>(
- loc, global.resultType(), global.getSymbol());
- builder.create<fir::CopyOp>(loc, srcAddr, compAddr,
- /*noOverlap=*/true);
+ auto srcAddr = fir::AddrOfOp::create(
+ builder, loc, global.resultType(), global.getSymbol());
+ fir::CopyOp::create(builder, loc, srcAddr, compAddr,
+ /*noOverlap=*/true);
} else {
Fortran::lower::StatementContext inlineCtx;
Fortran::lower::SymMap emptyMap;
@@ -951,7 +950,7 @@ static void genDerivedTypeComponentInit(
hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR(
loc, converter, objDetails->init().value(), emptyMap,
inlineCtx);
- builder.create<hlfir::AssignOp>(loc, rhs, lhs);
+ hlfir::AssignOp::create(builder, loc, rhs, lhs);
}
} else {
// Scalar component: Evaluate the expression and store directly.
@@ -960,10 +959,10 @@ static void genDerivedTypeComponentInit(
mlir::Value initVal = fir::getBase(exInitVal);
if (fir::isa_ref_type(initVal.getType()) &&
!fir::isa_ref_type(compFirTy))
- initVal = builder.create<fir::LoadOp>(loc, initVal);
+ initVal = fir::LoadOp::create(builder, loc, initVal);
mlir::Value castVal =
builder.createConvert(loc, compFirTy, initVal);
- builder.create<fir::StoreOp>(loc, castVal, compAddr);
+ fir::StoreOp::create(builder, loc, castVal, compAddr);
}
}
} else if (Fortran::semantics::IsAllocatableOrPointer(compSym)) {
@@ -982,13 +981,13 @@ static void genDerivedTypeComponentInit(
builder, global, [&](fir::FirOpBuilder &b) {
mlir::Value nullBox = fir::factory::createUnallocatedBox(
b, loc, compFirTy, mlir::ValueRange{});
- b.create<fir::HasValueOp>(loc, nullBox);
+ fir::HasValueOp::create(b, loc, nullBox);
});
}
- auto srcAddr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
- global.getSymbol());
- mlir::Value loadedBox = builder.create<fir::LoadOp>(loc, srcAddr);
- builder.create<fir::StoreOp>(loc, loadedBox, compAddr);
+ auto srcAddr = fir::AddrOfOp::create(builder, loc, global.resultType(),
+ global.getSymbol());
+ mlir::Value loadedBox = fir::LoadOp::create(builder, loc, srcAddr);
+ fir::StoreOp::create(builder, loc, loadedBox, compAddr);
} else if (Fortran::lower::hasDefaultInitialization(compSym)) {
// Subcase A.3: Nested derived type requires initialization.
// Derived type has no explicit initialization but contains
@@ -1012,7 +1011,7 @@ static void genDerivedTypeComponentInit(
mlir::Value initVal = genDefaultInitializerValue(
converter, loc, compSym, compFirTy, stmtCtx);
mlir::Value castVal = builder.createConvert(loc, compFirTy, initVal);
- builder.create<fir::StoreOp>(loc, castVal, compAddr);
+ fir::StoreOp::create(builder, loc, castVal, compAddr);
}
}
}
@@ -1041,13 +1040,13 @@ static void genDerivedTypeComponentInit(
} else {
procBox = fir::factory::createNullBoxProc(b, loc, compFirTy);
}
- b.create<fir::HasValueOp>(loc, procBox);
+ fir::HasValueOp::create(b, loc, procBox);
});
}
- auto srcAddr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
- global.getSymbol());
- mlir::Value loadedBox = builder.create<fir::LoadOp>(loc, srcAddr);
- builder.create<fir::StoreOp>(loc, loadedBox, compAddr);
+ auto srcAddr = fir::AddrOfOp::create(builder, loc, global.resultType(),
+ global.getSymbol());
+ mlir::Value loadedBox = fir::LoadOp::create(builder, loc, srcAddr);
+ fir::StoreOp::create(builder, loc, loadedBox, compAddr);
} else {
// Has no initialization.
continue;
@@ -1068,8 +1067,8 @@ void Fortran::lower::defaultInitializeAtRuntime(
// 15.5.2.12 point 3, absent optional dummies are not initialized.
// Creating descriptor/passing null descriptor to the runtime would
// create runtime crashes.
- auto isPresent = builder.create<fir::IsPresentOp>(loc, builder.getI1Type(),
- fir::getBase(exv));
+ auto isPresent = fir::IsPresentOp::create(builder, loc, builder.getI1Type(),
+ fir::getBase(exv));
builder.genIfThen(loc, isPresent)
.genThen([&]() {
auto box = builder.createBox(loc, exv);
@@ -1123,7 +1122,7 @@ void Fortran::lower::defaultInitializeAtRuntime(
converter, loc, details->init().value(), stmtCtx);
mlir::Value castTo =
builder.createConvert(loc, symTy, fir::getBase(initVal));
- builder.create<fir::HasValueOp>(loc, castTo);
+ fir::HasValueOp::create(builder, loc, castTo);
});
} else if (!global) {
global = builder.createGlobal(loc, symTy, globalName, linkage,
@@ -1138,13 +1137,13 @@ void Fortran::lower::defaultInitializeAtRuntime(
mlir::Value initVal = genDefaultInitializerValue(
converter, loc, sym, symTy, stmtCtx);
mlir::Value castTo = builder.createConvert(loc, symTy, initVal);
- builder.create<fir::HasValueOp>(loc, castTo);
+ fir::HasValueOp::create(builder, loc, castTo);
});
}
- auto addrOf = builder.create<fir::AddrOfOp>(loc, global.resultType(),
- global.getSymbol());
- builder.create<fir::CopyOp>(loc, addrOf, fir::getBase(exv),
- /*noOverlap=*/true);
+ auto addrOf = fir::AddrOfOp::create(builder, loc, global.resultType(),
+ global.getSymbol());
+ fir::CopyOp::create(builder, loc, addrOf, fir::getBase(exv),
+ /*noOverlap=*/true);
}
} else {
mlir::Value box = builder.createBox(loc, exv);
>From a09c761d8498644dd4e95603dd2a451a6acf7b3c Mon Sep 17 00:00:00 2001
From: hechenxi <hechenxi at bosc.ac.cn>
Date: Fri, 20 Mar 2026 20:04:00 +0800
Subject: [PATCH 3/7] Correct the format.
---
flang/lib/Lower/ConvertVariable.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index c114643d89e5a..8f2320729cfdd 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -917,8 +917,8 @@ static void genDerivedTypeComponentInit(
fir::HasValueOp::create(b, loc, initBox);
});
}
- auto srcAddr = fir::AddrOfOp::create(builder, loc, global.resultType(),
- global.getSymbol());
+ auto srcAddr = fir::AddrOfOp::create(
+ builder, loc, global.resultType(), global.getSymbol());
mlir::Value loadedBox = fir::LoadOp::create(builder, loc, srcAddr);
fir::StoreOp::create(builder, loc, loadedBox, compAddr);
} else {
@@ -1141,7 +1141,7 @@ void Fortran::lower::defaultInitializeAtRuntime(
});
}
auto addrOf = fir::AddrOfOp::create(builder, loc, global.resultType(),
- global.getSymbol());
+ global.getSymbol());
fir::CopyOp::create(builder, loc, addrOf, fir::getBase(exv),
/*noOverlap=*/true);
}
>From d9d8c06d4fad7f46af1a89c00b1318ce3309e192 Mon Sep 17 00:00:00 2001
From: hechenxi <hechenxi at bosc.ac.cn>
Date: Thu, 26 Mar 2026 15:47:12 +0800
Subject: [PATCH 4/7] New component-wise initialization logic.
---
flang/lib/Lower/ConvertVariable.cpp | 296 ++++++++---------------
flang/test/Lower/component-wise-init.f90 | 149 +++++++-----
2 files changed, 181 insertions(+), 264 deletions(-)
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 8f2320729cfdd..91b21e80621f3 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -49,11 +49,6 @@
#include "llvm/Support/Debug.h"
#include <optional>
-static llvm::cl::opt<bool> enablePreciseInit(
- "enable-precise-init",
- llvm::cl::desc("Enable precise component initialization for derived types"),
- llvm::cl::init(false));
-
static llvm::cl::opt<bool>
allowAssumedRank("allow-assumed-rank",
llvm::cl::desc("Enable assumed rank lowering"),
@@ -818,43 +813,39 @@ mustBeDefaultInitializedAtRuntime(const Fortran::lower::pft::Variable &var) {
return Fortran::lower::hasDefaultInitialization(sym);
}
-namespace {
-/// Determines if \p sym represents a complex derived type.
-/// A derived type is considered complex if it contains allocatable, pointer,
-/// or procedure pointer components, or nested complex derived types.
-static bool isComplexDerivedType(const Fortran::semantics::Symbol &sym) {
+/// Determines whether a derived type component requires non-trivial
+/// initialization. A component requires non-trivial initialization if it is an
+/// allocatable or pointer data component, or if it is a nested derived type
+/// that contains such components.
+static bool RequiresNonTrivialComponentInitialization(
+ const Fortran::semantics::Symbol &sym) {
const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType();
if (!declTy || !declTy->AsDerived())
return false;
const Fortran::semantics::DerivedTypeSpec &derivedSpec = *declTy->AsDerived();
const Fortran::semantics::Scope *scope = derivedSpec.GetScope();
- if (!scope)
- return false;
+ assert(scope && "derived type has no scope");
const auto &typeDetails =
derivedSpec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
+
for (const auto &compName : typeDetails.componentNames()) {
auto iter = scope->find(compName);
- if (iter == scope->cend())
- continue;
+ assert(iter != scope->cend() && "component symbol not found in scope");
const Fortran::semantics::Symbol &compSym = iter->second.get();
const auto *objDetails =
compSym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- const auto *procDetails =
- compSym.detailsIf<Fortran::semantics::ProcEntityDetails>();
- if (Fortran::semantics::IsAllocatableOrPointer(compSym)) {
- return true;
- } else if (procDetails && procDetails->init().has_value()) {
- return true;
- } else if (objDetails && objDetails->init() && compSym.Rank() > 0) {
- return true;
- } else if (isComplexDerivedType(compSym)) {
+ // If data component is an allocatable/pointer,
+ // or a nested derived type that requires initialization,
+ // return true.
+ if (objDetails && (Fortran::semantics::IsAllocatableOrPointer(compSym) ||
+ RequiresNonTrivialComponentInitialization(compSym))) {
return true;
}
}
return false;
}
-/// Performs precise, component-wise initialization for \p derivedSpec,
+/// Performs component-wise initialization for \p derivedSpec,
/// selectively generating IR only for components that require it.
static void genDerivedTypeComponentInit(
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
@@ -862,31 +853,34 @@ static void genDerivedTypeComponentInit(
mlir::Value baseAddr, fir::RecordType recTy) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
const Fortran::semantics::Scope *scope = derivedSpec.GetScope();
- if (!scope)
- return;
+ assert(scope && "derived type has no scope");
const auto &typeDetails =
derivedSpec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
+
for (const auto &compName : typeDetails.componentNames()) {
auto scopeIter = scope->find(compName);
- if (scopeIter == scope->cend())
- continue;
+ assert(scopeIter != scope->cend() &&
+ "component name must exist in its scope");
const Fortran::semantics::Symbol &compSym = scopeIter->second.get();
+ // Only process data components; procedure pointers are ignored.
const auto *objDetails =
compSym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- const auto *procDetails =
- compSym.detailsIf<Fortran::semantics::ProcEntityDetails>();
- // Determine if the component requires initialization.
- // Dynamic descriptors (pointers/allocatables) and explicitly initialized
- // entities must be processed.
- bool needsInit = Fortran::semantics::IsAllocatableOrPointer(compSym) ||
- (objDetails && objDetails->init()) ||
- (procDetails && procDetails->init().has_value());
- if (!needsInit && !Fortran::lower::hasDefaultInitialization(compSym))
+ if (!objDetails)
+ continue;
+
+ bool isPtrOrAlloc = Fortran::semantics::IsAllocatableOrPointer(compSym);
+ const Fortran::semantics::DeclTypeSpec *declTy = compSym.GetType();
+ bool isNestedDerived = declTy && declTy->AsDerived();
+ // Targets are pointer or allocatable components, or nested derived types
+ // containing them.
+ bool isTargetComponent =
+ isPtrOrAlloc ||
+ (isNestedDerived && RequiresNonTrivialComponentInitialization(compSym));
+ if (!isTargetComponent)
continue;
std::string name = converter.getRecordTypeFieldName(compSym);
mlir::Type compFirTy = recTy.getType(name);
- if (!compFirTy)
- continue;
+ assert(compFirTy && "Component field type not found in RecordType");
// Compute the memory coordinate of the current component.
auto fieldIdx = fir::FieldIndexOp::create(
builder, loc, fir::FieldType::get(recTy.getContext()), name, recTy,
@@ -894,167 +888,73 @@ static void genDerivedTypeComponentInit(
auto compAddr =
fir::CoordinateOp::create(builder, loc, builder.getRefType(compFirTy),
baseAddr, mlir::ValueRange{fieldIdx});
+ if (isPtrOrAlloc) {
+ // Target 1: pointer or allocatable component.
+ mlir::Value nullBox = fir::factory::createUnallocatedBox(
+ builder, loc, compFirTy, mlir::ValueRange{});
+ fir::StoreOp::create(builder, loc, nullBox, compAddr);
+ } else if (isNestedDerived) {
+ // Target 2: Nested derived type containing pointer/allocatable
+ // components.
+ auto nestedRecTy = mlir::cast<fir::RecordType>(compFirTy);
+ genDerivedTypeComponentInit(converter, loc, *declTy->AsDerived(),
+ compAddr, nestedRecTy);
+ }
+ }
+}
- // Case A: Standard data components (ObjectEntityDetails).
- if (objDetails) {
- if (objDetails->init()) {
- // Subcase A.1: Component has explicit initialization.
- if (Fortran::semantics::IsPointer(compSym)) {
- // Subcase A.1.1: Pointer with explicit target.
- std::string globalName = fir::NameUniquer::doGenerated(
- (converter.mangleName(derivedSpec) + fir::kNameSeparator + name +
- fir::kNameSeparator + "init")
- .str());
- fir::GlobalOp global = builder.getNamedGlobal(globalName);
- if (!global) {
- global = builder.createGlobal(loc, compFirTy, globalName,
- builder.createInternalLinkage(),
- mlir::Attribute{}, true);
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &b) {
- mlir::Value initBox = Fortran::lower::genInitialDataTarget(
- converter, loc, compFirTy, *objDetails->init());
- fir::HasValueOp::create(b, loc, initBox);
- });
+/// Checks if a derived type meets the criteria for component-wise
+/// initialization. The type must contain at least one pointer/allocatable
+/// component, and strictly NO explicit initialization anywhere in its
+/// hierarchy.
+static bool isEligibleForComponentWiseInit(
+ const Fortran::semantics::DerivedTypeSpec &derivedSpec) {
+ bool hasPtrOrAlloc = false;
+ auto checkImpl = [&](const Fortran::semantics::DerivedTypeSpec &spec,
+ auto &self) -> bool {
+ const Fortran::semantics::Scope *scope = spec.scope();
+ assert(scope && "derived type has no scope");
+ const auto &typeDetails =
+ spec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
+ for (const auto &compName : typeDetails.componentNames()) {
+ auto scopeIter = scope->find(compName);
+ assert(scopeIter != scope->cend() &&
+ "component name must exist in its scope");
+ const Fortran::semantics::Symbol &comp = scopeIter->second.get();
+ const auto *objDetails =
+ comp.detailsIf<Fortran::semantics::ObjectEntityDetails>();
+ const auto *procDetails =
+ comp.detailsIf<Fortran::semantics::ProcEntityDetails>();
+ // If any data component or procedure pointer has explicit
+ // initialization, abort and fall back to the global memcpy approach.
+ if ((objDetails && objDetails->init()) ||
+ (procDetails && procDetails->init())) {
+ return false;
+ }
+ if (Fortran::semantics::IsAllocatableOrPointer(comp)) {
+ hasPtrOrAlloc = true;
+ continue;
+ }
+ // Recursively traverse nested derived types.
+ if (const Fortran::semantics::DeclTypeSpec *declTy = comp.GetType()) {
+ if (const Fortran::semantics::DerivedTypeSpec *nestedSpec =
+ declTy->AsDerived()) {
+ // If it is an array of derived types that requires initialization,
+ // fall back to memcpy to avoid generating expensive runtime loops.
+ if (comp.Rank() > 0 &&
+ RequiresNonTrivialComponentInitialization(comp)) {
+ return false;
}
- auto srcAddr = fir::AddrOfOp::create(
- builder, loc, global.resultType(), global.getSymbol());
- mlir::Value loadedBox = fir::LoadOp::create(builder, loc, srcAddr);
- fir::StoreOp::create(builder, loc, loadedBox, compAddr);
- } else {
- // Subcase A.1.2: Non-pointer components with explicit initialization.
- Fortran::lower::StatementContext stmtCtx(/*cleanupProhibited=*/true);
- if (mlir::isa<fir::SequenceType>(compFirTy)) {
- std::string globalName = fir::NameUniquer::doGenerated(
- (converter.mangleName(derivedSpec) + fir::kNameSeparator +
- name + fir::kNameSeparator + "arr_init")
- .str());
- fir::GlobalOp global = builder.getNamedGlobal(globalName);
- if (!global) {
- const auto &initExpr = objDetails->init().value();
- cuf::DataAttributeAttr dataAttr = {};
- global = Fortran::lower::tryCreatingDenseGlobal(
- builder, loc, compFirTy, globalName,
- builder.createInternalLinkage(), /*isConst=*/true, initExpr,
- dataAttr);
- }
- if (global) {
- auto srcAddr = fir::AddrOfOp::create(
- builder, loc, global.resultType(), global.getSymbol());
- fir::CopyOp::create(builder, loc, srcAddr, compAddr,
- /*noOverlap=*/true);
- } else {
- Fortran::lower::StatementContext inlineCtx;
- Fortran::lower::SymMap emptyMap;
- hlfir::Entity lhs{compAddr};
- hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR(
- loc, converter, objDetails->init().value(), emptyMap,
- inlineCtx);
- hlfir::AssignOp::create(builder, loc, rhs, lhs);
- }
- } else {
- // Scalar component: Evaluate the expression and store directly.
- fir::ExtendedValue exInitVal = genInitializerExprValue(
- converter, loc, objDetails->init().value(), stmtCtx);
- mlir::Value initVal = fir::getBase(exInitVal);
- if (fir::isa_ref_type(initVal.getType()) &&
- !fir::isa_ref_type(compFirTy))
- initVal = fir::LoadOp::create(builder, loc, initVal);
- mlir::Value castVal =
- builder.createConvert(loc, compFirTy, initVal);
- fir::StoreOp::create(builder, loc, castVal, compAddr);
+ if (!self(*nestedSpec, self)) {
+ return false;
}
}
- } else if (Fortran::semantics::IsAllocatableOrPointer(compSym)) {
- // Subcase A.2: Pointer or allocatable without initialization.
- // Create deallocated/disassociated value.
- std::string globalName = fir::NameUniquer::doGenerated(
- (converter.mangleName(derivedSpec) + fir::kNameSeparator + name +
- fir::kNameSeparator + "null_box")
- .str());
- fir::GlobalOp global = builder.getNamedGlobal(globalName);
- if (!global) {
- global = builder.createGlobal(loc, compFirTy, globalName,
- builder.createInternalLinkage(),
- mlir::Attribute{}, true);
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &b) {
- mlir::Value nullBox = fir::factory::createUnallocatedBox(
- b, loc, compFirTy, mlir::ValueRange{});
- fir::HasValueOp::create(b, loc, nullBox);
- });
- }
- auto srcAddr = fir::AddrOfOp::create(builder, loc, global.resultType(),
- global.getSymbol());
- mlir::Value loadedBox = fir::LoadOp::create(builder, loc, srcAddr);
- fir::StoreOp::create(builder, loc, loadedBox, compAddr);
- } else if (Fortran::lower::hasDefaultInitialization(compSym)) {
- // Subcase A.3: Nested derived type requires initialization.
- // Derived type has no explicit initialization but contains
- // components requiring initialization.
- if (mlir::isa<fir::SequenceType>(compFirTy) &&
- isComplexDerivedType(compSym)) {
- // Complex derived type arrays.
- mlir::Value box =
- builder.createBox(loc, fir::ExtendedValue(compAddr));
- fir::runtime::genDerivedTypeInitialize(builder, loc, box);
- } else if (isComplexDerivedType(compSym)) {
- // Complex derived type scalars.
- const Fortran::semantics::DeclTypeSpec *compDeclTy =
- compSym.GetType();
- auto nestedRecTy = mlir::dyn_cast<fir::RecordType>(compFirTy);
- genDerivedTypeComponentInit(converter, loc, *compDeclTy->AsDerived(),
- compAddr, nestedRecTy);
- } else {
- // Simple derived type scalars.
- Fortran::lower::StatementContext stmtCtx;
- mlir::Value initVal = genDefaultInitializerValue(
- converter, loc, compSym, compFirTy, stmtCtx);
- mlir::Value castVal = builder.createConvert(loc, compFirTy, initVal);
- fir::StoreOp::create(builder, loc, castVal, compAddr);
- }
- }
- }
- // Case B: Procedure pointers (ProcEntityDetails).
- else if (procDetails) {
- if (procDetails->init().has_value()) {
- // Has a procedure or NULL() target.
- std::string globalName = fir::NameUniquer::doGenerated(
- (converter.mangleName(derivedSpec) + fir::kNameSeparator + name +
- fir::kNameSeparator + "init")
- .str());
- fir::GlobalOp global = builder.getNamedGlobal(globalName);
- if (!global) {
- global = builder.createGlobal(loc, compFirTy, globalName,
- builder.createInternalLinkage(),
- mlir::Attribute{}, true);
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &b) {
- mlir::Value procBox;
- auto targetSym = *procDetails->init();
- if (targetSym) {
- procBox =
- Fortran::lower::convertProcedureDesignatorInitialTarget(
- converter, loc, *targetSym);
- procBox = b.createConvert(loc, compFirTy, procBox);
- } else {
- procBox = fir::factory::createNullBoxProc(b, loc, compFirTy);
- }
- fir::HasValueOp::create(b, loc, procBox);
- });
- }
- auto srcAddr = fir::AddrOfOp::create(builder, loc, global.resultType(),
- global.getSymbol());
- mlir::Value loadedBox = fir::LoadOp::create(builder, loc, srcAddr);
- fir::StoreOp::create(builder, loc, loadedBox, compAddr);
- } else {
- // Has no initialization.
- continue;
}
}
- }
+ return true;
+ };
+ return checkImpl(derivedSpec, checkImpl) && hasPtrOrAlloc;
}
-} // namespace
/// Call default initialization runtime routine to initialize \p var.
void Fortran::lower::defaultInitializeAtRuntime(
@@ -1083,7 +983,7 @@ void Fortran::lower::defaultInitializeAtRuntime(
mlir::Type symTy = converter.genType(sym);
const auto *details =
sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- bool useFastInit =
+ bool isDerivedTypeScalar =
details && !Fortran::semantics::IsPolymorphic(sym) &&
declTy->category() ==
Fortran::semantics::DeclTypeSpec::Category::TypeDerived &&
@@ -1091,11 +991,11 @@ void Fortran::lower::defaultInitializeAtRuntime(
!sym.test(Fortran::semantics::Symbol::Flag::OmpPrivate) &&
!sym.test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate) &&
!Fortran::semantics::HasCUDAComponent(sym);
- if (useFastInit) {
- if (enablePreciseInit) {
- // Precise initialization
+ if (isDerivedTypeScalar) {
+ const auto &derivedSpec = *declTy->AsDerived();
+ if (isEligibleForComponentWiseInit(derivedSpec)) {
+ // Component-wise initialization
mlir::Value baseAddr = fir::getBase(exv);
- const auto &derivedSpec = *sym.GetType()->AsDerived();
auto recTy = mlir::cast<fir::RecordType>(
fir::unwrapPassByRefType(baseAddr.getType()));
genDerivedTypeComponentInit(converter, loc, derivedSpec, baseAddr,
diff --git a/flang/test/Lower/component-wise-init.f90 b/flang/test/Lower/component-wise-init.f90
index 2b751e784dc47..99633062c7619 100644
--- a/flang/test/Lower/component-wise-init.f90
+++ b/flang/test/Lower/component-wise-init.f90
@@ -1,94 +1,111 @@
-! RUN: bbc -emit-fir -enable-precise-init %s -o - | FileCheck %s
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
! Test for precise component-wise initialization of derived types
! to avoid generating large, fully-initialized global templates (sparse initialization).
module my_types
- type :: InnerType
- integer :: flag = 42
+ ! Clean internal type: contains only allocatable and pointer components,
+ ! without any explicit initialization.
+ type :: InnerClean
real, pointer :: p
real, allocatable :: arr(:)
- end type InnerType
+ end type InnerClean
- type :: OuterType
+ ! ============================================================================
+ ! Test Case 1: Type meeting all criteria for precise component-wise init (Target)
+ ! No arrays of derived types, no explicit initialization.
+ ! ============================================================================
+ type :: TargetType
real, pointer :: q
- integer :: explicit_arr(3) = [10, 20, 30]
- real(8) :: uninit_buffer(80, 100, 100)
- type(InnerType) :: nested
- type(InnerType) :: nested_arr(2)
- end type OuterType
+ real(8) :: uninit_buffer(80, 100) ! Large uninitialized array; should be bypassed.
+ type(InnerClean) :: nested_scalar ! Scalar derived type; should be expanded recursively.
+ end type TargetType
+
+ ! ============================================================================
+ ! Test Case 2: Type triggering fallback A (contains an array of derived type)
+ ! ============================================================================
+ type :: FallbackArrayType
+ type(InnerClean) :: nested_arr(10) ! Array of derived type; must trigger fallback.
+ end type FallbackArrayType
+
+ ! ============================================================================
+ ! Test Case 3: Type triggering fallback B (contains explicit initialization)
+ ! ============================================================================
+ type :: FallbackExplicitType
+ real, pointer :: p
+ integer :: flag = 999 ! Explicit initialization; must trigger gatekeeper!
+ end type FallbackExplicitType
end module my_types
-subroutine test_complex_init()
- use my_types
- type(OuterType) :: my_var
- call do_something(my_var)
-end subroutine test_complex_init
-
-! ==============================================================================
-! FileCheck Assertions
-! ==============================================================================
-
-! CHECK-LABEL: func.func @_QPtest_complex_init()
-
-! Ensure we allocate the local variable
-! CHECK: %[[MY_VAR:.*]] = fir.alloca !fir.type<_QMmy_typesToutertype{{.*}}>
! ------------------------------------------------------------------------------
-! 1. Check pointer 'q' initialization (First component, offset 0, no coordinate_of needed)
+! Test 1: FIR generation for precise component-wise initialization
! ------------------------------------------------------------------------------
-! CHECK: %[[Q_NULL_BOX_ADDR:.*]] = fir.address_of(@_QQ_QMmy_typesToutertype.q.{{(null_box|init)}})
-! CHECK: %[[Q_NULL_BOX:.*]] = fir.load %[[Q_NULL_BOX_ADDR]]
-! CHECK: fir.store %[[Q_NULL_BOX]] to %{{.*}}
+subroutine test_target()
+ use my_types
+ type(TargetType) :: my_var
+ call do_something_target(my_var)
+end subroutine test_target
-! ------------------------------------------------------------------------------
-! 2. Check explicit array initialization
-! ------------------------------------------------------------------------------
-! CHECK: %[[EXPLICIT_ARR_ADDR:.*]] = fir.coordinate_of %{{.*}}, explicit_arr
-! CHECK: %[[EXPLICIT_ARR_INIT:.*]] = fir.address_of(@_QQ_QMmy_typesToutertype.explicit_arr.arr_init)
-! CHECK: fir.copy %[[EXPLICIT_ARR_INIT]] to %[[EXPLICIT_ARR_ADDR]]
+! CHECK-LABEL: func.func @_QPtest_target()
+! Match the alloca and the subsequent declare
+! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<_QMmy_typesTtargettype{{.*}}>
+! CHECK: %[[MY_VAR:.*]] = fir.declare %[[ALLOCA]]
-! ------------------------------------------------------------------------------
-! 3. Check scalar derived type 'nested' component-wise precise initialization
-! ------------------------------------------------------------------------------
-! CHECK: %[[NESTED_ADDR:.*]] = fir.coordinate_of %{{.*}}, nested
+! 1. Check initialization of the outermost pointer 'q'
+! CHECK: %[[Q_ADDR:.*]] = fir.coordinate_of %[[MY_VAR]], q
+! CHECK: fir.store %{{.*}} to %[[Q_ADDR]]
-! -> Check 'flag' (integer = 42)
-! CHECK: %[[FLAG_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], flag
-! CHECK: fir.store %c42{{.*}} to %[[FLAG_ADDR]]
+! 2. Check recursive precise initialization of the scalar derived type 'nested_scalar'
+! CHECK: %[[NESTED_ADDR:.*]] = fir.coordinate_of %[[MY_VAR]], nested_scalar
-! -> Check 'p' (pointer)
+! -> Check internal pointer 'p'
! CHECK: %[[P_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], p
-! CHECK: %[[P_INIT_ADDR:.*]] = fir.address_of(@_QQ_QMmy_typesTinnertype.p.{{(null_box|init)}})
-! CHECK: %[[P_INIT_VAL:.*]] = fir.load %[[P_INIT_ADDR]]
-! CHECK: fir.store %[[P_INIT_VAL]] to %[[P_ADDR]]
+! CHECK: fir.store %{{.*}} to %[[P_ADDR]]
-! -> Check 'arr' (allocatable)
+! -> Check internal allocatable array 'arr'
! CHECK: %[[ARR_ADDR:.*]] = fir.coordinate_of %[[NESTED_ADDR]], arr
-! CHECK: %[[ARR_INIT_ADDR:.*]] = fir.address_of(@_QQ_QMmy_typesTinnertype.arr.null_box)
-! CHECK: %[[ARR_INIT_VAL:.*]] = fir.load %[[ARR_INIT_ADDR]]
-! CHECK: fir.store %[[ARR_INIT_VAL]] to %[[ARR_ADDR]]
+! CHECK: fir.store %{{.*}} to %[[ARR_ADDR]]
-! ------------------------------------------------------------------------------
-! 4. Check derived type array 'nested_arr' initialization (Runtime call)
-! ------------------------------------------------------------------------------
-! CHECK: %[[NESTED_ARR_ADDR:.*]] = fir.coordinate_of %{{.*}}, nested_arr
-! CHECK: %[[NESTED_ARR_BOX:.*]] = fir.embox %[[NESTED_ARR_ADDR]]
-! CHECK: %[[NESTED_ARR_PTR:.*]] = fir.convert %[[NESTED_ARR_BOX]]
-! CHECK: fir.call @_FortranAInitialize(%[[NESTED_ARR_PTR]], {{.*}})
+! CRITICAL 1: Ensure NO expensive runtime calls are generated.
+! CHECK-NOT: fir.call @_FortranAInitialize
+
+! CRITICAL 2: Ensure NO large global initialization templates are generated for TargetType.
+! CHECK-NOT: fir.global internal @_QQ_QMmy_typesTtargettype.DerivedInit
! ------------------------------------------------------------------------------
-! Global Variables Check
+! Test 2: Fallback mechanism for arrays of derived types
! ------------------------------------------------------------------------------
+subroutine test_fallback_array()
+ use my_types
+ type(FallbackArrayType) :: var_array
+ call do_something_array(var_array)
+end subroutine test_fallback_array
-! CRITICAL: Ensure NO full derived type initialization templates are generated!
-! We should NOT see fir.global for the entire DerivedInit.
-! CHECK-NOT: fir.global internal @_QQ_QMmy_typesToutertype.DerivedInit
-! CHECK-NOT: fir.global internal @_QQ_QMmy_typesTinnertype.DerivedInit
+! CHECK-LABEL: func.func @_QPtest_fallback_array()
+! CHECK: %[[ALLOCA_ARR:.*]] = fir.alloca !fir.type<_QMmy_typesTfallbackarraytype{{.*}}>
+! CHECK: %[[VAR_ARRAY:.*]] = fir.declare %[[ALLOCA_ARR]]
+!
+! Ensure FallbackArrayType falls back to the highly optimized memcpy from a global template,
+! entirely avoiding the runtime loop initialization.
+! CHECK: %[[GLOBAL_INIT_ARR:.*]] = fir.address_of(@_QQ_QMmy_typesTfallbackarraytype.DerivedInit)
+! CHECK: fir.copy %[[GLOBAL_INIT_ARR]] to %[[VAR_ARRAY]]
-! Verify the fine-grained component global constants exist
-! CHECK-DAG: fir.global internal @_QQ_QMmy_typesToutertype.explicit_arr.arr_init(dense<[10, 20, 30]> : tensor<3xi32>)
-! CHECK-DAG: fir.global internal @_QQ_QMmy_typesToutertype.q.{{(null_box|init)}}
-! CHECK-DAG: fir.global internal @_QQ_QMmy_typesTinnertype.p.{{(null_box|init)}}
-! CHECK-DAG: fir.global internal @_QQ_QMmy_typesTinnertype.arr.null_box
\ No newline at end of file
+
+! ------------------------------------------------------------------------------
+! Test 3: Fallback mechanism for explicit initialization
+! ------------------------------------------------------------------------------
+subroutine test_fallback_explicit()
+ use my_types
+ type(FallbackExplicitType) :: var_explicit
+ call do_something_explicit(var_explicit)
+end subroutine test_fallback_explicit
+
+! CHECK-LABEL: func.func @_QPtest_fallback_explicit()
+! CHECK: %[[ALLOCA_EXP:.*]] = fir.alloca !fir.type<_QMmy_typesTfallbackexplicittype{{.*}}>
+! CHECK: %[[VAR_EXPLICIT:.*]] = fir.declare %[[ALLOCA_EXP]]
+!
+! Ensure types with explicit initialization trigger the gatekeeper and fall back to the old logic.
+! CHECK: %[[GLOBAL_INIT_EXP:.*]] = fir.address_of(@_QQ_QMmy_typesTfallbackexplicittype.DerivedInit)
+! CHECK: fir.copy %[[GLOBAL_INIT_EXP]] to %[[VAR_EXPLICIT]]
\ No newline at end of file
>From 364e5dc2722af774d8011b6dec6c6fc2842c184e Mon Sep 17 00:00:00 2001
From: hechenxi <hechenxi at bosc.ac.cn>
Date: Wed, 8 Apr 2026 19:11:22 +0800
Subject: [PATCH 5/7] Refactor derived type initialization and update tests.
---
flang/lib/Lower/ConvertVariable.cpp | 257 ++++++++----------
.../Lower/HLFIR/structure-constructor.f90 | 215 +++++++++------
.../Lower/OpenMP/private-derived-type.f90 | 12 +-
flang/test/Lower/call-copy-in-out.f90 | 257 ++++++++++++++----
flang/test/Lower/component-wise-init.f90 | 2 +-
flang/test/Lower/default-initialization.f90 | 64 +++--
.../test/Lower/derived-type-finalization.f90 | 111 +++++---
flang/test/Lower/derived-type-temp.f90 | 8 +-
.../Lower/forall/forall-allocatable-2.f90 | 75 ++---
flang/test/Lower/pointer-default-init.f90 | 8 +-
10 files changed, 606 insertions(+), 403 deletions(-)
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 91b21e80621f3..767173f654e53 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -45,6 +45,8 @@
#include "flang/Runtime/allocator-registry-consts.h"
#include "flang/Semantics/runtime-type-info.h"
#include "flang/Semantics/tools.h"
+#include "flang/Semantics/type.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include <optional>
@@ -813,38 +815,6 @@ mustBeDefaultInitializedAtRuntime(const Fortran::lower::pft::Variable &var) {
return Fortran::lower::hasDefaultInitialization(sym);
}
-/// Determines whether a derived type component requires non-trivial
-/// initialization. A component requires non-trivial initialization if it is an
-/// allocatable or pointer data component, or if it is a nested derived type
-/// that contains such components.
-static bool RequiresNonTrivialComponentInitialization(
- const Fortran::semantics::Symbol &sym) {
- const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType();
- if (!declTy || !declTy->AsDerived())
- return false;
- const Fortran::semantics::DerivedTypeSpec &derivedSpec = *declTy->AsDerived();
- const Fortran::semantics::Scope *scope = derivedSpec.GetScope();
- assert(scope && "derived type has no scope");
- const auto &typeDetails =
- derivedSpec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
-
- for (const auto &compName : typeDetails.componentNames()) {
- auto iter = scope->find(compName);
- assert(iter != scope->cend() && "component symbol not found in scope");
- const Fortran::semantics::Symbol &compSym = iter->second.get();
- const auto *objDetails =
- compSym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- // If data component is an allocatable/pointer,
- // or a nested derived type that requires initialization,
- // return true.
- if (objDetails && (Fortran::semantics::IsAllocatableOrPointer(compSym) ||
- RequiresNonTrivialComponentInitialization(compSym))) {
- return true;
- }
- }
- return false;
-}
-
/// Performs component-wise initialization for \p derivedSpec,
/// selectively generating IR only for components that require it.
static void genDerivedTypeComponentInit(
@@ -852,81 +822,123 @@ static void genDerivedTypeComponentInit(
const Fortran::semantics::DerivedTypeSpec &derivedSpec,
mlir::Value baseAddr, fir::RecordType recTy) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
- const Fortran::semantics::Scope *scope = derivedSpec.GetScope();
- assert(scope && "derived type has no scope");
- const auto &typeDetails =
- derivedSpec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
-
- for (const auto &compName : typeDetails.componentNames()) {
- auto scopeIter = scope->find(compName);
- assert(scopeIter != scope->cend() &&
- "component name must exist in its scope");
- const Fortran::semantics::Symbol &compSym = scopeIter->second.get();
- // Only process data components; procedure pointers are ignored.
- const auto *objDetails =
- compSym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- if (!objDetails)
- continue;
-
- bool isPtrOrAlloc = Fortran::semantics::IsAllocatableOrPointer(compSym);
- const Fortran::semantics::DeclTypeSpec *declTy = compSym.GetType();
- bool isNestedDerived = declTy && declTy->AsDerived();
- // Targets are pointer or allocatable components, or nested derived types
- // containing them.
- bool isTargetComponent =
- isPtrOrAlloc ||
- (isNestedDerived && RequiresNonTrivialComponentInitialization(compSym));
- if (!isTargetComponent)
+ // Flattened DFS traversal to visit only the leaf components.
+ Fortran::semantics::UltimateComponentIterator ultimateIter{derivedSpec};
+ for (auto it = ultimateIter.begin(); it != ultimateIter.end(); ++it) {
+ const Fortran::semantics::Symbol &comp = *it;
+ if (!comp.has<Fortran::semantics::ObjectEntityDetails>() ||
+ !Fortran::semantics::IsAllocatableOrPointer(comp))
continue;
- std::string name = converter.getRecordTypeFieldName(compSym);
- mlir::Type compFirTy = recTy.getType(name);
- assert(compFirTy && "Component field type not found in RecordType");
- // Compute the memory coordinate of the current component.
- auto fieldIdx = fir::FieldIndexOp::create(
- builder, loc, fir::FieldType::get(recTy.getContext()), name, recTy,
- mlir::ValueRange{});
- auto compAddr =
- fir::CoordinateOp::create(builder, loc, builder.getRefType(compFirTy),
- baseAddr, mlir::ValueRange{fieldIdx});
- if (isPtrOrAlloc) {
- // Target 1: pointer or allocatable component.
- mlir::Value nullBox = fir::factory::createUnallocatedBox(
- builder, loc, compFirTy, mlir::ValueRange{});
- fir::StoreOp::create(builder, loc, nullBox, compAddr);
- } else if (isNestedDerived) {
- // Target 2: Nested derived type containing pointer/allocatable
- // components.
- auto nestedRecTy = mlir::cast<fir::RecordType>(compFirTy);
- genDerivedTypeComponentInit(converter, loc, *declTy->AsDerived(),
- compAddr, nestedRecTy);
+ // Retrieve the nested symbol path from the root type to this ultimate
+ // component.
+ auto path = it.GetComponentPath();
+ mlir::Value currentAddr = baseAddr;
+ fir::RecordType currentRecTy = recTy;
+ // Traverse the path and calculate memory coordinates.
+ for (const Fortran::semantics::Symbol &pathSym : path) {
+ const Fortran::semantics::Symbol *symPtr = &pathSym;
+ // Generate coordinate for this nesting level.
+ std::string name = converter.getRecordTypeFieldName(*symPtr);
+ mlir::Type compFirTy = currentRecTy.getType(name);
+ assert(compFirTy && "Component field type not found in RecordType");
+ auto fieldIdx = fir::FieldIndexOp::create(
+ builder, loc, fir::FieldType::get(currentRecTy.getContext()), name,
+ currentRecTy, mlir::ValueRange{});
+ currentAddr =
+ fir::CoordinateOp::create(builder, loc, builder.getRefType(compFirTy),
+ currentAddr, mlir::ValueRange{fieldIdx});
+ currentRecTy = mlir::dyn_cast<fir::RecordType>(compFirTy);
}
+ mlir::Type finalCompFirTy = fir::unwrapPassByRefType(currentAddr.getType());
+ mlir::Value nullBox = fir::factory::createUnallocatedBox(
+ builder, loc, finalCompFirTy, mlir::ValueRange{});
+ fir::StoreOp::create(builder, loc, nullBox, currentAddr);
}
}
-/// Checks if a derived type meets the criteria for component-wise
-/// initialization. The type must contain at least one pointer/allocatable
-/// component, and strictly NO explicit initialization anywhere in its
-/// hierarchy.
+/// Initializes a derived type via a bulk memory copy (memcpy).
+/// This method generates a global constant containing the default
+/// initialized state of the type, and copies it directly into the
+/// target memory location.
+static void
+genInlinedInitWithMemcpy(Fortran::lower::AbstractConverter &converter,
+ const Fortran::semantics::Symbol &sym,
+ mlir::Type symTy, const fir::ExtendedValue &exv,
+ const Fortran::semantics::ObjectEntityDetails *details,
+ const Fortran::semantics::DeclTypeSpec *declTy) {
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ mlir::Location symLoc = genLocation(converter, sym);
+ std::string globalName = fir::NameUniquer::doGenerated(
+ (converter.mangleName(*declTy->AsDerived()) + fir::kNameSeparator +
+ fir::kDerivedTypeInitSuffix)
+ .str());
+ mlir::StringAttr linkage = builder.createInternalLinkage();
+ fir::GlobalOp global = builder.getNamedGlobal(globalName);
+ if (!global && details->init()) {
+ global = builder.createGlobal(symLoc, symTy, globalName, linkage,
+ mlir::Attribute{},
+ /*isConst=*/true,
+ /*isTarget=*/false,
+ /*dataAttr=*/{});
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &builder) {
+ Fortran::lower::StatementContext stmtCtx(
+ /*cleanupProhibited=*/true);
+ fir::ExtendedValue initVal = genInitializerExprValue(
+ converter, symLoc, details->init().value(), stmtCtx);
+ mlir::Value castTo =
+ builder.createConvert(symLoc, symTy, fir::getBase(initVal));
+ fir::HasValueOp::create(builder, symLoc, castTo);
+ });
+ } else if (!global) {
+ global = builder.createGlobal(symLoc, symTy, globalName, linkage,
+ mlir::Attribute{},
+ /*isConst=*/true,
+ /*isTarget=*/false,
+ /*dataAttr=*/{});
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &builder) {
+ Fortran::lower::StatementContext stmtCtx(
+ /*cleanupProhibited=*/true);
+ mlir::Value initVal = genDefaultInitializerValue(converter, symLoc,
+ sym, symTy, stmtCtx);
+ mlir::Value castTo = builder.createConvert(symLoc, symTy, initVal);
+ fir::HasValueOp::create(builder, symLoc, castTo);
+ });
+ }
+ auto addrOf = fir::AddrOfOp::create(builder, symLoc, global.resultType(),
+ global.getSymbol());
+ fir::CopyOp::create(builder, symLoc, addrOf, fir::getBase(exv),
+ /*noOverlap=*/true);
+}
+
+/// Checks if a derived type is eligible for component-wise initialization.
+/// This is preferred over a bulk memcpy when the type contains at least
+/// one pointer/allocatable component, but no components with explicit
+/// default initializers.
static bool isEligibleForComponentWiseInit(
const Fortran::semantics::DerivedTypeSpec &derivedSpec) {
bool hasPtrOrAlloc = false;
- auto checkImpl = [&](const Fortran::semantics::DerivedTypeSpec &spec,
- auto &self) -> bool {
- const Fortran::semantics::Scope *scope = spec.scope();
+ // Worklist for iterative traversal of the derived type tree.
+ llvm::SmallVector<const Fortran::semantics::DerivedTypeSpec *> worklist;
+ worklist.push_back(&derivedSpec);
+ while (!worklist.empty()) {
+ const Fortran::semantics::DerivedTypeSpec *currentSpec =
+ worklist.pop_back_val();
+ const Fortran::semantics::Scope *scope = currentSpec->scope();
assert(scope && "derived type has no scope");
const auto &typeDetails =
- spec.typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
+ currentSpec->typeSymbol().get<Fortran::semantics::DerivedTypeDetails>();
for (const auto &compName : typeDetails.componentNames()) {
auto scopeIter = scope->find(compName);
assert(scopeIter != scope->cend() &&
"component name must exist in its scope");
const Fortran::semantics::Symbol &comp = scopeIter->second.get();
+ // Return false if any component has an explicit default initializer.
const auto *objDetails =
comp.detailsIf<Fortran::semantics::ObjectEntityDetails>();
const auto *procDetails =
comp.detailsIf<Fortran::semantics::ProcEntityDetails>();
- // If any data component or procedure pointer has explicit
- // initialization, abort and fall back to the global memcpy approach.
if ((objDetails && objDetails->init()) ||
(procDetails && procDetails->init())) {
return false;
@@ -935,25 +947,23 @@ static bool isEligibleForComponentWiseInit(
hasPtrOrAlloc = true;
continue;
}
- // Recursively traverse nested derived types.
+ // Traverse nested derived types.
if (const Fortran::semantics::DeclTypeSpec *declTy = comp.GetType()) {
if (const Fortran::semantics::DerivedTypeSpec *nestedSpec =
declTy->AsDerived()) {
- // If it is an array of derived types that requires initialization,
- // fall back to memcpy to avoid generating expensive runtime loops.
- if (comp.Rank() > 0 &&
- RequiresNonTrivialComponentInitialization(comp)) {
- return false;
- }
- if (!self(*nestedSpec, self)) {
- return false;
+ if (Fortran::lower::hasDefaultInitialization(comp)) {
+ // Return false for arrays of derived types requiring
+ // initialization.
+ if (comp.Rank() > 0) {
+ return false;
+ }
+ worklist.push_back(nestedSpec);
}
}
}
}
- return true;
- };
- return checkImpl(derivedSpec, checkImpl) && hasPtrOrAlloc;
+ }
+ return hasPtrOrAlloc;
}
/// Call default initialization runtime routine to initialize \p var.
@@ -994,56 +1004,15 @@ void Fortran::lower::defaultInitializeAtRuntime(
if (isDerivedTypeScalar) {
const auto &derivedSpec = *declTy->AsDerived();
if (isEligibleForComponentWiseInit(derivedSpec)) {
- // Component-wise initialization
+ // Component-wise initialization.
mlir::Value baseAddr = fir::getBase(exv);
auto recTy = mlir::cast<fir::RecordType>(
fir::unwrapPassByRefType(baseAddr.getType()));
genDerivedTypeComponentInit(converter, loc, derivedSpec, baseAddr,
recTy);
} else {
- std::string globalName = fir::NameUniquer::doGenerated(
- (converter.mangleName(*declTy->AsDerived()) + fir::kNameSeparator +
- fir::kDerivedTypeInitSuffix)
- .str());
- mlir::Location loc = genLocation(converter, sym);
- mlir::StringAttr linkage = builder.createInternalLinkage();
- fir::GlobalOp global = builder.getNamedGlobal(globalName);
- if (!global && details->init()) {
- global = builder.createGlobal(loc, symTy, globalName, linkage,
- mlir::Attribute{},
- /*isConst=*/true,
- /*isTarget=*/false,
- /*dataAttr=*/{});
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &builder) {
- Fortran::lower::StatementContext stmtCtx(
- /*cleanupProhibited=*/true);
- fir::ExtendedValue initVal = genInitializerExprValue(
- converter, loc, details->init().value(), stmtCtx);
- mlir::Value castTo =
- builder.createConvert(loc, symTy, fir::getBase(initVal));
- fir::HasValueOp::create(builder, loc, castTo);
- });
- } else if (!global) {
- global = builder.createGlobal(loc, symTy, globalName, linkage,
- mlir::Attribute{},
- /*isConst=*/true,
- /*isTarget=*/false,
- /*dataAttr=*/{});
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &builder) {
- Fortran::lower::StatementContext stmtCtx(
- /*cleanupProhibited=*/true);
- mlir::Value initVal = genDefaultInitializerValue(
- converter, loc, sym, symTy, stmtCtx);
- mlir::Value castTo = builder.createConvert(loc, symTy, initVal);
- fir::HasValueOp::create(builder, loc, castTo);
- });
- }
- auto addrOf = fir::AddrOfOp::create(builder, loc, global.resultType(),
- global.getSymbol());
- fir::CopyOp::create(builder, loc, addrOf, fir::getBase(exv),
- /*noOverlap=*/true);
+ // Initialize via bulk memory copy from a global constant.
+ genInlinedInitWithMemcpy(converter, sym, symTy, exv, details, declTy);
}
} else {
mlir::Value box = builder.createBox(loc, exv);
diff --git a/flang/test/Lower/HLFIR/structure-constructor.f90 b/flang/test/Lower/HLFIR/structure-constructor.f90
index 094aeaa14f682..871bd645b41c3 100644
--- a/flang/test/Lower/HLFIR/structure-constructor.f90
+++ b/flang/test/Lower/HLFIR/structure-constructor.f90
@@ -38,12 +38,13 @@ end subroutine test1
! CHECK-LABEL: func.func @_QPtest1(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}> {bindc_name = "res", uniq_name = "_QFtest1Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest1Eres"} : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>)
! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>>
! CHECK: %[[VAL_6:.*]] = arith.constant 4 : index
-! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
+! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %[[SCOPE]] arg 1 {uniq_name = "_QFtest1Ex"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>)
! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_8]]#0 : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> !fir.box<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>
! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
@@ -51,9 +52,9 @@ end subroutine test1
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> !fir.box<none>
! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_10]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: fir.call @_FortranAInitialize(%[[VAL_12]], %[[VAL_13]], %[[VAL_11]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_15:.*]] = arith.constant 4 : index
-! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_8]]#0{"c"} typeparams %[[VAL_15]] : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, index) -> !fir.ref<!fir.char<1,4>>
-! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_16]] temporary_lhs : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>
+! CHECK: %[[VAL_14:.*]] = arith.constant 4 : index
+! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_8]]#0{"c"} typeparams %[[VAL_14]] : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, index) -> !fir.ref<!fir.char<1,4>>
+! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_15]] temporary_lhs : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>
! CHECK: hlfir.assign %[[VAL_8]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>
! CHECK: return
! CHECK: }
@@ -67,11 +68,12 @@ end subroutine test2
! CHECK-LABEL: func.func @_QPtest2(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt2{i:!fir.array<10xi32>}> {bindc_name = "res", uniq_name = "_QFtest2Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest2Eres"} : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>)
! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index
! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
+! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[SCOPE]] arg 1 {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>)
! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_7]]#0 : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> !fir.box<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>
! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
@@ -79,10 +81,10 @@ end subroutine test2
! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> !fir.box<none>
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_9]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: fir.call @_FortranAInitialize(%[[VAL_11]], %[[VAL_12]], %[[VAL_10]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_14:.*]] = arith.constant 10 : index
-! CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_14]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_7]]#0{"i"} <%[[VAL_15]]> shape %[[VAL_15]] : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.shape<1>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>>
-! CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_16]] temporary_lhs : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>
+! CHECK: %[[VAL_13:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_14:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_7]]#0{"i"} <%[[VAL_14]]> shape %[[VAL_14]] : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.shape<1>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>>
+! CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_15]] temporary_lhs : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>
! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>
! CHECK: return
! CHECK: }
@@ -96,26 +98,31 @@ end subroutine test3
! CHECK-LABEL: func.func @_QPtest3(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {bindc_name = "res", uniq_name = "_QFtest3Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest3Eres"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>)
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt3.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_3]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
-! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>)
-! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>)
-! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
-! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
-! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<none>
-! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
-! CHECK: fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"r"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_20:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_21:.*]]:3 = fir.box_dims %[[VAL_19]], %[[VAL_20]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
-! CHECK: %[[VAL_22:.*]] = fir.shift %[[VAL_21]]#0 : (index) -> !fir.shift<1>
-! CHECK: %[[VAL_23:.*]] = fir.rebox %[[VAL_19]](%[[VAL_22]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
-! CHECK: fir.store %[[VAL_23]] to %[[VAL_18]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_3]]#0, r : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_5:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
+! CHECK: %[[VAL_6:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_5]](%[[VAL_7]]) : (!fir.ptr<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
+! CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>)
+! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>)
+! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_10]]#0 : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
+! CHECK: %[[VAL_13:.*]] = arith.constant {{[0-9]*}} : i32
+! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
+! CHECK: fir.call @_FortranAInitialize(%[[VAL_14]], %[[VAL_15]], %[[VAL_13]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_10]]#0{"r"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_18:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_19:.*]]:3 = fir.box_dims %[[VAL_17]], %[[VAL_18]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_20:.*]] = fir.shift %[[VAL_19]]#0 : (index) -> !fir.shift<1>
+! CHECK: %[[VAL_21:.*]] = fir.rebox %[[VAL_17]](%[[VAL_20]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
+! CHECK: fir.store %[[VAL_21]] to %[[VAL_16]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: hlfir.assign %[[VAL_10]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
! CHECK: return
! CHECK: }
@@ -128,37 +135,41 @@ end subroutine test4
! CHECK-LABEL: func.func @_QPtest4(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}> {bindc_name = "res", uniq_name = "_QFtest4Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest4Eres"} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>)
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt4.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_3]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
-! CHECK: %[[VAL_10:.*]] = arith.constant 2 : index
-! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_10]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>)
-! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>)
-! CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_12]]#0 : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
-! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
-! CHECK: %[[VAL_15:.*]] = arith.constant {{[0-9]*}} : i32
-! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
-! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_14]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
-! CHECK: fir.call @_FortranAInitialize(%[[VAL_16]], %[[VAL_17]], %[[VAL_15]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_19:.*]] = arith.constant 2 : index
-! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_12]]#0{"c"} typeparams %[[VAL_19]] {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
-! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
-! CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_21]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,2>>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (!fir.heap<!fir.array<?x!fir.char<1,2>>>) -> i64
-! CHECK: %[[VAL_24:.*]] = arith.constant 0 : i64
-! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i64
-! CHECK: fir.if %[[VAL_25]] {
-! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_3]]#0, c : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_5:.*]] = fir.zero_bits !fir.heap<!fir.array<?x!fir.char<1,2>>>
+! CHECK: %[[VAL_6:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_5]](%[[VAL_7]]) : (!fir.heap<!fir.array<?x!fir.char<1,2>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>
+! CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_9:.*]] = arith.constant 2 : index
+! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_9]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>)
+! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>)
+! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
+! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
+! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
+! CHECK: fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: %[[VAL_17:.*]] = arith.constant 2 : index
+! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"c"} typeparams %[[VAL_17]] {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_20:.*]] = fir.box_addr %[[VAL_19]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,2>>>
+! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.char<1,2>>>) -> i64
+! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
+! CHECK: fir.if %[[VAL_23]] {
+! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_18]] realloc keep_lhs_len temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
! CHECK: }
-! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
-! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_27]]
+! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
+! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_25]])
! CHECK: return
! CHECK: }
-
subroutine test5(x)
use types
type(t4), allocatable :: x(:)
@@ -168,31 +179,36 @@ end subroutine test5
! CHECK-LABEL: func.func @_QPtest5(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}> {bindc_name = "res", uniq_name = "_QFtest5Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest5Eres"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>)
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt5.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_3]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
-! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest5Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
-! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>)
-! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
-! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
-! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
-! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
-! CHECK: fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"t5m"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: %[[VAL_20:.*]] = fir.box_addr %[[VAL_19]] : (!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>) -> !fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>
-! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>) -> i64
-! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
-! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
-! CHECK: fir.if %[[VAL_23]] {
-! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_18]] realloc temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_3]]#0, t5m : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_5:.*]] = fir.zero_bits !fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>
+! CHECK: %[[VAL_6:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_5]](%[[VAL_7]]) : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>
+! CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest5Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
+! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>)
+! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_10]]#0 : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
+! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
+! CHECK: %[[VAL_13:.*]] = arith.constant {{[0-9]*}} : i32
+! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
+! CHECK: fir.call @_FortranAInitialize(%[[VAL_14]], %[[VAL_15]], %[[VAL_13]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_10]]#0{"t5m"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_18:.*]] = fir.box_addr %[[VAL_17]] : (!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>) -> !fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>
+! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>) -> i64
+! CHECK: %[[VAL_20:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_21:.*]] = arith.cmpi ne, %[[VAL_19]], %[[VAL_20]] : i64
+! CHECK: fir.if %[[VAL_21]] {
+! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: hlfir.assign %[[VAL_22]] to %[[VAL_16]] realloc temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
! CHECK: }
-! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_24]]
+! CHECK: hlfir.assign %[[VAL_10]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
+! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_23]])
! CHECK: return
! CHECK: }
@@ -211,15 +227,21 @@ end subroutine test6
! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>>> {bindc_name = ".tmp.arrayctor"}
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>
! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>>
! CHECK: %[[VAL_9:.*]] = arith.constant 4 : index
-! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest6Ec"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
+! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %[[SCOPE]] arg 2 {uniq_name = "_QFtest6Ec"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
! CHECK: %[[VAL_11:.*]] = fir.alloca !fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}> {bindc_name = "res", uniq_name = "_QFtest6Eres"}
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFtest6Eres"} : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>)
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt6.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_12]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>
-! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest6Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
+! CHECK: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_12]]#0, t5 : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
+! CHECK: %[[VAL_14:.*]] = fir.coordinate_of %[[VAL_13]], t5m : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_15:.*]] = fir.zero_bits !fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>
+! CHECK: %[[VAL_16:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_16]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_15]](%[[VAL_17]]) : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>
+! CHECK: fir.store %[[VAL_18]] to %[[VAL_14]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest6Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>)
! CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]]#0 : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.box<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>
! CHECK: %[[VAL_22:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
@@ -279,9 +301,9 @@ end subroutine test6
! CHECK: hlfir.assign %[[VAL_70]] to %[[VAL_44]] temporary_lhs : !hlfir.expr<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>>
! CHECK: hlfir.assign %[[VAL_20]]#0 to %[[VAL_12]]#0 : !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>
! CHECK: %[[VAL_71:.*]] = fir.convert %[[VAL_21]] : (!fir.box<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_71]]
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_71]])
! CHECK: %[[VAL_72:.*]] = fir.convert %[[VAL_29]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_72]]
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_72]])
! CHECK: return
! CHECK: }
@@ -299,11 +321,16 @@ end subroutine test7
! CHECK-LABEL: func.func @_QPtest7(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>
-! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest7En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest7En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QFtest7Ex"}
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest7Ex"} : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt7.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_4]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_4]]#0, c2 : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+! CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_6]](%[[VAL_8]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+! CHECK: fir.store %[[VAL_9]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
@@ -315,6 +342,8 @@ end subroutine test7
! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32>
! CHECK: hlfir.assign %[[VAL_19]] to %[[VAL_18]] temporary_lhs : i32, !fir.ref<i32>
! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_4]]#0 : !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_20]])
! CHECK: return
! CHECK: }
@@ -328,10 +357,13 @@ subroutine test8
end subroutine test8
! CHECK-LABEL: func.func @_QPtest8() {
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}> {bindc_name = "res", uniq_name = "_QFtest8Eres"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest8Eres"} : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>)
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt8.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_2]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
+! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_2]]#0, c : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
+! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.heap<!fir.char<1,11>>
+! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]] : (!fir.heap<!fir.char<1,11>>) -> !fir.box<!fir.heap<!fir.char<1,11>>>
+! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,12>>> {bindc_name = "x", uniq_name = "_QFtest8Ex"}
! CHECK: %[[VAL_10:.*]] = arith.constant 12 : index
! CHECK: %[[VAL_11:.*]] = fir.zero_bits !fir.heap<!fir.char<1,12>>
@@ -359,7 +391,7 @@ end subroutine test8
! CHECK: }
! CHECK: hlfir.assign %[[VAL_14]]#0 to %[[VAL_2]]#0 : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_15]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_30]]
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_30]])
! CHECK: return
! CHECK: }
@@ -373,10 +405,13 @@ subroutine test9
end subroutine test9
! CHECK-LABEL: func.func @_QPtest9() {
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}> {bindc_name = "res", uniq_name = "_QFtest9Eres"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest9Eres"} : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>)
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtypesTt8.DerivedInit) : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_2]]#0 no_overlap : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
+! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_2]]#0, c : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
+! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.heap<!fir.char<1,11>>
+! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]] : (!fir.heap<!fir.char<1,11>>) -> !fir.box<!fir.heap<!fir.char<1,11>>>
+! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
! CHECK: %[[VAL_9:.*]] = arith.constant 12 : index
! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.char<1,12> {bindc_name = "x", uniq_name = "_QFtest9Ex"}
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] typeparams %[[VAL_9]] {uniq_name = "_QFtest9Ex"} : (!fir.ref<!fir.char<1,12>>, index) -> (!fir.ref<!fir.char<1,12>>, !fir.ref<!fir.char<1,12>>)
@@ -392,11 +427,10 @@ end subroutine test9
! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.ref<!fir.char<1,12>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_2]]#0 : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_21]]
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_21]])
! CHECK: return
! CHECK: }
-
! Test character non-allocatable component initialization
! from character allocatable of different size.
subroutine test10
@@ -407,6 +441,7 @@ subroutine test10
end subroutine test10
! CHECK-LABEL: func.func @_QPtest10() {
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}>
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}> {bindc_name = "res", uniq_name = "_QFtest10Eres"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest10Eres"} : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>)
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,12>>> {bindc_name = "x", uniq_name = "_QFtest10Ex"}
diff --git a/flang/test/Lower/OpenMP/private-derived-type.f90 b/flang/test/Lower/OpenMP/private-derived-type.f90
index 3947a0d68b58c..fef0867045703 100644
--- a/flang/test/Lower/OpenMP/private-derived-type.f90
+++ b/flang/test/Lower/OpenMP/private-derived-type.f90
@@ -16,12 +16,12 @@ subroutine s4
end subroutine s4
! CHECK: omp.private {type = private} @[[DERIVED_PRIV:.*]] : !fir.type<{{.*}}y3{x:!fir.box<!fir.heap<i32>>}> init {
-! CHECK: %[[VAL_25:.*]] = fir.embox %[[VAL_23:.*]] : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
+! CHECK: %[[VAL_25:.*]] = fir.embox %{{.*}} : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
! CHECK: %[[VAL_26:.*]] = fir.address_of
! CHECK: %[[VAL_27:.*]] = arith.constant 8 : i32
! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_25]] : (!fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_26]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
-! Check we do call FortranAInitialize on the derived type
+! Check we do call FortranAInitialize on the derived type
! CHECK: fir.call @_FortranAInitialize(%[[VAL_28]], %[[VAL_29]], %[[VAL_27]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
! CHECK: }
@@ -29,14 +29,16 @@ end subroutine s4
! Example of how the lowering for regular derived type variables:
! CHECK: %[[VAL_DERIVED_ALLOCA:.*]] = fir.alloca !fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}> {bindc_name = "v", uniq_name = "_QFs4Ev"}
! CHECK: %[[VAL_DERIVED_DECLARE:.*]]:2 = hlfir.declare %[[VAL_DERIVED_ALLOCA]] {{.*}}
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QFs4Ty3.DerivedInit) : !fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[VAL_DERIVED_DECLARE]]#0 no_overlap : {{.*}}
+! CHECK: %[[VAL_COORD:.*]] = fir.coordinate_of %[[VAL_DERIVED_DECLARE]]#0, x : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.ref<!fir.box<!fir.heap<i32>>>
+! CHECK: %[[VAL_ZERO:.*]] = fir.zero_bits !fir.heap<i32>
+! CHECK: %[[VAL_EMBOX:.*]] = fir.embox %[[VAL_ZERO]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>>
+! CHECK: fir.store %[[VAL_EMBOX]] to %[[VAL_COORD]] : !fir.ref<!fir.box<!fir.heap<i32>>>
! CHECK: omp.parallel {
! CHECK: omp.wsloop private(@[[DERIVED_PRIV]] %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : !fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>, !fir.ref<i32>) {
! CHECK: }
! CHECK: %[[VAL_39:.*]] = fir.embox %[[VAL_DERIVED_DECLARE]]#0 : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
! CHECK: %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (!fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
-! Check the derived type is destroyed
+! Check the derived type is destroyed
! CHECK: fir.call @_FortranADestroy(%[[VAL_40]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: return
! CHECK: }
diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90
index fa2182ac11bac..c35a998b738a4 100644
--- a/flang/test/Lower/call-copy-in-out.f90
+++ b/flang/test/Lower/call-copy-in-out.f90
@@ -1,60 +1,107 @@
! Test copy-in / copy-out of non-contiguous variable passed as F77 array arguments.
-! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
+! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
! Nominal test
! CHECK-LABEL: func @_QPtest_assumed_shape_to_array(
! CHECK-SAME: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_assumed_shape_to_array(x)
real :: x(:)
-! CHECK: %[[x_decl:.*]]:2 = hlfir.declare %[[x]]
-! CHECK: %[[copy_in:.*]]:2 = hlfir.copy_in %[[x_decl]]#0 {{.*}}
-! CHECK: %[[addr:.*]] = fir.box_addr %[[copy_in]]#0
-! CHECK: fir.call @_QPbar(%[[addr]])
-! CHECK: hlfir.copy_out %{{.*}}, %[[copy_in]]#1 to %[[x_decl]]#0
+
+! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
+! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
+! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]] -> (!fir.heap<!fir.array<?xf32>>) {
+! CHECK: %[[box_addr:.*]] = fir.box_addr %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.heap<!fir.array<?xf32>>
+! CHECK: fir.result %[[box_addr]] : !fir.heap<!fir.array<?xf32>>
+! CHECK: } else {
+! Creating temp
+! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x:.*]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1 {uniq_name = ".copyinout"}
+
+! Copy-in
+! CHECK-DAG: %[[shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
+! CHECK-DAG: %[[temp_box:.*]] = fir.embox %[[temp]](%[[shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+! CHECK-DAG: fir.store %[[temp_box]] to %[[temp_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
+! CHECK-DAG: %[[temp_box_addr:.*]] = fir.convert %[[temp_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[arg_box:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
+! CHECK-DAG: fir.call @_FortranAAssignTemporary(%[[temp_box_addr]], %[[arg_box]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: fir.result %[[temp]] : !fir.heap<!fir.array<?xf32>>
+
+! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: fir.call @_QPbar(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
+
+! Copy-out
+! CHECK-DAG: %[[shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
+! CHECK-DAG: %[[temp_box:.*]] = fir.embox %[[addr]](%[[shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+! CHECK: %[[rebox:.*]] = fir.rebox %[[temp_box]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+! CHECK: fir.store %[[rebox]] to %[[temp_box_ref:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK-DAG: fir.store %[[x]] to %[[arg_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
+! CHECK-DAG: %[[arg_box_addr:.*]] = fir.convert %[[arg_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: %[[temp_box_cast:.*]] = fir.convert %[[temp_box_ref]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK-DAG: fir.call @_FortranACopyOutAssign(%[[arg_box_addr]], %[[temp_box_cast]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<i8>, i32) -> ()
+
call bar(x)
end subroutine
! Test that copy-in/copy-out does not trigger the re-evaluation of
! the designator expression.
! CHECK-LABEL: func @_QPeval_expr_only_once(
+! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.array<200xf32>>{{.*}}) {
subroutine eval_expr_only_once(x)
integer :: only_once
real :: x(200)
! CHECK: fir.call @_QPonly_once()
-! CHECK: hlfir.designate
-! CHECK: hlfir.copy_in
-! CHECK-NOT: fir.call @_QPonly_once()
-! CHECK: fir.call @_QPbar
+! CHECK: %[[x_section:.*]] = fir.embox %[[x]](%{{.*}}) [%{{.*}}] : (!fir.ref<!fir.array<200xf32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<?xf32>>
+! CHECK: %[[box_none:.*]] = fir.convert %[[x_section]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
+! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
+! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]] -> (!fir.heap<!fir.array<?xf32>>) {
+
+! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>
! CHECK-NOT: fir.call @_QPonly_once()
-! CHECK: hlfir.copy_out
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK-NOT: fir.call @_QPonly_once()
+
+! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: fir.call @_QPbar(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
call bar(x(1:200:only_once()))
+
+! CHECK-NOT: fir.call @_QPonly_once()
+! CHECK: fir.call @_FortranACopyOutAssign
+! CHECK-NOT: fir.call @_QPonly_once()
+
end subroutine
! Test no copy-in/copy-out is generated for contiguous assumed shapes.
! CHECK-LABEL: func @_QPtest_contiguous(
+! CHECK-SAME: %[[x:.*]]: !fir.box<!fir.array<?xf32>>
subroutine test_contiguous(x)
real, contiguous :: x(:)
-! CHECK-NOT: hlfir.copy_in
-! CHECK: fir.call @_QPbar
-! CHECK-NOT: hlfir.copy_out
+! CHECK: %[[addr:.*]] = fir.box_addr %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK-NOT: fir.call @_FortranAAssignTemporary
+! CHECK: fir.call @_QPbar(%[[addr]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
call bar(x)
+! CHECK-NOT: fir.call @_FortranACopyOutAssign
+! CHECK: return
end subroutine
! Test the parenthesis are preventing copy-out.
-! CHECK-LABEL: func @_QPtest_parenthesis(
+! CHECK: func @_QPtest_parenthesis(
+! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_parenthesis(x)
real :: x(:)
-! CHECK: hlfir.elemental
-! CHECK: hlfir.associate
-! CHECK: fir.call @_QPbar
-! CHECK: hlfir.end_associate
-! CHECK-NOT: hlfir.copy_out
+! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1 {uniq_name = ".array.expr"}
+! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[temp]]
+! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: fir.call @_QPbar(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
call bar((x))
+! CHECK-NOT: fir.call @_FortranACopyOutAssign
+! CHECK: return
end subroutine
! Test copy-in in is skipped for intent(out) arguments.
-! CHECK-LABEL: func @_QPtest_intent_out(
+! CHECK: func @_QPtest_intent_out(
+! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_intent_out(x)
real :: x(:)
interface
@@ -62,14 +109,26 @@ subroutine bar_intent_out(x)
real, intent(out) :: x(100)
end subroutine
end interface
-! CHECK: hlfir.copy_in
-! CHECK: fir.call @_QPbar_intent_out
-! CHECK: hlfir.copy_out
+! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
+! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
+! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
+! CHECK: } else {
+! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
+! CHECK-NOT: fir.call @_FortranAAssignTemporary
+! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
+! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
+! CHECK: fir.call @_QPbar_intent_out(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
call bar_intent_out(x)
+
+! CHECK: fir.if %[[not_contiguous]]
+! CHECK: fir.call @_FortranACopyOutAssign
+! CHECK: return
end subroutine
! Test copy-out is skipped for intent(out) arguments.
! CHECK-LABEL: func.func @_QPtest_intent_in(
+! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_intent_in(x)
real :: x(:)
interface
@@ -77,15 +136,30 @@ subroutine bar_intent_in(x)
real, intent(in) :: x(100)
end subroutine
end interface
-! CHECK: hlfir.copy_in
-! CHECK: fir.call @_QPbar_intent_in
-! CHECK: hlfir.copy_out
-! CHECK-SAME: ) -> ()
+! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
+! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
+! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
+! CHECK: } else {
+! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
+! CHECK: %[[temp_shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
+! CHECK: %[[temp_box:.*]] = fir.embox %[[temp]](%[[temp_shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+! CHECK: fir.store %[[temp_box]] to %[[temp_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
+! CHECK: %[[temp_box_addr:.*]] = fir.convert %[[temp_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: fir.call @_FortranAAssignTemporary(%[[temp_box_addr]],
+! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
+! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
+! CHECK: fir.call @_QPbar_intent_in(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
call bar_intent_in(x)
+! CHECK: fir.if %[[not_contiguous]]
+! CHECK: fir.zero
+! CHECK: fir.call @_FortranACopyOutAssign
+! CHECK: return
end subroutine
! Test copy-in/copy-out is done for intent(inout)
-! CHECK-LABEL: func @_QPtest_intent_inout(
+! CHECK: func @_QPtest_intent_inout(
+! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_intent_inout(x)
real :: x(:)
interface
@@ -93,55 +167,111 @@ subroutine bar_intent_inout(x)
real, intent(inout) :: x(100)
end subroutine
end interface
-! CHECK: hlfir.copy_in
-! CHECK: fir.call @_QPbar_intent_inout
-! CHECK: hlfir.copy_out
-! CHECK-SAME: to
+! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
+! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
+! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
+! CHECK: } else {
+! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
+! CHECK: fir.call @_FortranAAssign
+! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
+! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
+! CHECK: fir.call @_QPbar_intent_inout(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
call bar_intent_inout(x)
+! CHECK: fir.if %[[not_contiguous]]
+! CHECK: fir.call @_FortranACopyOutAssign
+! CHECK: return
end subroutine
! Test characters are handled correctly
! CHECK-LABEL: func @_QPtest_char(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.char<1,10>>>{{.*}}) {
subroutine test_char(x)
+! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
+! CHECK: %[[VAL_5:.*]] = fir.call @_FortranAIsContiguous(%[[VAL_4]]) fastmath<contract> : (!fir.box<none>) -> i1
+! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.heap<!fir.array<?x!fir.char<1,10>>>) {
+! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: fir.result %[[VAL_7]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: } else {
+! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_8]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?x!fir.char<1,10>>, %[[VAL_9]]#1 {uniq_name = ".copyinout"}
+! CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_9]]#1 : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_10]](%[[VAL_11]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: fir.store %[[VAL_12]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranAAssignTemporary(%[[VAL_15]], %[[VAL_16]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: }
+! CHECK: %[[VAL_19:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_19]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_21:.*]] = arith.constant false
+! CHECK: %[[VAL_22:.*]] = arith.cmpi eq, %[[VAL_5]], %[[VAL_21]] : i1
+! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_24:.*]] : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,?>>
+! CHECK: %[[VAL_25:.*]] = fir.emboxchar %[[VAL_23]], %[[VAL_3]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+! CHECK: fir.call @_QPbar_char(%[[VAL_25]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
+! CHECK: fir.if %[[VAL_22]] {
+! CHECK: %[[VAL_26:.*]] = fir.shape %[[VAL_20]]#1 : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_24]](%[[VAL_26]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: %[[REBOX:.*]] = fir.rebox %[[VAL_27]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>
+! CHECK: fir.store %[[REBOX]] to %[[TMP_BOX_REF:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>
+! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
+! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[VAL_32:.*]] = fir.convert %[[TMP_BOX_REF]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: fir.call @_FortranACopyOutAssign(%[[VAL_31]], %[[VAL_32]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<i8>, i32) -> ()
+! CHECK: }
+
character(10) :: x(:)
-! CHECK: hlfir.copy_in
-! CHECK: fir.call @_QPbar_char
-! CHECK: hlfir.copy_out
call bar_char(x)
+ ! CHECK: return
+ ! CHECK: }
end subroutine test_char
! CHECK-LABEL: func @_QPtest_scalar_substring_does_no_trigger_copy_inout
+! CHECK-SAME: %[[arg0:.*]]: !fir.boxchar<1>
subroutine test_scalar_substring_does_no_trigger_copy_inout(c, i, j)
character(*) :: c
integer :: i, j
- ! CHECK: hlfir.designate
- ! CHECK-NOT: hlfir.copy_in
- ! CHECK: fir.call @_QPbar_char_2
- ! CHECK-NOT: hlfir.copy_out
+ ! CHECK: %[[unbox:.*]]:2 = fir.unboxchar %[[arg0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+ ! CHECK: %[[c:.*]] = fir.convert %[[unbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
+ ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[c]], %{{.*}} : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
+ ! CHECK: %[[substr:.*]] = fir.convert %[[coor]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.char<1,?>>
+ ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[substr]], %{{.*}} : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+ ! CHECK: fir.call @_QPbar_char_2(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> ()
call bar_char_2(c(i:j))
end subroutine
! CHECK-LABEL: func @_QPissue871(
+! CHECK-SAME: %[[p:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.type<_QFissue871Tt{i:i32}>>>>{{.*}})
subroutine issue871(p)
! Test passing implicit derived from scalar pointer (no copy-in/out).
type t
integer :: i
end type t
type(t), pointer :: p
- ! CHECK-NOT: hlfir.copy_in
- ! CHECK: fir.call @_QPbar_derived
+ ! CHECK: %[[box_load:.*]] = fir.load %[[p]]
+ ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]]
+ ! CHECK: %[[cast:.*]] = fir.convert %[[addr]]
+ ! CHECK: fir.call @_QPbar_derived(%[[cast]])
call bar_derived(p)
end subroutine
! CHECK-LABEL: func @_QPissue871_array(
+! CHECK-SAME: %[[p:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFissue871_arrayTt{i:i32}>>>>>
subroutine issue871_array(p)
! Test passing implicit derived from contiguous pointer (no copy-in/out).
type t
integer :: i
end type t
type(t), pointer, contiguous :: p(:)
- ! CHECK-NOT: hlfir.copy_in
- ! CHECK: fir.call @_QPbar_derived_array
+ ! CHECK: %[[box_load:.*]] = fir.load %[[p]]
+ ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]]
+ ! CHECK: %[[cast:.*]] = fir.convert %[[addr]]
+ ! CHECK: fir.call @_QPbar_derived_array(%[[cast]])
call bar_derived_array(p)
end subroutine
@@ -151,10 +281,10 @@ subroutine whole_components()
type t
integer :: i(100)
end type
+ ! CHECK: %[[a:.*]] = fir.alloca !fir.type<_QFwhole_componentsTt{i:!fir.array<100xi32>}>
type(t) :: a
- ! CHECK: hlfir.designate
- ! CHECK-NOT: hlfir.copy_in
- ! CHECK: fir.call @_QPbar_integer
+ ! CHECK: %[[addr:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_componentsTt{i:!fir.array<100xi32>}>>) -> !fir.ref<!fir.array<100xi32>>
+ ! CHECK: fir.call @_QPbar_integer(%[[addr]]) {{.*}}: (!fir.ref<!fir.array<100xi32>>) -> ()
call bar_integer(a%i)
end subroutine
@@ -164,10 +294,19 @@ subroutine whole_component_contiguous_pointer()
type t
integer, pointer, contiguous :: i(:)
end type
+ ! CHECK: %[[a:.*]] = fir.alloca !fir.type<_QFwhole_component_contiguous_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>
type(t) :: a
- ! CHECK: hlfir.designate
- ! CHECK-NOT: hlfir.copy_in
- ! CHECK: fir.call @_QPbar_integer
+ ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+ ! CHECK: %[[zero:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>>
+ ! CHECK: %[[c0:.*]] = arith.constant 0 : index
+ ! CHECK: %[[shape:.*]] = fir.shape %[[c0]] : (index) -> !fir.shape<1>
+ ! CHECK: %[[embox:.*]] = fir.embox %[[zero]](%[[shape]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>>
+ ! CHECK: fir.store %[[embox]] to %[[coor]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+ ! CHECK: %[[coor2:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+ ! CHECK: %[[box_load:.*]] = fir.load %[[coor2]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+ ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.ptr<!fir.array<?xi32>>
+ ! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.ptr<!fir.array<?xi32>>) -> !fir.ref<!fir.array<100xi32>>
+ ! CHECK: fir.call @_QPbar_integer(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xi32>>) -> ()
call bar_integer(a%i)
end subroutine
@@ -177,9 +316,21 @@ subroutine whole_component_contiguous_char_pointer()
type t
character(:), pointer, contiguous :: i(:)
end type
+ ! CHECK: %[[a:.*]] = fir.alloca !fir.type<_QFwhole_component_contiguous_char_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>}>
type(t) :: a
- ! CHECK: hlfir.designate
- ! CHECK-NOT: hlfir.copy_in
- ! CHECK: fir.call @_QPbar_char_3
+ ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_char_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
+ ! CHECK: %[[zero:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.char<1,?>>>
+ ! CHECK: %[[c0_1:.*]] = arith.constant 0 : index
+ ! CHECK: %[[shape:.*]] = fir.shape %[[c0_1]] : (index) -> !fir.shape<1>
+ ! CHECK: %[[c0_2:.*]] = arith.constant 0 : index
+ ! CHECK: %[[embox:.*]] = fir.embox %[[zero]](%[[shape]]) typeparams %[[c0_2]] : (!fir.ptr<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>
+ ! CHECK: fir.store %[[embox]] to %[[coor]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
+ ! CHECK: %[[coor2:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_char_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
+ ! CHECK: %[[box_load:.*]] = fir.load %[[coor2]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
+ ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>) -> !fir.ptr<!fir.array<?x!fir.char<1,?>>>
+ ! CHECK: %[[len:.*]] = fir.box_elesize %[[box_load]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>) -> index
+ ! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.ptr<!fir.array<?x!fir.char<1,?>>>) -> !fir.ref<!fir.char<1,?>>
+ ! CHECK: %[[emboxchar:.*]] = fir.emboxchar %[[cast]], %[[len]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+ ! CHECK: fir.call @_QPbar_char_3(%[[emboxchar]]) {{.*}}: (!fir.boxchar<1>) -> ()
call bar_char_3(a%i)
end subroutine
diff --git a/flang/test/Lower/component-wise-init.f90 b/flang/test/Lower/component-wise-init.f90
index 99633062c7619..6145d049ba21e 100644
--- a/flang/test/Lower/component-wise-init.f90
+++ b/flang/test/Lower/component-wise-init.f90
@@ -108,4 +108,4 @@ end subroutine test_fallback_explicit
!
! Ensure types with explicit initialization trigger the gatekeeper and fall back to the old logic.
! CHECK: %[[GLOBAL_INIT_EXP:.*]] = fir.address_of(@_QQ_QMmy_typesTfallbackexplicittype.DerivedInit)
-! CHECK: fir.copy %[[GLOBAL_INIT_EXP]] to %[[VAR_EXPLICIT]]
\ No newline at end of file
+! CHECK: fir.copy %[[GLOBAL_INIT_EXP]] to %[[VAR_EXPLICIT]]
diff --git a/flang/test/Lower/default-initialization.f90 b/flang/test/Lower/default-initialization.f90
index f64d7185015f7..c2a4673c537af 100644
--- a/flang/test/Lower/default-initialization.f90
+++ b/flang/test/Lower/default-initialization.f90
@@ -21,9 +21,9 @@ module test_dinit
! Test local scalar is default initialized
! CHECK-LABEL: func @_QMtest_dinitPlocal()
subroutine local
- !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocalEx"}
- !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
- !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{i:i32}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocalEx"}
+ !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
+ !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
type(t) :: x
print *, x%i
end subroutine
@@ -31,9 +31,9 @@ subroutine local
! Test local array is default initialized
! CHECK-LABEL: func @_QMtest_dinitPlocal_array()
subroutine local_array()
- ! CHECK: %[[x:.*]] = fir.alloca !fir.array<4x!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[x:.*]] = fir.alloca !fir.array<4x!fir.type<_QMtest_dinitTt{i:i32}>>
! CHECK: %[[xshape:.*]] = fir.shape %c4{{.*}} : (index) -> !fir.shape<1>
- ! CHECK: %[[xbox:.*]] = fir.embox %[[x]](%[[xshape]]) : (!fir.ref<!fir.array<4x!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<4x!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>>
+ ! CHECK: %[[xbox:.*]] = fir.embox %[[x]](%[[xshape]]) : (!fir.ref<!fir.array<4x!fir.type<_QMtest_dinitTt{i:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<4x!fir.type<_QMtest_dinitTt{i:i32}>>>
! CHECK: %[[xboxNone:.*]] = fir.convert %[[xbox]]
! CHECK: fir.call @_FortranAInitialize(%[[xboxNone]], %{{.*}}, %{{.*}}) {{.*}}: (!fir.box<none>, !fir.ref<i8>, i32) -> ()
type(t) :: x(4)
@@ -44,38 +44,41 @@ subroutine local_array()
! scalars.
! CHECK-LABEL: func @_QMtest_dinitPlocal_alloc_comp()
subroutine local_alloc_comp
- !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt_alloc_comp{{(,sequence)?}}{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocal_alloc_compEx"}
- !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt_alloc_comp.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{{(,sequence)?}}{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
- !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{{(,sequence)?}}{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{{(,sequence)?}}{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
+ !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt_alloc_comp{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocal_alloc_compEx"}
+ !CHECK: %[[COORD:.*]] = fir.coordinate_of %[[x]], i : (!fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ !CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+ !CHECK: %[[SHAPE:.*]] = fir.shape %c0{{.*}} : (index) -> !fir.shape<1>
+ !CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+ !CHECK: fir.store %[[EMBOX]] to %[[COORD]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
type(t_alloc_comp) :: x
end subroutine
! Test function results are default initialized.
- ! CHECK-LABEL: func @_QMtest_dinitPresult() -> !fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>
+ ! CHECK-LABEL: func @_QMtest_dinitPresult() -> !fir.type<_QMtest_dinitTt{i:i32}>
function result()
- !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}> {bindc_name = "result", uniq_name = "_QMtest_dinitFresultEresult"}
- !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
- !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{i:i32}> {bindc_name = "result", uniq_name = "_QMtest_dinitFresultEresult"}
+ !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
+ !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
type(t) :: result
end function
! Test intent(out) dummies are default initialized
! CHECK-LABEL: func @_QMtest_dinitPintent_out(
- ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
subroutine intent_out(x)
- !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
- !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
+ !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
type(t), intent(out) :: x
end subroutine
! Test that optional intent(out) are default initialized only when
! present.
! CHECK-LABEL: func @_QMtest_dinitPintent_out_optional(
- ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>> {fir.bindc_name = "x", fir.optional})
+ ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>> {fir.bindc_name = "x", fir.optional})
subroutine intent_out_optional(x)
- ! CHECK: %[[isPresent:.*]] = fir.is_present %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>) -> i1
+ ! CHECK: %[[isPresent:.*]] = fir.is_present %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>) -> i1
! CHECK: fir.if %[[isPresent]] {
- ! CHECK: %[[xbox:.*]] = fir.embox %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>) -> !fir.box<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[xbox:.*]] = fir.embox %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>) -> !fir.box<!fir.type<_QMtest_dinitTt{i:i32}>>
! CHECK: %[[xboxNone:.*]] = fir.convert %[[xbox]]
! CHECK: fir.call @_FortranAInitialize(%[[xboxNone]], %{{.*}}, %{{.*}}) {{.*}}: (!fir.box<none>, !fir.ref<i8>, i32) -> ()
! CHECK: }
@@ -89,32 +92,33 @@ subroutine local_eq()
integer :: zi
! CHECK: %[[equiv:.*]] = fir.alloca !fir.array<4xi8>
! CHECK: %[[xcoor:.*]] = fir.coordinate_of %[[equiv]], %c0{{.*}} : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
- ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
- ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
- ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
equivalence (x, zi)
print *, i
end subroutine
! Test local equivalences with both equivalenced entities being
- ! default initialized. Note that the standard allow default initialization
- ! to be performed several times as long as the values are the same. So
- ! far that is what lowering is doing to stay simple.
+ ! default initialized.
+ ! Note that the standard allow default initialization
+ ! to be performed several times as long as the values are the same.
+ ! So far that is what lowering is doing to stay simple.
! CHECK-LABEL: func @_QMtest_dinitPlocal_eq2()
subroutine local_eq2()
type(tseq) :: x
type(tseq) :: y
! CHECK: %[[equiv:.*]] = fir.alloca !fir.array<4xi8>
! CHECK: %[[xcoor:.*]] = fir.coordinate_of %[[equiv]], %c0{{.*}} : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
- ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
- ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
- ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
! CHECK: %[[ycoor:.*]] = fir.coordinate_of %[[equiv]], %c0{{.*}} : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
- ! CHECK: %[[y:.*]] = fir.convert %[[ycoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
- ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
- ! CHECK: fir.copy %[[ADDR]] to %[[y]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[y:.*]] = fir.convert %[[ycoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: fir.copy %[[ADDR]] to %[[y]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
equivalence (x, y)
print *, y%i
end subroutine
diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90
index 352bc64c72945..4a0decef86d09 100644
--- a/flang/test/Lower/derived-type-finalization.f90
+++ b/flang/test/Lower/derived-type-finalization.f90
@@ -1,5 +1,5 @@
! Test derived type finalization
-! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s
! Missing tests:
! - finalization within BLOCK construct
@@ -55,21 +55,25 @@ subroutine test_lhs_allocatable()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_lhs() {
+! CHECK: %[[BOXREF:.*]] = fir.alloca !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
! CHECK: %[[LHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "lhs", uniq_name = "_QMderived_type_finalizationFtest_lhsElhs"}
-! CHECK: %[[LHS_DECL:.*]]:2 = hlfir.declare %[[LHS]]
-! CHECK: %[[RHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "rhs", uniq_name = "_QMderived_type_finalizationFtest_lhsErhs"}
-! CHECK: %[[RHS_DECL:.*]]:2 = hlfir.declare %[[RHS]]
-! CHECK: hlfir.assign %[[RHS_DECL]]#0 to %[[LHS_DECL]]#0
-! CHECK: fir.call @_FortranADestroy
-! CHECK: fir.call @_FortranADestroy
+! CHECK: %[[EMBOX:.*]] = fir.embox %[[LHS]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: fir.store %[[EMBOX]] to %[[BOXREF]] : !fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[BOXREF]] : (!fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: fir.call @_FortranAAssign(%[[BOX_NONE]], {{.*}}
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_lhs_allocatable() {
! CHECK: %[[LHS:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "lhs", uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs"}
-! CHECK: %[[LHS_DECL:.*]]:2 = hlfir.declare %[[LHS]]
+! CHECK: %[[LHS_ADDR:.*]] = fir.alloca !fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs.addr"}
! CHECK: %[[RHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "rhs", uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableErhs"}
-! CHECK: %[[RHS_DECL:.*]]:2 = hlfir.declare %[[RHS]]
-! CHECK: hlfir.assign %[[RHS_DECL]]#0 to %[[LHS_DECL]]#0 realloc
-! CHECK: fir.call @_FortranADestroy
+! CHECK: %[[LHS_ADDR_LOAD:.*]] = fir.load %[[LHS_ADDR]] : !fir.ref<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[ADDR_I64:.*]] = fir.convert %[[LHS_ADDR_LOAD]] : (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> i64
+! CHECK: %[[C0:.*]] = arith.constant 0 : i64
+! CHECK: %[[IS_NULL:.*]] = arith.cmpi ne, %[[ADDR_I64]], %[[C0]] : i64
+! CHECK: fir.if %[[IS_NULL]] {
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[LHS]] : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: }
! 7.5.6.3 point 2. Finalization on explicit deallocation.
subroutine test_deallocate()
@@ -79,10 +83,10 @@ subroutine test_deallocate()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_deallocate() {
-! CHECK: %[[T:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
-! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
-! CHECK: fir.call @_FortranAAllocatableAllocate
-! CHECK: fir.call @_FortranAAllocatableDeallocate
+! CHECK: %[[LOCAL_T:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "t", uniq_name = "_QMderived_type_finalizationFtest_deallocateEt"}
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[LOCAL_T]] : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! 7.5.6.3 point 2. Finalization of disassociated target.
subroutine test_target_finalization()
@@ -92,10 +96,13 @@ subroutine test_target_finalization()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_target_finalization() {
-! CHECK: %[[P:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
-! CHECK: %[[P_DECL:.*]]:2 = hlfir.declare %[[P]]
+! CHECK: %[[P:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "p", uniq_name = "_QMderived_type_finalizationFtest_target_finalizationEp"}
+! CHECK: %[[ADDR:.*]] = fir.alloca !fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {uniq_name = "_QMderived_type_finalizationFtest_target_finalizationEp.addr"}
+! CHECK: %[[zero:.*]] = fir.zero_bits !fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: fir.store %[[zero]] to %[[ADDR]] : !fir.ref<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
! CHECK: fir.call @_FortranAPointerAllocateSource
-! CHECK: fir.call @_FortranAPointerDeallocate
+! CHECK: %[[P_BOX_NONE:.*]] = fir.convert %[[P]] : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %{{.*}} = fir.call @_FortranAPointerDeallocate(%[[P_BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! 7.5.6.3 point 3. Finalize on END.
subroutine test_end_finalization()
@@ -103,9 +110,11 @@ subroutine test_end_finalization()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_end_finalization() {
-! CHECK: %[[T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}>
-! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
-! CHECK: fir.call @_FortranADestroy
+! CHECK: %[[LOCAL_T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "t", uniq_name = "_QMderived_type_finalizationFtest_end_finalizationEt"}
+! CHECK: %[[EMBOX:.*]] = fir.embox %[[LOCAL_T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: return
! test with multiple return.
subroutine test_end_finalization2(a)
@@ -117,12 +126,21 @@ subroutine test_end_finalization2(a)
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_end_finalization2(
! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "a"}) {
-! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]]
! CHECK: %[[T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "t", uniq_name = "_QMderived_type_finalizationFtest_end_finalization2Et"}
-! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
-! CHECK: cf.cond_br
-! CHECK: hlfir.assign
-! CHECK: fir.call @_FortranADestroy
+! CHECK: %[[LOAD_A:.*]] = fir.load %[[A]] : !fir.ref<!fir.logical<4>>
+! CHECK: %[[CONV_A:.*]] = fir.convert %[[LOAD_A]] : (!fir.logical<4>) -> i1
+! CHECK: cf.cond_br %[[CONV_A]], ^bb1, ^bb2
+! CHECK: ^bb1:
+! CHECK: cf.br ^bb3
+! CHECK: ^bb2:
+! CHECK: %[[C10:.*]] = arith.constant 10 : i32
+! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[T]], a : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.ref<i32>
+! CHECK: fir.store %[[C10]] to %[[COORD_A]] : !fir.ref<i32>
+! CHECK: cf.br ^bb3
+! CHECK: ^bb3:
+! CHECK: %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
! CHECK: return
! CHECK: }
@@ -137,14 +155,12 @@ subroutine test_fct_ref()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_fct_ref() {
-! CHECK: %[[RES:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = ".result"}
-! CHECK: %[[TY:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
-! CHECK: %[[TY_DECL:.*]]:2 = hlfir.declare %[[TY]]
-! CHECK: %[[RES_DECL:.*]]:2 = hlfir.declare %[[RES]]
+! CHECK: %[[RESULT:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = ".result"}
! CHECK: %[[CALL_RES:.*]] = fir.call @_QMderived_type_finalizationPret_type()
-! CHECK: fir.save_result %[[CALL_RES]] to %[[RES_DECL]]#0
-! CHECK: hlfir.assign %[[RES_DECL]]#0 to %[[TY_DECL]]#0 realloc
-! CHECK: fir.call @_FortranADestroy(%{{.*}})
+! CHECK: fir.save_result %[[CALL_RES]] to %[[RESULT]] : !fir.type<_QMderived_type_finalizationTt1{a:i32}>, !fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[EMBOX:.*]] = fir.embox %[[RESULT]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
! CHECK: return
subroutine test_finalize_intent_out(t)
@@ -153,8 +169,9 @@ subroutine test_finalize_intent_out(t)
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_finalize_intent_out(
! CHECK-SAME: %[[T:.*]]: !fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {fir.bindc_name = "t"}) {
-! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
-! CHECK: fir.call @_FortranADestroy(%{{.*}})
+! CHECK: %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}}: (!fir.box<none>) -> ()
! CHECK: return
function get_t1(i)
@@ -170,7 +187,7 @@ subroutine test_nonpointer_function()
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_nonpointer_function() {
! CHECK: %[[TMP:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = ".result"}
! CHECK: %{{.*}} = fir.call @_FortranAioBeginExternalListOutput
-! CHECK: %[[RES:.*]] = fir.call @_QMderived_type_finalizationPget_t1(%{{.*}})
+! CHECK: %[[RES:.*]] = fir.call @_QMderived_type_finalizationPget_t1(%{{.*}}) {{.*}} : (!fir.ref<i32>) -> !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
! CHECK: fir.save_result %[[RES]] to %[[TMP]] : !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>, !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>
! CHECK: %{{.*}} = fir.call @_FortranAioOutputDerivedType
! CHECK-NOT: fir.call @_FortranADestroy
@@ -185,11 +202,15 @@ subroutine test_avoid_double_finalization(a)
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_avoid_double_finalization(
! CHECK: %[[b:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt3{t:!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>}> {bindc_name = "b", uniq_name = "_QMderived_type_finalizationFtest_avoid_double_finalizationEb"}
-! CHECK: %[[b_DECL:.*]]:2 = hlfir.declare %[[b]]
-! CHECK: fir.copy %{{.*}} to %[[b_DECL]]#0
+! CHECK: %[[COORD_T:.*]] = fir.coordinate_of %[[b]], t : (!fir.ref<!fir.type<_QMderived_type_finalizationTt3{t:!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>}>>) -> !fir.ref<!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
+! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[COORD_T]], a : (!fir.ref<!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>>
+! CHECK: %[[SHAPE:.*]] = fir.shape %c0{{.*}} : (index) -> !fir.shape<1>
+! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>>
+! CHECK: fir.store %[[EMBOX]] to %[[COORD_A]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-NOT: fir.call @_FortranADestroy
-! CHECK: hlfir.assign
-! CHECK: fir.call @_FortranADestroy
+! CHECK: fir.call @_FortranAAssign(
+! CHECK: fir.call @_FortranADestroy(
function no_func_ret_finalize() result(ty)
type(t1) :: ty
@@ -197,7 +218,7 @@ function no_func_ret_finalize() result(ty)
end function
! CHECK-LABEL: func.func @_QMderived_type_finalizationPno_func_ret_finalize() -> !fir.type<_QMderived_type_finalizationTt1{a:i32}> {
-! CHECK: hlfir.assign
+! CHECK: fir.call @_FortranAAssign
! CHECK-NOT: fir.call @_FortranADestroy
! CHECK: return %{{.*}} : !fir.type<_QMderived_type_finalizationTt1{a:i32}>
@@ -214,9 +235,11 @@ subroutine test_avoid_double_free()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_avoid_double_free() {
+! CHECK: %[[RES:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>> {bindc_name = ".result"}
! CHECK: fir.call @_FortranAAllocatableAllocateSource(
-! CHECK: fir.call @_FortranADestroy
-! CHECK: fir.call @_FortranAAllocatableDeallocatePolymorphic
+! CHECK-NOT: fir.freemem %{{.*}} : !fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[RES_CONV:.*]] = fir.convert %[[RES]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[RES_CONV]]) {{.*}} : (!fir.box<none>) -> ()
subroutine t4_final(this)
type(t4) :: this
@@ -227,7 +250,7 @@ subroutine local_t4()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPlocal_t4()
-! CHECK: fir.call @_FortranADestroy(%{{.*}}) fastmath<contract> : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranADestroy(%2) fastmath<contract> : (!fir.box<none>) -> ()
end module
diff --git a/flang/test/Lower/derived-type-temp.f90 b/flang/test/Lower/derived-type-temp.f90
index b6363c2b8636f..3e5e3b8e0a9e1 100644
--- a/flang/test/Lower/derived-type-temp.f90
+++ b/flang/test/Lower/derived-type-temp.f90
@@ -13,7 +13,9 @@ program derived_temp_init
y = t2(x)
end
-! CHECK: %[[ALLOC:.*]] = fir.alloca !fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}> {bindc_name = "x", uniq_name = "_QFEx"}
+! CHECK: %[[ALLOC:.*]] = fir.alloca !fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}> {bindc_name = "x", uniq_name = "_QFEx"}
! CHECK: %[[x:.*]]:2 = hlfir.declare %[[ALLOC]] {{.*}}
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QFTt1.DerivedInit) : !fir.ref<!fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[x]]#0 no_overlap : !fir.ref<!fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}>>
+! CHECK: %[[COOR:.*]] = fir.coordinate_of %[[x]]#0, i : (!fir.ref<!fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}>>) -> !fir.ref<!fir.box<!fir.heap<i32>>>
+! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap<i32>
+! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>>
+! CHECK: fir.store %[[EMBOX]] to %[[COOR]] : !fir.ref<!fir.box<!fir.heap<i32>>>
diff --git a/flang/test/Lower/forall/forall-allocatable-2.f90 b/flang/test/Lower/forall/forall-allocatable-2.f90
index 3fb4aa17f45e6..c6b8232fa4ede 100644
--- a/flang/test/Lower/forall/forall-allocatable-2.f90
+++ b/flang/test/Lower/forall/forall-allocatable-2.f90
@@ -1,6 +1,6 @@
! Test forall lowering
-! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
subroutine forall_with_allocatable2(a1)
real :: a1(:)
@@ -14,36 +14,49 @@ subroutine forall_with_allocatable2(a1)
end forall
end subroutine forall_with_allocatable2
-! CHECK-LABEL: func.func @_QPforall_with_allocatable2(
-! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a1"}) {
-! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
-! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg 1 {uniq_name = "_QFforall_with_allocatable2Ea1"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
-! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "thing", uniq_name = "_QFforall_with_allocatable2Ething"}
-! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFforall_with_allocatable2Ething"} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
-! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QQ_QFforall_with_allocatable2Tt.DerivedInit) : !fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
-! CHECK: fir.copy %[[VAL_10]] to %[[VAL_9]]#0 no_overlap : !fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
-! CHECK: %[[VAL_11:.*]] = arith.constant 5 : i32
-! CHECK: %[[VAL_12:.*]] = arith.constant 15 : i32
-! CHECK: hlfir.forall lb {
-! CHECK: hlfir.yield %[[VAL_11]] : i32
-! CHECK: } ub {
-! CHECK: hlfir.yield %[[VAL_12]] : i32
-! CHECK: } (%[[VAL_13:.*]]: i32) {
-! CHECK: %[[VAL_14:.*]] = hlfir.forall_index "i" %[[VAL_13]] : (i32) -> !fir.ref<i32>
-! CHECK: hlfir.region_assign {
-! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref<i32>
-! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64
-! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
-! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref<f32>
-! CHECK: hlfir.yield %[[VAL_18]] : f32
-! CHECK: } to {
-! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_9]]#0{"arr"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_19]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_14]] : !fir.ref<i32>
-! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_21]] : (i32) -> i64
-! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_22]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i64) -> !fir.ref<f32>
-! CHECK: hlfir.yield %[[VAL_23]] : !fir.ref<f32>
-! CHECK: }
+! CHECK-LABEL: func @_QPforall_with_allocatable2(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
+! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
+! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "thing", uniq_name = "_QFforall_with_allocatable2Ething"}
+! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_2]], arr : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_4]](%[[VAL_6]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+! CHECK: fir.store %[[VAL_7]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_9:.*]] = arith.constant 5 : i32
+! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index
+! CHECK: %[[VAL_11:.*]] = arith.constant 15 : i32
+! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i32) -> index
+! CHECK: %[[VAL_13:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_2]], arr : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_17:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_18:.*]]:3 = fir.box_dims %[[VAL_16]], %[[VAL_17]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_19:.*]] = fir.box_addr %[[VAL_16]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+! CHECK: %[[VAL_20:.*]] = fir.shape_shift %[[VAL_18]]#0, %[[VAL_18]]#1 : (index, index) -> !fir.shapeshift<1>
+! CHECK: %[[VAL_21:.*]] = fir.array_load %[[VAL_19]](%[[VAL_20]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>) -> !fir.array<?xf32>
+! CHECK: %[[VAL_22:.*]] = fir.array_load %[[VAL_0]] : (!fir.box<!fir.array<?xf32>>) -> !fir.array<?xf32>
+! CHECK: %[[VAL_23:.*]] = fir.do_loop %[[VAL_24:.*]] = %[[VAL_10]] to %[[VAL_12]] step %[[VAL_13]] unordered iter_args(%[[VAL_25:.*]] = %[[VAL_21]]) -> (!fir.array<?xf32>) {
+! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_24]] : (index) -> i32
+! CHECK: fir.store %[[VAL_26]] to %[[VAL_1]] : !fir.ref<i32>
+! CHECK: %[[VAL_27:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
+! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i32) -> i64
+! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i64) -> index
+! CHECK: %[[VAL_31:.*]] = arith.subi %[[VAL_30]], %[[VAL_27]] : index
+! CHECK: %[[VAL_32:.*]] = fir.array_fetch %[[VAL_22]], %[[VAL_31]] : (!fir.array<?xf32>, index) -> f32
+! CHECK: %[[VAL_33:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
+! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_34]] : (i32) -> i64
+! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_35]] : (i64) -> index
+! CHECK: %[[VAL_37:.*]] = arith.subi %[[VAL_36]], %[[VAL_33]] : index
+! CHECK: %[[VAL_38:.*]] = fir.array_update %[[VAL_25]], %[[VAL_32]], %[[VAL_37]] : (!fir.array<?xf32>, f32, index) -> !fir.array<?xf32>
+! CHECK: fir.result %[[VAL_38]] : !fir.array<?xf32>
! CHECK: }
+! CHECK: fir.array_merge_store %[[VAL_21]], %[[VAL_39:.*]] to %[[VAL_19]] : !fir.array<?xf32>, !fir.array<?xf32>, !fir.heap<!fir.array<?xf32>>
+! CHECK: %[[VAL_40:.*]] = fir.embox %[[VAL_2]] : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (!fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[VAL_41]])
! CHECK: return
! CHECK: }
diff --git a/flang/test/Lower/pointer-default-init.f90 b/flang/test/Lower/pointer-default-init.f90
index dd9c7539b4f05..047485b23c877 100644
--- a/flang/test/Lower/pointer-default-init.f90
+++ b/flang/test/Lower/pointer-default-init.f90
@@ -39,8 +39,12 @@ subroutine test_local()
end subroutine
! CHECK-LABEL: func.func @_QPtest_local() {
! CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QFtest_localEx"}
-! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtestTt.DerivedInit) : !fir.ref<!fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
-! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
+! CHECK: %[[x_comp:.*]] = fir.coordinate_of %[[x]], x : (!fir.ref<!fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[zero:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
+! CHECK: %[[c0:.*]] = arith.constant 0 : index
+! CHECK: %[[shape:.*]] = fir.shape %[[c0]] : (index) -> !fir.shape<1>
+! CHECK: %[[embox:.*]] = fir.embox %[[zero]](%[[shape]]) : (!fir.ptr<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
+! CHECK: fir.store %[[embox]] to %[[x_comp]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
subroutine test_saved()
use test, only : t
>From 7e51c1398cacd4e1ad9fee0503c7d6d8cbf28606 Mon Sep 17 00:00:00 2001
From: hechenxi <hechenxi at bosc.ac.cn>
Date: Thu, 9 Apr 2026 12:31:39 +0800
Subject: [PATCH 6/7] Update test files
---
flang/test/Lower/call-copy-in-out.f90 | 258 ++++--------------
.../test/Lower/derived-type-finalization.f90 | 112 +++-----
.../Lower/forall/forall-allocatable-2.f90 | 80 +++---
3 files changed, 134 insertions(+), 316 deletions(-)
diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90
index c35a998b738a4..2fc78fcf1e65c 100644
--- a/flang/test/Lower/call-copy-in-out.f90
+++ b/flang/test/Lower/call-copy-in-out.f90
@@ -1,107 +1,60 @@
! Test copy-in / copy-out of non-contiguous variable passed as F77 array arguments.
-! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
! Nominal test
! CHECK-LABEL: func @_QPtest_assumed_shape_to_array(
! CHECK-SAME: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_assumed_shape_to_array(x)
real :: x(:)
-
-! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
-! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]] -> (!fir.heap<!fir.array<?xf32>>) {
-! CHECK: %[[box_addr:.*]] = fir.box_addr %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.heap<!fir.array<?xf32>>
-! CHECK: fir.result %[[box_addr]] : !fir.heap<!fir.array<?xf32>>
-! CHECK: } else {
-! Creating temp
-! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x:.*]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1 {uniq_name = ".copyinout"}
-
-! Copy-in
-! CHECK-DAG: %[[shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
-! CHECK-DAG: %[[temp_box:.*]] = fir.embox %[[temp]](%[[shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
-! CHECK-DAG: fir.store %[[temp_box]] to %[[temp_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
-! CHECK-DAG: %[[temp_box_addr:.*]] = fir.convert %[[temp_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
-! CHECK-DAG: %[[arg_box:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK-DAG: fir.call @_FortranAAssignTemporary(%[[temp_box_addr]], %[[arg_box]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: fir.result %[[temp]] : !fir.heap<!fir.array<?xf32>>
-
-! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-! CHECK: fir.call @_QPbar(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
-
-! Copy-out
-! CHECK-DAG: %[[shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
-! CHECK-DAG: %[[temp_box:.*]] = fir.embox %[[addr]](%[[shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
-! CHECK: %[[rebox:.*]] = fir.rebox %[[temp_box]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
-! CHECK: fir.store %[[rebox]] to %[[temp_box_ref:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK-DAG: fir.store %[[x]] to %[[arg_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
-! CHECK-DAG: %[[arg_box_addr:.*]] = fir.convert %[[arg_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
-! CHECK-DAG: %[[temp_box_cast:.*]] = fir.convert %[[temp_box_ref]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK-DAG: fir.call @_FortranACopyOutAssign(%[[arg_box_addr]], %[[temp_box_cast]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<i8>, i32) -> ()
-
+! CHECK: %[[x_decl:.*]]:2 = hlfir.declare %[[x]]
+! CHECK: %[[copy_in:.*]]:2 = hlfir.copy_in %[[x_decl]]#0 {{.*}}
+! CHECK: %[[addr:.*]] = fir.box_addr %[[copy_in]]#0
+! CHECK: fir.call @_QPbar(%[[addr]])
+! CHECK: hlfir.copy_out %{{.*}}, %[[copy_in]]#1 to %[[x_decl]]#0
call bar(x)
end subroutine
! Test that copy-in/copy-out does not trigger the re-evaluation of
! the designator expression.
! CHECK-LABEL: func @_QPeval_expr_only_once(
-! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.array<200xf32>>{{.*}}) {
subroutine eval_expr_only_once(x)
integer :: only_once
real :: x(200)
! CHECK: fir.call @_QPonly_once()
-! CHECK: %[[x_section:.*]] = fir.embox %[[x]](%{{.*}}) [%{{.*}}] : (!fir.ref<!fir.array<200xf32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<?xf32>>
-! CHECK: %[[box_none:.*]] = fir.convert %[[x_section]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
-! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]] -> (!fir.heap<!fir.array<?xf32>>) {
-
-! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>
-! CHECK-NOT: fir.call @_QPonly_once()
-! CHECK: fir.call @_FortranAAssignTemporary
+! CHECK: hlfir.designate
+! CHECK: hlfir.copy_in
! CHECK-NOT: fir.call @_QPonly_once()
-
-! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-! CHECK: fir.call @_QPbar(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
- call bar(x(1:200:only_once()))
-
+! CHECK: fir.call @_QPbar
! CHECK-NOT: fir.call @_QPonly_once()
-! CHECK: fir.call @_FortranACopyOutAssign
+! CHECK: hlfir.copy_out
! CHECK-NOT: fir.call @_QPonly_once()
-
+ call bar(x(1:200:only_once()))
end subroutine
! Test no copy-in/copy-out is generated for contiguous assumed shapes.
! CHECK-LABEL: func @_QPtest_contiguous(
-! CHECK-SAME: %[[x:.*]]: !fir.box<!fir.array<?xf32>>
subroutine test_contiguous(x)
real, contiguous :: x(:)
-! CHECK: %[[addr:.*]] = fir.box_addr %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-! CHECK-NOT: fir.call @_FortranAAssignTemporary
-! CHECK: fir.call @_QPbar(%[[addr]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
+! CHECK-NOT: hlfir.copy_in
+! CHECK: fir.call @_QPbar
+! CHECK-NOT: hlfir.copy_out
call bar(x)
-! CHECK-NOT: fir.call @_FortranACopyOutAssign
-! CHECK: return
end subroutine
! Test the parenthesis are preventing copy-out.
-! CHECK: func @_QPtest_parenthesis(
-! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
+! CHECK-LABEL: func @_QPtest_parenthesis(
subroutine test_parenthesis(x)
real :: x(:)
-! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1 {uniq_name = ".array.expr"}
-! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[temp]]
-! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-! CHECK: fir.call @_QPbar(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
+! CHECK: hlfir.elemental
+! CHECK: hlfir.associate
+! CHECK: fir.call @_QPbar
+! CHECK: hlfir.end_associate
+! CHECK-NOT: hlfir.copy_out
call bar((x))
-! CHECK-NOT: fir.call @_FortranACopyOutAssign
-! CHECK: return
end subroutine
! Test copy-in in is skipped for intent(out) arguments.
-! CHECK: func @_QPtest_intent_out(
-! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
+! CHECK-LABEL: func @_QPtest_intent_out(
subroutine test_intent_out(x)
real :: x(:)
interface
@@ -109,26 +62,14 @@ subroutine bar_intent_out(x)
real, intent(out) :: x(100)
end subroutine
end interface
-! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
-! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
-! CHECK: } else {
-! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
-! CHECK-NOT: fir.call @_FortranAAssignTemporary
-! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
-! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
-! CHECK: fir.call @_QPbar_intent_out(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
+! CHECK: hlfir.copy_in
+! CHECK: fir.call @_QPbar_intent_out
+! CHECK: hlfir.copy_out
call bar_intent_out(x)
-
-! CHECK: fir.if %[[not_contiguous]]
-! CHECK: fir.call @_FortranACopyOutAssign
-! CHECK: return
end subroutine
-! Test copy-out is skipped for intent(out) arguments.
+! Test copy-out is skipped for intent(in) arguments.
! CHECK-LABEL: func.func @_QPtest_intent_in(
-! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
subroutine test_intent_in(x)
real :: x(:)
interface
@@ -136,30 +77,14 @@ subroutine bar_intent_in(x)
real, intent(in) :: x(100)
end subroutine
end interface
-! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
-! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
-! CHECK: } else {
-! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
-! CHECK: %[[temp_shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
-! CHECK: %[[temp_box:.*]] = fir.embox %[[temp]](%[[temp_shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
-! CHECK: fir.store %[[temp_box]] to %[[temp_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
-! CHECK: %[[temp_box_addr:.*]] = fir.convert %[[temp_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: fir.call @_FortranAAssignTemporary(%[[temp_box_addr]],
-! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
-! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
-! CHECK: fir.call @_QPbar_intent_in(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
+! CHECK: hlfir.copy_in
+! CHECK: fir.call @_QPbar_intent_in
+! CHECK: hlfir.copy_out %{{.*}}, %{{.*}} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, i1) -> ()
call bar_intent_in(x)
-! CHECK: fir.if %[[not_contiguous]]
-! CHECK: fir.zero
-! CHECK: fir.call @_FortranACopyOutAssign
-! CHECK: return
end subroutine
! Test copy-in/copy-out is done for intent(inout)
-! CHECK: func @_QPtest_intent_inout(
-! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
+! CHECK-LABEL: func @_QPtest_intent_inout(
subroutine test_intent_inout(x)
real :: x(:)
interface
@@ -167,111 +92,55 @@ subroutine bar_intent_inout(x)
real, intent(inout) :: x(100)
end subroutine
end interface
-! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
-! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
-! CHECK: } else {
-! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
-! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
-! CHECK: fir.call @_FortranAAssign
-! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
-! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
-! CHECK: fir.call @_QPbar_intent_inout(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
+! CHECK: hlfir.copy_in
+! CHECK: fir.call @_QPbar_intent_inout
+! CHECK: hlfir.copy_out
+! CHECK-SAME: to
call bar_intent_inout(x)
-! CHECK: fir.if %[[not_contiguous]]
-! CHECK: fir.call @_FortranACopyOutAssign
-! CHECK: return
end subroutine
! Test characters are handled correctly
! CHECK-LABEL: func @_QPtest_char(
-! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.char<1,10>>>{{.*}}) {
subroutine test_char(x)
-! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
-! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
-! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index
-! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
-! CHECK: %[[VAL_5:.*]] = fir.call @_FortranAIsContiguous(%[[VAL_4]]) fastmath<contract> : (!fir.box<none>) -> i1
-! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.heap<!fir.array<?x!fir.char<1,10>>>) {
-! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.heap<!fir.array<?x!fir.char<1,10>>>
-! CHECK: fir.result %[[VAL_7]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
-! CHECK: } else {
-! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_8]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
-! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?x!fir.char<1,10>>, %[[VAL_9]]#1 {uniq_name = ".copyinout"}
-! CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_9]]#1 : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_10]](%[[VAL_11]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
-! CHECK: fir.store %[[VAL_12]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranAAssignTemporary(%[[VAL_15]], %[[VAL_16]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
-! CHECK: }
-! CHECK: %[[VAL_19:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_19]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
-! CHECK: %[[VAL_21:.*]] = arith.constant false
-! CHECK: %[[VAL_22:.*]] = arith.cmpi eq, %[[VAL_5]], %[[VAL_21]] : i1
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_24:.*]] : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,?>>
-! CHECK: %[[VAL_25:.*]] = fir.emboxchar %[[VAL_23]], %[[VAL_3]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
-! CHECK: fir.call @_QPbar_char(%[[VAL_25]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
-! CHECK: fir.if %[[VAL_22]] {
-! CHECK: %[[VAL_26:.*]] = fir.shape %[[VAL_20]]#1 : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_24]](%[[VAL_26]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
-! CHECK: %[[REBOX:.*]] = fir.rebox %[[VAL_27]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>
-! CHECK: fir.store %[[REBOX]] to %[[TMP_BOX_REF:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>
-! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
-! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[VAL_32:.*]] = fir.convert %[[TMP_BOX_REF]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: fir.call @_FortranACopyOutAssign(%[[VAL_31]], %[[VAL_32]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, !fir.ref<i8>, i32) -> ()
-! CHECK: }
-
character(10) :: x(:)
+! CHECK: hlfir.copy_in
+! CHECK: fir.call @_QPbar_char
+! CHECK: hlfir.copy_out
call bar_char(x)
- ! CHECK: return
- ! CHECK: }
end subroutine test_char
! CHECK-LABEL: func @_QPtest_scalar_substring_does_no_trigger_copy_inout
-! CHECK-SAME: %[[arg0:.*]]: !fir.boxchar<1>
subroutine test_scalar_substring_does_no_trigger_copy_inout(c, i, j)
character(*) :: c
integer :: i, j
- ! CHECK: %[[unbox:.*]]:2 = fir.unboxchar %[[arg0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
- ! CHECK: %[[c:.*]] = fir.convert %[[unbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
- ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[c]], %{{.*}} : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
- ! CHECK: %[[substr:.*]] = fir.convert %[[coor]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.char<1,?>>
- ! CHECK: %[[boxchar:.*]] = fir.emboxchar %[[substr]], %{{.*}} : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
- ! CHECK: fir.call @_QPbar_char_2(%[[boxchar]]) {{.*}}: (!fir.boxchar<1>) -> ()
+ ! CHECK: hlfir.designate
+ ! CHECK-NOT: hlfir.copy_in
+ ! CHECK: fir.call @_QPbar_char_2
+ ! CHECK-NOT: hlfir.copy_out
call bar_char_2(c(i:j))
end subroutine
! CHECK-LABEL: func @_QPissue871(
-! CHECK-SAME: %[[p:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.type<_QFissue871Tt{i:i32}>>>>{{.*}})
subroutine issue871(p)
! Test passing implicit derived from scalar pointer (no copy-in/out).
type t
integer :: i
end type t
type(t), pointer :: p
- ! CHECK: %[[box_load:.*]] = fir.load %[[p]]
- ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]]
- ! CHECK: %[[cast:.*]] = fir.convert %[[addr]]
- ! CHECK: fir.call @_QPbar_derived(%[[cast]])
+ ! CHECK-NOT: hlfir.copy_in
+ ! CHECK: fir.call @_QPbar_derived
call bar_derived(p)
end subroutine
! CHECK-LABEL: func @_QPissue871_array(
-! CHECK-SAME: %[[p:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFissue871_arrayTt{i:i32}>>>>>
subroutine issue871_array(p)
! Test passing implicit derived from contiguous pointer (no copy-in/out).
type t
integer :: i
end type t
type(t), pointer, contiguous :: p(:)
- ! CHECK: %[[box_load:.*]] = fir.load %[[p]]
- ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]]
- ! CHECK: %[[cast:.*]] = fir.convert %[[addr]]
- ! CHECK: fir.call @_QPbar_derived_array(%[[cast]])
+ ! CHECK-NOT: hlfir.copy_in
+ ! CHECK: fir.call @_QPbar_derived_array
call bar_derived_array(p)
end subroutine
@@ -281,10 +150,10 @@ subroutine whole_components()
type t
integer :: i(100)
end type
- ! CHECK: %[[a:.*]] = fir.alloca !fir.type<_QFwhole_componentsTt{i:!fir.array<100xi32>}>
type(t) :: a
- ! CHECK: %[[addr:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_componentsTt{i:!fir.array<100xi32>}>>) -> !fir.ref<!fir.array<100xi32>>
- ! CHECK: fir.call @_QPbar_integer(%[[addr]]) {{.*}}: (!fir.ref<!fir.array<100xi32>>) -> ()
+ ! CHECK: hlfir.designate
+ ! CHECK-NOT: hlfir.copy_in
+ ! CHECK: fir.call @_QPbar_integer
call bar_integer(a%i)
end subroutine
@@ -294,19 +163,10 @@ subroutine whole_component_contiguous_pointer()
type t
integer, pointer, contiguous :: i(:)
end type
- ! CHECK: %[[a:.*]] = fir.alloca !fir.type<_QFwhole_component_contiguous_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>
type(t) :: a
- ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
- ! CHECK: %[[zero:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>>
- ! CHECK: %[[c0:.*]] = arith.constant 0 : index
- ! CHECK: %[[shape:.*]] = fir.shape %[[c0]] : (index) -> !fir.shape<1>
- ! CHECK: %[[embox:.*]] = fir.embox %[[zero]](%[[shape]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>>
- ! CHECK: fir.store %[[embox]] to %[[coor]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
- ! CHECK: %[[coor2:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
- ! CHECK: %[[box_load:.*]] = fir.load %[[coor2]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
- ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.ptr<!fir.array<?xi32>>
- ! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.ptr<!fir.array<?xi32>>) -> !fir.ref<!fir.array<100xi32>>
- ! CHECK: fir.call @_QPbar_integer(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xi32>>) -> ()
+ ! CHECK: hlfir.designate
+ ! CHECK-NOT: hlfir.copy_in
+ ! CHECK: fir.call @_QPbar_integer
call bar_integer(a%i)
end subroutine
@@ -316,21 +176,9 @@ subroutine whole_component_contiguous_char_pointer()
type t
character(:), pointer, contiguous :: i(:)
end type
- ! CHECK: %[[a:.*]] = fir.alloca !fir.type<_QFwhole_component_contiguous_char_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>}>
type(t) :: a
- ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_char_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
- ! CHECK: %[[zero:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.char<1,?>>>
- ! CHECK: %[[c0_1:.*]] = arith.constant 0 : index
- ! CHECK: %[[shape:.*]] = fir.shape %[[c0_1]] : (index) -> !fir.shape<1>
- ! CHECK: %[[c0_2:.*]] = arith.constant 0 : index
- ! CHECK: %[[embox:.*]] = fir.embox %[[zero]](%[[shape]]) typeparams %[[c0_2]] : (!fir.ptr<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>
- ! CHECK: fir.store %[[embox]] to %[[coor]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
- ! CHECK: %[[coor2:.*]] = fir.coordinate_of %[[a]], i : (!fir.ref<!fir.type<_QFwhole_component_contiguous_char_pointerTt{i:!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
- ! CHECK: %[[box_load:.*]] = fir.load %[[coor2]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
- ! CHECK: %[[addr:.*]] = fir.box_addr %[[box_load]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>) -> !fir.ptr<!fir.array<?x!fir.char<1,?>>>
- ! CHECK: %[[len:.*]] = fir.box_elesize %[[box_load]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>) -> index
- ! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.ptr<!fir.array<?x!fir.char<1,?>>>) -> !fir.ref<!fir.char<1,?>>
- ! CHECK: %[[emboxchar:.*]] = fir.emboxchar %[[cast]], %[[len]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
- ! CHECK: fir.call @_QPbar_char_3(%[[emboxchar]]) {{.*}}: (!fir.boxchar<1>) -> ()
+ ! CHECK: hlfir.designate
+ ! CHECK-NOT: hlfir.copy_in
+ ! CHECK: fir.call @_QPbar_char_3
call bar_char_3(a%i)
end subroutine
diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90
index 4a0decef86d09..032c82b9de04e 100644
--- a/flang/test/Lower/derived-type-finalization.f90
+++ b/flang/test/Lower/derived-type-finalization.f90
@@ -1,5 +1,5 @@
! Test derived type finalization
-! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
! Missing tests:
! - finalization within BLOCK construct
@@ -55,25 +55,21 @@ subroutine test_lhs_allocatable()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_lhs() {
-! CHECK: %[[BOXREF:.*]] = fir.alloca !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
! CHECK: %[[LHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "lhs", uniq_name = "_QMderived_type_finalizationFtest_lhsElhs"}
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[LHS]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: fir.store %[[EMBOX]] to %[[BOXREF]] : !fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[BOXREF]] : (!fir.ref<!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: fir.call @_FortranAAssign(%[[BOX_NONE]], {{.*}}
+! CHECK: %[[LHS_DECL:.*]]:2 = hlfir.declare %[[LHS]]
+! CHECK: %[[RHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "rhs", uniq_name = "_QMderived_type_finalizationFtest_lhsErhs"}
+! CHECK: %[[RHS_DECL:.*]]:2 = hlfir.declare %[[RHS]]
+! CHECK: hlfir.assign %[[RHS_DECL]]#0 to %[[LHS_DECL]]#0
+! CHECK: fir.call @_FortranADestroy
+! CHECK: fir.call @_FortranADestroy
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_lhs_allocatable() {
! CHECK: %[[LHS:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "lhs", uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs"}
-! CHECK: %[[LHS_ADDR:.*]] = fir.alloca !fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableElhs.addr"}
+! CHECK: %[[LHS_DECL:.*]]:2 = hlfir.declare %[[LHS]]
! CHECK: %[[RHS:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "rhs", uniq_name = "_QMderived_type_finalizationFtest_lhs_allocatableErhs"}
-! CHECK: %[[LHS_ADDR_LOAD:.*]] = fir.load %[[LHS_ADDR]] : !fir.ref<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
-! CHECK: %[[ADDR_I64:.*]] = fir.convert %[[LHS_ADDR_LOAD]] : (!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> i64
-! CHECK: %[[C0:.*]] = arith.constant 0 : i64
-! CHECK: %[[IS_NULL:.*]] = arith.cmpi ne, %[[ADDR_I64]], %[[C0]] : i64
-! CHECK: fir.if %[[IS_NULL]] {
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[LHS]] : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
-! CHECK: }
+! CHECK: %[[RHS_DECL:.*]]:2 = hlfir.declare %[[RHS]]
+! CHECK: hlfir.assign %[[RHS_DECL]]#0 to %[[LHS_DECL]]#0 realloc
+! CHECK: fir.call @_FortranADestroy
! 7.5.6.3 point 2. Finalization on explicit deallocation.
subroutine test_deallocate()
@@ -83,10 +79,10 @@ subroutine test_deallocate()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_deallocate() {
-! CHECK: %[[LOCAL_T:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "t", uniq_name = "_QMderived_type_finalizationFtest_deallocateEt"}
-! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[LOCAL_T]] : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+! CHECK: %[[T:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
+! CHECK: fir.call @_FortranAAllocatableAllocate
+! CHECK: fir.call @_FortranAAllocatableDeallocate
! 7.5.6.3 point 2. Finalization of disassociated target.
subroutine test_target_finalization()
@@ -96,13 +92,10 @@ subroutine test_target_finalization()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_target_finalization() {
-! CHECK: %[[P:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = "p", uniq_name = "_QMderived_type_finalizationFtest_target_finalizationEp"}
-! CHECK: %[[ADDR:.*]] = fir.alloca !fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {uniq_name = "_QMderived_type_finalizationFtest_target_finalizationEp.addr"}
-! CHECK: %[[zero:.*]] = fir.zero_bits !fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: fir.store %[[zero]] to %[[ADDR]] : !fir.ref<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[P:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[P_DECL:.*]]:2 = hlfir.declare %[[P]]
! CHECK: fir.call @_FortranAPointerAllocateSource
-! CHECK: %[[P_BOX_NONE:.*]] = fir.convert %[[P]] : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %{{.*}} = fir.call @_FortranAPointerDeallocate(%[[P_BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+! CHECK: fir.call @_FortranAPointerDeallocate
! 7.5.6.3 point 3. Finalize on END.
subroutine test_end_finalization()
@@ -110,11 +103,9 @@ subroutine test_end_finalization()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_end_finalization() {
-! CHECK: %[[LOCAL_T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "t", uniq_name = "_QMderived_type_finalizationFtest_end_finalizationEt"}
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[LOCAL_T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
-! CHECK: return
+! CHECK: %[[T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}>
+! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
+! CHECK: fir.call @_FortranADestroy
! test with multiple return.
subroutine test_end_finalization2(a)
@@ -126,21 +117,12 @@ subroutine test_end_finalization2(a)
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_end_finalization2(
! CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "a"}) {
+! CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]]
! CHECK: %[[T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "t", uniq_name = "_QMderived_type_finalizationFtest_end_finalization2Et"}
-! CHECK: %[[LOAD_A:.*]] = fir.load %[[A]] : !fir.ref<!fir.logical<4>>
-! CHECK: %[[CONV_A:.*]] = fir.convert %[[LOAD_A]] : (!fir.logical<4>) -> i1
-! CHECK: cf.cond_br %[[CONV_A]], ^bb1, ^bb2
-! CHECK: ^bb1:
-! CHECK: cf.br ^bb3
-! CHECK: ^bb2:
-! CHECK: %[[C10:.*]] = arith.constant 10 : i32
-! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[T]], a : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.ref<i32>
-! CHECK: fir.store %[[C10]] to %[[COORD_A]] : !fir.ref<i32>
-! CHECK: cf.br ^bb3
-! CHECK: ^bb3:
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
+! CHECK: cf.cond_br
+! CHECK: hlfir.assign
+! CHECK: fir.call @_FortranADestroy
! CHECK: return
! CHECK: }
@@ -155,12 +137,14 @@ subroutine test_fct_ref()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_fct_ref() {
-! CHECK: %[[RESULT:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = ".result"}
-! CHECK: %[[CALL_RES:.*]] = fir.call @_QMderived_type_finalizationPret_type()
-! CHECK: fir.save_result %[[CALL_RES]] to %[[RESULT]] : !fir.type<_QMderived_type_finalizationTt1{a:i32}>, !fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[RESULT]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: %[[RES:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = ".result"}
+! CHECK: %[[TY:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[TY_DECL:.*]]:2 = hlfir.declare %[[TY]]
+! CHECK: %[[CALL_RES:.*]] = fir.call @_QMderived_type_finalizationPret_type() fastmath<contract> : () -> !fir.type<_QMderived_type_finalizationTt1{a:i32}>
+! CHECK: fir.save_result %[[CALL_RES]] to %[[RES]]
+! CHECK: %[[RES_DECL:.*]]:2 = hlfir.declare %[[RES]]
+! CHECK: hlfir.assign %[[RES_DECL]]#0 to %[[TY_DECL]]#0 realloc
+! CHECK: fir.call @_FortranADestroy(%{{.*}})
! CHECK: return
subroutine test_finalize_intent_out(t)
@@ -169,9 +153,8 @@ subroutine test_finalize_intent_out(t)
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_finalize_intent_out(
! CHECK-SAME: %[[T:.*]]: !fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>> {fir.bindc_name = "t"}) {
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}}: (!fir.box<none>) -> ()
+! CHECK: %[[T_DECL:.*]]:2 = hlfir.declare %[[T]]
+! CHECK: fir.call @_FortranADestroy(%{{.*}})
! CHECK: return
function get_t1(i)
@@ -187,7 +170,7 @@ subroutine test_nonpointer_function()
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_nonpointer_function() {
! CHECK: %[[TMP:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>> {bindc_name = ".result"}
! CHECK: %{{.*}} = fir.call @_FortranAioBeginExternalListOutput
-! CHECK: %[[RES:.*]] = fir.call @_QMderived_type_finalizationPget_t1(%{{.*}}) {{.*}} : (!fir.ref<i32>) -> !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
+! CHECK: %[[RES:.*]] = fir.call @_QMderived_type_finalizationPget_t1(%{{.*}})
! CHECK: fir.save_result %[[RES]] to %[[TMP]] : !fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>, !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>
! CHECK: %{{.*}} = fir.call @_FortranAioOutputDerivedType
! CHECK-NOT: fir.call @_FortranADestroy
@@ -202,15 +185,10 @@ subroutine test_avoid_double_finalization(a)
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_avoid_double_finalization(
! CHECK: %[[b:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt3{t:!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>}> {bindc_name = "b", uniq_name = "_QMderived_type_finalizationFtest_avoid_double_finalizationEb"}
-! CHECK: %[[COORD_T:.*]] = fir.coordinate_of %[[b]], t : (!fir.ref<!fir.type<_QMderived_type_finalizationTt3{t:!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>}>>) -> !fir.ref<!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
-! CHECK: %[[COORD_A:.*]] = fir.coordinate_of %[[COORD_T]], a : (!fir.ref<!fir.type<_QMderived_type_finalizationTt2{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
-! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>>
-! CHECK: %[[SHAPE:.*]] = fir.shape %c0{{.*}} : (index) -> !fir.shape<1>
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>>
-! CHECK: fir.store %[[EMBOX]] to %[[COORD_A]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[b_DECL:.*]]:2 = hlfir.declare %[[b]]
+! CHECK: hlfir.assign %{{.*}} to %[[b_DECL]]#0
! CHECK-NOT: fir.call @_FortranADestroy
-! CHECK: fir.call @_FortranAAssign(
-! CHECK: fir.call @_FortranADestroy(
+! CHECK: fir.call @_FortranADestroy
function no_func_ret_finalize() result(ty)
type(t1) :: ty
@@ -218,7 +196,7 @@ function no_func_ret_finalize() result(ty)
end function
! CHECK-LABEL: func.func @_QMderived_type_finalizationPno_func_ret_finalize() -> !fir.type<_QMderived_type_finalizationTt1{a:i32}> {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: hlfir.assign
! CHECK-NOT: fir.call @_FortranADestroy
! CHECK: return %{{.*}} : !fir.type<_QMderived_type_finalizationTt1{a:i32}>
@@ -235,11 +213,9 @@ subroutine test_avoid_double_free()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPtest_avoid_double_free() {
-! CHECK: %[[RES:.*]] = fir.alloca !fir.class<!fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>> {bindc_name = ".result"}
! CHECK: fir.call @_FortranAAllocatableAllocateSource(
-! CHECK-NOT: fir.freemem %{{.*}} : !fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
-! CHECK: %[[RES_CONV:.*]] = fir.convert %[[RES]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[RES_CONV]]) {{.*}} : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranADestroy
+! CHECK: fir.call @_FortranAAllocatableDeallocatePolymorphic
subroutine t4_final(this)
type(t4) :: this
@@ -250,7 +226,7 @@ subroutine local_t4()
end subroutine
! CHECK-LABEL: func.func @_QMderived_type_finalizationPlocal_t4()
-! CHECK: fir.call @_FortranADestroy(%2) fastmath<contract> : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranADestroy(%{{.*}}) fastmath<contract> : (!fir.box<none>) -> ()
end module
diff --git a/flang/test/Lower/forall/forall-allocatable-2.f90 b/flang/test/Lower/forall/forall-allocatable-2.f90
index c6b8232fa4ede..730ae1ab4e6c6 100644
--- a/flang/test/Lower/forall/forall-allocatable-2.f90
+++ b/flang/test/Lower/forall/forall-allocatable-2.f90
@@ -1,6 +1,6 @@
! Test forall lowering
-! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
subroutine forall_with_allocatable2(a1)
real :: a1(:)
@@ -14,49 +14,43 @@ subroutine forall_with_allocatable2(a1)
end forall
end subroutine forall_with_allocatable2
-! CHECK-LABEL: func @_QPforall_with_allocatable2(
-! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
-! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
-! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "thing", uniq_name = "_QFforall_with_allocatable2Ething"}
-! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_2]], arr : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
-! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_4]](%[[VAL_6]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
-! CHECK: fir.store %[[VAL_7]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_9:.*]] = arith.constant 5 : i32
-! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index
+! CHECK-LABEL: func.func @_QPforall_with_allocatable2(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a1"}) {
+! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg 1 {uniq_name = "_QFforall_with_allocatable2Ea1"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "thing", uniq_name = "_QFforall_with_allocatable2Ething"}
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFforall_with_allocatable2Ething"} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
+! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_4]]#0, arr : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+! CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_6]](%[[VAL_8]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+! CHECK: fir.store %[[VAL_9]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_10:.*]] = arith.constant 5 : i32
! CHECK: %[[VAL_11:.*]] = arith.constant 15 : i32
-! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i32) -> index
-! CHECK: %[[VAL_13:.*]] = arith.constant 1 : index
-! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_2]], arr : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_17:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_18:.*]]:3 = fir.box_dims %[[VAL_16]], %[[VAL_17]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
-! CHECK: %[[VAL_19:.*]] = fir.box_addr %[[VAL_16]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
-! CHECK: %[[VAL_20:.*]] = fir.shape_shift %[[VAL_18]]#0, %[[VAL_18]]#1 : (index, index) -> !fir.shapeshift<1>
-! CHECK: %[[VAL_21:.*]] = fir.array_load %[[VAL_19]](%[[VAL_20]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>) -> !fir.array<?xf32>
-! CHECK: %[[VAL_22:.*]] = fir.array_load %[[VAL_0]] : (!fir.box<!fir.array<?xf32>>) -> !fir.array<?xf32>
-! CHECK: %[[VAL_23:.*]] = fir.do_loop %[[VAL_24:.*]] = %[[VAL_10]] to %[[VAL_12]] step %[[VAL_13]] unordered iter_args(%[[VAL_25:.*]] = %[[VAL_21]]) -> (!fir.array<?xf32>) {
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_24]] : (index) -> i32
-! CHECK: fir.store %[[VAL_26]] to %[[VAL_1]] : !fir.ref<i32>
-! CHECK: %[[VAL_27:.*]] = arith.constant 1 : index
-! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
-! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i32) -> i64
-! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i64) -> index
-! CHECK: %[[VAL_31:.*]] = arith.subi %[[VAL_30]], %[[VAL_27]] : index
-! CHECK: %[[VAL_32:.*]] = fir.array_fetch %[[VAL_22]], %[[VAL_31]] : (!fir.array<?xf32>, index) -> f32
-! CHECK: %[[VAL_33:.*]] = arith.constant 1 : index
-! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
-! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_34]] : (i32) -> i64
-! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_35]] : (i64) -> index
-! CHECK: %[[VAL_37:.*]] = arith.subi %[[VAL_36]], %[[VAL_33]] : index
-! CHECK: %[[VAL_38:.*]] = fir.array_update %[[VAL_25]], %[[VAL_32]], %[[VAL_37]] : (!fir.array<?xf32>, f32, index) -> !fir.array<?xf32>
-! CHECK: fir.result %[[VAL_38]] : !fir.array<?xf32>
+! CHECK: hlfir.forall lb {
+! CHECK: hlfir.yield %[[VAL_10]] : i32
+! CHECK: } ub {
+! CHECK: hlfir.yield %[[VAL_11]] : i32
+! CHECK: } (%[[VAL_12:.*]]: i32) {
+! CHECK: %[[VAL_13:.*]] = hlfir.forall_index "i" %[[VAL_12]] : (i32) -> !fir.ref<i32>
+! CHECK: hlfir.region_assign {
+! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i32) -> i64
+! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_15]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<f32>
+! CHECK: hlfir.yield %[[VAL_17]] : f32
+! CHECK: } to {
+! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_4]]#0{"arr"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
+! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64
+! CHECK: %[[VAL_22:.*]] = hlfir.designate %[[VAL_19]] (%[[VAL_21]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i64) -> !fir.ref<f32>
+! CHECK: hlfir.yield %[[VAL_22]] : !fir.ref<f32>
+! CHECK: }
! CHECK: }
-! CHECK: fir.array_merge_store %[[VAL_21]], %[[VAL_39:.*]] to %[[VAL_19]] : !fir.array<?xf32>, !fir.array<?xf32>, !fir.heap<!fir.array<?xf32>>
-! CHECK: %[[VAL_40:.*]] = fir.embox %[[VAL_2]] : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
-! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (!fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[VAL_41]])
+! CHECK: %[[VAL_23:.*]] = fir.embox %[[VAL_4]]#0 : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_23]] : (!fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[VAL_24]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: return
! CHECK: }
>From 050c5edc8ed16e5285285af979168f5e104b4aca Mon Sep 17 00:00:00 2001
From: hechenxi <hechenxi at bosc.ac.cn>
Date: Thu, 9 Apr 2026 13:55:23 +0800
Subject: [PATCH 7/7] Update test files
---
.../Lower/HLFIR/structure-constructor.f90 | 160 +++++++++---------
.../Lower/OpenMP/private-derived-type.f90 | 6 +-
flang/test/Lower/call-copy-in-out.f90 | 5 +-
flang/test/Lower/default-initialization.f90 | 57 +++----
.../test/Lower/derived-type-finalization.f90 | 4 +-
flang/test/Lower/derived-type-temp.f90 | 2 +-
.../Lower/forall/forall-allocatable-2.f90 | 60 +++----
7 files changed, 143 insertions(+), 151 deletions(-)
diff --git a/flang/test/Lower/HLFIR/structure-constructor.f90 b/flang/test/Lower/HLFIR/structure-constructor.f90
index 871bd645b41c3..f2d2c094198b3 100644
--- a/flang/test/Lower/HLFIR/structure-constructor.f90
+++ b/flang/test/Lower/HLFIR/structure-constructor.f90
@@ -38,13 +38,12 @@ end subroutine test1
! CHECK-LABEL: func.func @_QPtest1(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}> {bindc_name = "res", uniq_name = "_QFtest1Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest1Eres"} : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>)
! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>>
! CHECK: %[[VAL_6:.*]] = arith.constant 4 : index
-! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %[[SCOPE]] arg 1 {uniq_name = "_QFtest1Ex"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
+! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest1Ex"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>)
! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_8]]#0 : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> !fir.box<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>
! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
@@ -52,9 +51,9 @@ end subroutine test1
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> !fir.box<none>
! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_10]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: fir.call @_FortranAInitialize(%[[VAL_12]], %[[VAL_13]], %[[VAL_11]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_14:.*]] = arith.constant 4 : index
-! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_8]]#0{"c"} typeparams %[[VAL_14]] : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, index) -> !fir.ref<!fir.char<1,4>>
-! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_15]] temporary_lhs : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>
+! CHECK: %[[VAL_15:.*]] = arith.constant 4 : index
+! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_8]]#0{"c"} typeparams %[[VAL_15]] : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, index) -> !fir.ref<!fir.char<1,4>>
+! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_16]] temporary_lhs : !fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>
! CHECK: hlfir.assign %[[VAL_8]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>
! CHECK: return
! CHECK: }
@@ -68,12 +67,11 @@ end subroutine test2
! CHECK-LABEL: func.func @_QPtest2(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt2{i:!fir.array<10xi32>}> {bindc_name = "res", uniq_name = "_QFtest2Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest2Eres"} : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>)
! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index
! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[SCOPE]] arg 1 {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
+! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest2Ex"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>)
! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_7]]#0 : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> !fir.box<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>
! CHECK: %[[VAL_9:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
@@ -81,10 +79,10 @@ end subroutine test2
! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>) -> !fir.box<none>
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_9]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
! CHECK: fir.call @_FortranAInitialize(%[[VAL_11]], %[[VAL_12]], %[[VAL_10]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_13:.*]] = arith.constant 10 : index
-! CHECK: %[[VAL_14:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_7]]#0{"i"} <%[[VAL_14]]> shape %[[VAL_14]] : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.shape<1>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>>
-! CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_15]] temporary_lhs : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>
+! CHECK: %[[VAL_14:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_14]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_7]]#0{"i"} <%[[VAL_15]]> shape %[[VAL_15]] : (!fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.shape<1>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>>
+! CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_16]] temporary_lhs : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>
! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>, !fir.ref<!fir.type<_QMtypesTt2{i:!fir.array<10xi32>}>>
! CHECK: return
! CHECK: }
@@ -98,7 +96,6 @@ end subroutine test3
! CHECK-LABEL: func.func @_QPtest3(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {bindc_name = "res", uniq_name = "_QFtest3Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest3Eres"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>)
! CHECK: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_3]]#0, r : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
@@ -107,22 +104,22 @@ end subroutine test3
! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_5]](%[[VAL_7]]) : (!fir.ptr<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
! CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>)
-! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>)
-! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_10]]#0 : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
-! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
-! CHECK: %[[VAL_13:.*]] = arith.constant {{[0-9]*}} : i32
-! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<none>
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
-! CHECK: fir.call @_FortranAInitialize(%[[VAL_14]], %[[VAL_15]], %[[VAL_13]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_10]]#0{"r"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_18:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_19:.*]]:3 = fir.box_dims %[[VAL_17]], %[[VAL_18]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
-! CHECK: %[[VAL_20:.*]] = fir.shift %[[VAL_19]]#0 : (index) -> !fir.shift<1>
-! CHECK: %[[VAL_21:.*]] = fir.rebox %[[VAL_17]](%[[VAL_20]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
-! CHECK: fir.store %[[VAL_21]] to %[[VAL_16]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
-! CHECK: hlfir.assign %[[VAL_10]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>)
+! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>)
+! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
+! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
+! CHECK: fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"r"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_20:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_21:.*]]:3 = fir.box_dims %[[VAL_19]], %[[VAL_20]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_22:.*]] = fir.shift %[[VAL_21]]#0 : (index) -> !fir.shift<1>
+! CHECK: %[[VAL_23:.*]] = fir.rebox %[[VAL_19]](%[[VAL_22]]) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
+! CHECK: fir.store %[[VAL_23]] to %[[VAL_18]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt3{r:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>
! CHECK: return
! CHECK: }
@@ -135,7 +132,6 @@ end subroutine test4
! CHECK-LABEL: func.func @_QPtest4(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}> {bindc_name = "res", uniq_name = "_QFtest4Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest4Eres"} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>)
! CHECK: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_3]]#0, c : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
@@ -144,32 +140,33 @@ end subroutine test4
! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_5]](%[[VAL_7]]) : (!fir.heap<!fir.array<?x!fir.char<1,2>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>
! CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
-! CHECK: %[[VAL_9:.*]] = arith.constant 2 : index
-! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_9]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>)
-! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>)
-! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
-! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
-! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
-! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
-! CHECK: fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_17:.*]] = arith.constant 2 : index
-! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"c"} typeparams %[[VAL_17]] {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
-! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
-! CHECK: %[[VAL_20:.*]] = fir.box_addr %[[VAL_19]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,2>>>
-! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.char<1,2>>>) -> i64
-! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
-! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
-! CHECK: fir.if %[[VAL_23]] {
-! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
-! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_18]] realloc keep_lhs_len temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_10:.*]] = arith.constant 2 : index
+! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_10]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest4Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, index, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>)
+! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>)
+! CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_12]]#0 : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
+! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
+! CHECK: %[[VAL_15:.*]] = arith.constant {{[0-9]*}} : i32
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_14]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
+! CHECK: fir.call @_FortranAInitialize(%[[VAL_16]], %[[VAL_17]], %[[VAL_15]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: %[[VAL_19:.*]] = arith.constant 2 : index
+! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_12]]#0{"c"} typeparams %[[VAL_19]] {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_21]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,2>>>
+! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (!fir.heap<!fir.array<?x!fir.char<1,2>>>) -> i64
+! CHECK: %[[VAL_24:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i64
+! CHECK: fir.if %[[VAL_25]] {
+! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
+! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>>
! CHECK: }
-! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
-! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_25]])
+! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>, !fir.ref<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>
+! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_27]]
! CHECK: return
! CHECK: }
+
subroutine test5(x)
use types
type(t4), allocatable :: x(:)
@@ -179,7 +176,6 @@ end subroutine test5
! CHECK-LABEL: func.func @_QPtest5(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}> {bindc_name = "res", uniq_name = "_QFtest5Eres"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest5Eres"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>)
! CHECK: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_3]]#0, t5m : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
@@ -188,27 +184,27 @@ end subroutine test5
! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_5]](%[[VAL_7]]) : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>
! CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest5Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
-! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>)
-! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_10]]#0 : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
-! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
-! CHECK: %[[VAL_13:.*]] = arith.constant {{[0-9]*}} : i32
-! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
-! CHECK: fir.call @_FortranAInitialize(%[[VAL_14]], %[[VAL_15]], %[[VAL_13]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_10]]#0{"t5m"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: %[[VAL_18:.*]] = fir.box_addr %[[VAL_17]] : (!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>) -> !fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>
-! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>) -> i64
-! CHECK: %[[VAL_20:.*]] = arith.constant 0 : i64
-! CHECK: %[[VAL_21:.*]] = arith.cmpi ne, %[[VAL_19]], %[[VAL_20]] : i64
-! CHECK: fir.if %[[VAL_21]] {
-! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: hlfir.assign %[[VAL_22]] to %[[VAL_16]] realloc temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest5Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
+! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>)
+! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
+! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
+! CHECK: %[[VAL_14:.*]] = arith.constant {{[0-9]*}} : i32
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{[0-9]*}}>>) -> !fir.ref<i8>
+! CHECK: fir.call @_FortranAInitialize(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
+! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_11]]#0{"t5m"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: %[[VAL_20:.*]] = fir.box_addr %[[VAL_19]] : (!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>) -> !fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>
+! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>) -> i64
+! CHECK: %[[VAL_22:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_23:.*]] = arith.cmpi ne, %[[VAL_21]], %[[VAL_22]] : i64
+! CHECK: fir.if %[[VAL_23]] {
+! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
+! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_18]] realloc temporary_lhs : !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
! CHECK: }
-! CHECK: hlfir.assign %[[VAL_10]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_23]])
+! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>, !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
+! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_24]]
! CHECK: return
! CHECK: }
@@ -227,11 +223,10 @@ end subroutine test6
! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>>> {bindc_name = ".tmp.arrayctor"}
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>
! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,4>>
! CHECK: %[[VAL_9:.*]] = arith.constant 4 : index
-! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %[[SCOPE]] arg 2 {uniq_name = "_QFtest6Ec"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
+! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_9]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest6Ec"} : (!fir.ref<!fir.char<1,4>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,4>>, !fir.ref<!fir.char<1,4>>)
! CHECK: %[[VAL_11:.*]] = fir.alloca !fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}> {bindc_name = "res", uniq_name = "_QFtest6Eres"}
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFtest6Eres"} : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>)
! CHECK: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_12]]#0, t5 : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.ref<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>
@@ -241,7 +236,7 @@ end subroutine test6
! CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_16]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_15]](%[[VAL_17]]) : (!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>
! CHECK: fir.store %[[VAL_18]] to %[[VAL_14]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>
-! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest6Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
+! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest6Ex"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>>)
! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>)
! CHECK: %[[VAL_21:.*]] = fir.embox %[[VAL_20]]#0 : (!fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.box<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>
! CHECK: %[[VAL_22:.*]] = fir.address_of(@_QQclX{{.*}}) : !fir.ref<!fir.char<1,{{[0-9]*}}>>
@@ -301,9 +296,9 @@ end subroutine test6
! CHECK: hlfir.assign %[[VAL_70]] to %[[VAL_44]] temporary_lhs : !hlfir.expr<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>>
! CHECK: hlfir.assign %[[VAL_20]]#0 to %[[VAL_12]]#0 : !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>
! CHECK: %[[VAL_71:.*]] = fir.convert %[[VAL_21]] : (!fir.box<!fir.type<_QMtypesTt6{t5:!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_71]])
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_71]]
! CHECK: %[[VAL_72:.*]] = fir.convert %[[VAL_29]] : (!fir.box<!fir.type<_QMtypesTt5{t5m:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMtypesTt4{c:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,2>>>>}>>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_72]])
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_72]]
! CHECK: return
! CHECK: }
@@ -321,8 +316,7 @@ end subroutine test7
! CHECK-LABEL: func.func @_QPtest7(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
-! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[SCOPE]] arg 1 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest7En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest7En"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QFtest7Ex"}
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest7Ex"} : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_4]]#0, c2 : (!fir.ref<!fir.type<_QMtypesTt7{c1:i32,c2:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
@@ -357,7 +351,6 @@ subroutine test8
end subroutine test8
! CHECK-LABEL: func.func @_QPtest8() {
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}> {bindc_name = "res", uniq_name = "_QFtest8Eres"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest8Eres"} : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>)
! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_2]]#0, c : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
@@ -391,7 +384,7 @@ end subroutine test8
! CHECK: }
! CHECK: hlfir.assign %[[VAL_14]]#0 to %[[VAL_2]]#0 : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_15]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_30]])
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_30]]
! CHECK: return
! CHECK: }
@@ -405,7 +398,6 @@ subroutine test9
end subroutine test9
! CHECK-LABEL: func.func @_QPtest9() {
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}> {bindc_name = "res", uniq_name = "_QFtest9Eres"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest9Eres"} : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>)
! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_2]]#0, c : (!fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
@@ -427,10 +419,11 @@ end subroutine test9
! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.ref<!fir.char<1,12>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,11>>>>
! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_2]]#0 : !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>, !fir.ref<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.type<_QMtypesTt8{c:!fir.box<!fir.heap<!fir.char<1,11>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_21]])
+! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_21]]
! CHECK: return
! CHECK: }
+
! Test character non-allocatable component initialization
! from character allocatable of different size.
subroutine test10
@@ -441,7 +434,6 @@ subroutine test10
end subroutine test10
! CHECK-LABEL: func.func @_QPtest10() {
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}>
-! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMtypesTt1{c:!fir.char<1,4>}> {bindc_name = "res", uniq_name = "_QFtest10Eres"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest10Eres"} : (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>) -> (!fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref<!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>)
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,12>>> {bindc_name = "x", uniq_name = "_QFtest10Ex"}
diff --git a/flang/test/Lower/OpenMP/private-derived-type.f90 b/flang/test/Lower/OpenMP/private-derived-type.f90
index fef0867045703..c286ea29c62aa 100644
--- a/flang/test/Lower/OpenMP/private-derived-type.f90
+++ b/flang/test/Lower/OpenMP/private-derived-type.f90
@@ -16,12 +16,12 @@ subroutine s4
end subroutine s4
! CHECK: omp.private {type = private} @[[DERIVED_PRIV:.*]] : !fir.type<{{.*}}y3{x:!fir.box<!fir.heap<i32>>}> init {
-! CHECK: %[[VAL_25:.*]] = fir.embox %{{.*}} : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
+! CHECK: %[[VAL_25:.*]] = fir.embox %[[VAL_23:.*]] : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
! CHECK: %[[VAL_26:.*]] = fir.address_of
! CHECK: %[[VAL_27:.*]] = arith.constant 8 : i32
! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_25]] : (!fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_26]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
-! Check we do call FortranAInitialize on the derived type
+! Check we do call FortranAInitialize on the derived type
! CHECK: fir.call @_FortranAInitialize(%[[VAL_28]], %[[VAL_29]], %[[VAL_27]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> ()
! CHECK: }
@@ -38,7 +38,7 @@ end subroutine s4
! CHECK: }
! CHECK: %[[VAL_39:.*]] = fir.embox %[[VAL_DERIVED_DECLARE]]#0 : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
! CHECK: %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (!fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
-! Check the derived type is destroyed
+! Check the derived type is destroyed
! CHECK: fir.call @_FortranADestroy(%[[VAL_40]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: return
! CHECK: }
diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90
index 2fc78fcf1e65c..e29c106d67c40 100644
--- a/flang/test/Lower/call-copy-in-out.f90
+++ b/flang/test/Lower/call-copy-in-out.f90
@@ -68,7 +68,7 @@ subroutine bar_intent_out(x)
call bar_intent_out(x)
end subroutine
-! Test copy-out is skipped for intent(in) arguments.
+! Test copy-out is skipped for intent(out) arguments.
! CHECK-LABEL: func.func @_QPtest_intent_in(
subroutine test_intent_in(x)
real :: x(:)
@@ -79,7 +79,8 @@ subroutine bar_intent_in(x)
end interface
! CHECK: hlfir.copy_in
! CHECK: fir.call @_QPbar_intent_in
-! CHECK: hlfir.copy_out %{{.*}}, %{{.*}} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, i1) -> ()
+! CHECK: hlfir.copy_out
+! CHECK-SAME: %{{.*}}, %{{.*}} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, i1) -> ()
call bar_intent_in(x)
end subroutine
diff --git a/flang/test/Lower/default-initialization.f90 b/flang/test/Lower/default-initialization.f90
index c2a4673c537af..76e29587dffb9 100644
--- a/flang/test/Lower/default-initialization.f90
+++ b/flang/test/Lower/default-initialization.f90
@@ -21,9 +21,9 @@ module test_dinit
! Test local scalar is default initialized
! CHECK-LABEL: func @_QMtest_dinitPlocal()
subroutine local
- !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{i:i32}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocalEx"}
- !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
- !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
+ !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocalEx"}
+ !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
type(t) :: x
print *, x%i
end subroutine
@@ -31,9 +31,9 @@ subroutine local
! Test local array is default initialized
! CHECK-LABEL: func @_QMtest_dinitPlocal_array()
subroutine local_array()
- ! CHECK: %[[x:.*]] = fir.alloca !fir.array<4x!fir.type<_QMtest_dinitTt{i:i32}>>
+ ! CHECK: %[[x:.*]] = fir.alloca !fir.array<4x!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
! CHECK: %[[xshape:.*]] = fir.shape %c4{{.*}} : (index) -> !fir.shape<1>
- ! CHECK: %[[xbox:.*]] = fir.embox %[[x]](%[[xshape]]) : (!fir.ref<!fir.array<4x!fir.type<_QMtest_dinitTt{i:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<4x!fir.type<_QMtest_dinitTt{i:i32}>>>
+ ! CHECK: %[[xbox:.*]] = fir.embox %[[x]](%[[xshape]]) : (!fir.ref<!fir.array<4x!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<4x!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>>
! CHECK: %[[xboxNone:.*]] = fir.convert %[[xbox]]
! CHECK: fir.call @_FortranAInitialize(%[[xboxNone]], %{{.*}}, %{{.*}}) {{.*}}: (!fir.box<none>, !fir.ref<i8>, i32) -> ()
type(t) :: x(4)
@@ -44,7 +44,7 @@ subroutine local_array()
! scalars.
! CHECK-LABEL: func @_QMtest_dinitPlocal_alloc_comp()
subroutine local_alloc_comp
- !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt_alloc_comp{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocal_alloc_compEx"}
+ !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt_alloc_comp{{(,sequence)?}}{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "x", uniq_name = "_QMtest_dinitFlocal_alloc_compEx"}
!CHECK: %[[COORD:.*]] = fir.coordinate_of %[[x]], i : (!fir.ref<!fir.type<_QMtest_dinitTt_alloc_comp{i:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
!CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
!CHECK: %[[SHAPE:.*]] = fir.shape %c0{{.*}} : (index) -> !fir.shape<1>
@@ -54,31 +54,31 @@ subroutine local_alloc_comp
end subroutine
! Test function results are default initialized.
- ! CHECK-LABEL: func @_QMtest_dinitPresult() -> !fir.type<_QMtest_dinitTt{i:i32}>
+ ! CHECK-LABEL: func @_QMtest_dinitPresult() -> !fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>
function result()
- !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{i:i32}> {bindc_name = "result", uniq_name = "_QMtest_dinitFresultEresult"}
- !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
- !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
+ !CHECK: %[[x:.*]] = fir.alloca !fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}> {bindc_name = "result", uniq_name = "_QMtest_dinitFresultEresult"}
+ !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
type(t) :: result
end function
! Test intent(out) dummies are default initialized
! CHECK-LABEL: func @_QMtest_dinitPintent_out(
- ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
+ ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
subroutine intent_out(x)
- !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
- !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>
+ !CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTt.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
+ !CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>, !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
type(t), intent(out) :: x
end subroutine
! Test that optional intent(out) are default initialized only when
! present.
! CHECK-LABEL: func @_QMtest_dinitPintent_out_optional(
- ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>> {fir.bindc_name = "x", fir.optional})
+ ! CHECK-SAME: %[[x:.*]]: !fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>> {fir.bindc_name = "x", fir.optional})
subroutine intent_out_optional(x)
- ! CHECK: %[[isPresent:.*]] = fir.is_present %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>) -> i1
+ ! CHECK: %[[isPresent:.*]] = fir.is_present %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>) -> i1
! CHECK: fir.if %[[isPresent]] {
- ! CHECK: %[[xbox:.*]] = fir.embox %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{i:i32}>>) -> !fir.box<!fir.type<_QMtest_dinitTt{i:i32}>>
+ ! CHECK: %[[xbox:.*]] = fir.embox %[[x]] : (!fir.ref<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>) -> !fir.box<!fir.type<_QMtest_dinitTt{{(,sequence)?}}{i:i32}>>
! CHECK: %[[xboxNone:.*]] = fir.convert %[[xbox]]
! CHECK: fir.call @_FortranAInitialize(%[[xboxNone]], %{{.*}}, %{{.*}}) {{.*}}: (!fir.box<none>, !fir.ref<i8>, i32) -> ()
! CHECK: }
@@ -92,33 +92,32 @@ subroutine local_eq()
integer :: zi
! CHECK: %[[equiv:.*]] = fir.alloca !fir.array<4xi8>
! CHECK: %[[xcoor:.*]] = fir.coordinate_of %[[equiv]], %c0{{.*}} : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
- ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
- ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>
- ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
equivalence (x, zi)
print *, i
end subroutine
! Test local equivalences with both equivalenced entities being
- ! default initialized.
- ! Note that the standard allow default initialization
- ! to be performed several times as long as the values are the same.
- ! So far that is what lowering is doing to stay simple.
+ ! default initialized. Note that the standard allow default initialization
+ ! to be performed several times as long as the values are the same. So
+ ! far that is what lowering is doing to stay simple.
! CHECK-LABEL: func @_QMtest_dinitPlocal_eq2()
subroutine local_eq2()
type(tseq) :: x
type(tseq) :: y
! CHECK: %[[equiv:.*]] = fir.alloca !fir.array<4xi8>
! CHECK: %[[xcoor:.*]] = fir.coordinate_of %[[equiv]], %c0{{.*}} : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
- ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
- ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>
- ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: %[[x:.*]] = fir.convert %[[xcoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: fir.copy %[[ADDR]] to %[[x]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
! CHECK: %[[ycoor:.*]] = fir.coordinate_of %[[equiv]], %c0{{.*}} : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
- ! CHECK: %[[y:.*]] = fir.convert %[[ycoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
- ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>
- ! CHECK: fir.copy %[[ADDR]] to %[[y]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{i:i32}>>
+ ! CHECK: %[[y:.*]] = fir.convert %[[ycoor]] : (!fir.ref<i8>) -> !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: %[[ADDR:.*]] = fir.address_of(@_QQ_QMtest_dinitTtseq.DerivedInit) : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
+ ! CHECK: fir.copy %[[ADDR]] to %[[y]] no_overlap : !fir.ref<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>, !fir.ptr<!fir.type<_QMtest_dinitTtseq{{(,sequence)?}}{i:i32}>>
equivalence (x, y)
print *, y%i
end subroutine
diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90
index 032c82b9de04e..6c4b5f6e2b02c 100644
--- a/flang/test/Lower/derived-type-finalization.f90
+++ b/flang/test/Lower/derived-type-finalization.f90
@@ -140,8 +140,8 @@ subroutine test_fct_ref()
! CHECK: %[[RES:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = ".result"}
! CHECK: %[[TY:.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>>
! CHECK: %[[TY_DECL:.*]]:2 = hlfir.declare %[[TY]]
-! CHECK: %[[CALL_RES:.*]] = fir.call @_QMderived_type_finalizationPret_type() fastmath<contract> : () -> !fir.type<_QMderived_type_finalizationTt1{a:i32}>
-! CHECK: fir.save_result %[[CALL_RES]] to %[[RES]]
+! CHECK: %[[CALL_RES:.*]] = fir.call @_QMderived_type_finalizationPret_type()
+! CHECK: fir.save_result %[[CALL_RES]] to %[[RES]] :
! CHECK: %[[RES_DECL:.*]]:2 = hlfir.declare %[[RES]]
! CHECK: hlfir.assign %[[RES_DECL]]#0 to %[[TY_DECL]]#0 realloc
! CHECK: fir.call @_FortranADestroy(%{{.*}})
diff --git a/flang/test/Lower/derived-type-temp.f90 b/flang/test/Lower/derived-type-temp.f90
index 3e5e3b8e0a9e1..c2ee34e53ba7f 100644
--- a/flang/test/Lower/derived-type-temp.f90
+++ b/flang/test/Lower/derived-type-temp.f90
@@ -13,7 +13,7 @@ program derived_temp_init
y = t2(x)
end
-! CHECK: %[[ALLOC:.*]] = fir.alloca !fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}> {bindc_name = "x", uniq_name = "_QFEx"}
+! CHECK: %[[ALLOC:.*]] = fir.alloca !fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}> {bindc_name = "x", uniq_name = "_QFEx"}
! CHECK: %[[x:.*]]:2 = hlfir.declare %[[ALLOC]] {{.*}}
! CHECK: %[[COOR:.*]] = fir.coordinate_of %[[x]]#0, i : (!fir.ref<!fir.type<_QFTt1{i:!fir.box<!fir.heap<i32>>}>>) -> !fir.ref<!fir.box<!fir.heap<i32>>>
! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap<i32>
diff --git a/flang/test/Lower/forall/forall-allocatable-2.f90 b/flang/test/Lower/forall/forall-allocatable-2.f90
index 730ae1ab4e6c6..513d2f6731f1d 100644
--- a/flang/test/Lower/forall/forall-allocatable-2.f90
+++ b/flang/test/Lower/forall/forall-allocatable-2.f90
@@ -15,42 +15,42 @@ subroutine forall_with_allocatable2(a1)
end subroutine forall_with_allocatable2
! CHECK-LABEL: func.func @_QPforall_with_allocatable2(
-! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a1"}) {
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a1"}) {
! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
-! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg 1 {uniq_name = "_QFforall_with_allocatable2Ea1"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
-! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "thing", uniq_name = "_QFforall_with_allocatable2Ething"}
-! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFforall_with_allocatable2Ething"} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
-! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_4]]#0, arr : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
-! CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1>
-! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_6]](%[[VAL_8]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
-! CHECK: fir.store %[[VAL_9]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_10:.*]] = arith.constant 5 : i32
-! CHECK: %[[VAL_11:.*]] = arith.constant 15 : i32
+! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] arg 1 {uniq_name = "_QFforall_with_allocatable2Ea1"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}> {bindc_name = "thing", uniq_name = "_QFforall_with_allocatable2Ething"}
+! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFforall_with_allocatable2Ething"} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>, !fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>)
+! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_9]]#0, arr : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_3:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_6:.*]] = fir.embox %[[VAL_3]](%[[VAL_5]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+! CHECK: fir.store %[[VAL_6]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_11:.*]] = arith.constant 5 : i32
+! CHECK: %[[VAL_12:.*]] = arith.constant 15 : i32
! CHECK: hlfir.forall lb {
-! CHECK: hlfir.yield %[[VAL_10]] : i32
-! CHECK: } ub {
! CHECK: hlfir.yield %[[VAL_11]] : i32
-! CHECK: } (%[[VAL_12:.*]]: i32) {
-! CHECK: %[[VAL_13:.*]] = hlfir.forall_index "i" %[[VAL_12]] : (i32) -> !fir.ref<i32>
+! CHECK: } ub {
+! CHECK: hlfir.yield %[[VAL_12]] : i32
+! CHECK: } (%[[VAL_13:.*]]: i32) {
+! CHECK: %[[VAL_14:.*]] = hlfir.forall_index "i" %[[VAL_13]] : (i32) -> !fir.ref<i32>
! CHECK: hlfir.region_assign {
-! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
-! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i32) -> i64
-! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_15]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
-! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<f32>
-! CHECK: hlfir.yield %[[VAL_17]] : f32
+! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref<i32>
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64
+! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref<f32>
+! CHECK: hlfir.yield %[[VAL_18]] : f32
! CHECK: } to {
-! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_4]]#0{"arr"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
-! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64
-! CHECK: %[[VAL_22:.*]] = hlfir.designate %[[VAL_19]] (%[[VAL_21]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i64) -> !fir.ref<f32>
-! CHECK: hlfir.yield %[[VAL_22]] : !fir.ref<f32>
+! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_9]]#0{"arr"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_19]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_14]] : !fir.ref<i32>
+! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_21]] : (i32) -> i64
+! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_20]] (%[[VAL_22]]) : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i64) -> !fir.ref<f32>
+! CHECK: hlfir.yield %[[VAL_23]] : !fir.ref<f32>
! CHECK: }
! CHECK: }
-! CHECK: %[[VAL_23:.*]] = fir.embox %[[VAL_4]]#0 : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_23]] : (!fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
-! CHECK: fir.call @_FortranADestroy(%[[VAL_24]]) fastmath<contract> : (!fir.box<none>) -> ()
+! CHECK: %[[VAL_24:.*]] = fir.embox %[[VAL_9]]#0 : (!fir.ref<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>
+! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (!fir.box<!fir.type<_QFforall_with_allocatable2Tt{i:i32,arr:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.box<none>
+! CHECK: fir.call @_FortranADestroy(%[[VAL_25]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: return
! CHECK: }
More information about the flang-commits
mailing list