[flang-commits] [flang] [flang] Enumeration Type: (PR 4/5) Lowering (PR #193571)
via flang-commits
flang-commits at lists.llvm.org
Thu Oct 1 19:49:57 PDT 2026
================
@@ -0,0 +1,542 @@
+! Test lowering of enumeration types to HLFIR/FIR.
+! Enumeration types lower to i32 values representing 1-based ordinal positions.
+! RUN: %flang_fc1 -fenumeration-type -emit-hlfir %s -o - | FileCheck %s
+
+module enum_mod
+ enumeration type :: color
+ enumerator :: red, green, blue
+ end enumeration type
+end module
+
+! -----------------------------------------------------------------------------
+! Test enumeration type maps to i32 (not fir.type)
+! -----------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @_QPtest_enum_variable()
+subroutine test_enum_variable()
+ use enum_mod
+ type(color) :: c
+ ! CHECK: %[[ALLOC:.*]] = fir.alloca i32
+ ! CHECK: hlfir.declare %[[ALLOC]]
+ c = red
+end subroutine
+
+! -----------------------------------------------------------------------------
+! Test enumerator constants lower to i32 constants
+! -----------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @_QPtest_enumerator_constants()
+subroutine test_enumerator_constants()
+ use enum_mod
+ type(color) :: c
+ ! CHECK: %[[RED:.*]] = arith.constant 1 : i32
+ ! CHECK: hlfir.assign %[[RED]]
+ c = red
+ ! CHECK: %[[GREEN:.*]] = arith.constant 2 : i32
+ ! CHECK: hlfir.assign %[[GREEN]]
+ c = green
+ ! CHECK: %[[BLUE:.*]] = arith.constant 3 : i32
+ ! CHECK: hlfir.assign %[[BLUE]]
+ c = blue
+end subroutine
+
+! -----------------------------------------------------------------------------
+! Test enumeration constructor — color(n) → i32 constant
+! -----------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @_QPtest_constructor()
+subroutine test_constructor()
+ use enum_mod
+ type(color) :: c
+ ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
+ ! CHECK: hlfir.assign %[[C2]]
+ ! Constant argument is range-checked at compile time (semantics), so no
+ ! runtime range check is emitted here.
+ ! CHECK-NOT: fir.call @{{.*}}ReportFatalUserError
+ c = color(2)
+end subroutine
+
+! -----------------------------------------------------------------------------
+! Test enumeration constructor — color(i) runtime range check
+! -----------------------------------------------------------------------------
+
+! A non-constant argument cannot be range-checked at compile time, so lowering
+! emits an always-on runtime check (1 <= i <= enumeratorCount) with fatal
+! error termination (F2023 7.6.2 para 5).
+
+! CHECK-LABEL: func.func @_QPtest_constructor_runtime(
+! CHECK-SAME: %[[ARG:.*]]: !fir.ref<i32>
+subroutine test_constructor_runtime(i)
+ use enum_mod
+ integer, intent(in) :: i
+ type(color) :: c
+ ! CHECK: %[[ORD:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+ ! CHECK-DAG: %[[ONE:.*]] = arith.constant 1 : i32
+ ! CHECK-DAG: %[[MAX:.*]] = arith.constant 3 : i32
+ ! CHECK: %[[LOW:.*]] = arith.cmpi slt, %[[ORD]], %[[ONE]] : i32
+ ! CHECK: %[[HIGH:.*]] = arith.cmpi sgt, %[[ORD]], %[[MAX]] : i32
+ ! CHECK: %[[OOR:.*]] = arith.ori %[[LOW]], %[[HIGH]] : i1
+ ! CHECK: fir.if %[[OOR]] {
+ ! CHECK: fir.call @{{.*}}ReportFatalUserError
+ ! CHECK: }
+ ! CHECK: hlfir.assign %[[ORD]]
+ c = color(i)
+end subroutine
+
+! -----------------------------------------------------------------------------
+! Test enumeration comparisons (relational operators)
+! -----------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @_QPtest_comparisons(
+! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32>{{.*}}, %[[ARG1:.*]]: !fir.ref<i32>{{.*}})
+subroutine test_comparisons(c1, c2)
+ use enum_mod
+ type(color), intent(in) :: c1, c2
+ logical :: l
+ ! CHECK: %[[V1:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+ ! CHECK: %[[V2:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+ ! CHECK: arith.cmpi eq, %[[V1]], %[[V2]] : i32
+ l = (c1 == c2)
+ ! CHECK: arith.cmpi slt
+ l = (c1 < c2)
+ ! CHECK: arith.cmpi sle
+ l = (c1 <= c2)
+ ! CHECK: arith.cmpi sgt
+ l = (c1 > c2)
+ ! CHECK: arith.cmpi sge
+ l = (c1 >= c2)
+ ! CHECK: arith.cmpi ne
+ l = (c1 /= c2)
+end subroutine
+
+! -----------------------------------------------------------------------------
+! Test INT() conversion of enumeration values
+! -----------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @_QPtest_int_conversion()
+subroutine test_int_conversion()
+ use enum_mod
+ integer :: i
+ ! CHECK: %[[C1:.*]] = arith.constant 1 : i32
+ i = int(red)
----------------
MattPD wrote:
Variable INT and KIND=8 now have direct lowering coverage and return the expected ordinals.
https://github.com/llvm/llvm-project/pull/193571
More information about the flang-commits
mailing list