Skip to content

Commit 6822708

Browse files
authored
[flang] Correct handling of assumed-rank allocatables in ALLOCATE (#66718)
Construct entities that are associations from selectors in ASSOCIATE, CHANGE TEAMS, and SELECT TYPE constructs do not have the ALLOCATABLE or POINTER attributes, even when associating with allocatables or pointers; associations from selectors in SELECT RANK constructs do have those attributes.
1 parent 01475dc commit 6822708

File tree

3 files changed

+44
-20
lines changed

3 files changed

+44
-20
lines changed

flang/lib/Evaluate/tools.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,8 +1475,16 @@ bool IsObjectPointer(const Symbol *original) {
14751475

14761476
bool IsAllocatableOrObjectPointer(const Symbol *original) {
14771477
if (original) {
1478-
const Symbol &symbol{GetAssociationRoot(*original)};
1479-
return IsAllocatable(symbol) || (IsPointer(symbol) && !IsProcedure(symbol));
1478+
const Symbol &ultimate{original->GetUltimate()};
1479+
if (const auto *assoc{ultimate.detailsIf<AssocEntityDetails>()}) {
1480+
// Only SELECT RANK construct entities can be ALLOCATABLE/POINTER.
1481+
return (assoc->rank() || assoc->IsAssumedSize() ||
1482+
assoc->IsAssumedRank()) &&
1483+
IsAllocatableOrObjectPointer(UnwrapWholeSymbolDataRef(assoc->expr()));
1484+
} else {
1485+
return IsAllocatable(ultimate) ||
1486+
(IsPointer(ultimate) && !IsProcedure(ultimate));
1487+
}
14801488
} else {
14811489
return false;
14821490
}

flang/lib/Semantics/check-allocate.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,11 @@ class AllocationCheckerHelper {
8989
const int allocateCoarraySpecRank_{0};
9090
const parser::Name &name_{parser::GetLastName(allocateObject_)};
9191
// no USE or host association
92-
const Symbol *original_{
92+
const Symbol *ultimate_{
9393
name_.symbol ? &name_.symbol->GetUltimate() : nullptr};
94-
// no USE, host, or construct association
95-
const Symbol *symbol_{original_ ? &ResolveAssociations(*original_) : nullptr};
96-
const DeclTypeSpec *type_{symbol_ ? symbol_->GetType() : nullptr};
97-
const int rank_{original_ ? original_->Rank() : 0};
98-
const int corank_{symbol_ ? symbol_->Corank() : 0};
94+
const DeclTypeSpec *type_{ultimate_ ? ultimate_->GetType() : nullptr};
95+
const int rank_{ultimate_ ? ultimate_->Rank() : 0};
96+
const int corank_{ultimate_ ? ultimate_->Corank() : 0};
9997
bool hasDeferredTypeParameter_{false};
10098
bool isUnlimitedPolymorphic_{false};
10199
bool isAbstract_{false};
@@ -448,11 +446,11 @@ static bool HaveCompatibleLengths(
448446
}
449447

450448
bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
451-
if (!symbol_) {
449+
if (!ultimate_) {
452450
CHECK(context.AnyFatalError());
453451
return false;
454452
}
455-
if (!IsVariableName(*symbol_)) { // C932 pre-requisite
453+
if (!IsVariableName(*ultimate_)) { // C932 pre-requisite
456454
context.Say(name_.source,
457455
"Name in ALLOCATE statement must be a variable name"_err_en_US);
458456
return false;
@@ -465,7 +463,7 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
465463
return false;
466464
}
467465
GatherAllocationBasicInfo();
468-
if (!IsAllocatableOrPointer(*symbol_)) { // C932
466+
if (!IsAllocatableOrObjectPointer(ultimate_)) { // C932
469467
context.Say(name_.source,
470468
"Entity in ALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);
471469
return false;
@@ -537,11 +535,16 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
537535
}
538536
}
539537
// Shape related checks
540-
if (symbol_ && evaluate::IsAssumedRank(*symbol_)) {
538+
if (ultimate_ && evaluate::IsAssumedRank(*ultimate_)) {
541539
context.Say(name_.source,
542540
"An assumed-rank object may not appear in an ALLOCATE statement"_err_en_US);
543541
return false;
544542
}
543+
if (ultimate_ && IsAssumedSizeArray(*ultimate_) && context.AnyFatalError()) {
544+
// An assumed-size dummy array or RANK(*) case of SELECT RANK will have
545+
// already been diagnosed; don't pile on.
546+
return false;
547+
}
545548
if (rank_ > 0) {
546549
if (!hasAllocateShapeSpecList()) {
547550
// C939
@@ -568,7 +571,7 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
568571
.Say(name_.source,
569572
"The number of shape specifications, when they appear, must match the rank of allocatable object"_err_en_US)
570573
.Attach(
571-
original_->name(), "Declared here with rank %d"_en_US, rank_);
574+
ultimate_->name(), "Declared here with rank %d"_en_US, rank_);
572575
return false;
573576
}
574577
}
@@ -587,7 +590,7 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
587590
"If SOURCE appears, the related expression must be scalar or have the same rank as each allocatable object in ALLOCATE"_err_en_US)
588591
.Attach(allocateInfo_.sourceExprLoc.value(),
589592
"SOURCE expression has rank %d"_en_US, allocateInfo_.sourceExprRank)
590-
.Attach(symbol_->name(),
593+
.Attach(ultimate_->name(),
591594
"Allocatable object declared here with rank %d"_en_US, rank_);
592595
return false;
593596
}
@@ -611,11 +614,11 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
611614

612615
bool AllocationCheckerHelper::RunCoarrayRelatedChecks(
613616
SemanticsContext &context) const {
614-
if (!symbol_) {
617+
if (!ultimate_) {
615618
CHECK(context.AnyFatalError());
616619
return false;
617620
}
618-
if (evaluate::IsCoarray(*symbol_)) {
621+
if (evaluate::IsCoarray(*ultimate_)) {
619622
if (allocateInfo_.gotTypeSpec) {
620623
// C938
621624
if (const DerivedTypeSpec *
@@ -665,8 +668,8 @@ bool AllocationCheckerHelper::RunCoarrayRelatedChecks(
665668
context
666669
.Say(name_.source,
667670
"Corank of coarray specification in ALLOCATE must match corank of alloctable coarray"_err_en_US)
668-
.Attach(
669-
symbol_->name(), "Declared here with corank %d"_en_US, corank_);
671+
.Attach(ultimate_->name(), "Declared here with corank %d"_en_US,
672+
corank_);
670673
return false;
671674
}
672675
}

flang/test/Semantics/select-rank03.f90

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ subroutine allocatables(a)
4646
!ERROR: RANK (*) cannot be used when selector is POINTER or ALLOCATABLE
4747
rank (*)
4848
!ERROR: Whole assumed-size array 'a' may not appear here without subscripts
49-
!ERROR: Entity in ALLOCATE statement must have the ALLOCATABLE or POINTER attribute
5049
allocate(a)
5150
!ERROR: Whole assumed-size array 'a' may not appear here without subscripts
5251
deallocate(a)
@@ -58,6 +57,21 @@ subroutine allocatables(a)
5857
deallocate(a)
5958
a = 1.
6059
end select
60+
! Test nested associations
61+
select rank(a)
62+
rank default
63+
select rank(a)
64+
rank default
65+
select rank(a)
66+
rank (0)
67+
allocate(a) ! ok
68+
deallocate(a) ! ok
69+
rank (1)
70+
allocate(a(1)) ! ok
71+
deallocate(a) ! ok
72+
end select
73+
end select
74+
end select
6175
end
6276
subroutine pointers(p)
6377
real, pointer :: p(..)
@@ -103,7 +117,6 @@ subroutine pointers(p)
103117
!ERROR: RANK (*) cannot be used when selector is POINTER or ALLOCATABLE
104118
rank (*)
105119
!ERROR: Whole assumed-size array 'p' may not appear here without subscripts
106-
!ERROR: Entity in ALLOCATE statement must have the ALLOCATABLE or POINTER attribute
107120
allocate(p)
108121
!ERROR: Whole assumed-size array 'p' may not appear here without subscripts
109122
deallocate(p)

0 commit comments

Comments
 (0)