[flang-commits] [flang] [llvm] [flang] Enumeration Type: (PR 3/5) Intrinsics + I/O + Modules (PR #193235)

via flang-commits flang-commits at lists.llvm.org
Wed Jul 1 00:22:35 PDT 2026


================
@@ -1290,7 +1290,82 @@ Expr<T> FoldOperation(FoldingContext &context, FunctionRef<T> &&funcRef) {
       return Folder<T>{context}.UNPACK(std::move(funcRef));
     }
     // TODO: extends_type_of, same_type_as
-    if constexpr (!std::is_same_v<T, SomeDerived>) {
+    if constexpr (std::is_same_v<T, SomeDerived>) {
+      // Fold enumeration type intrinsics: HUGE(enum), NEXT(enum),
+      // PREVIOUS(enum)
+      if (name == "huge") {
+        // HUGE was eagerly folded — the first arg is the constant result
+        if (args.size() >= 1 && args[0]) {
+          if (auto *expr{UnwrapExpr<Expr<SomeDerived>>(args[0])}) {
+            return std::move(*expr);
+          }
+        }
+      } else if (name == "next" || name == "previous") {
+        // Don't fold if STAT is present — STAT assignment is a side effect
+        if (args.size() >= 2 && args[1]) {
+          return Expr<T>{std::move(funcRef)};
+        }
+        if (args.size() >= 1 && args[0]) {
+          if (auto *expr{UnwrapExpr<Expr<SomeDerived>>(args[0])}) {
+            if (auto type{expr->GetType()}) {
+              if (const auto *derived{GetDerivedTypeSpec(*type)}) {
+                if (derived->IsEnumerationType()) {
+                  if (const auto *scope{derived->GetScope()}) {
+                    auto ordIter{scope->find(semantics::SourceName{
+                        semantics::DerivedTypeDetails::ordinalComponentName,
+                        sizeof(semantics::DerivedTypeDetails::
+                            ordinalComponentName) -
+                            1})};
+                    if (ordIter != scope->end()) {
+                      const semantics::Symbol &ordSym{*ordIter->second};
+                      int count{derived->typeSymbol()
+                              .GetUltimate()
+                              .get<semantics::DerivedTypeDetails>()
+                              .enumeratorCount()};
+                      // Extract ordinal from constant value
+                      if (auto *constant{
+                              UnwrapConstantValue<SomeDerived>(*expr)}) {
----------------
MattPD wrote:

NEXT/PREVIOUS/INT are elemental for enums, but folding extracts a scalar ordinal, so a constant array argument cannot be used in a constant context:
```fortran
module m
  enumeration type :: color
    enumerator :: red, green, blue
  end enumeration type
  integer, parameter :: a(3) = int([red, green, blue])
end module
```
The compiler reports `error: Value of named constant 'a' (...) cannot be computed as a constant value`, though runtime array arguments work. Is compile-time folding of array-valued enum intrinsics in scope for this PR, or should these expressions intentionally remain non-constant for now?

https://github.com/llvm/llvm-project/pull/193235


More information about the flang-commits mailing list