[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.
This commit is contained in:
parent
3af202abf8
commit
24e9ee44a8
@ -1026,18 +1026,40 @@ public:
|
||||
if (x.base().Rank() == 0) {
|
||||
return (*this)(x.GetLastSymbol());
|
||||
} else {
|
||||
if (Result baseIsContiguous{(*this)(x.base())}) {
|
||||
const DataRef &base{x.base()};
|
||||
if (Result baseIsContiguous{(*this)(base)}) {
|
||||
if (!*baseIsContiguous) {
|
||||
return false;
|
||||
} else {
|
||||
bool sizeKnown{false};
|
||||
if (auto constShape{GetConstantExtents(context_, x)}) {
|
||||
sizeKnown = true;
|
||||
if (GetSize(*constShape) <= 1) {
|
||||
return true; // empty or singleton
|
||||
}
|
||||
}
|
||||
const Symbol &last{base.GetLastSymbol()};
|
||||
if (auto type{DynamicType::From(last)}) {
|
||||
CHECK(type->category() == TypeCategory::Derived);
|
||||
if (!type->IsPolymorphic()) {
|
||||
const auto &derived{type->GetDerivedTypeSpec()};
|
||||
if (const auto *scope{derived.scope()}) {
|
||||
auto iter{scope->begin()};
|
||||
if (++iter == scope->end()) {
|
||||
return true; // type has but one component
|
||||
} else if (sizeKnown) {
|
||||
return false; // multiple components & array size is known > 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: should be true if base is contiguous and this is only
|
||||
// component, or when the base has at most one element
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
Result operator()(const ComplexPart &x) const {
|
||||
// TODO: should be true when base is empty array, too
|
||||
// TODO: should be true when base is empty array or singleton, too
|
||||
return x.complex().Rank() == 0;
|
||||
}
|
||||
Result operator()(const Substring &x) const {
|
||||
|
||||
@ -136,7 +136,7 @@ end subroutine
|
||||
! 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>>)
|
||||
! CHECK: %[[VAL_8:.*]] = arith.constant 5 : index
|
||||
! 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
|
||||
! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_9]] : !fir.ref<!fir.char<1,5>>, !fir.box<!fir.array<10x!fir.char<1,5>>>
|
||||
! CHECK: hlfir.assign %[[VAL_7]]#0 to %[[VAL_9]] : !fir.ref<!fir.char<1,5>>, !fir.ref<!fir.array<10x!fir.char<1,5>>>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
@ -163,7 +163,7 @@ end subroutine
|
||||
! 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>>>)
|
||||
! CHECK: %[[VAL_12:.*]] = arith.constant 10 : index
|
||||
! 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
|
||||
! 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>>>
|
||||
! 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>>>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
@ -192,7 +192,7 @@ end subroutine
|
||||
! 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>>)
|
||||
! CHECK: %[[VAL_14:.*]] = hlfir.elemental %[[VAL_4]] unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> {
|
||||
! CHECK: ^bb0(%[[VAL_15:.*]]: index):
|
||||
! 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>>
|
||||
! 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>>
|
||||
! CHECK: %[[VAL_17:.*]] = arith.constant false
|
||||
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (!fir.ref<!fir.char<1,10>>) -> !fir.ref<i8>
|
||||
! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_9]] : (index) -> i64
|
||||
|
||||
27
flang/test/Semantics/contiguous02.f90
Normal file
27
flang/test/Semantics/contiguous02.f90
Normal file
@ -0,0 +1,27 @@
|
||||
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
|
||||
subroutine s1
|
||||
type :: d1
|
||||
real :: x
|
||||
end type
|
||||
type :: d2
|
||||
type(d1) :: x
|
||||
end type
|
||||
type(d1), target :: a(5)
|
||||
type(d2), target :: b(5)
|
||||
real, pointer, contiguous :: c(:)
|
||||
c => a%x ! okay, type has single component
|
||||
c => b%x%x ! okay, types have single components
|
||||
end
|
||||
|
||||
subroutine s2
|
||||
type :: d1
|
||||
real :: x, y
|
||||
end type
|
||||
type(d1), target :: b(5)
|
||||
real, pointer, contiguous :: c(:)
|
||||
!ERROR: CONTIGUOUS pointer may not be associated with a discontiguous target
|
||||
c => b%x
|
||||
c => b(1:1)%x ! okay, one element
|
||||
!ERROR: CONTIGUOUS pointer may not be associated with a discontiguous target
|
||||
c => b(1:2)%x
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user