Skip to content

Commit bc991d9

Browse files
committed
[flang][hlfir] Array constructor lowering [part 4/4]
Enable character and derived type array constructor lowering. Nothing special needs to be done other than lowering the types before the array constructor lowering. Derived type are forced to use the runtime for now to avoid undesired usage of user defined assignment that hlfir.assign may trigger when using the runtime. Differential Revision: https://reviews.llvm.org/D144548
1 parent 7f81dd4 commit bc991d9

File tree

3 files changed

+205
-17
lines changed

3 files changed

+205
-17
lines changed

flang/lib/Lower/ConvertArrayConstructor.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,20 @@ class ArrayCtorLoweringStrategy {
477477
// and chooses the lowering strategy.
478478
//===----------------------------------------------------------------------===//
479479

480+
/// Helper to lower a scalar extent expression (like implied-do bounds).
481+
static mlir::Value lowerExtentExpr(mlir::Location loc,
482+
Fortran::lower::AbstractConverter &converter,
483+
Fortran::lower::SymMap &symMap,
484+
Fortran::lower::StatementContext &stmtCtx,
485+
const Fortran::evaluate::ExtentExpr &expr) {
486+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
487+
mlir::IndexType idxTy = builder.getIndexType();
488+
hlfir::Entity value = Fortran::lower::convertExprToHLFIR(
489+
loc, converter, toEvExpr(expr), symMap, stmtCtx);
490+
value = hlfir::loadTrivialScalar(loc, builder, value);
491+
return builder.createConvert(loc, idxTy, value);
492+
}
493+
480494
namespace {
481495
/// Helper class to lower the array constructor type and its length parameters.
482496
/// The length parameters, if any, are only lowered if this does not require
@@ -503,7 +517,10 @@ struct LengthAndTypeCollector<Fortran::evaluate::SomeDerived> {
503517
&arrayCtorExpr,
504518
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
505519
mlir::SmallVectorImpl<mlir::Value> &lengths) {
506-
TODO(loc, "collect derived type and length");
520+
// Array constructors cannot be unlimited polymorphic (C7113), so there must
521+
// be a derived type spec available.
522+
return Fortran::lower::translateDerivedTypeToFIRType(
523+
converter, arrayCtorExpr.result().derivedTypeSpec());
507524
}
508525
};
509526

@@ -517,7 +534,17 @@ struct LengthAndTypeCollector<Character<Kind>> {
517534
const Fortran::evaluate::ArrayConstructor<Character<Kind>> &arrayCtorExpr,
518535
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
519536
mlir::SmallVectorImpl<mlir::Value> &lengths) {
520-
TODO(loc, "collect character type and length");
537+
llvm::SmallVector<Fortran::lower::LenParameterTy> typeLengths;
538+
if (const Fortran::evaluate::ExtentExpr *lenExpr = arrayCtorExpr.LEN()) {
539+
lengths.push_back(
540+
lowerExtentExpr(loc, converter, symMap, stmtCtx, *lenExpr));
541+
if (std::optional<std::int64_t> cstLen =
542+
Fortran::evaluate::ToInt64(*lenExpr))
543+
typeLengths.push_back(*cstLen);
544+
}
545+
return Fortran::lower::getFIRType(&converter.getMLIRContext(),
546+
Fortran::common::TypeCategory::Character,
547+
Kind, typeLengths);
521548
}
522549
};
523550
} // namespace
@@ -611,20 +638,6 @@ ArrayCtorAnalysis::ArrayCtorAnalysis(
611638
}
612639
}
613640

