[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
Thu Aug 6 22:46:32 PDT 2026
================
@@ -1255,6 +1255,110 @@ template <int KIND>
Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FunctionRef<Type<TypeCategory::Logical, KIND>> &&);
+// Fold NEXT(enum) / PREVIOUS(enum) to a constant enumerator (scalar or array)
+// when the argument is a constant enumeration value. Returns the folded
+// constant, or the original reference left unfolded (e.g. at a boundary,
+// where error termination is deferred to run time).
+static inline Expr<SomeDerived> FoldEnumerationNextOrPrevious(
+ FoldingContext &context, FunctionRef<SomeDerived> &&funcRef, bool isNext) {
+ ActualArguments &args{funcRef.arguments()};
+ // Don't fold if STAT is present — STAT assignment is a side effect
+ if (args.size() >= 2 && args[1]) {
+ return Expr<SomeDerived>{std::move(funcRef)};
+ }
+ auto *expr{args.size() >= 1 && args[0]
+ ? UnwrapExpr<Expr<SomeDerived>>(args[0])
+ : nullptr};
+ if (!expr) {
+ return Expr<SomeDerived>{std::move(funcRef)};
+ }
+ const auto *derived{GetEnumerationTypeSpec(expr->GetType())};
+ const semantics::Scope *scope{derived ? derived->GetScope() : nullptr};
+ if (!scope) {
+ return Expr<SomeDerived>{std::move(funcRef)};
+ }
+ auto ordIter{scope->find(
+ semantics::SourceName{semantics::DerivedTypeDetails::ordinalComponentName,
+ sizeof(semantics::DerivedTypeDetails::ordinalComponentName) - 1})};
+ if (ordIter == scope->end()) {
+ return Expr<SomeDerived>{std::move(funcRef)};
+ }
+ const semantics::Symbol &ordSym{*ordIter->second};
+ int count{derived->typeSymbol()
+ .GetUltimate()
+ .get<semantics::DerivedTypeDetails>()
+ .enumeratorCount()};
+ auto *constant{UnwrapConstantValue<SomeDerived>(*expr)};
+ if (!constant) {
+ return Expr<SomeDerived>{std::move(funcRef)};
+ }
+ // A boundary hit (NEXT() of the last enumerator or PREVIOUS() of the first)
+ // without STAT= is a runtime error termination, so in an ordinary expression
+ // it is left unfolded and deferred to run time. In a required-constant
----------------
MattPD wrote:
Confirmed: Both boundary cases now diagnose instead of aborting, with no regression elsewhere. I left a separate comment on the `inConstantContext()` guard.
https://github.com/llvm/llvm-project/pull/193235
More information about the flang-commits
mailing list