[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:33 PDT 2026
================
@@ -698,6 +703,92 @@ void ModFileWriter::PutDECStructure(
decls_ << "end structure\n";
}
+void ModFileWriter::PutEnumerationType(const Symbol &typeSymbol) {
+ auto &details{typeSymbol.get<DerivedTypeDetails>()};
+ PutAttrs(decls_ << "enumeration type", typeSymbol.attrs());
+ decls_ << "::" << typeSymbol.name() << '\n';
+ // Collect the enumerator PARAMETER symbols of this enumeration type from the
+ // enclosing scope, sorted by ordinal value. The intrinsic enumerators
+ // created by the ENUMERATOR statement carry
+ // Symbol::Flag::EnumeratorParameter, which distinguishes them from
+ // user-declared PARAMETERs of the same enumeration type; only the flagged
+ // symbols are listed here and suppressed from standalone emission.
+ struct EnumeratorInfo {
+ SourceName name;
+ const Symbol *sym{nullptr};
+ int ordinal{0};
+ };
+ int count{details.enumeratorCount()};
+ std::vector<EnumeratorInfo> enumerators(count); // indexed by ordinal-1
+ std::vector<bool> filled(count, false);
+ for (const auto &ref : typeSymbol.owner().GetSymbols()) {
+ if (ref->test(Symbol::Flag::EnumeratorParameter)) {
+ if (const auto *obj{ref->detailsIf<ObjectEntityDetails>()}) {
+ if (obj->type() &&
+ obj->type()->category() == DeclTypeSpec::TypeDerived &&
+ &obj->type()->derivedTypeSpec().typeSymbol() == &typeSymbol) {
+ int ordinal{0};
+ if (const auto &init{obj->init()}) {
+ // The init may be a bare StructureConstructor or a
+ // Constant<SomeDerived> (after folding). Use
+ // GetScalarConstantValue which handles both.
+ if (auto ctor{
+ evaluate::GetScalarConstantValue<evaluate::SomeDerived>(
+ *init)}) {
+ for (const auto &[compRef, val] : *ctor) {
+ if (auto intVal{evaluate::ToInt64(val.value())}) {
+ ordinal = static_cast<int>(*intVal);
+ }
+ }
+ }
+ }
+ if (ordinal >= 1 && ordinal <= count && !filled[ordinal - 1]) {
+ enumerators[ordinal - 1] = {ref->name(), &*ref, ordinal};
+ filled[ordinal - 1] = true;
+ }
+ }
+ }
+ }
+ }
+ if (!enumerators.empty()) {
+ decls_ << "enumerator::";
+ bool first{true};
+ for (const auto &e : enumerators) {
+ if (!first) {
+ decls_ << ',';
+ }
+ decls_ << e.name;
+ first = false;
+ }
+ decls_ << '\n';
+ }
+ decls_ << "end enumeration type\n";
+ // Emit accessibility only for enumerators that differ from the default the
+ // reader will apply the ENUMERATION TYPE access-spec if present, otherwise
+ // the module default.
+ if (!isSubmodule_) {
+ Attr enumDefault{Attr::PUBLIC};
+ if (const Symbol *modSym{typeSymbol.owner().symbol()}) {
+ if (const auto *modDetails{modSym->detailsIf<ModuleDetails>()}) {
+ if (modDetails->isDefaultPrivate()) {
----------------
MattPD wrote:
Confirmed: Both accessibility cases survive the module-file round trip. I found no other declaration shape that fails.
https://github.com/llvm/llvm-project/pull/193235
More information about the flang-commits
mailing list