diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -1475,7 +1475,20 @@ ArrayConstructor result{MakeSpecific(std::move(values_))}; if constexpr (T::category == TypeCategory::Character) { if (auto len{type_->LEN()}) { - if (IsConstantExpr(*len)) { + // The ac-do-variables may be treated as constant expressions, + // if some conditions on ac-implied-do-control hold (10.1.12 (12)). + // At the same time, they may be treated as constant expressions + // only in the context of the ac-implied-do, but setting + // the character length here may result in complete elimination + // of the ac-implied-do. For example: + // character(10) :: c + // ... len([(c(i:i), integer(8)::i = 1,4)]) + // would be evaulated into: + // ... int(max(0_8,i-i+1_8),kind=4) + // with a dangling reference to the ac-do-variable. + // Prevent this by checking for the ac-do-variable references + // in the 'len' expression. + if (!ContainsAnyImpliedDoIndex(*len) && IsConstantExpr(*len)) { result.set_LEN(std::move(*len)); } } diff --git a/flang/test/Evaluate/rewrite01.f90 b/flang/test/Evaluate/rewrite01.f90 --- a/flang/test/Evaluate/rewrite01.f90 +++ b/flang/test/Evaluate/rewrite01.f90 @@ -234,10 +234,13 @@ subroutine array_ctor_implied_do_index(x, j) integer :: x(:) integer(8) :: j + character(10) :: c !CHECK: PRINT *, size([INTEGER(4)::(x(1_8:i:1_8),INTEGER(8)::i=1_8,2_8,1_8)]) print *, size([(x(1:i), integer(8)::i=1,2)]) !CHECK: PRINT *, int(0_8+2_8*(0_8+max((j-1_8+1_8)/1_8,0_8)),kind=4) print *, size([(x(1:j), integer(8)::i=1,2)]) + !CHECK: PRINT *, len([(c(i:i),INTEGER(8)::i=1_8,4_8,1_8)]) + print *, len([(c(i:i), integer(8)::i = 1,4)]) end subroutine end module