614-
/// Helper to lower a scalar extent expression (like implied-do bounds).
615-
static mlir::Value lowerExtentExpr(mlir::Location loc,
616-
Fortran::lower::AbstractConverter &converter,
617-
Fortran::lower::SymMap &symMap,
618-
Fortran::lower::StatementContext &stmtCtx,
619-
const Fortran::evaluate::ExtentExpr &expr) {
620-
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
621-
mlir::IndexType idxTy = builder.getIndexType();
622-
hlfir::Entity value = Fortran::lower::convertExprToHLFIR(
623-
loc, converter, toEvExpr(expr), symMap, stmtCtx);
624-
value = hlfir::loadTrivialScalar(loc, builder, value);
625-
return builder.createConvert(loc, idxTy, value);
626-
}
627-
628641
/// Does \p expr contain no calls to user function?
629642
static bool isCallFreeExpr(const Fortran::evaluate::ExtentExpr &expr) {
630643
for (const Fortran::semantics::Symbol &symbol :
@@ -679,7 +692,7 @@ static ArrayCtorLoweringStrategy selectArrayCtorLoweringStrategy(
679692
// Based on what was gathered and the result of the analysis, select and
680693
// instantiate the right lowering strategy for the array constructor.
681694
if (!extent || needToEvaluateOneExprToGetLengthParameters ||
682-
analysis.anyArrayExpr)
695+
analysis.anyArrayExpr || declaredType.getEleTy().isa<fir::RecordType>())
683696
return RuntimeTempStrategy(
684697
loc, builder, declaredType,
685698
extent ? std::optional<mlir::Value>(extent) : std::nullopt, lengths,
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
! Test lowering of character array constructors to HLFIR.
2+
! RUN: bbc -emit-fir -hlfir -o - %s | FileCheck %s
3+
4+
module chararrayctor
5+
character(3), target :: ctarg1 = "abc"
6+
character(3), target :: ctarg2 = "def"
7+
contains
8+
9+
subroutine test_pre_computed_length(c1, c2)
10+
character(*) :: c1, c2
11+
call takes_char([character(3):: c1, c2])
12+
end subroutine
13+
! CHECK-LABEL: func.func @_QMchararrayctorPtest_pre_computed_length(
14+
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %{{.*}}Ec1"
15+
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %{{.*}}Ec2"
16+
! CHECK: %[[VAL_12:.*]] = arith.constant 2 : index
17+
! CHECK: %[[VAL_13:.*]] = arith.constant 3 : i64
18+
! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i64) -> index
19+
! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index
20+
! CHECK: %[[VAL_16:.*]] = fir.allocmem !fir.array<2x!fir.char<1,3>> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
21+
! CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
22+
! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_16]](%[[VAL_17]]) typeparams %[[VAL_14]] {uniq_name = ".tmp.arrayctor"} : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, !fir.shape<1>, index) -> (!fir.heap<!fir.array<2x!fir.char<1,3>>>, !fir.heap<!fir.array<2x!fir.char<1,3>>>)
23+
! CHECK: %[[VAL_19:.*]] = arith.constant 3 : i64
24+
! CHECK: %[[VAL_20:.*]] = hlfir.set_length %[[VAL_9]]#0 len %[[VAL_19]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,3>>
25+
! CHECK: %[[VAL_21:.*]] = arith.addi %[[VAL_15]], %[[VAL_15]] : index
26+
! CHECK: %[[VAL_22:.*]] = hlfir.designate %[[VAL_18]]#0 (%[[VAL_15]]) typeparams %[[VAL_14]] : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, index, index) -> !fir.ref<!fir.char<1,3>>
27+
! CHECK: hlfir.assign %[[VAL_20]] to %[[VAL_22]] : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>
28+
! CHECK: %[[VAL_23:.*]] = arith.constant 3 : i64
29+
! CHECK: %[[VAL_24:.*]] = hlfir.set_length %[[VAL_11]]#0 len %[[VAL_23]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,3>>
30+
! CHECK: %[[VAL_25:.*]] = hlfir.designate %[[VAL_18]]#0 (%[[VAL_21]]) typeparams %[[VAL_14]] : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, index, index) -> !fir.ref<!fir.char<1,3>>
31+
! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_25]] : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>
32+
! CHECK: %[[VAL_26:.*]] = arith.constant true
33+
! CHECK: %[[VAL_27:.*]] = hlfir.as_expr %[[VAL_18]]#0 move %[[VAL_26]] : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, i1) -> !hlfir.expr<2x!fir.char<1,3>>
34+
! CHECK: fir.call @_QMchararrayctorPtakes_char
35+
! CHECK: hlfir.destroy %[[VAL_27]] : !hlfir.expr<2x!fir.char<1,3>>
36+
37+
subroutine test_dynamic_length()
38+
call takes_char([char_pointer(1), char_pointer(2)])
39+
end subroutine
40+
! CHECK-LABEL: func.func @_QMchararrayctorPtest_dynamic_length() {
41+
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.char<1,?>>> {bindc_name = ".result"}
42+
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.char<1,?>>> {bindc_name = ".result"}
43+
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.array<10xi64> {bindc_name = ".rt.arrayctor.vector"}
44+
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>> {bindc_name = ".tmp.arrayctor"}
45+
! CHECK: %[[VAL_10:.*]] = arith.constant 2 : index
46+
! CHECK: %[[VAL_11:.*]] = arith.constant 0 : index
47+
! CHECK: %[[VAL_12:.*]] = fir.zero_bits !fir.heap<!fir.array<2x!fir.char<1,?>>>
48+
! CHECK: %[[VAL_13:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1>
49+
! CHECK: %[[VAL_14:.*]] = fir.embox %[[VAL_12]](%[[VAL_13]]) typeparams %[[VAL_11]] : (!fir.heap<!fir.array<2x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>
50+
! CHECK: fir.store %[[VAL_14]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>>
51+
! CHECK: %[[VAL_15:.*]] = arith.constant true
52+
! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<10xi64>>) -> !fir.llvm_ptr<i8>
53+
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>>) -> !fir.ref<!fir.box<none>>
54+
! CHECK: %[[VAL_22:.*]] = fir.call @_FortranAInitArrayConstructorVector(%[[VAL_16]], %[[VAL_20]], %[[VAL_15]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.ref<!fir.box<none>>, i1, i32, !fir.ref<i8>, i32) -> none
55+
! CHECK: fir.call @_QMchararrayctorPchar_pointer(
56+
! CHECK: fir.call @_FortranAPushArrayConstructorValue(%[[VAL_16]], %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.box<none>) -> none
57+
! CHECK: fir.call @_QMchararrayctorPchar_pointer(
58+
! CHECK: fir.call @_FortranAPushArrayConstructorValue(%[[VAL_16]], %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.box<none>) -> none
59+
! CHECK: %[[VAL_45:.*]] = arith.constant true
60+
! CHECK: %[[VAL_46:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>>
61+
! CHECK: %[[VAL_47:.*]] = hlfir.as_expr %[[VAL_46]] move %[[VAL_45]] : (!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>, i1) -> !hlfir.expr<2x!fir.char<1,?>>
62+
! CHECK: fir.call @_QMchararrayctorPtakes_char(
63+
! CHECK: hlfir.destroy %[[VAL_47]] : !hlfir.expr<2x!fir.char<1,?>>
64+
65+
66+
! Code below is only relevant for end-to-end test validation purpose.
67+
function char_pointer(i)
68+
integer :: i
69+
character(:), pointer :: char_pointer
70+
if (i.eq.1) then
71+
char_pointer => ctarg1
72+
else
73+
char_pointer => ctarg2
74+
end if
75+
end function
76+
subroutine takes_char(c)
77+
character(*) :: c(:)
78+
print *, "got : ", c
79+
end subroutine
80+
end module
81+
82+
use chararrayctor
83+
print *, "expect: ab cde"
84+
call test_pre_computed_length("ab", "cdefg")
85+
print *, "expect: abcdef"
86+
call test_dynamic_length()
87+
end
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
! Test lowering of derived type array constructors to HLFIR.
2+
! RUN: bbc -emit-fir -hlfir --polymorphic-type -o - %s | FileCheck %s
3+
4+
module types
5+
type simple
6+
integer :: i
7+
integer :: j
8+
end type
9+
end module
10+
module derivedarrayctor
11+
use types
12+
contains
13+
subroutine test_simple(s1, s2)
14+
type(simple) :: s1, s2
15+
call takes_simple([s1, s2])
16+
end subroutine
17+
! CHECK-LABEL: func.func @_QMderivedarrayctorPtest_simple(
18+
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.array<10xi64> {bindc_name = ".rt.arrayctor.vector"}
19+
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>> {bindc_name = ".tmp.arrayctor"}
20+
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}Es1"
21+
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}Es2"
22+
! CHECK: %[[VAL_6:.*]] = arith.constant 2 : index
23+
! CHECK: %[[VAL_7:.*]] = fir.allocmem !fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
24+
! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
25+
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_8]]) {uniq_name = ".tmp.arrayctor"} : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>)
26+
! CHECK: %[[VAL_10:.*]] = fir.embox %[[VAL_9]]#1(%[[VAL_8]]) : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>
27+
! CHECK: fir.store %[[VAL_10]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>
28+
! CHECK: %[[VAL_11:.*]] = arith.constant false
29+
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<10xi64>>) -> !fir.llvm_ptr<i8>
30+
! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>) -> !fir.ref<!fir.box<none>>
31+
! CHECK: %[[VAL_18:.*]] = fir.call @_FortranAInitArrayConstructorVector(%[[VAL_12]], %[[VAL_16]], %[[VAL_11]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.ref<!fir.box<none>>, i1, i32, !fir.ref<i8>, i32) -> none
32+
! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_4]]#1 : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
33+
! CHECK: %[[VAL_20:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_19]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
34+
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_5]]#1 : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
35+
! CHECK: %[[VAL_22:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_21]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
36+
! CHECK: %[[VAL_23:.*]] = arith.constant true
37+
! CHECK: %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_9]]#0 move %[[VAL_23]] : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, i1) -> !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
38+
! CHECK: fir.call @_QMderivedarrayctorPtakes_simple
39+
! CHECK: hlfir.destroy %[[VAL_24]] : !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
40+
41+
subroutine test_with_polymorphic(s1, s2)
42+
class(simple) :: s1, s2
43+
call takes_simple([s1, s2])
44+
end subroutine
45+
! CHECK-LABEL: func.func @_QMderivedarrayctorPtest_with_polymorphic(
46+
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.array<10xi64> {bindc_name = ".rt.arrayctor.vector"}
47+
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>> {bindc_name = ".tmp.arrayctor"}
48+
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}Es1"
49+
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}Es2"
50+
! CHECK: %[[VAL_6:.*]] = arith.constant 2 : index
51+
! CHECK: %[[VAL_7:.*]] = fir.allocmem !fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
52+
! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
53+
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_8]]) {uniq_name = ".tmp.arrayctor"} : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>)
54+
! CHECK: %[[VAL_10:.*]] = fir.embox %[[VAL_9]]#1(%[[VAL_8]]) : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>
55+
! CHECK: fir.store %[[VAL_10]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>
56+
! CHECK: %[[VAL_11:.*]] = arith.constant false
57+
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<10xi64>>) -> !fir.llvm_ptr<i8>
58+
! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>) -> !fir.ref<!fir.box<none>>
59+
! CHECK: %[[VAL_18:.*]] = fir.call @_FortranAInitArrayConstructorVector(%[[VAL_12]], %[[VAL_16]], %[[VAL_11]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.ref<!fir.box<none>>, i1, i32, !fir.ref<i8>, i32) -> none
60+
! CHECK: %[[VAL_19A:.*]] = fir.box_addr %[[VAL_4]]#1 : (!fir.class<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
61+
! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_19A]] : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
62+
! CHECK: %[[VAL_20:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_19]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
63+
! CHECK: %[[VAL_21A:.*]] = fir.box_addr %[[VAL_5]]#1 : (!fir.class<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
64+
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_21A]] : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
65+
! CHECK: %[[VAL_22:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_21]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
66+
! CHECK: %[[VAL_23:.*]] = arith.constant true
67+
! CHECK: %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_9]]#0 move %[[VAL_23]] : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, i1) -> !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
68+
! CHECK: fir.call @_QMderivedarrayctorPtakes_simple
69+
! CHECK: hlfir.destroy %[[VAL_24]] : !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
70+
71+
subroutine takes_simple(s)
72+
type(simple) :: s(:)
73+
print *, "got :", s
74+
end subroutine
75+
end module
76+
77+
use derivedarrayctor
78+
type(simple) :: s1, s2
79+
s1%i = 1
80+
s1%j = 2
81+
s2%i = 3
82+
s2%j = 4
83+
84+
print *, "expect: 1 2 3 4"
85+
call test_simple(s1, s2)
86+
print *, "expect: 1 2 3 4"
87+
call test_with_polymorphic(s1, s2)
88+
end

0 commit comments

Comments
 (0)