[flang-commits] [flang] [flang] Re-land PR#97337 (PR #98656)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Jul 12 10:42:16 PDT 2024
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/98656
>From 9f1cfe084ca75cd8fc9a730f1d23fd5d85ca6246 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Mon, 1 Jul 2024 12:05:43 -0700
Subject: [PATCH 1/2] [flang] Adjust semantics of the char length of an array
constructor
An implied DO loop with no trips in an array constructor does not have
a well-defined character length unless its data items have a length that
is constant expression. That works, but the implementation is too broadly
applied. An array constructor with an explicit type-spec always has a
well-defined length.
---
flang/lib/Semantics/expression.cpp | 3 ++-
flang/test/Lower/HLFIR/array-ctor-character.f90 | 9 +++++----
flang/test/Semantics/array-constr-len.f90 | 1 -
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 90900d9acb6ad..844ffd44604ba 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1584,7 +1584,8 @@ class ArrayConstructorContext {
std::optional<Expr<SubscriptInteger>> LengthIfGood() const {
if (type_) {
auto len{type_->LEN()};
- if (len && IsConstantExpr(*len) && !ContainsAnyImpliedDoIndex(*len)) {
+ if (explicitType_ ||
+ (len && IsConstantExpr(*len) && !ContainsAnyImpliedDoIndex(*len))) {
return len;
}
}
diff --git a/flang/test/Lower/HLFIR/array-ctor-character.f90 b/flang/test/Lower/HLFIR/array-ctor-character.f90
index 85e6ed27fe077..881085b370ffe 100644
--- a/flang/test/Lower/HLFIR/array-ctor-character.f90
+++ b/flang/test/Lower/HLFIR/array-ctor-character.f90
@@ -93,10 +93,11 @@ subroutine test_set_length_sanitize(i, 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_2:.*]]:2 = hlfir.declare {{.*}}Ec1
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %arg0
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
+! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_3]]#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,?>>
+! CHECK: %[[VAL_29:.*]] = hlfir.set_length %[[VAL_2]]#0 len %[[VAL_28]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,?>>
diff --git a/flang/test/Semantics/array-constr-len.f90 b/flang/test/Semantics/array-constr-len.f90
index a785c9e2ece6d..4de9c76c7041c 100644
--- a/flang/test/Semantics/array-constr-len.f90
+++ b/flang/test/Semantics/array-constr-len.f90
@@ -10,6 +10,5 @@ subroutine subr(s,n)
print *, [(s(1:j),j=1,0)]
print *, [(s(1:1),j=1,0)] ! ok
print *, [character(2)::(s(1:n),j=1,0)] ! ok
- !ERROR: Array constructor implied DO loop has no iterations and indeterminate character length
print *, [character(n)::(s(1:n),j=1,0)]
end
>From 82cea79dbe116eb45483ee75ad1a251f3b00725f Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Fri, 12 Jul 2024 09:04:23 -0700
Subject: [PATCH 2/2] [flang] Re-land PR#97337
Pull request https://github.com/llvm/llvm-project/pull/97337 was
reverted by https://github.com/llvm/llvm-project/pull/98612 due
to two failing tests in llvm-test-suite -- which I ran, as always,
but must have bungled or misinterpreted (mea culpa).
The failing tests were llvm-test-suite/Fortran/gfortran/regression/
char_length_{20,21}.f90. They have array constructors with
explicit character types whose dynamic length values are negative
at runtime and which must be interpreted as zero.
This patch extends the original to cover those cases.
---
flang/lib/Semantics/expression.cpp | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 844ffd44604ba..2d91962a24a4c 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -63,7 +63,7 @@ std::optional<Expr<SubscriptInteger>> DynamicTypeWithLength::LEN() const {
}
static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
- const std::optional<parser::TypeSpec> &spec) {
+ const std::optional<parser::TypeSpec> &spec, FoldingContext &context) {
if (spec) {
if (const semantics::DeclTypeSpec *typeSpec{spec->declTypeSpec}) {
// Name resolution sets TypeSpec::declTypeSpec only when it's valid
@@ -80,7 +80,13 @@ static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
const semantics::ParamValue &len{cts.length()};
// N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() &
// type guards, but not in array constructors.
- return DynamicTypeWithLength{DynamicType{kind, len}};
+ DynamicTypeWithLength type{DynamicType{kind, len}};
+ if (auto lenExpr{type.LEN()}) {
+ type.length = Fold(context,
+ AsExpr(Extremum<SubscriptInteger>{Ordering::Greater,
+ Expr<SubscriptInteger>{0}, std::move(*lenExpr)}));
+ }
+ return type;
} else {
return DynamicTypeWithLength{DynamicType{category, kind}};
}
@@ -1940,7 +1946,8 @@ MaybeExpr ArrayConstructorContext::ToExpr() {
MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
const parser::AcSpec &acSpec{array.v};
- ArrayConstructorContext acContext{*this, AnalyzeTypeSpec(acSpec.type)};
+ ArrayConstructorContext acContext{
+ *this, AnalyzeTypeSpec(acSpec.type, GetFoldingContext())};
for (const parser::AcValue &value : acSpec.values) {
acContext.Add(value);
}
More information about the flang-commits
mailing list