[flang-commits] [flang] [flang] Fix null pointer dereference in OUT_OF_RANGE folding (PR #224270)
via flang-commits
flang-commits at lists.llvm.org
Thu Sep 17 04:29:28 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: ejose02
<details>
<summary>Changes</summary>
Issue
- Folding OUT_OF_RANGE with -fdefault-integer-8 caused an internal compiler error in CompareUnsigned().
- The failure occurred because the unsigned comparison produced LOGICAL(8), while the code expected LogicalResult, which is LOGICAL(4).
Reproducer:
```fortran
program out_of_range_reproducer
integer, parameter :: i1 = selected_int_kind(2)
integer, parameter :: wp = selected_real_kind(6)
logical, parameter :: result(*) = out_of_range( &
[127.0_wp, 128.0_wp, -128.0_wp, -129.0_wp], 0_i1)
end program
```
Compile Using: `flang -fc1 -fdefault-integer-8 out_of_range_reproducer.f90`
Compiler crashes with : `fatal internal error: nullptr dereference`
Root cause
- RewriteOutOfRange() generates an unsigned comparison for the REAL to INTEGER range check:
```
OUT_OF_RANGE
-> RewriteOutOfRange<8>()
-> CompareUnsigned("bgt", ...)
-> ApplyIntrinsic() returns Expr<LOGICAL(8)>
-> Unwrap as Expr<LOGICAL(4)> fails
-> nullptr dereference
```
- The original code assumed that ApplyIntrinsic() always returned LogicalResult:
`return DEREF(UnwrapExpr<Expr<LogicalResult>>(result));`
- However, ApplyIntrinsic() can return a valid logical expression of a different kind. Unwrapping LOGICAL(8) directly as LOGICAL(4) returned a null pointer and caused the crash.
Fix
- Unwrap the result as SomeLogical, allowing any supported logical kind.
- Convert it explicitly to LogicalResult before returning:
```
auto &logical{DEREF(UnwrapExpr<Expr<SomeLogical>>(result))};
return ConvertToType<LogicalResult>(std::move(logical));
```
- This preserves the existing return type of CompareUnsigned() while correctly handling non-default logical kinds.
---
Full diff: https://github.com/llvm/llvm-project/pull/224270.diff
2 Files Affected:
- (modified) flang/lib/Evaluate/fold-logical.cpp (+2-1)
- (added) flang/test/Evaluate/fold-out-of-range-integer-8.f90 (+17)
``````````diff
diff --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp
index ab8c5876a13f5..3be91c0b5882b 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -430,7 +430,8 @@ static Expr<LogicalResult> CompareUnsigned(FoldingContext &context,
Expr<SomeType> result{ApplyIntrinsic(context, intrin,
ActualArguments{
ActualArgument{std::move(x)}, ActualArgument{std::move(y)}})};
- return DEREF(UnwrapExpr<Expr<LogicalResult>>(result));
+ auto &logical{DEREF(UnwrapExpr<Expr<SomeLogical>>(result))};
+ return ConvertToType<LogicalResult>(std::move(logical));
}
// Determines the right kind of INTEGER to hold the bits of a REAL type.
diff --git a/flang/test/Evaluate/fold-out-of-range-integer-8.f90 b/flang/test/Evaluate/fold-out-of-range-integer-8.f90
new file mode 100644
index 0000000000000..1322407302471
--- /dev/null
+++ b/flang/test/Evaluate/fold-out-of-range-integer-8.f90
@@ -0,0 +1,17 @@
+! RUN: %python %S/test_folding.py %s %flang_fc1 -fdefault-integer-8
+
+! Verify that folding OUT_OF_RANGE works when the default integer and
+! logical kinds are promoted to kind 8.
+
+module test_out_of_range_default_integer_8
+ integer, parameter :: i1 = selected_int_kind(2)
+ integer, parameter :: wp = selected_real_kind(6)
+
+ logical, parameter :: expected(*) = &
+ [.false., .true., .false., .true.]
+
+ logical, parameter :: result(*) = out_of_range( &
+ [127.0_wp, 128.0_wp, -128.0_wp, -129.0_wp], 0_i1)
+
+ logical, parameter :: test_result = all(result .eqv. expected)
+ end module
``````````
</details>
https://github.com/llvm/llvm-project/pull/224270
More information about the flang-commits
mailing list