[flang-commits] [flang] flang: allow EXIT to accept integer arguments of any kind (PR #174610)
via flang-commits
flang-commits at lists.llvm.org
Mon Jan 19 08:55:45 PST 2026
https://github.com/blazie2004 updated https://github.com/llvm/llvm-project/pull/174610
>From 083a655a22da3558d34f149266246e944031f0bb Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Tue, 6 Jan 2026 09:28:25 -0600
Subject: [PATCH 1/3] flang: allow EXIT to accept integer arguments of any kind
---
flang/lib/Evaluate/intrinsics.cpp | 15 ++++++++++++---
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 9 +++++++--
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index da39f199cab43..2e22819ce4e30 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1604,7 +1604,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
{"cmdmsg", DefaultChar, Rank::scalar, Optionality::optional,
common::Intent::InOut}},
{}, Rank::elemental, IntrinsicClass::impureSubroutine},
- {"exit", {{"status", DefaultInt, Rank::scalar, Optionality::optional}}, {},
+ {"exit", {{"status", AnyInt, Rank::scalar, Optionality::optional}}, {},
Rank::elemental, IntrinsicClass::impureSubroutine},
{"free", {{"ptr", Addressable}}, {}},
{"flush",
@@ -2157,8 +2157,16 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
semantics::IsTeamType(&type->GetDerivedTypeSpec());
break;
case KindCode::defaultIntegerKind:
- argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Integer);
- break;
+ if (name == "exit" && d.keyword == "status" &&
+ type->category() == TypeCategory::Integer) {
+ // GNU / CCE compatibility: allow any integer kind
+ argOk = true;
+ } else {
+ argOk = type->kind() ==
+ defaults.GetDefaultKind(TypeCategory::Integer);
+ }
+ break;
+
case KindCode::defaultRealKind:
argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Real);
break;
@@ -2286,6 +2294,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
d.keyword, type->AsFortran());
return std::nullopt;
}
+
}
// Check the ranks of the arguments against the intrinsic's interface.
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 75a74eeb18417..ccf500f852fbf 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -3852,12 +3852,17 @@ void IntrinsicLibrary::genExit(llvm::ArrayRef<fir::ExtendedValue> args) {
EXIT_SUCCESS)
: fir::getBase(args[0]);
- assert(status.getType() == builder.getDefaultIntegerType() &&
- "STATUS parameter must be an INTEGER of default kind");
+ mlir::Type defaultIntTy = builder.getDefaultIntegerType();
+
+ // Convert INTEGER(any kind) → default INTEGER
+ if (status.getType() != defaultIntTy) {
+ status = builder.createConvert(loc, defaultIntTy, status);
+ }
fir::runtime::genExit(builder, loc, status);
}
+
// EXPONENT
mlir::Value IntrinsicLibrary::genExponent(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
>From 48b34887bfbf8c2828b321621bfc002df4e79ede Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Sun, 11 Jan 2026 11:32:36 -0600
Subject: [PATCH 2/3] flang: update EXIT intrinsic argument matching
---
flang/lib/Evaluate/intrinsics.cpp | 24 ++++++-------------
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 10 +++++---
flang/test/Semantics/exit-nondefault-kind.f90 | 16 +++++++++++++
3 files changed, 30 insertions(+), 20 deletions(-)
create mode 100644 flang/test/Semantics/exit-nondefault-kind.f90
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 2e22819ce4e30..5e8f4b1c3c93c 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1914,7 +1914,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
// arguments in a procedure reference.
std::size_t dummyArgPatterns{0};
for (; dummyArgPatterns < maxArguments && dummy[dummyArgPatterns].keyword;
- ++dummyArgPatterns) {
+ ++dummyArgPatterns) {
}
// MAX and MIN (and others that map to them) allow their last argument to
// be repeated indefinitely. The actualForDummy vector is sized
@@ -2157,16 +2157,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
semantics::IsTeamType(&type->GetDerivedTypeSpec());
break;
case KindCode::defaultIntegerKind:
- if (name == "exit" && d.keyword == "status" &&
- type->category() == TypeCategory::Integer) {
- // GNU / CCE compatibility: allow any integer kind
- argOk = true;
- } else {
- argOk = type->kind() ==
- defaults.GetDefaultKind(TypeCategory::Integer);
- }
- break;
-
+ argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Integer);
+ break;
case KindCode::defaultRealKind:
argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Real);
break;
@@ -2294,9 +2286,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
d.keyword, type->AsFortran());
return std::nullopt;
}
-
}
-
// Check the ranks of the arguments against the intrinsic's interface.
const ActualArgument *arrayArg{nullptr};
const char *arrayArgName{nullptr};
@@ -2748,7 +2738,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
// Rearrange the actual arguments into dummy argument order.
ActualArguments rearranged(dummies);
for (std::size_t j{0}; j < dummies; ++j) {
- if (ActualArgument *arg{actualForDummy[j]}) {
+ if (ActualArgument * arg{actualForDummy[j]}) {
rearranged[j] = std::move(*arg);
}
}
@@ -3645,7 +3635,7 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
parser::Messages specificBuffer;
auto specificRange{specificFuncs_.equal_range(call.name)};
for (auto specIter{specificRange.first}; specIter != specificRange.second;
- ++specIter) {
+ ++specIter) {
// We only need to check the cases with distinct generic names.
if (const char *genericName{specIter->second->generic}) {
if (auto specificCall{
@@ -3667,13 +3657,13 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
if (context.languageFeatures().IsEnabled(common::LanguageFeature::
UseGenericIntrinsicWhenSpecificDoesntMatch)) {
for (auto specIter{specificRange.first}; specIter != specificRange.second;
- ++specIter) {
+ ++specIter) {
// We only need to check the cases with distinct generic names.
if (const char *genericName{specIter->second->generic}) {
if (specIter->second->useGenericAndForceResultType) {
auto genericRange{genericFuncs_.equal_range(genericName)};
for (auto genIter{genericRange.first}; genIter != genericRange.second;
- ++genIter) {
+ ++genIter) {
if (auto specificCall{
matchOrBufferMessages(*genIter->second, specificBuffer)}) {
// Force the call result type to the specific intrinsic result
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index ccf500f852fbf..7018ff79f7f04 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -2293,7 +2293,6 @@ bool static hasAbsentOptional(llvm::ArrayRef<fir::ExtendedValue> args) {
return true;
return false;
}
-
template <typename GeneratorType>
mlir::Value
IntrinsicLibrary::outlineInWrapper(GeneratorType generator,
@@ -3854,6 +3853,13 @@ void IntrinsicLibrary::genExit(llvm::ArrayRef<fir::ExtendedValue> args) {
mlir::Type defaultIntTy = builder.getDefaultIntegerType();
+ // Warn about non-default integer kinds with -pedantic
+ if (status.getType() != defaultIntTy) {
+ mlir::emitWarning(
+ loc,
+ "EXIT intrinsic with non-default INTEGER kind is a language extension");
+ }
+
// Convert INTEGER(any kind) → default INTEGER
if (status.getType() != defaultIntTy) {
status = builder.createConvert(loc, defaultIntTy, status);
@@ -3861,8 +3867,6 @@ void IntrinsicLibrary::genExit(llvm::ArrayRef<fir::ExtendedValue> args) {
fir::runtime::genExit(builder, loc, status);
}
-
-
// EXPONENT
mlir::Value IntrinsicLibrary::genExponent(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
diff --git a/flang/test/Semantics/exit-nondefault-kind.f90 b/flang/test/Semantics/exit-nondefault-kind.f90
new file mode 100644
index 0000000000000..2a0424e846523
--- /dev/null
+++ b/flang/test/Semantics/exit-nondefault-kind.f90
@@ -0,0 +1,16 @@
+! Test that EXIT accepts INTEGER of any kind
+! RUN: %flang_fc1 %s
+
+program test_exit_any_integer
+ implicit none
+ integer(1) :: s1 = 1
+ integer(2) :: s2 = 2
+ integer(4) :: s4 = 4
+ integer(8) :: s8 = 8
+
+ call exit(s1)
+ call exit(s2)
+ call exit(s4)
+ call exit(s8)
+
+end program test_exit_any_integer
\ No newline at end of file
>From 6c316695e0c9fb7a993522dd3c43c6eed87cf9f6 Mon Sep 17 00:00:00 2001
From: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Date: Mon, 19 Jan 2026 03:38:52 -0600
Subject: [PATCH 3/3] removed warning from IntrinsicCall.cpp
---
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 8 --------
1 file changed, 8 deletions(-)
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 7018ff79f7f04..dd74de43faabf 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -3852,14 +3852,6 @@ void IntrinsicLibrary::genExit(llvm::ArrayRef<fir::ExtendedValue> args) {
: fir::getBase(args[0]);
mlir::Type defaultIntTy = builder.getDefaultIntegerType();
-
- // Warn about non-default integer kinds with -pedantic
- if (status.getType() != defaultIntTy) {
- mlir::emitWarning(
- loc,
- "EXIT intrinsic with non-default INTEGER kind is a language extension");
- }
-
// Convert INTEGER(any kind) → default INTEGER
if (status.getType() != defaultIntTy) {
status = builder.createConvert(loc, defaultIntTy, status);
More information about the flang-commits
mailing list