[flang-commits] [flang] 97e3f60 - [flang] Don't allow non-standard data conversions of potentially abse… (#87391)
via flang-commits
flang-commits at lists.llvm.org
Mon Apr 8 11:56:39 PDT 2024
Author: Peter Klausler
Date: 2024-04-08T11:56:36-07:00
New Revision: 97e3f605d5b574899d9f012032349bbf84c4dcfb
URL: https://github.com/llvm/llvm-project/commit/97e3f605d5b574899d9f012032349bbf84c4dcfb
DIFF: https://github.com/llvm/llvm-project/commit/97e3f605d5b574899d9f012032349bbf84c4dcfb.diff
LOG: [flang] Don't allow non-standard data conversions of potentially abse… (#87391)
…nt arguments
Arguments to the intrinsic functions MAX and MIN after the first two are
optional. When these actual arguments might not be present at run time,
emit a compilation time error if they require data conversion (a
non-standard but nearly universal language extension); such a conversion
would crash if the argument was absent.
Other compilers either disallow data conversions entirely on MAX/MIN or
crash at run time if a converted argument is absent.
Fixes https://github.com/llvm/llvm-project/issues/87046.
Added:
flang/test/Semantics/intrinsics04.f90
Modified:
flang/docs/Extensions.md
flang/lib/Semantics/check-call.cpp
Removed:
################################################################################
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index d44242de17d567..4c3847291a3f3b 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -346,6 +346,10 @@ end
* A `NAMELIST` input group may begin with either `&` or `$`.
* A comma in a fixed-width numeric input field terminates the
field rather than signaling an invalid character error.
+* Arguments to the intrinsic functions `MAX` and `MIN` are converted
+ when necessary to the type of the result.
+ An `OPTIONAL`, `POINTER`, or `ALLOCATABLE` argument after
+ the first two cannot be converted, as it may not be present.
### Extensions supported when enabled by options
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 51a16ee155fabb..bd2f755855172a 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -1466,6 +1466,29 @@ static void CheckImage_Index(evaluate::ActualArguments &arguments,
}
}
+// Ensure that any optional argument that might be absent at run time
+// does not require data conversion.
+static void CheckMaxMin(const characteristics::Procedure &proc,
+ evaluate::ActualArguments &arguments,
+ parser::ContextualMessages &messages) {
+ if (proc.functionResult) {
+ if (const auto *typeAndShape{proc.functionResult->GetTypeAndShape()}) {
+ for (std::size_t j{2}; j < arguments.size(); ++j) {
+ if (arguments[j]) {
+ if (const auto *expr{arguments[j]->UnwrapExpr()};
+ expr && evaluate::MayBePassedAsAbsentOptional(*expr)) {
+ if (auto thisType{expr->GetType()};
+ thisType && *thisType != typeAndShape->type()) {
+ messages.Say(arguments[j]->sourceLocation(),
+ "An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE"_err_en_US);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
// MOVE_ALLOC (F'2023 16.9.147)
static void CheckMove_Alloc(evaluate::ActualArguments &arguments,
parser::ContextualMessages &messages) {
@@ -1733,13 +1756,15 @@ static void CheckTransfer(evaluate::ActualArguments &arguments,
}
}
-static void CheckSpecificIntrinsic(evaluate::ActualArguments &arguments,
- SemanticsContext &context, const Scope *scope,
- const evaluate::SpecificIntrinsic &intrinsic) {
+static void CheckSpecificIntrinsic(const characteristics::Procedure &proc,
+ evaluate::ActualArguments &arguments, SemanticsContext &context,
+ const Scope *scope, const evaluate::SpecificIntrinsic &intrinsic) {
if (intrinsic.name == "associated") {
CheckAssociated(arguments, context, scope);
} else if (intrinsic.name == "image_index") {
CheckImage_Index(arguments, context.foldingContext().messages());
+ } else if (intrinsic.name == "max" || intrinsic.name == "min") {
+ CheckMaxMin(proc, arguments, context.foldingContext().messages());
} else if (intrinsic.name == "move_alloc") {
CheckMove_Alloc(arguments, context.foldingContext().messages());
} else if (intrinsic.name == "present") {
@@ -1790,7 +1815,7 @@ static parser::Messages CheckExplicitInterface(
CheckElementalConformance(messages, proc, actuals, foldingContext);
}
if (intrinsic) {
- CheckSpecificIntrinsic(actuals, context, scope, *intrinsic);
+ CheckSpecificIntrinsic(proc, actuals, context, scope, *intrinsic);
}
return buffer;
}
diff --git a/flang/test/Semantics/intrinsics04.f90 b/flang/test/Semantics/intrinsics04.f90
new file mode 100644
index 00000000000000..a7d646e5c016e7
--- /dev/null
+++ b/flang/test/Semantics/intrinsics04.f90
@@ -0,0 +1,25 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! A potentially absent actual argument cannot require data type conversion.
+subroutine s(o,a,p)
+ integer(2), intent(in), optional :: o
+ integer(2), intent(in), allocatable :: a
+ integer(2), intent(in), pointer :: p
+ !ERROR: An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE
+ print *, max(1, 2, o)
+ !ERROR: An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE
+ print *, max(1, 2, a)
+ !ERROR: An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE
+ print *, max(1, 2, p)
+ !ERROR: An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE
+ print *, min(1, 2, o)
+ !ERROR: An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE
+ print *, min(1, 2, a)
+ !ERROR: An actual argument to MAX/MIN requiring data conversion may not be OPTIONAL, POINTER, or ALLOCATABLE
+ print *, min(1, 2, p)
+ print *, max(1_2, 2_2, o) ! ok
+ print *, max(1_2, 2_2, a) ! ok
+ print *, max(1_2, 2_2, p) ! ok
+ print *, min(1_2, 2_2, o) ! ok
+ print *, min(1_2, 2_2, a) ! ok
+ print *, min(1_2, 2_2, p) ! ok
+end
More information about the flang-commits
mailing list