Skip to content

Commit 376713f

Browse files
authored
[flang] Accept CLASS(*) array in EOSHIFT (#116114)
The intrinsic processing code wasn't allowing the ARRAY= argument to the EOSHIFT intrinsic function to be CLASS(*). That case seems to conform to the standard, although only one compiler could actually handle it, so allow for it. Fixes #115923.
1 parent 17daa84 commit 376713f

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ static constexpr TypePattern SameCharNoLen{CharType, KindCode::sameKind};
168168
static constexpr TypePattern SameLogical{LogicalType, KindCode::same};
169169
static constexpr TypePattern SameRelatable{RelatableType, KindCode::same};
170170
static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same};
171-
static constexpr TypePattern SameDerivedType{
172-
CategorySet{TypeCategory::Derived}, KindCode::same};
173171
static constexpr TypePattern SameType{AnyType, KindCode::same};
174172

175173
// Match some kind of some INTEGER or REAL type(s); when argument types
@@ -438,6 +436,12 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
438436
{"shift", AnyInt}},
439437
SameInt},
440438
{"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt},
439+
{"eoshift",
440+
{{"array", SameType, Rank::array},
441+
{"shift", AnyInt, Rank::dimRemovedOrScalar},
442+
// BOUNDARY= is not optional for non-intrinsic types
443+
{"boundary", SameType, Rank::dimRemovedOrScalar}, OptionalDIM},
444+
SameType, Rank::conformable, IntrinsicClass::transformationalFunction},
441445
{"eoshift",
442446
{{"array", SameIntrinsic, Rank::array},
443447
{"shift", AnyInt, Rank::dimRemovedOrScalar},
@@ -446,14 +450,6 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
446450
OptionalDIM},
447451
SameIntrinsic, Rank::conformable,
448452
IntrinsicClass::transformationalFunction},
449-
{"eoshift",
450-
{{"array", SameDerivedType, Rank::array},
451-
{"shift", AnyInt, Rank::dimRemovedOrScalar},
452-
// BOUNDARY= is not optional for derived types
453-
{"boundary", SameDerivedType, Rank::dimRemovedOrScalar},
454-
OptionalDIM},
455-
SameDerivedType, Rank::conformable,
456-
IntrinsicClass::transformationalFunction},
457453
{"epsilon",
458454
{{"x", SameReal, Rank::anyOrAssumedRank, Optionality::required,
459455
common::Intent::In, {ArgFlag::canBeMoldNull}}},
@@ -1937,12 +1933,16 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
19371933
dimArg = j;
19381934
argOk = true;
19391935
break;
1940-
case KindCode::same:
1936+
case KindCode::same: {
19411937
if (!sameArg) {
19421938
sameArg = arg;
19431939
}
1944-
argOk = type->IsTkLenCompatibleWith(sameArg->GetType().value());
1945-
break;
1940+
// Check both ways so that a CLASS(*) actuals to
1941+
// MOVE_ALLOC and EOSHIFT both work.
1942+
auto sameType{sameArg->GetType().value()};
1943+
argOk = sameType.IsTkLenCompatibleWith(*type) ||
1944+
type->IsTkLenCompatibleWith(sameType);
1945+
} break;
19461946
case KindCode::sameKind:
19471947
if (!sameArg) {
19481948
sameArg = arg;

flang/runtime/transformational.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ShiftControl {
4646
lb_[k++] = shiftDim.LowerBound();
4747
if (shiftDim.Extent() != source.GetDimension(j).Extent()) {
4848
terminator_.Crash("%s: on dimension %d, SHIFT= has extent %jd but "
49-
"SOURCE= has extent %jd",
49+
"ARRAY= has extent %jd",
5050
which, k, static_cast<std::intmax_t>(shiftDim.Extent()),
5151
static_cast<std::intmax_t>(source.GetDimension(j).Extent()));
5252
}
@@ -460,7 +460,7 @@ void RTDEF(Cshift)(Descriptor &result, const Descriptor &source,
460460
RUNTIME_CHECK(terminator, rank > 1);
461461
if (dim < 1 || dim > rank) {
462462
terminator.Crash(
463-
"CSHIFT: DIM=%d must be >= 1 and <= SOURCE= rank %d", dim, rank);
463+
"CSHIFT: DIM=%d must be >= 1 and <= ARRAY= rank %d", dim, rank);
464464
}
465465
ShiftControl shiftControl{shift, terminator, dim};
466466
shiftControl.Init(source, "CSHIFT");
@@ -527,7 +527,7 @@ void RTDEF(Eoshift)(Descriptor &result, const Descriptor &source,
527527
RUNTIME_CHECK(terminator, rank > 1);
528528
if (dim < 1 || dim > rank) {
529529
terminator.Crash(
530-
"EOSHIFT: DIM=%d must be >= 1 and <= SOURCE= rank %d", dim, rank);
530+
"EOSHIFT: DIM=%d must be >= 1 and <= ARRAY= rank %d", dim, rank);
531531
}
532532
std::size_t elementLen{
533533
AllocateResult(result, source, rank, extent, terminator, "EOSHIFT")};
@@ -538,7 +538,7 @@ void RTDEF(Eoshift)(Descriptor &result, const Descriptor &source,
538538
RUNTIME_CHECK(terminator, boundary->type() == source.type());
539539
if (boundary->ElementBytes() != elementLen) {
540540
terminator.Crash("EOSHIFT: BOUNDARY= has element byte length %zd, but "
541-
"SOURCE= has length %zd",
541+
"ARRAY= has length %zd",
542542
boundary->ElementBytes(), elementLen);
543543
}
544544
if (boundaryRank > 0) {
@@ -547,7 +547,7 @@ void RTDEF(Eoshift)(Descriptor &result, const Descriptor &source,
547547
if (j != dim - 1) {
548548
if (boundary->GetDimension(k).Extent() != extent[j]) {
549549
terminator.Crash("EOSHIFT: BOUNDARY= has extent %jd on dimension "
550-
"%d but must conform with extent %jd of SOURCE=",
550+
"%d but must conform with extent %jd of ARRAY=",
551551
static_cast<std::intmax_t>(boundary->GetDimension(k).Extent()),
552552
k + 1, static_cast<std::intmax_t>(extent[j]));
553553
}
@@ -611,7 +611,7 @@ void RTDEF(EoshiftVector)(Descriptor &result, const Descriptor &source,
611611
RUNTIME_CHECK(terminator, boundary->type() == source.type());
612612
if (boundary->ElementBytes() != elementLen) {
613613
terminator.Crash("EOSHIFT: BOUNDARY= has element byte length %zd but "
614-
"SOURCE= has length %zd",
614+
"ARRAY= has length %zd",
615615
boundary->ElementBytes(), elementLen);
616616
}
617617
}
@@ -658,7 +658,7 @@ void RTDEF(Pack)(Descriptor &result, const Descriptor &source,
658658
RUNTIME_CHECK(terminator, vector->rank() == 1);
659659
RUNTIME_CHECK(terminator, source.type() == vector->type());
660660
if (source.ElementBytes() != vector->ElementBytes()) {
661-
terminator.Crash("PACK: SOURCE= has element byte length %zd, but VECTOR= "
661+
terminator.Crash("PACK: ARRAY= has element byte length %zd, but VECTOR= "
662662
"has length %zd",
663663
source.ElementBytes(), vector->ElementBytes());
664664
}

flang/test/Evaluate/bug115923.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
! RUN: %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck %s
2+
! Ensure that EOSHIFT's ARRAY= argument and result can be CLASS(*).
3+
! CHECK-NOT: error:
4+
! CHECK: warning: Source of TRANSFER is polymorphic
5+
! CHECK: warning: Mold of TRANSFER is polymorphic
6+
program p
7+
type base
8+
integer j
9+
end type
10+
type, extends(base) :: extended
11+
integer k
12+
end type
13+
class(base), allocatable :: polyArray(:,:,:)
14+
class(*), allocatable :: unlimited(:)
15+
allocate(polyArray, source=reshape([(extended(n,n-1),n=1,8)],[2,2,2]))
16+
allocate(unlimited, source=[(base(9),n=1,16)])
17+
select type (x => eoshift(transfer(polyArray, unlimited), -4, base(-1)))
18+
type is (base); print *, 'base', x
19+
type is (extended); print *, 'extended?', x
20+
class default; print *, 'class default??'
21+
end select
22+
end

0 commit comments

Comments
 (0)