[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