[flang-commits] [flang] Enumeration Type PR01 - Initial Addition of Enumeration Type as an extension of Derived Type (PR #191491)
via flang-commits
flang-commits at lists.llvm.org
Fri Apr 10 11:56:04 PDT 2026
https://github.com/kwyatt-ext created https://github.com/llvm/llvm-project/pull/191491
This PR creates the concept of an ENUMERATIONTYPE. It is implemented as a special case of a Derived Type internally to the compiler.
>From a5f935eaa45da067d1a964a1ab3ba69a572b2542 Mon Sep 17 00:00:00 2001
From: Kevin Wyatt <kwyatt at hpe.com>
Date: Wed, 25 Mar 2026 15:36:25 -0500
Subject: [PATCH 1/2] Enumeration Type PR01 - Initial Addition of Type as an
extension of Derived Type
---
flang/include/flang/Semantics/symbol.h | 8 ++++++++
flang/include/flang/Semantics/tools.h | 2 ++
flang/include/flang/Semantics/type.h | 11 ++++++++++-
flang/lib/Evaluate/type.cpp | 2 ++
flang/lib/Lower/ConvertType.cpp | 3 +++
flang/lib/Semantics/symbol.cpp | 1 +
flang/lib/Semantics/tools.cpp | 11 +++++++++++
flang/lib/Semantics/type.cpp | 6 ++++++
8 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 4c422ac5f471a..72b09e2b89dd6 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -497,6 +497,10 @@ class DerivedTypeDetails {
const SymbolVector ¶mDeclOrder() const { return paramDeclOrder_; }
bool sequence() const { return sequence_; }
bool isDECStructure() const { return isDECStructure_; }
+ bool isEnumerationType() const { return isEnumerationType_; }
+ void set_isEnumerationType(bool x = true) { isEnumerationType_ = x; }
+ int enumeratorCount() const { return enumeratorCount_; }
+ void set_enumeratorCount(int n) { enumeratorCount_ = n; }
std::map<SourceName, SymbolRef> &finals() { return finals_; }
const std::map<SourceName, SymbolRef> &finals() const { return finals_; }
bool isForwardReferenced() const { return isForwardReferenced_; }
@@ -548,6 +552,10 @@ class DerivedTypeDetails {
bool isForwardReferenced_{false};
std::map<SourceName, const parser::Expr *> originalKindParameterMap_;
+ // These fields are only used if the derived type is an enumeration type.
+ bool isEnumerationType_{false};
+ int enumeratorCount_{0};
+
friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const DerivedTypeDetails &);
};
diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index d2e2be2548d2e..808e885b2b3c5 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -197,6 +197,8 @@ bool IsExternal(const Symbol &);
bool IsModuleProcedure(const Symbol &);
bool HasCoarray(const parser::Expr &);
bool IsAssumedType(const Symbol &);
+bool IsEnumerationType(const Symbol &);
+bool IsEnumerationType(const DerivedTypeSpec &);
bool IsPolymorphic(const Symbol &);
bool IsUnlimitedPolymorphic(const Symbol &);
bool IsPolymorphicAllocatable(const Symbol &);
diff --git a/flang/include/flang/Semantics/type.h b/flang/include/flang/Semantics/type.h
index 3a07b6ee2ec1c..9d0a2427c1b6f 100644
--- a/flang/include/flang/Semantics/type.h
+++ b/flang/include/flang/Semantics/type.h
@@ -263,7 +263,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &, const ArraySpec &);
// The name may not match the symbol's name in case of a USE rename.
class DerivedTypeSpec {
public:
- enum class Category { DerivedType, IntrinsicVector, PairVector, QuadVector };
+ enum class Category {
+ DerivedType,
+ IntrinsicVector,
+ PairVector,
+ QuadVector,
+ EnumerationType
+ };
using RawParameter = std::pair<const parser::Keyword *, ParamValue>;
using RawParameters = std::vector<RawParameter>;
@@ -335,6 +341,9 @@ class DerivedTypeSpec {
return category_ == Category::IntrinsicVector ||
category_ == Category::PairVector || category_ == Category::QuadVector;
}
+ bool IsEnumerationType() const {
+ return category_ == Category::EnumerationType;
+ }
private:
SourceName name_;
diff --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp
index 99dc8b1e5c676..40e34b42ba3f6 100644
--- a/flang/lib/Evaluate/type.cpp
+++ b/flang/lib/Evaluate/type.cpp
@@ -170,6 +170,8 @@ std::size_t DynamicType::GetAlignment(
} else {
common::die("Missing scope for Vector type.");
}
+ case semantics::DerivedTypeSpec::Category::EnumerationType:
+ break; // treat like DerivedType for alignment purposes
}
} else {
return targetCharacteristics.GetAlignment(category_, kind());
diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index 0d343968374f0..28d2c1be5e6fc 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -371,6 +371,9 @@ struct TypeBuilderImpl {
mlir::IntegerType::get(context, 1));
case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType):
Fortran::common::die("Vector element type not implemented");
+ case (Fortran::semantics::DerivedTypeSpec::Category::EnumerationType):
+ Fortran::common::die(
+ "Vector element type not implemented for enumeration");
}
}
diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index ed0715a422e78..65c8eb2e3d040 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -580,6 +580,7 @@ llvm::raw_ostream &operator<<(
llvm::raw_ostream &operator<<(
llvm::raw_ostream &os, const DerivedTypeDetails &x) {
DumpBool(os, "sequence", x.sequence_);
+ DumpBool(os, "isEnumerationType", x.isEnumerationType_);
DumpList(os, "components", x.componentNames_);
return os;
}
diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index 68307f7504e28..a792e65aab9fa 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -1070,6 +1070,17 @@ bool IsAssumedType(const Symbol &symbol) {
return false;
}
+bool IsEnumerationType(const Symbol &symbol) {
+ if (const auto *details{symbol.detailsIf<DerivedTypeDetails>()}) {
+ return details->isEnumerationType();
+ }
+ return false;
+}
+
+bool IsEnumerationType(const DerivedTypeSpec &derived) {
+ return derived.IsEnumerationType();
+}
+
bool IsPolymorphic(const Symbol &symbol) {
if (const DeclTypeSpec * type{symbol.GetType()}) {
return type->IsPolymorphic();
diff --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp
index bb8fddbffd945..13b3b041087cd 100644
--- a/flang/lib/Semantics/type.cpp
+++ b/flang/lib/Semantics/type.cpp
@@ -738,6 +738,8 @@ std::string DerivedTypeSpec::VectorTypeAsFortran() const {
break;
case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType):
Fortran::common::die("Vector element type not implemented");
+ case (Fortran::semantics::DerivedTypeSpec::Category::EnumerationType):
+ Fortran::common::die("Vector element type not implemented for enumeration");
}
return buf;
}
@@ -745,6 +747,10 @@ std::string DerivedTypeSpec::VectorTypeAsFortran() const {
std::string DerivedTypeSpec::AsFortran() const {
std::string buf;
llvm::raw_string_ostream ss{buf};
+ if (IsEnumerationType()) {
+ ss << "ENUMERATION TYPE :: " << originalTypeSymbol_.name();
+ return buf;
+ }
ss << originalTypeSymbol_.name();
if (!rawParameters_.empty()) {
CHECK(parameters_.empty());
>From 88f594d667ce1df5742095218fc61b6a980615a0 Mon Sep 17 00:00:00 2001
From: Kevin Wyatt <kwyatt at hpe.com>
Date: Fri, 10 Apr 2026 13:50:34 -0500
Subject: [PATCH 2/2] Correcting GetAlignment() issue.
---
flang/lib/Evaluate/type.cpp | 13 ++++++-------
flang/lib/Semantics/type.cpp | 14 ++++++++++++++
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp
index 40e34b42ba3f6..7c1fc804d69ef 100644
--- a/flang/lib/Evaluate/type.cpp
+++ b/flang/lib/Evaluate/type.cpp
@@ -158,8 +158,9 @@ std::size_t DynamicType::GetAlignment(
switch (GetDerivedTypeSpec().category()) {
SWITCH_COVERS_ALL_CASES
case semantics::DerivedTypeSpec::Category::DerivedType:
- if (derived_ && derived_->scope()) {
- return derived_->scope()->alignment().value_or(1);
+ case semantics::DerivedTypeSpec::Category::EnumerationType:
+ if (derived_ && derived_->GetScope()) {
+ return derived_->GetScope()->alignment().value_or(1);
}
break;
case semantics::DerivedTypeSpec::Category::IntrinsicVector:
@@ -170,8 +171,6 @@ std::size_t DynamicType::GetAlignment(
} else {
common::die("Missing scope for Vector type.");
}
- case semantics::DerivedTypeSpec::Category::EnumerationType:
- break; // treat like DerivedType for alignment purposes
}
} else {
return targetCharacteristics.GetAlignment(category_, kind());
@@ -201,9 +200,9 @@ std::optional<Expr<SubscriptInteger>> DynamicType::MeasureSizeInBytes(
}
break;
case TypeCategory::Derived:
- if (!IsPolymorphic() && derived_ && derived_->scope()) {
- auto size{derived_->scope()->size()};
- auto align{aligned ? derived_->scope()->alignment().value_or(0) : 0};
+ if (!IsPolymorphic() && derived_ && derived_->GetScope()) {
+ auto size{derived_->GetScope()->size()};
+ auto align{aligned ? derived_->GetScope()->alignment().value_or(0) : 0};
auto alignedSize{align > 0 ? ((size + align - 1) / align) * align : size};
return Expr<SubscriptInteger>{
static_cast<ConstantSubscript>(alignedSize)};
diff --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp
index 13b3b041087cd..9b91c32adbc76 100644
--- a/flang/lib/Semantics/type.cpp
+++ b/flang/lib/Semantics/type.cpp
@@ -355,6 +355,20 @@ void DerivedTypeSpec::Instantiate(Scope &containingScope) {
return;
}
instantiated_ = true;
+
+ if (IsEnumerationType()) {
+ // Enumeration types have no components, no parameters, and need
+ // no instantiation, but scope_ must be set so that callers of
+ // scope() (e.g., GetAlignment, MeasureSizeInBytes) can access
+ // the type's size and alignment.
+ scope_ = typeSymbol_.scope();
+ Scope &mutableTypeScope{const_cast<Scope &>(*scope_)};
+ if (!mutableTypeScope.derivedTypeSpec()) {
+ mutableTypeScope.set_derivedTypeSpec(*this);
+ }
+ return;
+ }
+
auto &context{containingScope.context()};
auto &foldingContext{context.foldingContext()};
if (IsForwardReferenced()) {
More information about the flang-commits
mailing list