From 278495fac836ec78e9148b709725577f232cd44d Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Thu, 7 Aug 2025 14:23:32 -0300 Subject: [PATCH] [flang] Preserve dynamic length of characters in ALLOCATE Fixes #151895 --- flang/lib/Lower/Allocatable.cpp | 10 ++++++ flang/test/Lower/OpenMP/private-character.f90 | 35 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 flang/test/Lower/OpenMP/private-character.f90 diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 15cd9770b35ba..90e79dca29491 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -484,6 +484,16 @@ class AllocateStmtHelper { return; } + // Preserve characters' dynamic length. + if (lenParams.empty() && box.isCharacter() && + !box.hasNonDeferredLenParams()) { + auto charTy = mlir::dyn_cast(box.getEleTy()); + if (charTy && charTy.hasDynamicLen()) { + fir::ExtendedValue exv{box}; + lenParams.push_back(fir::factory::readCharLen(builder, loc, exv)); + } + } + // Generate a sequence of runtime calls. errorManager.genStatCheck(builder, loc); genAllocateObjectInit(box, allocatorIdx); diff --git a/flang/test/Lower/OpenMP/private-character.f90 b/flang/test/Lower/OpenMP/private-character.f90 new file mode 100644 index 0000000000000..3f0a5bb81cc38 --- /dev/null +++ b/flang/test/Lower/OpenMP/private-character.f90 @@ -0,0 +1,35 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s + +!CHECK-LABEL: func @_QPtest_dynlen_char_ptr +!CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[A:.*]] : !fir.ref>>>) { +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_dynlen_char_ptrEa"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +!CHECK: %[[A_VAL:.*]] = fir.load %[[A_DECL]]#0 : !fir.ref>>> +!CHECK: %[[LEN:.*]] = fir.box_elesize %[[A_VAL]] : (!fir.box>>) -> index +!CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> +!CHECK: %[[LEN_I64:.*]] = fir.convert %[[LEN]] : (index) -> i64 +!CHECK: fir.call @_FortranAPointerNullifyCharacter(%[[A_BOX_NONE]], %[[LEN_I64]], {{.*}}) +subroutine test_dynlen_char_ptr(i) + character(i), pointer :: a + + !$omp parallel private(a) + allocate(a) + a = "abc" + !$omp end parallel +end subroutine + +!CHECK-LABEL: func @_QPtest_dynlen_char_ptr_array +!CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[A:.*]] : !fir.ref>>>>) { +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_dynlen_char_ptr_arrayEa"} : (!fir.ref>>>>) -> (!fir.ref>>>>, !fir.ref>>>>) +!CHECK: %[[A_VAL:.*]] = fir.load %[[A_DECL]]#0 +!CHECK: %[[LEN:.*]] = fir.box_elesize %[[A_VAL]] +!CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> +!CHECK: %[[LEN_I64:.*]] = fir.convert %[[LEN]] : (index) -> i64 +!CHECK: fir.call @_FortranAPointerNullifyCharacter(%[[A_BOX_NONE]], %[[LEN_I64]], {{.*}}) +subroutine test_dynlen_char_ptr_array(i) + character(i), pointer :: a(:) + + !$omp parallel private(a) + allocate(a(i)) + a = "abc" + !$omp end parallel +end subroutine