[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:28:46 PDT 2026


https://github.com/ejose02 created https://github.com/llvm/llvm-project/pull/224270

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.

>From 08f689d3f308ec9fb3924133b36c96cbaccd25b0 Mon Sep 17 00:00:00 2001
From: ejose <ejose at amd.com>
Date: Thu, 17 Sep 2026 09:32:13 +0000
Subject: [PATCH] [flang] Fix null pointer dereference in OUT_OF_RANGE folding

ApplyIntrinsic may return a logical expression whose kind differs from
LogicalResult. With -fdefault-integer-8, the unsigned comparison used by
RewriteOutOfRange returns LOGICAL(8), while CompareUnsigned attempts to
unwrap it directly as LOGICAL(4), causing a null pointer dereference.

Unwrap the result as SomeLogical and explicitly convert it to
LogicalResult.
---
 flang/lib/Evaluate/fold-logical.cpp             |  3 ++-
 .../Evaluate/fold-out-of-range-integer-8.f90    | 17 +++++++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/Evaluate/fold-out-of-range-integer-8.f90

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



More information about the flang-commits mailing list