[flang-commits] [flang] [flang] sanitize set_length in lowering (PR #80412)

via flang-commits flang-commits at lists.llvm.org
Fri Feb 2 02:07:37 PST 2024


https://github.com/jeanPerier created https://github.com/llvm/llvm-project/pull/80412

In fortran, it is possible to give a negative "i" in "character(i)" in which case the standard says the length is zero. So the length must be sanitized as max(0, user_input) in lowering.

This is already done when lowering specification parts, but was not done when "character(i)" appears in array constructors. Sanitize the length when lowering SetLength in lowering.

Fixes https://github.com/llvm/llvm-project/issues/80270

>From 2fe991374f4e00a713dd9b3514d494333d7c9ae1 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Fri, 2 Feb 2024 01:59:31 -0800
Subject: [PATCH] [flang] sanitize set_length in lowering

In fortran, it is possible to give a negative "i" in "character(i)"
in which case the standard says the length is zero. So the length
must be sanitized as max(0, user_input) in lowering.

This is already done when lowering specification parts, but was not done
when "character(i)" appears in array constructors. Sanitize the length when
lowering SetLength in lowering.
---
 flang/lib/Lower/ConvertExprToHLFIR.cpp          |  5 ++++-
 flang/test/Lower/HLFIR/array-ctor-character.f90 | 14 ++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index ba3acd8bba5f8..68ecaa19d2d5d 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1219,8 +1219,11 @@ struct BinaryOp<Fortran::evaluate::SetLength<KIND>> {
                                          fir::FirOpBuilder &builder, const Op &,
                                          hlfir::Entity string,
                                          hlfir::Entity length) {
+    // The input length may be a user input and needs to be sanitized as per
+    // Fortran 2018 7.4.4.2 point 5.
+    mlir::Value safeLength = fir::factory::genMaxWithZero(builder, loc, length);
     return hlfir::EntityWithAttributes{
-        builder.create<hlfir::SetLengthOp>(loc, string, length)};
+        builder.create<hlfir::SetLengthOp>(loc, string, safeLength)};
   }
   static void
   genResultTypeParams(mlir::Location, fir::FirOpBuilder &, hlfir::Entity,
diff --git a/flang/test/Lower/HLFIR/array-ctor-character.f90 b/flang/test/Lower/HLFIR/array-ctor-character.f90
index 7304eb24a647f..85e6ed27fe077 100644
--- a/flang/test/Lower/HLFIR/array-ctor-character.f90
+++ b/flang/test/Lower/HLFIR/array-ctor-character.f90
@@ -86,3 +86,17 @@ subroutine takes_char(c)
   print *, "expect: abcdef"
   call test_dynamic_length()
 end
+
+subroutine test_set_length_sanitize(i, c1)
+  integer(8) :: i
+  character(*) :: c1
+  call takes_char([character(len=i):: c1])
+end subroutine
+! CHECK-LABEL:   func.func @_QPtest_set_length_sanitize(
+! CHECK:   %[[VAL_6:.*]]:2 = hlfir.declare {{.*}}Ec1
+! CHECK:   %[[VAL_9:.*]]:2 = hlfir.declare {{.*}}Ei
+! CHECK:   %[[VAL_25:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i64>
+! CHECK:   %[[VAL_26:.*]] = arith.constant 0 : i64
+! CHECK:   %[[VAL_27:.*]] = arith.cmpi sgt, %[[VAL_25]], %[[VAL_26]] : i64
+! CHECK:   %[[VAL_28:.*]] = arith.select %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : i64
+! CHECK:   %[[VAL_29:.*]] = hlfir.set_length %[[VAL_6]]#0 len %[[VAL_28]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,?>>



More information about the flang-commits mailing list