Skip to content

Commit 24e9ee4

Browse files
authored
[flang] Improve contiguity checker for component references (#153222)
Component references to array values had a couple of TODOs in the contiguity checker; implement them so that contiguity errors/warnings and code generation are more accurate. Specifically, "a(1:1)%b" is contiguous because there's a single element; "a(1:2)%b" is contiguous when the type of "a" has but a single component. The case of multiple components in the type is discontiguous when the array is known to have multiple elements.
1 parent 3af202a commit 24e9ee4

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

flang/lib/Evaluate/check-expression.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,18 +1026,40 @@ class IsContiguousHelper
10261026
if (x.base().Rank() == 0) {
10271027
return (*this)(x.GetLastSymbol());
10281028
} else {
1029-
if (Result baseIsContiguous{(*this)(x.base())}) {
1029+
const DataRef &base{x.base()};
1030+
if (Result baseIsContiguous{(*this)(base)}) {
10301031
if (!*baseIsContiguous) {
10311032
return false;
1033+
} else {
1034+
bool sizeKnown{false};
1035+
if (auto constShape{GetConstantExtents(context_, x)}) {
1036+
sizeKnown = true;
1037+
if (GetSize(*constShape) <= 1) {
1038+
return true; // empty or singleton
1039+
}
1040+
}
1041+
const Symbol &last{base.GetLastSymbol()};
1042+
if (auto type{DynamicType::From(last)}) {
1043+
CHECK(type->category() == TypeCategory::Derived);
1044+
if (!type->IsPolymorphic()) {
1045+
const auto &derived{type->GetDerivedTypeSpec()};
1046+
if (const auto *scope{derived.scope()}) {
1047+
auto iter{scope->begin()};
1048+
if (++iter == scope->end()) {
1049+
return true; // type has but one component
1050+
} else if (sizeKnown) {
1051+
return false; // multiple components & array size is known > 1
1052+
}
1053+
}
1054+
}
1055+
}
10321056
}
1033-
// TODO: should be true if base is contiguous and this is only
1034-
// component, or when the base has at most one element
10351057
}
10361058
return std::nullopt;
10371059
}
10381060
}
10391061
Result operator()(const ComplexPart &x) const {
1040-
// TODO: should be true when base is empty array, too
1062+
// TODO: should be true when base is empty array or singleton, too
10411063
return x.complex().Rank() == 0;
10421064
}
10431065
Result operator()(const Substring &x) const {

flang/test/Lower/components.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ subroutine lhs_char_section(a)
136136
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX68656C6C6F"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
137137
! CHECK: %[[VAL_8:.*]] = arith.constant 5 : index
138138
! CHECK: %[[VAL_9:.*]] = hlfir.designate %[[VAL_4]]#0{"c"} shape %[[VAL_3]] typeparams %[[VAL_8]] : (!fir.ref<!fir.array<10x!fir.type<_QFlhs_char_sectionTt
139-
! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_9]] : !fir.ref<!fir.char<1,5>>, !fir.box<!fir.array<10x!fir.char<1,5>>>
139+
! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_9]] : !fir.ref<!fir.char<1,5>>, !fir.ref<!fir.array<10x!fir.char<1,5>>>
140140
! CHECK: return
141141
! CHECK: }
142142

@@ -163,7 +163,7 @@ subroutine rhs_char_section(a, c)
163163
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_10]]) typeparams %[[VAL_8]] dummy_scope %[[VAL_2]] {uniq_name = "_QFrhs_char_sectionEc"} : (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.shape<1>, index, !fir.dscope) -> (!fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>>)
164164
! CHECK: %[[VAL_12:.*]] = arith.constant 10 : index
165165
! CHECK: %[[VAL_13:.*]] = hlfir.designate %[[VAL_5]]#0{"c"} shape %[[VAL_4]] typeparams %[[VAL_12]] : (!fir.ref<!fir.array<10x!fir.type<_QFrhs_char_sectionTt
166-
! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_11]]#0 : !fir.box<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>>
166+
! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_11]]#0 : !fir.ref<!fir.array<10x!fir.char<1,10>>>, !fir.ref<!fir.array<10x!fir.char<1,10>>>
167167
! CHECK: return
168168
! CHECK: }
169169

@@ -192,7 +192,7 @@ subroutine elemental_char_section(a, i)
192192
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_11]] typeparams %[[VAL_12]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX68656C6C6F"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
193193
! CHECK: %[[VAL_14:.*]] = hlfir.elemental %[[VAL_4]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> {
194194
! CHECK: ^bb0(%[[VAL_15:.*]]: index):
195-
! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_10]] (%[[VAL_15]]) typeparams %[[VAL_9]] : (!fir.box<!fir.array<10x!fir.char<1,10>>>, index, index) -> !fir.ref<!fir.char<1,10>>
195+
! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_10]] (%[[VAL_15]]) typeparams %[[VAL_9]] : (!fir.ref<!fir.array<10x!fir.char<1,10>>>, index, index) -> !fir.ref<!fir.char<1,10>>
196196
! CHECK: %[[VAL_17:.*]] = arith.constant false
197197
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (!fir.ref<!fir.char<1,10>>) -> !fir.ref<i8>
198198
! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_9]] : (index) -> i64
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
2+
subroutine s1
3+
type :: d1
4+
real :: x
5+
end type
6+
type :: d2
7+
type(d1) :: x
8+
end type
9+
type(d1), target :: a(5)
10+
type(d2), target :: b(5)
11+
real, pointer, contiguous :: c(:)
12+
c => a%x ! okay, type has single component
13+
c => b%x%x ! okay, types have single components
14+
end
15+
16+
subroutine s2
17+
type :: d1
18+
real :: x, y
19+
end type
20+
type(d1), target :: b(5)
21+
real, pointer, contiguous :: c(:)
22+
!ERROR: CONTIGUOUS pointer may not be associated with a discontiguous target
23+
c => b%x
24+
c => b(1:1)%x ! okay, one element
25+
!ERROR: CONTIGUOUS pointer may not be associated with a discontiguous target
26+
c => b(1:2)%x
27+
end

0 commit comments

Comments
 (0)