diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -1315,7 +1315,11 @@ ExtValue genval(const Fortran::evaluate::SetLength &x) { mlir::Value newLenValue = genunbox(x.right()); fir::ExtendedValue lhs = gen(x.left()); - return replaceScalarCharacterLength(lhs, newLenValue); + fir::factory::CharacterExprHelper charHelper(builder, getLoc()); + fir::CharBoxValue temp = charHelper.createCharacterTemp( + charHelper.getCharacterType(fir::getBase(lhs).getType()), newLenValue); + charHelper.createAssign(temp, lhs); + return fir::ExtendedValue{temp}; } template diff --git a/flang/test/Lower/statement-function.f90 b/flang/test/Lower/statement-function.f90 --- a/flang/test/Lower/statement-function.f90 +++ b/flang/test/Lower/statement-function.f90 @@ -101,6 +101,7 @@ test_stmt_character = func(c, j) end function + ! Test statement function with a character actual argument whose ! length may be different than the dummy length (the dummy length ! must be used inside the statement function). @@ -145,3 +146,34 @@ PRINT *, I(2.5) ! CHECK: fir.call {{.*}}EndIo END subroutine bug247 + +! Test that the argument is truncated to the length of the dummy argument. +subroutine truncate_arg + character(4) arg + character(10) stmt_fct + stmt_fct(arg) = arg + print *, stmt_fct('longer_arg') +end subroutine + +! CHECK-LABEL: @_QPtruncate_arg +! CHECK: %[[c4:.*]] = arith.constant 4 : i32 +! CHECK: %[[arg:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> +! CHECK: %[[cast_arg:.*]] = fir.convert %[[arg]] : (!fir.ref>) -> !fir.ref> +! CHECK: %[[c10:.*]] = arith.constant 10 : i64 +! CHECK: %[[temp:.*]] = fir.alloca !fir.char<1,10> {bindc_name = ".chrtmp"} +! CHECK: %[[c10_index:.*]] = fir.convert %[[c10]] : (i64) -> index +! CHECK: %[[c4_index:.*]] = fir.convert %[[c4]] : (i32) -> index +! CHECK: %[[cmpi:.*]] = arith.cmpi slt, %[[c10_index]], %[[c4_index]] : index +! CHECK: %[[select:.*]] = arith.select %[[cmpi]], %[[c10_index]], %[[c4_index]] : index +! CHECK: %[[c1:.*]] = arith.constant 1 : i64 +! CHECK: %[[select_i64:.*]] = fir.convert %[[select]] : (index) -> i64 +! CHECK: %[[length:.*]] = arith.muli %[[c1]], %[[select_i64]] : i64 +! CHECK: %[[cast_temp_i8:.*]] = fir.convert %[[temp]] : (!fir.ref>) -> !fir.ref +! CHECK: %[[cast_arg_i8:.*]] = fir.convert %[[cast_arg]] : (!fir.ref>) -> !fir.ref +! CHECK: fir.call @llvm.memmove.p0.p0.i64(%[[cast_temp_i8]], %[[cast_arg_i8]], %[[length]], %{{.*}}) : (!fir.ref, !fir.ref, i64, i1) -> () +! CHECK: %[[c1_i64:.*]] = arith.constant 1 : i64 +! CHECK: %[[ub:.*]] = arith.subi %[[c10]], %[[c1_i64]] : i64 +! CHECK: %[[ub_index:.*]] = fir.convert %[[ub]] : (i64) -> index +! CHECK: fir.do_loop %{{.*}} = %[[select]] to %[[ub_index]] step %{{.*}} { +! CHECK: %[[cast_temp:.*]] = fir.convert %[[temp:.*]] : (!fir.ref>) -> !fir.ref +! CHECK: %{{.*}} = fir.call @_FortranAioOutputAscii(%{{.*}}, %[[cast_temp]], %[[c10]]) : (!fir.ref, !fir.ref, i64) -> i1