[flang-commits] [flang] 24db885 - [flang] Check for polymorphism in DEALLOCATE statements in pure procedures
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Dec 15 16:40:01 PST 2022
Author: Peter Klausler
Date: 2022-12-15T16:39:48-08:00
New Revision: 24db8859497f9a5be35e92050ce9b08730dc04ff
URL: https://github.com/llvm/llvm-project/commit/24db8859497f9a5be35e92050ce9b08730dc04ff
DIFF: https://github.com/llvm/llvm-project/commit/24db8859497f9a5be35e92050ce9b08730dc04ff.diff
LOG: [flang] Check for polymorphism in DEALLOCATE statements in pure procedures
Semantic checking for DEALLOCATE statements omitted checks for
polymorphic objects and ultimate allocatable components in a pure
procedure, which if not caught would allow execution of an impure
FINAL subroutine defined on a type extension.
Differential Revision: https://reviews.llvm.org/D140129
Added:
flang/test/Semantics/deallocate07.f90
Modified:
flang/lib/Semantics/check-deallocate.cpp
flang/lib/Semantics/check-deallocate.h
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-deallocate.cpp b/flang/lib/Semantics/check-deallocate.cpp
index 0b21244b22cb1..5e46960e3350b 100644
--- a/flang/lib/Semantics/check-deallocate.cpp
+++ b/flang/lib/Semantics/check-deallocate.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "check-deallocate.h"
+#include "flang/Evaluate/type.h"
#include "flang/Parser/message.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/expression.h"
@@ -30,7 +31,7 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
symbol->GetUltimate())) { // C932
context_.Say(name.source,
"name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);
- } else {
+ } else if (CheckPolymorphism(name.source, *symbol)) {
context_.CheckIndexVarRedefine(name);
}
},
@@ -38,10 +39,14 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
// Only perform structureComponent checks it was successfully
// analyzed in expression analysis.
if (GetExpr(context_, allocateObject)) {
- if (!IsAllocatableOrPointer(
- *structureComponent.component.symbol)) { // C932
- context_.Say(structureComponent.component.source,
- "component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);
+ if (const Symbol *symbol{structureComponent.component.symbol}) {
+ if (!IsAllocatableOrPointer(*symbol)) { // C932
+ context_.Say(structureComponent.component.source,
+ "component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);
+ } else {
+ CheckPolymorphism(
+ structureComponent.component.source, *symbol);
+ }
}
}
},
@@ -71,4 +76,29 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
deallocOpt.u);
}
}
+
+bool DeallocateChecker::CheckPolymorphism(
+ parser::CharBlock source, const Symbol &symbol) {
+ if (FindPureProcedureContaining(context_.FindScope(source))) {
+ if (auto type{evaluate::DynamicType::From(symbol)}) {
+ if (type->IsPolymorphic()) {
+ context_.Say(source,
+ "'%s' may not be deallocated in a pure procedure because it is polymorphic"_err_en_US,
+ source);
+ return false;
+ }
+ if (!type->IsUnlimitedPolymorphic() &&
+ type->category() == TypeCategory::Derived) {
+ if (auto iter{FindPolymorphicAllocatableUltimateComponent(
+ type->GetDerivedTypeSpec())}) {
+ context_.Say(source,
+ "'%s' may not be deallocated in a pure procedure because its type has a polymorphic allocatable ultimate component '%s'"_err_en_US,
+ source, iter->name());
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/check-deallocate.h b/flang/lib/Semantics/check-deallocate.h
index 6aafb87a74793..cff75f7d5d8d3 100644
--- a/flang/lib/Semantics/check-deallocate.h
+++ b/flang/lib/Semantics/check-deallocate.h
@@ -22,6 +22,7 @@ class DeallocateChecker : public virtual BaseChecker {
void Leave(const parser::DeallocateStmt &);
private:
+ bool CheckPolymorphism(parser::CharBlock, const Symbol &);
SemanticsContext &context_;
};
} // namespace Fortran::semantics
diff --git a/flang/test/Semantics/deallocate07.f90 b/flang/test/Semantics/deallocate07.f90
new file mode 100644
index 0000000000000..2a3d036ec0b66
--- /dev/null
+++ b/flang/test/Semantics/deallocate07.f90
@@ -0,0 +1,21 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+
+module m
+ type t1
+ end type
+ type t2
+ class(t2), allocatable :: pc
+ end type
+ contains
+ pure subroutine subr(pp1, pp2, mp2)
+ class(t1), intent(in out), pointer :: pp1
+ class(t2), intent(in out) :: pp2
+ type(t2), pointer :: mp2
+ !ERROR: 'pp1' may not be deallocated in a pure procedure because it is polymorphic
+ deallocate(pp1)
+ !ERROR: 'pc' may not be deallocated in a pure procedure because it is polymorphic
+ deallocate(pp2%pc)
+ !ERROR: 'mp2' may not be deallocated in a pure procedure because its type has a polymorphic allocatable ultimate component 'pc'
+ deallocate(mp2)
+ end subroutine
+end module
More information about the flang-commits
mailing list