Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions flang/docs/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,17 @@ end
generic intrinsic function's inferred result type does not
match an explicit declaration. This message is a warning.

* There is no restriction in the standard against assigning
to a whole polymorphic allocatable under control of a `WHERE`
construct or statement, but there is no good portable
behavior to implement and the standard isn't entirely clear
what it should mean.
(Other compilers allow it, but the results are never meaningful;
some never change the type, some change the type according to
the value of the last mask element, some treat these
assignment statements as no-ops, and the rest crash during compilation.)
The compiler flags this case as an error.

## Standard features that might as well not be

* f18 supports designators with constant expressions, properly
Expand Down
6 changes: 5 additions & 1 deletion flang/lib/Semantics/assignment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class AssignmentContext {
void PopWhereContext();
void Analyze(const parser::AssignmentStmt &);
void Analyze(const parser::PointerAssignmentStmt &);
void Analyze(const parser::ConcurrentControl &);
SemanticsContext &context() { return context_; }

private:
Expand Down Expand Up @@ -76,6 +75,11 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
whole{evaluate::UnwrapWholeSymbolOrComponentDataRef(lhs)}) {
if (IsAllocatable(whole->GetUltimate())) {
flags.set(DefinabilityFlag::PotentialDeallocation);
if (IsPolymorphic(*whole) && whereDepth_ > 0) {
Say(lhsLoc,
"Assignment to whole polymorphic allocatable '%s' may not be nested in a WHERE statement or construct"_err_en_US,
whole->name());
}
}
}
if (auto whyNot{WhyNotDefinable(lhsLoc, scope, flags, lhs)}) {
Expand Down
51 changes: 51 additions & 0 deletions flang/test/Semantics/bug133669.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
!RUN: %python %S/test_errors.py %s %flang_fc1
module m
contains
subroutine s(x, y, mask)
class(*), allocatable, intent(in out) :: x(:), y(:)
logical, intent(in) :: mask(:)
select type(x)
type is(integer)
print *, 'before, x is integer', x
type is(real)
print *, 'before, x is real', x
class default
print *, 'before, x has some other type'
end select
select type(y)
type is(integer)
print *, 'y is integer', y
type is(real)
print *, 'y is real', y
end select
print *, 'mask', mask
!ERROR: Assignment to whole polymorphic allocatable 'x' may not be nested in a WHERE statement or construct
where(mask) x = y
select type(x)
type is(integer)
print *, 'after, x is integer', x
type is(real)
print *, 'after, x is real', x
class default
print *, 'before, x has some other type'
end select
print *
end
end

program main
use m
class(*), allocatable :: x(:), y(:)
x = [1, 2]
y = [3., 4.]
call s(x, y, [.false., .false.])
x = [1, 2]
y = [3., 4.]
call s(x, y, [.false., .true.])
x = [1, 2]
y = [3., 4.]
call s(x, y, [.true., .false.])
x = [1, 2]
y = [3., 4.]
call s(x, y, [.true., .true.])
end program main