Skip to content

Commit 0c21377

Browse files
authored
[flang] Diagnose the impure procedure reference in finalization according to the rank of the entity (#85475)
Use the rank of the array section to determine which final procedure would be called in diagnosing whether that procedure is impure or not.
1 parent 487f356 commit 0c21377

File tree

4 files changed

+59
-13
lines changed

4 files changed

+59
-13
lines changed

flang/include/flang/Semantics/tools.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ const Symbol *IsFinalizable(const Symbol &,
180180
const Symbol *IsFinalizable(const DerivedTypeSpec &,
181181
std::set<const DerivedTypeSpec *> * = nullptr,
182182
bool withImpureFinalizer = false, std::optional<int> rank = std::nullopt);
183-
const Symbol *HasImpureFinal(const Symbol &);
183+
const Symbol *HasImpureFinal(
184+
const Symbol &, std::optional<int> rank = std::nullopt);
184185
// Is this type finalizable or does it contain any polymorphic allocatable
185186
// ultimate components?
186187
bool MayRequireFinalization(const DerivedTypeSpec &derived);

flang/lib/Semantics/check-do-forall.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,11 @@ class DoConcurrentBodyEnforce {
220220
if (MightDeallocatePolymorphic(*entity, DeallocateNonCoarray)) {
221221
SayDeallocateOfPolymorph(variable.GetSource(), *entity, reason);
222222
}
223-
if (const Symbol * impure{HasImpureFinal(*entity)}) {
224-
SayDeallocateWithImpureFinal(*entity, reason, *impure);
223+
if (const auto *assignment{GetAssignment(stmt)}) {
224+
const auto &lhs{assignment->lhs};
225+
if (const Symbol * impure{HasImpureFinal(*entity, lhs.Rank())}) {
226+
SayDeallocateWithImpureFinal(*entity, reason, *impure);
227+
}
225228
}
226229
}
227230
if (const auto *assignment{GetAssignment(stmt)}) {

flang/lib/Semantics/tools.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -827,15 +827,18 @@ static const Symbol *HasImpureFinal(
827827
return IsFinalizable(derived, nullptr, /*withImpureFinalizer=*/true, rank);
828828
}
829829

830-
const Symbol *HasImpureFinal(const Symbol &original) {
830+
const Symbol *HasImpureFinal(const Symbol &original, std::optional<int> rank) {
831831
const Symbol &symbol{ResolveAssociations(original)};
832832
if (symbol.has<ObjectEntityDetails>()) {
833833
if (const DeclTypeSpec * symType{symbol.GetType()}) {
834834
if (const DerivedTypeSpec * derived{symType->AsDerived()}) {
835-
// finalizable assumed-rank not allowed (C839)
836-
return evaluate::IsAssumedRank(symbol)
837-
? nullptr
838-
: HasImpureFinal(*derived, symbol.Rank());
835+
if (evaluate::IsAssumedRank(symbol)) {
836+
// finalizable assumed-rank not allowed (C839)
837+
return nullptr;
838+
} else {
839+
int actualRank{rank.value_or(symbol.Rank())};
840+
return HasImpureFinal(*derived, actualRank);
841+
}
839842
}
840843
}
841844
}

flang/test/Semantics/doconcurrent08.f90

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ module m2
209209
type :: impureFinal
210210
contains
211211
final :: impureSub
212+
final :: impureSubRank1
213+
final :: impureSubRank2
212214
end type
213215

214216
type :: pureFinal
@@ -222,28 +224,37 @@ impure subroutine impureSub(x)
222224
type(impureFinal), intent(in) :: x
223225
end subroutine
224226

227+
impure subroutine impureSubRank1(x)
228+
type(impureFinal), intent(in) :: x(:)
229+
end subroutine
230+
231+
impure subroutine impureSubRank2(x)
232+
type(impureFinal), intent(in) :: x(:,:)
233+
end subroutine
234+
225235
pure subroutine pureSub(x)
226236
type(pureFinal), intent(in) :: x
227237
end subroutine
228238

229239
subroutine s4()
230240
type(impureFinal), allocatable :: ifVar, ifvar1
241+
type(impureFinal), allocatable :: ifArr1(:), ifArr2(:,:)
242+
type(impureFinal) :: if0
231243
type(pureFinal), allocatable :: pfVar
232244
allocate(ifVar)
233245
allocate(ifVar1)
234246
allocate(pfVar)
247+
allocate(ifArr1(5), ifArr2(5,5))
235248

236249
! OK for an ordinary DO loop
237250
do i = 1,10
238251
if (i .eq. 1) deallocate(ifVar)
239252
end do
240253

241254
! OK to invoke a PURE FINAL procedure in a DO CONCURRENT
242-
! This case does not work currently because the compiler's test for
243-
! HasImpureFinal() in .../lib/Semantics/tools.cc doesn't work correctly
244-
! do concurrent (i = 1:10)
245-
! if (i .eq. 1) deallocate(pfVar)
246-
! end do
255+
do concurrent (i = 1:10)
256+
if (i .eq. 1) deallocate(pfVar)
257+
end do
247258

248259
! Error to invoke an IMPURE FINAL procedure in a DO CONCURRENT
249260
do concurrent (i = 1:10)
@@ -271,6 +282,34 @@ subroutine s4()
271282
ifvar = ifvar1
272283
end if
273284
end do
285+
286+
do concurrent (i = 1:5)
287+
if (i .eq. 1) then
288+
!ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresub' caused by assignment not allowed in DO CONCURRENT
289+
ifArr1(i) = if0
290+
end if
291+
end do
292+
293+
do concurrent (i = 1:5)
294+
if (i .eq. 1) then
295+
!ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresubrank1' caused by assignment not allowed in DO CONCURRENT
296+
ifArr1 = if0
297+
end if
298+
end do
299+
300+
do concurrent (i = 1:5)
301+
if (i .eq. 1) then
302+
!ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresubrank1' caused by assignment not allowed in DO CONCURRENT
303+
ifArr2(i,:) = if0
304+
end if
305+
end do
306+
307+
do concurrent (i = 1:5)
308+
if (i .eq. 1) then
309+
!ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresubrank2' caused by assignment not allowed in DO CONCURRENT
310+
ifArr2(:,:) = if0
311+
end if
312+
end do
274313
end subroutine s4
275314

276315
end module m2

0 commit comments

Comments
 (0)