-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] sanitize set_length in lowering #80412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
@llvm/pr-subscribers-flang-fir-hlfir Author: None (jeanPerier) ChangesIn 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 #80270 Full diff: https://github.com/llvm/llvm-project/pull/80412.diff 2 Files Affected:
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,?>>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for picking this up. Looks good to me and this does fix my issue.
char_length_2{0,1}.f90 were fixed in llvm/llvm-project#80412. Now that these successfully compile I thought I might as well re-categorise the other tests in the same group too.
char_length_2{0,1}.f90 were fixed in llvm/llvm-project#80412. Now that these successfully compile I thought I might as well re-categorise the other tests in the same group too.
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 llvm#80270
char_length_2{0,1}.f90 were fixed in llvm/llvm-project#80412. Now that these successfully compile I thought I might as well re-categorise the other tests in the same group too.
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 #80270