Skip to content

Commit 47b485c

Browse files
authored
[flang] Fix type of array constructor triplet (extension) (#92970)
The type of "[lo:hi:str]" is being forced to INTEGER(8), ignoring the types of the operands to the triplet. The type of a triplet should be whatever the type of "lo+hi+str" would be. (Array constructor triplets are a syntactic sugar extension for an implied DO loop.)
1 parent d03e56b commit 47b485c

File tree

2 files changed

+61
-24
lines changed

2 files changed

+61
-24
lines changed

flang/lib/Semantics/expression.cpp

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,16 +1600,23 @@ class ArrayConstructorContext {
16001600
parser::CharBlock name, std::int64_t lower, std::int64_t upper,
16011601
std::int64_t stride);
16021602

1603-
template <int KIND, typename A>
1604-
std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr(
1605-
const A &x) {
1606-
if (MaybeExpr y{exprAnalyzer_.Analyze(x)}) {
1603+
template <int KIND>
1604+
std::optional<Expr<Type<TypeCategory::Integer, KIND>>> ToSpecificInt(
1605+
MaybeExpr &&y) {
1606+
if (y) {
16071607
Expr<SomeInteger> *intExpr{UnwrapExpr<Expr<SomeInteger>>(*y)};
16081608
return Fold(exprAnalyzer_.GetFoldingContext(),
16091609
ConvertToType<Type<TypeCategory::Integer, KIND>>(
16101610
std::move(DEREF(intExpr))));
1611+
} else {
1612+
return std::nullopt;
16111613
}
1612-
return std::nullopt;
1614+
}
1615+
1616+
template <int KIND, typename A>
1617+
std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr(
1618+
const A &x) {
1619+
return ToSpecificInt<KIND>(exprAnalyzer_.Analyze(x));
16131620
}
16141621

16151622
// Nested array constructors all reference the same ExpressionAnalyzer,
@@ -1772,26 +1779,45 @@ void ArrayConstructorContext::Add(const parser::AcValue &x) {
17721779

17731780
// Transforms l:u(:s) into (_,_=l,u(,s)) with an anonymous index '_'
17741781
void ArrayConstructorContext::Add(const parser::AcValue::Triplet &triplet) {
1775-
std::optional<Expr<ImpliedDoIntType>> lower{
1776-
GetSpecificIntExpr<ImpliedDoIntType::kind>(std::get<0>(triplet.t))};
1777-
std::optional<Expr<ImpliedDoIntType>> upper{
1778-
GetSpecificIntExpr<ImpliedDoIntType::kind>(std::get<1>(triplet.t))};
1779-
std::optional<Expr<ImpliedDoIntType>> stride{
1780-
GetSpecificIntExpr<ImpliedDoIntType::kind>(std::get<2>(triplet.t))};
1781-
if (lower && upper) {
1782-
if (!stride) {
1783-
stride = Expr<ImpliedDoIntType>{1};
1784-
}
1785-
if (!type_) {
1786-
type_ = DynamicTypeWithLength{ImpliedDoIntType::GetType()};
1782+
MaybeExpr lowerExpr{exprAnalyzer_.Analyze(std::get<0>(triplet.t))};
1783+
MaybeExpr upperExpr{exprAnalyzer_.Analyze(std::get<1>(triplet.t))};
1784+
MaybeExpr strideExpr{exprAnalyzer_.Analyze(std::get<2>(triplet.t))};
1785+
if (lowerExpr && upperExpr) {
1786+
auto lowerType{lowerExpr->GetType()};
1787+
auto upperType{upperExpr->GetType()};
1788+
auto strideType{strideExpr ? strideExpr->GetType() : lowerType};
1789+
if (lowerType && upperType && strideType) {
1790+
int kind{lowerType->kind()};
1791+
if (upperType->kind() > kind) {
1792+
kind = upperType->kind();
1793+
}
1794+
if (strideType->kind() > kind) {
1795+
kind = strideType->kind();
1796+
}
1797+
auto lower{ToSpecificInt<ImpliedDoIntType::kind>(std::move(lowerExpr))};
1798+
auto upper{ToSpecificInt<ImpliedDoIntType::kind>(std::move(upperExpr))};
1799+
if (lower && upper) {
1800+
auto stride{
1801+
ToSpecificInt<ImpliedDoIntType::kind>(std::move(strideExpr))};
1802+
if (!stride) {
1803+
stride = Expr<ImpliedDoIntType>{1};
1804+
}
1805+
DynamicType type{TypeCategory::Integer, kind};
1806+
if (!type_) {
1807+
type_ = DynamicTypeWithLength{type};
1808+
}
1809+
parser::CharBlock anonymous;
1810+
if (auto converted{ConvertToType(type,
1811+
AsGenericExpr(
1812+
Expr<ImpliedDoIntType>{ImpliedDoIndex{anonymous}}))}) {
1813+
auto v{std::move(values_)};
1814+
Push(std::move(converted));
1815+
std::swap(v, values_);
1816+
values_.Push(ImpliedDo<SomeType>{anonymous, std::move(*lower),
1817+
std::move(*upper), std::move(*stride), std::move(v)});
1818+
}
1819+
}
17871820
}
1788-
auto v{std::move(values_)};
1789-
parser::CharBlock anonymous;
1790-
Push(Expr<SomeType>{
1791-
Expr<SomeInteger>{Expr<ImpliedDoIntType>{ImpliedDoIndex{anonymous}}}});
1792-
std::swap(v, values_);
1793-
values_.Push(ImpliedDo<SomeType>{anonymous, std::move(*lower),
1794-
std::move(*upper), std::move(*stride), std::move(v)});
17951821
}
17961822
}
17971823

flang/test/Evaluate/triplets01.f90

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
! RUN: %python %S/test_folding.py %s %flang_fc1
2+
module m
3+
logical, parameter :: test01 = all([1:10:2] == [(j, j=1,10,2)])
4+
logical, parameter :: test02 = kind([1:20:2]) == kind(1)
5+
logical, parameter :: test03 = all([10:1:-3,123] == [(j, j=10,1,-3),123])
6+
logical, parameter :: test04 = kind([10:1:-3,123]) == kind(1)
7+
logical, parameter :: test05 = kind([10_2:1_2:-3_2,123_2]) == 2
8+
logical, parameter :: test06 = all([10_2:1_2:-3_2,123_2] == [(j, integer(2)::j=10,1,-3),123_2])
9+
logical, parameter :: test07 = kind([10_2:1_4:-3_2]) == 4
10+
logical, parameter :: test08 = kind([10_2:1_4]) == 4
11+
end

0 commit comments

Comments
 (0)