[flang-commits] [flang] 7bd2eac - [flang] Check for elemental finalizer when defined object has vector subscript
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Dec 16 09:52:57 PST 2022
Author: Peter Klausler
Date: 2022-12-16T09:52:45-08:00
New Revision: 7bd2eace7d58883b87324a9fbdcc6217673282bb
URL: https://github.com/llvm/llvm-project/commit/7bd2eace7d58883b87324a9fbdcc6217673282bb
DIFF: https://github.com/llvm/llvm-project/commit/7bd2eace7d58883b87324a9fbdcc6217673282bb.diff
LOG: [flang] Check for elemental finalizer when defined object has vector subscript
When a defined object is an array with a vector subscript, and it has a
finalizable type, it may have a final subroutine with a matching or
assumed rank dummy argument that cannot be called. Unless there is
also a suitable elemental final subroutine, diagnose such a case
with an error message.
Differential Revision: https://reviews.llvm.org/D140131
Added:
flang/test/Semantics/definable02.f90
Modified:
flang/lib/Semantics/definable.cpp
Removed:
################################################################################
diff --git a/flang/lib/Semantics/definable.cpp b/flang/lib/Semantics/definable.cpp
index 32fe384f44bd..06f96a2dcf07 100644
--- a/flang/lib/Semantics/definable.cpp
+++ b/flang/lib/Semantics/definable.cpp
@@ -205,11 +205,52 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
const Scope &scope, DefinabilityFlags flags,
const evaluate::Expr<evaluate::SomeType> &expr) {
if (auto dataRef{evaluate::ExtractDataRef(expr, true, true)}) {
- if (!flags.test(DefinabilityFlag::VectorSubscriptIsOk) &&
- evaluate::HasVectorSubscript(expr)) {
- return parser::Message{at,
- "Variable '%s' has a vector subscript"_because_en_US,
- expr.AsFortran()};
+ if (evaluate::HasVectorSubscript(expr)) {
+ if (flags.test(DefinabilityFlag::VectorSubscriptIsOk)) {
+ if (auto type{expr.GetType()}) {
+ if (!type->IsUnlimitedPolymorphic() &&
+ type->category() == TypeCategory::Derived) {
+ // Seek the FINAL subroutine that should but cannot be called
+ // for this definition of an array with a vector-valued subscript.
+ // If there's an elemental FINAL subroutine, all is well; otherwise,
+ // if there is a FINAL subroutine with a matching or assumed rank
+ // dummy argument, there's no way to call it.
+ int rank{expr.Rank()};
+ const DerivedTypeSpec *spec{&type->GetDerivedTypeSpec()};
+ while (spec) {
+ bool anyElemental{false};
+ const Symbol *anyRankMatch{nullptr};
+ for (const auto &[_, ref] :
+ spec->typeSymbol().get<DerivedTypeDetails>().finals()) {
+ const Symbol &ultimate{ref->GetUltimate()};
+ anyElemental |= ultimate.attrs().test(Attr::ELEMENTAL);
+ if (const auto *subp{ultimate.detailsIf<SubprogramDetails>()}) {
+ if (!subp->dummyArgs().empty()) {
+ if (const Symbol * arg{subp->dummyArgs()[0]}) {
+ const auto *object{arg->detailsIf<ObjectEntityDetails>()};
+ if (arg->Rank() == rank ||
+ (object && object->IsAssumedRank())) {
+ anyRankMatch = &*ref;
+ }
+ }
+ }
+ }
+ }
+ if (anyRankMatch && !anyElemental) {
+ return parser::Message{at,
+ "Variable '%s' has a vector subscript and cannot be finalized by non-elemental subroutine '%s'"_because_en_US,
+ expr.AsFortran(), anyRankMatch->name()};
+ }
+ const auto *parent{FindParentTypeSpec(*spec)};
+ spec = parent ? parent->AsDerived() : nullptr;
+ }
+ }
+ }
+ } else {
+ return parser::Message{at,
+ "Variable '%s' has a vector subscript"_because_en_US,
+ expr.AsFortran()};
+ }
}
if (FindPureProcedureContaining(scope) &&
evaluate::ExtractCoarrayRef(expr)) {
diff --git a/flang/test/Semantics/definable02.f90 b/flang/test/Semantics/definable02.f90
new file mode 100644
index 000000000000..ab20b6701a66
--- /dev/null
+++ b/flang/test/Semantics/definable02.f90
@@ -0,0 +1,46 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+
+! Ensure that FINAL subroutine can be called for array with vector-valued
+! subscript.
+
+module m
+ type t1
+ contains
+ final :: f1
+ end type
+ type t2
+ contains
+ final :: f2
+ end type
+ type t3
+ contains
+ final :: f3
+ end type
+ contains
+ subroutine f1(x)
+ type(t1), intent(in out) :: x(:)
+ end subroutine
+ subroutine f2(x)
+ type(t2), intent(in out) :: x(..)
+ end subroutine
+ impure elemental subroutine f3(x)
+ type(t3), intent(in out) :: x
+ end subroutine
+end module
+
+program test
+ use m
+ type(t1) x1(1)
+ type(t2) x2(1)
+ type(t3) x3(1)
+ x1(:) = [t1()] ! ok
+ x2(:) = [t2()] ! ok
+ x3(:) = [t3()] ! ok
+ !ERROR: Left-hand side of assignment is not definable
+ !BECAUSE: Variable 'x1([INTEGER(8)::1_8])' has a vector subscript and cannot be finalized by non-elemental subroutine 'f1'
+ x1([1]) = [t1()]
+ !ERROR: Left-hand side of assignment is not definable
+ !BECAUSE: Variable 'x2([INTEGER(8)::1_8])' has a vector subscript and cannot be finalized by non-elemental subroutine 'f2'
+ x2([1]) = [t2()]
+ x3([1]) = [t3()] ! ok
+end
More information about the flang-commits
mailing list