[flang-commits] [flang] 77a57f6 - [flang] Avoid crash in statement function error case
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Jun 22 13:25:54 PDT 2023
Author: Peter Klausler
Date: 2023-06-22T13:25:41-07:00
New Revision: 77a57f6b250faf78637a44e88006923476421385
URL: https://github.com/llvm/llvm-project/commit/77a57f6b250faf78637a44e88006923476421385
DIFF: https://github.com/llvm/llvm-project/commit/77a57f6b250faf78637a44e88006923476421385.diff
LOG: [flang] Avoid crash in statement function error case
The predicate IsPureProcedure() crashes with infinite
recursion when presented with mutually recursive statement
functions -- an error case that should be recoverable.
Fix by adding a visited set.
Fixes bug https://github.com/llvm/llvm-project/issues/63231
Differential Revision: https://reviews.llvm.org/D153569
Added:
Modified:
flang/lib/Evaluate/tools.cpp
flang/test/Semantics/stmt-func01.f90
Removed:
################################################################################
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index befe286050559..4761407e4bcbd 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1272,16 +1272,21 @@ bool IsVariableName(const Symbol &original) {
ultimate.has<AssocEntityDetails>());
}
-bool IsPureProcedure(const Symbol &original) {
+static bool IsPureProcedureImpl(
+ const Symbol &original, semantics::UnorderedSymbolSet &set) {
// An ENTRY is pure if its containing subprogram is
const Symbol &symbol{DEREF(GetMainEntry(&original.GetUltimate()))};
+ if (set.find(symbol) != set.end()) {
+ return true;
+ }
+ set.emplace(symbol);
if (const auto *procDetails{symbol.detailsIf<ProcEntityDetails>()}) {
if (procDetails->procInterface()) {
// procedure with a pure interface
- return IsPureProcedure(*procDetails->procInterface());
+ return IsPureProcedureImpl(*procDetails->procInterface(), set);
}
} else if (const auto *details{symbol.detailsIf<ProcBindingDetails>()}) {
- return IsPureProcedure(details->symbol());
+ return IsPureProcedureImpl(details->symbol(), set);
} else if (!IsProcedure(symbol)) {
return false;
}
@@ -1293,7 +1298,7 @@ bool IsPureProcedure(const Symbol &original) {
if (&*ref == &symbol) {
return false; // error recovery, recursion is caught elsewhere
}
- if (IsFunction(*ref) && !IsPureProcedure(*ref)) {
+ if (IsFunction(*ref) && !IsPureProcedureImpl(*ref, set)) {
return false;
}
if (ref->GetUltimate().attrs().test(Attr::VOLATILE)) {
@@ -1308,6 +1313,11 @@ bool IsPureProcedure(const Symbol &original) {
!symbol.attrs().test(Attr::IMPURE));
}
+bool IsPureProcedure(const Symbol &original) {
+ semantics::UnorderedSymbolSet set;
+ return IsPureProcedureImpl(original, set);
+}
+
bool IsPureProcedure(const Scope &scope) {
const Symbol *symbol{scope.GetSymbol()};
return symbol && IsPureProcedure(*symbol);
diff --git a/flang/test/Semantics/stmt-func01.f90 b/flang/test/Semantics/stmt-func01.f90
index 0f4fed51c1184..1857143071808 100644
--- a/flang/test/Semantics/stmt-func01.f90
+++ b/flang/test/Semantics/stmt-func01.f90
@@ -34,7 +34,10 @@ pure integer function ifunc()
integer :: sf9
!ERROR: Defining expression of statement function 'sf9' cannot be converted to its result type INTEGER(4)
sf9(n) = "bad"
- sf10 = 1.
+ !ERROR: Statement function 'sf10' may not reference another statement function 'sf11' that is defined later
+ sf10(n) = sf11(n)
+ sf11(n) = sf10(n) ! mutual recursion, caused crash
+ sf13 = 1.
contains
real function explicit(x,y)
integer, intent(in) :: x
@@ -47,6 +50,6 @@ pure function arr()
end function
subroutine foo
!PORTABILITY: An implicitly typed statement function should not appear when the same symbol is available in its host scope
- sf10(x) = 2.*x
+ sf13(x) = 2.*x
end subroutine
end
More information about the flang-commits
mailing list