https://github.com/kwyatt-ext updated https://github.com/llvm/llvm-project/pull/231641
>From c6d8974827d13a23081f384d744afb8aa697b205 Mon Sep 17 00:00:00 2001 From: Kevin Wyatt <[email protected]> Date: Tue, 13 Oct 2026 12:48:08 -0500 Subject: [PATCH 1/3] - Removed gating to feature. - Modified tests to function with remove gate. - Updated documents to reflect addition of feature. --- clang/include/clang/Options/FlangOptions.td | 1 - clang/lib/Driver/ToolChains/Flang.cpp | 20 +++------- flang/docs/FortranStandardsSupport.md | 2 +- flang/docs/ReleaseNotes.md | 12 ++++++ flang/lib/Evaluate/intrinsics.cpp | 10 +---- flang/lib/Frontend/CompilerInvocation.cpp | 6 --- flang/lib/Semantics/resolve-names.cpp | 22 ----------- flang/lib/Support/Fortran-features.cpp | 4 -- .../enumeration-type-forall-stat-todo.f90 | 2 +- .../Lower/enumeration-type-next-previous.f90 | 4 +- flang/test/Lower/enumeration-type.f90 | 6 +-- .../enumeration-type-component-offset.f90 | 2 +- .../enumeration-type-component-usage.f90 | 2 +- .../enumeration-type-declarations.f90 | 10 +---- .../enumeration-type-explicit-value.f90 | 2 +- .../enumeration-type-forward-ref.f90 | 3 +- ...enumeration-type-intrinsics-array-fold.f90 | 2 +- .../enumeration-type-intrinsics-gating.f90 | 37 ++++++++++++------- .../enumeration-type-intrinsics-keyword.f90 | 2 +- .../enumeration-type-intrinsics-nonenum.f90 | 2 +- .../enumeration-type-intrinsics-valid.f90 | 2 +- .../Semantics/enumeration-type-intrinsics.f90 | 2 +- .../enumeration-type-io-pdt-order.f90 | 3 +- flang/test/Semantics/enumeration-type-io.f90 | 3 +- .../test/Semantics/enumeration-type-misc.f90 | 5 +-- .../enumeration-type-mod-readback.F90 | 10 ++--- flang/test/Semantics/enumeration-type-mod.f90 | 2 +- .../Semantics/enumeration-type-relational.f90 | 5 +-- 28 files changed, 69 insertions(+), 114 deletions(-) diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td index 2844ee854a120d..afc5ce85945003 100644 --- a/clang/include/clang/Options/FlangOptions.td +++ b/clang/include/clang/Options/FlangOptions.td @@ -193,7 +193,6 @@ defm unsigned : OptInFC1FFlag<"unsigned", "Enables UNSIGNED type">; defm out_of_bounds_subscripts : OptOutFC1FFlag<"out-of-bounds-subscripts", "Accept a constant subscript that is out of bounds, with a warning (default)", "Reject a constant subscript that is out of bounds with an error">; -defm enumeration_type : OptInFC1FFlag<"enumeration-type", "Enables F2023 ENUMERATION TYPE (experimental; FIR lowering is incomplete)">; defm openacc_default_none_scalars_strict : OptOutFC1FFlag<"openacc-default-none-scalars-strict", "Require explicit data clauses for all variables (including scalars) under OpenACC DEFAULT(NONE)", "Allow scalars without explicit data clauses under OpenACC DEFAULT(NONE) (default, pre-OpenACC-3.2 behavior)">; diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index a13c69a5b2a50a..f2eb0173bedb1b 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -228,20 +228,12 @@ void Flang::addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA, const auto &TC = getToolChain(); const Driver &D = TC.getDriver(); Args.addAllArgs(CmdArgs, - {options::OPT_module_dir, - options::OPT_fdebug_module_writer, - options::OPT_fintrinsic_modules_path, - options::OPT_pedantic, - options::OPT_std_EQ, - options::OPT_W_Joined, - options::OPT_fconvert_EQ, - options::OPT_fpass_plugin_EQ, - options::OPT_funderscoring, - options::OPT_fno_underscoring, - options::OPT_funsigned, - options::OPT_fno_unsigned, - options::OPT_fenumeration_type, - options::OPT_fno_enumeration_type, + {options::OPT_module_dir, options::OPT_fdebug_module_writer, + options::OPT_fintrinsic_modules_path, options::OPT_pedantic, + options::OPT_std_EQ, options::OPT_W_Joined, + options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ, + options::OPT_funderscoring, options::OPT_fno_underscoring, + options::OPT_funsigned, options::OPT_fno_unsigned, options::OPT_fout_of_bounds_subscripts, options::OPT_fno_out_of_bounds_subscripts, options::OPT_fopenacc_default_none_scalars_strict, diff --git a/flang/docs/FortranStandardsSupport.md b/flang/docs/FortranStandardsSupport.md index dd8bda23cb495f..ed53afeab8762d 100644 --- a/flang/docs/FortranStandardsSupport.md +++ b/flang/docs/FortranStandardsSupport.md @@ -53,7 +53,7 @@ status of all important Fortran 2023 features. The table entries are based on th | Using integer arrays to specify rank and bound of an array | N | | | Using an integer constant to specify rank | Y | | | Reduction specifier for do concurrent | P | | -| Enumerations | N | | +| Enumerations | P | New non-interoperable ENUMERATION TYPE supported, interoperable enum types not supported | ## Fortran 2018 All features except those listed in the following table are supported. Almost all of the unsupported features are related to diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md index 609ca499da3965..447f19ebd3f5b4 100644 --- a/flang/docs/ReleaseNotes.md +++ b/flang/docs/ReleaseNotes.md @@ -168,6 +168,18 @@ page](https://llvm.org/releases/). F2023 15.5.2.10 p1). Declare the target `SIMPLE` if it satisfies the `SIMPLE` constraints, or give the pointer or dummy an explicit `PURE` interface. +- Added support for the Fortran 2023 non-interoperable `ENUMERATION TYPE` + (F2023 7.6.2). An enumeration type is a distinct type whose values are + ordered, named enumerators. Supported features: + - declaration with `ENUMERATION TYPE` / `ENUMERATOR`, including + `ENUMERATION TYPE, PUBLIC/PRIVATE` and use through modules (module files + record enumeration types); + - enumeration constructors and use as named constants; + - relational operators (`==`, `/=`, `<`, `<=`, `>`, `>=`) between values of + the same enumeration type, and `SELECT CASE` on enumeration values; + - the `INT` intrinsic applied to an enumeration value, and the `HUGE`, + `NEXT` and `PREVIOUS` intrinsics; + - formatted I/O using the `I`, `B`, `O` and `Z` edit descriptors. ## Build System Changes diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 84a211251b6eaf..5839c0e672c0be 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -4159,15 +4159,7 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe( } } - // NEXT/PREVIOUS are enumeration-type-only intrinsics. They are only - // recognized as intrinsic names when the enumeration-type feature is - // enabled, so that pre-F2023 programs may still use those names for - // external procedures. This gating is symmetric with the one in - // resolve-names.cpp and should be removed once the feature is fully - // implemented. - if ((call.name == "next" || call.name == "previous") && - context.languageFeatures().IsEnabled( - common::LanguageFeature::EnumerationType)) { + if (call.name == "next" || call.name == "previous") { const semantics::DerivedTypeSpec *derived{nullptr}; if (const ActualArgument *arg{FindFirstDummyArgument(arguments, "a")}) { derived = GetEnumerationTypeSpec(arg->GetType()); diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index d4c6b44e114772..51333fdd95e1fb 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -939,12 +939,6 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, args.hasFlag(clang::options::OPT_fout_of_bounds_subscripts, clang::options::OPT_fno_out_of_bounds_subscripts, true)); - // -f{no-}enumeration-type (experimental; FIR lowering is incomplete) - opts.features.Enable(Fortran::common::LanguageFeature::EnumerationType, - args.hasFlag(clang::options::OPT_fenumeration_type, - clang::options::OPT_fno_enumeration_type, - false)); - // -frelaxed-c-loc-checks if (args.hasArg(clang::options::OPT_relaxed_c_loc)) { opts.features.Enable(Fortran::common::LanguageFeature::RelaxedCLocChecks); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 06bc617ca7506b..d5d5356288b5a0 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -172,18 +172,6 @@ class BaseVisitor { } bool IsIntrinsic( const SourceName &name, std::optional<Symbol::Flag> flag) const { - // TEMPORARY (enumeration-type feature gating): NEXT and PREVIOUS are only - // recognized as intrinsic names when the enumeration-type feature is - // enabled, so that pre-F2023 programs may still use those names for - // implicit external procedures. This gating is removed once the - // enumeration-type feature is fully implemented. - if (!context_->languageFeatures().IsEnabled( - common::LanguageFeature::EnumerationType)) { - const std::string nameStr{name.ToString()}; - if (nameStr == "next" || nameStr == "previous") { - return false; - } - } if (!flag) { return context_->intrinsics().IsIntrinsic(name.ToString()); } else if (flag == Symbol::Flag::Function) { @@ -6580,16 +6568,6 @@ void DeclarationVisitor::Post(const parser::EnumDef &) { // F2023 R766 EnumerationTypeDef — scope is pushed in Post(EnumerationTypeStmt) // and popped in Post(EndEnumerationTypeStmt). bool DeclarationVisitor::Pre(const parser::EnumerationTypeDef &x) { - const auto &source{ - std::get<parser::Statement<parser::EnumerationTypeStmt>>(x.t).source}; - // ENUMERATION TYPE is an experimental feature: semantics are partially - // implemented. FIR lowering is not implemented. - if (!context().IsEnabled(common::LanguageFeature::EnumerationType)) { - Say(source, "F2023 ENUMERATION TYPEs are not yet implemented"_err_en_US); - return false; - } - Say(source, - "ENUMERATION TYPE support is incomplete and should be enabled only for testing"_warn_en_US); BeginAttrs(); return true; } diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp index 9e0069781a117a..d0ff69deffb26b 100644 --- a/flang/lib/Support/Fortran-features.cpp +++ b/flang/lib/Support/Fortran-features.cpp @@ -145,10 +145,6 @@ LanguageFeatureControl::LanguageFeatureControl() { disable_.set(LanguageFeature::DefaultSave); disable_.set(LanguageFeature::SaveMainProgram); disable_.set(LanguageFeature::RelaxedCLocChecks); - // F2023 ENUMERATION TYPE: experimental. Semantics are implemented, but - // FIR lowering is not, so the feature is off by default and must be - // explicitly enabled (for testing) with -fenumeration-type. - disable_.set(LanguageFeature::EnumerationType); // These features, if enabled, conflict with valid standard usage, // so there are disabled here by default. disable_.set(LanguageFeature::BackslashEscapes); diff --git a/flang/test/Lower/HLFIR/enumeration-type-forall-stat-todo.f90 b/flang/test/Lower/HLFIR/enumeration-type-forall-stat-todo.f90 index 5bc1bb6276a702..568868b27081e0 100644 --- a/flang/test/Lower/HLFIR/enumeration-type-forall-stat-todo.f90 +++ b/flang/test/Lower/HLFIR/enumeration-type-forall-stat-todo.f90 @@ -1,5 +1,5 @@ ! Test that NEXT/PREVIOUS with STAT= inside FORALL hits the TODO diagnostic. -! RUN: %not_todo_cmd %flang_fc1 -fenumeration-type -emit-hlfir -o - %s 2>&1 | FileCheck %s +! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -o - %s 2>&1 | FileCheck %s ! CHECK: not yet implemented: NEXT/PREVIOUS with STAT= inside FORALL module enum_forall_mod diff --git a/flang/test/Lower/enumeration-type-next-previous.f90 b/flang/test/Lower/enumeration-type-next-previous.f90 index 0c2d76466f812c..84aebbb9666eef 100644 --- a/flang/test/Lower/enumeration-type-next-previous.f90 +++ b/flang/test/Lower/enumeration-type-next-previous.f90 @@ -1,6 +1,6 @@ ! Test lowering of the NEXT and PREVIOUS intrinsics for enumeration types. -! RUN: %flang_fc1 -fenumeration-type -emit-hlfir %s -o - | FileCheck %s -! RUN: %flang_fc1 -fenumeration-type -emit-fir %s -o /dev/null +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o /dev/null module enum_np_mod enumeration type :: color diff --git a/flang/test/Lower/enumeration-type.f90 b/flang/test/Lower/enumeration-type.f90 index 9b6ddfd595c740..dea023cb85acfc 100644 --- a/flang/test/Lower/enumeration-type.f90 +++ b/flang/test/Lower/enumeration-type.f90 @@ -1,9 +1,9 @@ ! Test lowering of enumeration types to HLFIR. ! An enumeration type lowers to a record type with a single i32 component, ! __ordinal, holding the 1-based ordinal of the enumerator. -! RUN: %flang_fc1 -fenumeration-type -emit-hlfir %s -o - | FileCheck %s -! RUN: %flang_fc1 -fenumeration-type -emit-fir %s -o /dev/null -! RUN: %flang_fc1 -fenumeration-type -emit-fir -mmlir -strict-fir-volatile-verifier %s -o /dev/null +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o /dev/null +! RUN: %flang_fc1 -emit-fir -mmlir -strict-fir-volatile-verifier %s -o /dev/null module enum_mod enumeration type :: color diff --git a/flang/test/Semantics/enumeration-type-component-offset.f90 b/flang/test/Semantics/enumeration-type-component-offset.f90 index 8cec31cfe4d7af..90f98a69b59bec 100644 --- a/flang/test/Semantics/enumeration-type-component-offset.f90 +++ b/flang/test/Semantics/enumeration-type-component-offset.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fdebug-dump-symbols -fenumeration-type %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-dump-symbols %s 2>&1 | FileCheck %s ! Regression test: a derived type with an enumeration-type component must be ! correctly sized once the enclosing type is instantiated (which happens as ! soon as a variable of it is declared). diff --git a/flang/test/Semantics/enumeration-type-component-usage.f90 b/flang/test/Semantics/enumeration-type-component-usage.f90 index 55d2595f336001..afb28ab1308753 100644 --- a/flang/test/Semantics/enumeration-type-component-usage.f90 +++ b/flang/test/Semantics/enumeration-type-component-usage.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fsyntax-only -fenumeration-type %s +! RUN: %flang_fc1 -fsyntax-only %s ! An enumeration type used as a derived-type component: default component ! initialization, whole-structure assignment, component assignment, use of the ! component in a relational, and arrays of the containing type must all compile. diff --git a/flang/test/Semantics/enumeration-type-declarations.f90 b/flang/test/Semantics/enumeration-type-declarations.f90 index 4f1e5dbc506873..23e0f14f63d6e4 100644 --- a/flang/test/Semantics/enumeration-type-declarations.f90 +++ b/flang/test/Semantics/enumeration-type-declarations.f90 @@ -1,11 +1,10 @@ -! RUN: %python %S/test_errors.py %s %flang_fc1 -fenumeration-type +! RUN: %python %S/test_errors.py %s %flang_fc1 ! Test declaration, constructor, and expression semantics for enumeration types ! C7114: access specifier only allowed in module subroutine test_access_specifier_outside_module() !ERROR: PRIVATE attribute may only appear in the specification part of a module !ERROR: Access specifier on ENUMERATION TYPE may only appear in the specification part of a module - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type, private :: color enumerator :: red, green, blue end enumeration type @@ -13,7 +12,6 @@ subroutine test_access_specifier_outside_module() ! Valid: basic declarations and usage subroutine test_basic_declarations() - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type @@ -32,7 +30,6 @@ subroutine test_basic_declarations() ! Valid: constructor syntax — color(n) where n is a positive integer <= count subroutine test_constructor_valid() - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type @@ -47,7 +44,6 @@ subroutine test_constructor_valid() ! Constructor errors subroutine test_constructor_errors() - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type @@ -78,7 +74,6 @@ subroutine test_constructor_errors() ! Component reference on enumeration type is not allowed subroutine test_component_reference() - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type @@ -93,7 +88,6 @@ subroutine test_component_reference() ! Module providing an enumeration type by USE association module enum_constructor_mod - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type @@ -132,7 +126,6 @@ subroutine test_constructor_errors_use() ! A duplicate enumerator name within an enumeration type is diagnosed as a ! clean semantic error. subroutine test_duplicate_enumerator() - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color !ERROR: 'red' is already declared in this scoping unit enumerator :: red, green, red @@ -143,7 +136,6 @@ subroutine test_duplicate_enumerator() ! numeric: assignment and arithmetic mixing an enumeration value with an ! integer (or two enumeration values) must be rejected. subroutine test_assignment_and_arithmetic() - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type diff --git a/flang/test/Semantics/enumeration-type-explicit-value.f90 b/flang/test/Semantics/enumeration-type-explicit-value.f90 index 839e5fed024c05..a14a7378ddcb0c 100644 --- a/flang/test/Semantics/enumeration-type-explicit-value.f90 +++ b/flang/test/Semantics/enumeration-type-explicit-value.f90 @@ -1,4 +1,4 @@ -! RUN: not %flang_fc1 -fsyntax-only -fenumeration-type %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s ! F2023 enumeration types do not permit explicit enumerator values (unlike the ! ENUM, BIND(C) construct). 'enumerator :: red = 1' must be rejected. diff --git a/flang/test/Semantics/enumeration-type-forward-ref.f90 b/flang/test/Semantics/enumeration-type-forward-ref.f90 index cd0523459298e4..4047089633753a 100644 --- a/flang/test/Semantics/enumeration-type-forward-ref.f90 +++ b/flang/test/Semantics/enumeration-type-forward-ref.f90 @@ -1,4 +1,4 @@ -! RUN: %python %S/test_errors.py %s %flang_fc1 -fenumeration-type +! RUN: %python %S/test_errors.py %s %flang_fc1 ! Forward reference to an enumeration type. ! ! F2023 C7116: the enumeration-type-name in an enumeration-type-spec shall be @@ -10,7 +10,6 @@ program p !ERROR: Enumeration type 'color' must be defined before it is referenced implicit type(color) (c) ! forward reference: 'color' defined below - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type diff --git a/flang/test/Semantics/enumeration-type-intrinsics-array-fold.f90 b/flang/test/Semantics/enumeration-type-intrinsics-array-fold.f90 index d7af7199aa4ba9..28b26b66604790 100644 --- a/flang/test/Semantics/enumeration-type-intrinsics-array-fold.f90 +++ b/flang/test/Semantics/enumeration-type-intrinsics-array-fold.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fdebug-dump-symbols -fenumeration-type %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fdebug-dump-symbols %s 2>&1 | FileCheck %s ! Regression test: the enumeration-type intrinsics INT/NEXT/PREVIOUS are ! elemental, so a constant array argument must fold elementwise in a constant ! context. Previously the enum fold path extracted only a scalar ordinal, so an diff --git a/flang/test/Semantics/enumeration-type-intrinsics-gating.f90 b/flang/test/Semantics/enumeration-type-intrinsics-gating.f90 index 3ccab11d02ef45..5deea2c234730b 100644 --- a/flang/test/Semantics/enumeration-type-intrinsics-gating.f90 +++ b/flang/test/Semantics/enumeration-type-intrinsics-gating.f90 @@ -1,26 +1,35 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -! Without -fenumeration-type, NEXT and PREVIOUS are not reserved intrinsic -! names, so a pre-F2023 program may use them as implicit external procedures. -! This exercises the enumeration-type feature gating in resolve-names.cpp and -! verifies the reference no longer triggers an internal compiler error. -! NOTE: This gating is TEMPORARY and is removed once the enumeration-type -! feature is fully implemented. +! NEXT and PREVIOUS are F2023 intrinsic functions. A pre-F2023 program that +! uses either name for its own procedure must declare it EXTERNAL. program p integer :: i real :: r + !ERROR: Argument of NEXT() must be of enumeration type i = next(5) + !ERROR: Argument of PREVIOUS() must be of enumeration type r = previous(3) end program -subroutine test_intrinsic_next_declaration() - ! Explicitly declaring NEXT intrinsic here (with the enumeration-type - ! feature disabled) must produce only the single expected diagnostic below. - ! Before the DeclareIntrinsic fix, the name was still incorrectly flagged - ! as an intrinsic function under the hood, risking a second, bogus - ! diagnostic when it was later referenced as a call below. - !ERROR: 'next' is not a known intrinsic procedure - intrinsic :: next +subroutine test_external() + external :: next, previous + integer :: next + real :: previous integer :: i + real :: r + i = next(5) + r = previous(3) +end subroutine + +subroutine test_intrinsic_declaration() + intrinsic :: next, previous + integer :: i + !ERROR: Argument of NEXT() must be of enumeration type i = next(5) end subroutine + +! The intrinsics are functions, so a CALL still refers to an external subroutine. +subroutine test_call() + call next(1) + call previous(1) +end subroutine diff --git a/flang/test/Semantics/enumeration-type-intrinsics-keyword.f90 b/flang/test/Semantics/enumeration-type-intrinsics-keyword.f90 index 85e70baf9ca0ee..e929b7f74522c2 100644 --- a/flang/test/Semantics/enumeration-type-intrinsics-keyword.f90 +++ b/flang/test/Semantics/enumeration-type-intrinsics-keyword.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fsyntax-only -fenumeration-type %s +! RUN: %flang_fc1 -fsyntax-only %s ! Verify keyword-order argument binding for enumeration-type intrinsics. ! INT(KIND=..., A=...) must recognize the enumeration argument even when it is ! not the first positional actual. This is a regression test: previously the diff --git a/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 b/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 index 37a04c6f0fffb6..087d0d4db5715e 100644 --- a/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 +++ b/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 @@ -1,4 +1,4 @@ -! RUN: not %flang_fc1 -fsyntax-only -fenumeration-type %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s ! With the enumeration-type feature enabled, NEXT and PREVIOUS require an ! argument of enumeration type. A non-enumeration argument must produce a ! proper diagnostic rather than an internal compiler error. diff --git a/flang/test/Semantics/enumeration-type-intrinsics-valid.f90 b/flang/test/Semantics/enumeration-type-intrinsics-valid.f90 index 04da086c11bc41..e8f9e18a46628e 100644 --- a/flang/test/Semantics/enumeration-type-intrinsics-valid.f90 +++ b/flang/test/Semantics/enumeration-type-intrinsics-valid.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fsyntax-only -fenumeration-type -pedantic %s +! RUN: %flang_fc1 -fsyntax-only -pedantic %s ! NEXT/PREVIOUS calls that must compile cleanly (F2023 16.9.151, 16.9.164). module enum_intrinsics_valid_mod diff --git a/flang/test/Semantics/enumeration-type-intrinsics.f90 b/flang/test/Semantics/enumeration-type-intrinsics.f90 index 43f1a5329d2a0c..d68cb090032adc 100644 --- a/flang/test/Semantics/enumeration-type-intrinsics.f90 +++ b/flang/test/Semantics/enumeration-type-intrinsics.f90 @@ -1,4 +1,4 @@ -! RUN: not %flang_fc1 -fsyntax-only -fenumeration-type -pedantic %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck %s ! Test intrinsics HUGE, NEXT, PREVIOUS, INT for enumeration types (F2023 7.6.2). module enum_intrinsics_mod diff --git a/flang/test/Semantics/enumeration-type-io-pdt-order.f90 b/flang/test/Semantics/enumeration-type-io-pdt-order.f90 index 36bbf6802d335f..159a820406e9d7 100644 --- a/flang/test/Semantics/enumeration-type-io-pdt-order.f90 +++ b/flang/test/Semantics/enumeration-type-io-pdt-order.f90 @@ -1,11 +1,10 @@ -! RUN: %python %S/test_errors.py %s %flang_fc1 -fenumeration-type +! RUN: %python %S/test_errors.py %s %flang_fc1 ! ! This test verifies that the transversal order for enumeration type components ! does not impact the correct recognition/reporting of unformatted output ! errors. module enum_pdt_order_mod - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type diff --git a/flang/test/Semantics/enumeration-type-io.f90 b/flang/test/Semantics/enumeration-type-io.f90 index 6196e5e8e814ec..b2bd53787de590 100644 --- a/flang/test/Semantics/enumeration-type-io.f90 +++ b/flang/test/Semantics/enumeration-type-io.f90 @@ -1,8 +1,7 @@ -! RUN: %python %S/test_errors.py %s %flang_fc1 -fenumeration-type +! RUN: %python %S/test_errors.py %s %flang_fc1 ! Test I/O constraints for enumeration types (F2023 7.6.2) module enum_io_mod - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type diff --git a/flang/test/Semantics/enumeration-type-misc.f90 b/flang/test/Semantics/enumeration-type-misc.f90 index 3c99682e8a690c..c43f80eaa24bca 100644 --- a/flang/test/Semantics/enumeration-type-misc.f90 +++ b/flang/test/Semantics/enumeration-type-misc.f90 @@ -1,19 +1,16 @@ -! RUN: %python %S/test_errors.py %s %flang_fc1 -fenumeration-type +! RUN: %python %S/test_errors.py %s %flang_fc1 ! Miscellaneous enumeration-type use cases: a single-enumerator type, MERGE over ! enumeration values, and enumeration-type argument association. module enum_misc_mod - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: direction enumerator :: north, south end enumeration type - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: single enumerator :: only end enumeration type diff --git a/flang/test/Semantics/enumeration-type-mod-readback.F90 b/flang/test/Semantics/enumeration-type-mod-readback.F90 index 92cd1cf6935ec5..3823931ff4a075 100644 --- a/flang/test/Semantics/enumeration-type-mod-readback.F90 +++ b/flang/test/Semantics/enumeration-type-mod-readback.F90 @@ -1,9 +1,9 @@ !RUN: rm -rf %t && mkdir -p %t -!RUN: %flang_fc1 -fenumeration-type -fsyntax-only -DSTEP=1 -J%t %s -!RUN: %flang_fc1 -fenumeration-type -fsyntax-only -DSTEP=2 -J%t %s -!RUN: not %flang_fc1 -fenumeration-type -fsyntax-only -DSTEP=3 -J%t %s 2>&1 | FileCheck --check-prefix=CHECK-PRIVTYPE %s -!RUN: not %flang_fc1 -fenumeration-type -fsyntax-only -DSTEP=4 -J%t %s 2>&1 | FileCheck --check-prefix=CHECK-LEAK %s -!RUN: %flang_fc1 -fenumeration-type -fsyntax-only -DSTEP=5 -J%t %s +!RUN: %flang_fc1 -fsyntax-only -DSTEP=1 -J%t %s +!RUN: %flang_fc1 -fsyntax-only -DSTEP=2 -J%t %s +!RUN: not %flang_fc1 -fsyntax-only -DSTEP=3 -J%t %s 2>&1 | FileCheck --check-prefix=CHECK-PRIVTYPE %s +!RUN: not %flang_fc1 -fsyntax-only -DSTEP=4 -J%t %s 2>&1 | FileCheck --check-prefix=CHECK-LEAK %s +!RUN: %flang_fc1 -fsyntax-only -DSTEP=5 -J%t %s ! Enumerator accessibility must survive being written to a module file and read ! back: each using unit below is compiled in a SEPARATE invocation that reloads diff --git a/flang/test/Semantics/enumeration-type-mod.f90 b/flang/test/Semantics/enumeration-type-mod.f90 index 7773a185e888db..ae8d6d30be259b 100644 --- a/flang/test/Semantics/enumeration-type-mod.f90 +++ b/flang/test/Semantics/enumeration-type-mod.f90 @@ -1,4 +1,4 @@ -! RUN: %python %S/test_modfile.py %s %flang_fc1 -fenumeration-type +! RUN: %python %S/test_modfile.py %s %flang_fc1 ! Check correct modfile generation for enumeration types. ! Basic enumeration type diff --git a/flang/test/Semantics/enumeration-type-relational.f90 b/flang/test/Semantics/enumeration-type-relational.f90 index abaa237bcedd3b..fe76aaf98f5362 100644 --- a/flang/test/Semantics/enumeration-type-relational.f90 +++ b/flang/test/Semantics/enumeration-type-relational.f90 @@ -1,18 +1,15 @@ -! RUN: %python %S/test_errors.py %s %flang_fc1 -fenumeration-type +! RUN: %python %S/test_errors.py %s %flang_fc1 ! Test relational operators and SELECT CASE for enumeration types (F2023 7.6.2) module enum_mod - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: color enumerator :: red, green, blue end enumeration type - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: direction enumerator :: north, south, east, west end enumeration type - !WARNING: ENUMERATION TYPE support is incomplete and should be enabled only for testing enumeration type :: w_value enumerator :: w1, w2, w3, w4, w5 end enumeration type >From 51481e0dfc7f3e088632b560335873c0382295b2 Mon Sep 17 00:00:00 2001 From: Kevin Wyatt <[email protected]> Date: Tue, 13 Oct 2026 15:02:35 -0500 Subject: [PATCH 2/3] Added 'G' extension and additional type check test. --- flang/docs/Extensions.md | 5 ++++ flang/test/Lower/enumeration-type.f90 | 39 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 958bf109c4632c..6edc40bf996771 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -659,6 +659,11 @@ The following extensions are not classified as `SIMPLE`: `CHDIR`, `DSECNDS`, `ET Use `-Wrelaxed-c-loc-checks` (alongside `-frelaxed-c-loc-checks`) to enable a diagnostic warning for affected call sites. [-frelaxed-c-loc-checks] +* In formatted I/O, an item of enumeration type may correspond to a `G` + edit descriptor, which is processed like an `I` edit descriptor (the + value written or read is the ordinal position). F2023 12.6.3 permits + only the `I`, `B`, `O`, and `Z` edit descriptors for enumeration type + items. No diagnostic is issued. ### Extensions and legacy features deliberately not supported diff --git a/flang/test/Lower/enumeration-type.f90 b/flang/test/Lower/enumeration-type.f90 index dea023cb85acfc..299320d106604c 100644 --- a/flang/test/Lower/enumeration-type.f90 +++ b/flang/test/Lower/enumeration-type.f90 @@ -528,6 +528,45 @@ subroutine test_allocate_color() allocate(color :: x) end subroutine +! SAME_TYPE_AS and EXTENDS_TYPE_OF are processor dependent when neither dynamic +! type is extensible. An enumeration value passed to CLASS(*) carries its own +! type descriptor, so the runtime sees (green, 7) as different types (F) and +! (green, blue) as the same type (T). + +! CHECK-LABEL: func.func @_QPtest_same_type_as( +subroutine test_same_type_as(a, b, same, extends) + class(*), intent(in) :: a, b + logical, intent(out) :: same, extends + ! CHECK: fir.call @_FortranASameTypeAs( + same = same_type_as(a, b) + ! CHECK: fir.call @_FortranAExtendsTypeOf( + extends = extends_type_of(a, b) +end subroutine + +! CHECK-LABEL: func.func @_QPtest_same_type_as_args() +subroutine test_same_type_as_args() + use enum_mod + interface + subroutine test_same_type_as(a, b, same, extends) + class(*), intent(in) :: a, b + logical, intent(out) :: same, extends + end subroutine + end interface + logical :: same, extends + ! CHECK: %[[G1:.*]] = fir.embox %{{.*}} : (!fir.ref<!fir.type<_QMenum_modTcolor{__ordinal:i32}>>) -> !fir.box<!fir.type<_QMenum_modTcolor{__ordinal:i32}>> + ! CHECK: %[[G1C:.*]] = fir.convert %[[G1]] : (!fir.box<!fir.type<_QMenum_modTcolor{__ordinal:i32}>>) -> !fir.class<none> + ! CHECK: %[[I:.*]] = fir.embox %{{.*}} : (!fir.ref<i32>) -> !fir.box<i32> + ! CHECK: %[[IC:.*]] = fir.rebox %[[I]] : (!fir.box<i32>) -> !fir.class<none> + ! CHECK: fir.call @_QPtest_same_type_as(%[[G1C]], %[[IC]], %{{.*}}, %{{.*}}) + call test_same_type_as(green, 7, same, extends) + ! CHECK: %[[G2:.*]] = fir.embox %{{.*}} : (!fir.ref<!fir.type<_QMenum_modTcolor{__ordinal:i32}>>) -> !fir.box<!fir.type<_QMenum_modTcolor{__ordinal:i32}>> + ! CHECK: %[[G2C:.*]] = fir.convert %[[G2]] : (!fir.box<!fir.type<_QMenum_modTcolor{__ordinal:i32}>>) -> !fir.class<none> + ! CHECK: %[[B:.*]] = fir.embox %{{.*}} : (!fir.ref<!fir.type<_QMenum_modTcolor{__ordinal:i32}>>) -> !fir.box<!fir.type<_QMenum_modTcolor{__ordinal:i32}>> + ! CHECK: %[[BC:.*]] = fir.convert %[[B]] : (!fir.box<!fir.type<_QMenum_modTcolor{__ordinal:i32}>>) -> !fir.class<none> + ! CHECK: fir.call @_QPtest_same_type_as(%[[G2C]], %[[BC]], %{{.*}}, %{{.*}}) + call test_same_type_as(green, blue, same, extends) +end subroutine + ! ----------------------------------------------------------------------------- ! Verify the enumeration globals ! ----------------------------------------------------------------------------- >From 279d7f77ef235d41605d608ccadf00c31eb63f87 Mon Sep 17 00:00:00 2001 From: Kevin Wyatt <[email protected]> Date: Mon, 19 Oct 2026 15:10:42 -0500 Subject: [PATCH 3/3] Address review feedback on enabling ENUMERATION TYPE - Enumeration types are not derived types (F2023 7.6.2), so IsExtensibleType() now returns false for them. As a result, CLASS(enum), CLASSOF(enum) and CLASS IS (enum) are rejected. - EXTENDS(enum) is rejected while the type is being resolved, so no parent component is created and later uses of the extended type don't produce misleading errors. - TYPE IS (enum) is still allowed with an unlimited polymorphic selector and is rejected otherwise. - Pointer assignment from a CLASS(*) target to an enumeration pointer is still rejected (C1017). - A defined I/O procedure whose dtv is an enumeration type is now reported as not having a derived type. - A type parameter list on an enumeration type, as in type(state(1)), is now an error instead of being silently dropped. - Removed the unused LanguageFeature::EnumerationType, along with -Wenumeration-type. - Release notes now cover the removed -f[no-]enumeration-type options, the NEXT/PREVIOUS name clash, and the known limitations. - Extensions.md: moved the G editing entry to the default extensions and added a note that CLASSOF requires an extensible type. - FortranStandardsSupport.md now says that named interoperable enums aren't supported. - New tests: enumeration-type-extensible.f90, a type parameter section in enumeration-type-declarations.f90, and module round-trip steps in enumeration-type-mod-readback.F90. - Fixed a stale comment in enumeration-type-intrinsics-nonenum.f90. --- clang/lib/Driver/ToolChains/Flang.cpp | 18 ++-- flang/docs/Extensions.md | 20 ++-- flang/docs/FortranStandardsSupport.md | 2 +- flang/docs/ReleaseNotes.md | 9 ++ .../include/flang/Support/Fortran-features.h | 2 +- flang/lib/Evaluate/tools.cpp | 4 +- flang/lib/Semantics/check-declarations.cpp | 4 +- flang/lib/Semantics/check-select-type.cpp | 15 ++- flang/lib/Semantics/pointer-assignment.cpp | 5 +- flang/lib/Semantics/resolve-names.cpp | 34 ++++--- .../enumeration-type-declarations.f90 | 31 ++++++ .../Semantics/enumeration-type-extensible.f90 | 94 +++++++++++++++++++ .../enumeration-type-intrinsics-nonenum.f90 | 6 +- .../enumeration-type-mod-readback.F90 | 47 ++++++++++ 14 files changed, 257 insertions(+), 34 deletions(-) create mode 100644 flang/test/Semantics/enumeration-type-extensible.f90 diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index f2eb0173bedb1b..ba51adc06a5637 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -228,12 +228,18 @@ void Flang::addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA, const auto &TC = getToolChain(); const Driver &D = TC.getDriver(); Args.addAllArgs(CmdArgs, - {options::OPT_module_dir, options::OPT_fdebug_module_writer, - options::OPT_fintrinsic_modules_path, options::OPT_pedantic, - options::OPT_std_EQ, options::OPT_W_Joined, - options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ, - options::OPT_funderscoring, options::OPT_fno_underscoring, - options::OPT_funsigned, options::OPT_fno_unsigned, + {options::OPT_module_dir, + options::OPT_fdebug_module_writer, + options::OPT_fintrinsic_modules_path, + options::OPT_pedantic, + options::OPT_std_EQ, + options::OPT_W_Joined, + options::OPT_fconvert_EQ, + options::OPT_fpass_plugin_EQ, + options::OPT_funderscoring, + options::OPT_fno_underscoring, + options::OPT_funsigned, + options::OPT_fno_unsigned, options::OPT_fout_of_bounds_subscripts, options::OPT_fno_out_of_bounds_subscripts, options::OPT_fopenacc_default_none_scalars_strict, diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 6edc40bf996771..f822220e4d4b8a 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -596,7 +596,12 @@ end program * When the argument to intrinsic `ALLOCATED(p)` is actually a pointer rather than an allocatable, it is interpreted as `ASSOCIATED(p)` with a stern warning. - +* In formatted I/O, an item of enumeration type may correspond to a `G` + edit descriptor, which is processed like an `I` edit descriptor (the + value written or read is the ordinal position). F2023 12.6.3 permits + only the `I`, `B`, `O`, and `Z` edit descriptors for enumeration type + items. No diagnostic is issued. + ### `SIMPLE` classification of extensions The following extensions are `SIMPLE`: `IARGC`, `INT2`, `INT8`, `INT_PTR_KIND`, `ISNAN`, @@ -659,11 +664,6 @@ The following extensions are not classified as `SIMPLE`: `CHDIR`, `DSECNDS`, `ET Use `-Wrelaxed-c-loc-checks` (alongside `-frelaxed-c-loc-checks`) to enable a diagnostic warning for affected call sites. [-frelaxed-c-loc-checks] -* In formatted I/O, an item of enumeration type may correspond to a `G` - edit descriptor, which is processed like an `I` edit descriptor (the - value written or read is the ordinal position). F2023 12.6.3 permits - only the `I`, `B`, `O`, and `Z` edit descriptors for enumeration type - items. No diagnostic is issued. ### Extensions and legacy features deliberately not supported @@ -760,6 +760,14 @@ The following extensions are not classified as `SIMPLE`: `CHDIR`, `DSECNDS`, `ET error. This can be a temporary flang limitation while enumeration-type support is incomplete, not a standard requirement. +* F2023 C712 prohibits only an assumed-type or intrinsic-type data-ref + in a `CLASSOF` type specifier, so it does not exclude a data-ref of a + non-extensible type, such as a `SEQUENCE` or `BIND(C)` derived type or + an enumeration type. A polymorphic entity of such a type could never + have a dynamic type other than its declared type, and C705 prohibits + the equivalent `CLASS` type specifier. Flang requires the data-ref of + `CLASSOF` to be of an extensible type and reports an error otherwise. + ## Standard features that might as well not be * Flang supports designators with constant expressions, properly diff --git a/flang/docs/FortranStandardsSupport.md b/flang/docs/FortranStandardsSupport.md index ed53afeab8762d..762d62da06427e 100644 --- a/flang/docs/FortranStandardsSupport.md +++ b/flang/docs/FortranStandardsSupport.md @@ -53,7 +53,7 @@ status of all important Fortran 2023 features. The table entries are based on th | Using integer arrays to specify rank and bound of an array | N | | | Using an integer constant to specify rank | Y | | | Reduction specifier for do concurrent | P | | -| Enumerations | P | New non-interoperable ENUMERATION TYPE supported, interoperable enum types not supported | +| Enumerations | P | New non-interoperable ENUMERATION TYPE supported, named interoperable enum types not yet supported | ## Fortran 2018 All features except those listed in the following table are supported. Almost all of the unsupported features are related to diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md index 447f19ebd3f5b4..05eb399225818e 100644 --- a/flang/docs/ReleaseNotes.md +++ b/flang/docs/ReleaseNotes.md @@ -180,6 +180,15 @@ page](https://llvm.org/releases/). - the `INT` intrinsic applied to an enumeration value, and the `HUGE`, `NEXT` and `PREVIOUS` intrinsics; - formatted I/O using the `I`, `B`, `O` and `Z` edit descriptors. + Known Limitations: + - unformatted I/O of enumeration types is rejected (issue 231638); + - formatted input is not range-checked (231636); + - NEXT/PREVIOUS with STAT= inside FORALL is not yet implemented (229873); + - WHERE with a derived-type vector-subscript gather fails to verify (230617). + Side effects: + - `-fenumeration-type` and `-fno-enumeration-type` have been removed; + - NEXT and PREVIOUS are new intrinsic functions, name re-use requires EXTERNAL + declaration or an explicit interface. ## Build System Changes diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h index 587221ba5dd6d6..5fe92201c7b5ec 100644 --- a/flang/include/flang/Support/Fortran-features.h +++ b/flang/include/flang/Support/Fortran-features.h @@ -61,7 +61,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines, MultipleProgramUnitsOnSameLine, AllocatedForAssociated, OpenMPThreadprivateEquivalence, RelaxedCLocChecks, CudaPinned, CUDAImplicitDataAttrSpelling, OpenAccDefaultNoneScalarsStrict, - OpenACCMultipleNamesInRoutine, EnumerationType, CUDAInit, + OpenACCMultipleNamesInRoutine, CUDAInit, PreferIntrinsicModuleUseAssociation, MultipleCommonBlockInit, OutOfBoundsSubscripts, ImplicitModulePrefix) diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index a27ce955ebd68b..b06bca4930c103 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -2982,7 +2982,9 @@ bool IsLenTypeParameter(const Symbol &symbol) { bool IsExtensibleType(const DerivedTypeSpec *derived) { return !IsSequenceOrBindCType(derived) && !IsIsoCType(derived) && - !(derived && derived->IsVectorType()); + !(derived && derived->IsVectorType()) && + !(derived && + derived->typeSymbol().get<DerivedTypeDetails>().isEnumerationType()); } bool IsSequenceOrBindCType(const DerivedTypeSpec *derived) { diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 2abefd381850ad..2a6cbda3c7c747 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -3710,7 +3710,9 @@ void CheckHelper::CheckAlreadySeenDefinedIo(const DerivedTypeSpec &derivedType, void CheckHelper::CheckDioDummyIsDerived(const Symbol &proc, const Symbol &arg, common::DefinedIo ioKind, const Symbol &generic) { if (const DeclTypeSpec *type{arg.GetType()}) { - if (const DerivedTypeSpec *derivedType{type->AsDerived()}) { + // An enumeration type is not a derived type (F2023 R1221). + if (const DerivedTypeSpec *derivedType{type->AsDerived()}; + derivedType && !IsEnumerationType(derivedType->typeSymbol())) { if (derivedType->IsVectorType()) { messages_.Say(arg.name(), "Dummy argument '%s' of a defined input/output procedure must not be a vector type"_err_en_US, diff --git a/flang/lib/Semantics/check-select-type.cpp b/flang/lib/Semantics/check-select-type.cpp index 406d48d7961186..2b90f9d77291ab 100644 --- a/flang/lib/Semantics/check-select-type.cpp +++ b/flang/lib/Semantics/check-select-type.cpp @@ -98,8 +98,16 @@ class TypeCaseValues { "LEN type parameter as assumed"_err_en_US); typeSpecRetVal = false; } + } else if (const DerivedTypeSpec *derived{spec->AsDerived()}; + IsEnumerationType(derived->typeSymbol())) { + // An enumeration type extends nothing (F2023 C1167). + typeSpecRetVal = true; + if (!selectorType_.IsUnlimitedPolymorphic()) { + context_.Say(stmt.source, + "If selector is not unlimited polymorphic, an enumeration type specification must not be specified in the type guard statement"_err_en_US); + typeSpecRetVal = false; + } } else { - const DerivedTypeSpec *derived{spec->AsDerived()}; typeSpecRetVal = PassesDerivedTypeChecks( *derived, parser::FindSourceLocation(typeSpec)); } @@ -108,6 +116,11 @@ class TypeCaseValues { [&](const parser::DerivedTypeSpec &x) { CHECK(x.derivedTypeSpec); const semantics::DerivedTypeSpec *derived{x.derivedTypeSpec}; + if (IsEnumerationType(derived->typeSymbol())) { // R1156 + context_.Say(parser::FindSourceLocation(x), + "An enumeration type may not appear in a CLASS IS type guard statement"_err_en_US); + return false; + } return PassesDerivedTypeChecks( *derived, parser::FindSourceLocation(x)); }, diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp index 7425f831b51b48..55c3d7fd320ae7 100644 --- a/flang/lib/Semantics/pointer-assignment.cpp +++ b/flang/lib/Semantics/pointer-assignment.cpp @@ -466,7 +466,10 @@ bool PointerAssignmentChecker::LhsOkForUnlimitedPoly() const { } else if (type.IsUnlimitedPolymorphic()) { return true; } else { - return !IsExtensibleType(&type.GetDerivedTypeSpec()); + // F2023 C1017 does not permit enumeration types here. + const DerivedTypeSpec &derived{type.GetDerivedTypeSpec()}; + return !IsExtensibleType(&derived) && + !IsEnumerationType(derived.typeSymbol()); } } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index d5d5356288b5a0..1f4c37fed13a46 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -7260,9 +7260,23 @@ void DeclarationVisitor::Post(const parser::DerivedTypeSpec &x) { if (!spec) { return; } + const auto &typeParamSpecs{std::get<std::list<parser::TypeParamSpec>>(x.t)}; + // Enumeration types are a special case of derived types and are handled + // differently. + if (spec->typeSymbol().get<DerivedTypeDetails>().isEnumerationType()) { + if (!typeParamSpecs.empty()) { // F2023 7.6.2 + Say(typeName.source, + "Enumeration type '%s' has no type parameters"_err_en_US); + } + spec->set_category(DerivedTypeSpec::Category::EnumerationType); + DeclTypeSpec &type{currScope().MakeDerivedType( + GetDeclTypeSpecCategory(), std::move(*spec))}; + SetDeclTypeSpec(type); + x.derivedTypeSpec = &GetDeclTypeSpec()->derivedTypeSpec(); + return; + } bool seenAnyName{false}; - for (const auto &typeParamSpec : - std::get<std::list<parser::TypeParamSpec>>(x.t)) { + for (const auto &typeParamSpec : typeParamSpecs) { const auto &optKeyword{ std::get<std::optional<parser::Keyword>>(typeParamSpec.t)}; std::optional<SourceName> name; @@ -7292,17 +7306,6 @@ void DeclarationVisitor::Post(const parser::DerivedTypeSpec &x) { // in the current scope, this spec will be moved into that collection. const auto &dtDetails{spec->typeSymbol().get<DerivedTypeDetails>()}; auto category{GetDeclTypeSpecCategory()}; - - // Enumeration types are a special case of derived types and are handled - // differently. - if (dtDetails.isEnumerationType()) { - spec->set_category(DerivedTypeSpec::Category::EnumerationType); - DeclTypeSpec &type{currScope().MakeDerivedType(category, std::move(*spec))}; - SetDeclTypeSpec(type); - x.derivedTypeSpec = &GetDeclTypeSpec()->derivedTypeSpec(); - return; - } - if (dtDetails.isForwardReferenced()) { DeclTypeSpec &type{currScope().MakeDerivedType(category, std::move(*spec))}; SetDeclTypeSpec(type); @@ -8765,6 +8768,11 @@ std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveExtendsType( Say(extendsName->source, "Derived type '%s' cannot extend itself"_err_en_US); } else if (auto dtSpec{ResolveDerivedType(*extendsName)}) { + // Reject now so that no parent component of enumeration type is made. + if (IsEnumerationType(dtSpec->typeSymbol())) { + Say(extendsName->source, "The parent type is not extensible"_err_en_US); + return std::nullopt; + } if (!dtSpec->IsForwardReferenced()) { return dtSpec; } diff --git a/flang/test/Semantics/enumeration-type-declarations.f90 b/flang/test/Semantics/enumeration-type-declarations.f90 index 23e0f14f63d6e4..9fb5c0d365d04c 100644 --- a/flang/test/Semantics/enumeration-type-declarations.f90 +++ b/flang/test/Semantics/enumeration-type-declarations.f90 @@ -156,3 +156,34 @@ subroutine test_assignment_and_arithmetic() !ERROR: Operands of + must be numeric; have TYPE(color) and TYPE(color) c = red + green end subroutine + +! An enumeration type has no type parameters (F2023 7.6.2), so no type-spec may +! give it a type-param-spec-list. An enumeration constructor is still valid. +subroutine test_type_parameters(u) + enumeration type :: state + enumerator :: off, on + end enumeration type + type :: holder + !ERROR: Enumeration type 'state' has no type parameters + type(state(1)) :: comp + end type + class(*), intent(in) :: u + !ERROR: Enumeration type 'state' has no type parameters + type(state(1)) :: a + !ERROR: Enumeration type 'state' has no type parameters + type(state(k=2)) :: b + !ERROR: Enumeration type 'state' has no type parameters + type(state(:)), allocatable :: c + class(*), allocatable :: d + + a = state(1) + b = off + !ERROR: Enumeration type 'state' has no type parameters + allocate(state(1) :: d) + deallocate(d) + allocate(d, source=state(2)) + select type (u) + !ERROR: Enumeration type 'state' has no type parameters + type is (state(1)) + end select +end subroutine diff --git a/flang/test/Semantics/enumeration-type-extensible.f90 b/flang/test/Semantics/enumeration-type-extensible.f90 new file mode 100644 index 00000000000000..bbcae08188f14c --- /dev/null +++ b/flang/test/Semantics/enumeration-type-extensible.f90 @@ -0,0 +1,94 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! An enumeration type is not a derived type (F2023 7.6.2), so it is not an +! extensible type (F2023 7.5.7.1). + +module enum_ext_mod + enumeration type :: color + enumerator :: red, green + end enumeration type + + type :: base + end type + + !ERROR: The parent type is not extensible + type, extends(color) :: child + integer :: n = 0 + end type + + ! The rejected EXTENDS must not leave a hidden parent component behind. + type, extends(child) :: grandchild + integer :: k + end type + + !ERROR: Non-extensible derived type 'color' may not be used with CLASS keyword + class(color), allocatable :: x + +contains + subroutine use_child() + type(child) :: c + type(grandchild) :: g + c = child(n=1) + c%n = c%n + 1 + g = grandchild(k=3) + end subroutine + + subroutine classof_enum(e) + type(color), intent(in) :: e + !ERROR: CLASSOF requires a data-ref of extensible type + classof(e), allocatable :: f + end subroutine + + subroutine type_is_ok(u) + class(*), intent(in) :: u + select type (u) + type is (color) + end select + end subroutine + + subroutine class_is_enum(u) + class(*), intent(in) :: u + select type (u) + !ERROR: An enumeration type may not appear in a CLASS IS type guard statement + class is (color) + end select + end subroutine + + subroutine type_is_not_unlimited(b) + class(base), intent(in) :: b + select type (b) + !ERROR: If selector is not unlimited polymorphic, an enumeration type specification must not be specified in the type guard statement + type is (color) + end select + end subroutine + + subroutine pointer_to_unlimited(q) + class(*), pointer, intent(in) :: q + type(color), pointer :: p + !ERROR: Pointer type must be unlimited polymorphic or non-extensible derived type when target is unlimited polymorphic + p => q + end subroutine + + subroutine same_type(a, b) + type(color), intent(in) :: a, b + !ERROR: Actual argument for 'a=' has type 'color', but was expected to be an extensible or unlimited polymorphic type + print *, same_type_as(a, b) + end subroutine +end module + +module enum_ext_dio_mod + enumeration type :: color + enumerator :: red, green + end enumeration type + interface write(formatted) + subroutine wf(dtv, unit, iotype, vlist, iostat, iomsg) + import color + !ERROR: Dummy argument 'dtv' of a defined input/output procedure must have a derived type + type(color), intent(in) :: dtv + integer, intent(in) :: unit + character(*), intent(in) :: iotype + integer, intent(in) :: vlist(:) + integer, intent(out) :: iostat + character(*), intent(inout) :: iomsg + end subroutine + end interface +end module diff --git a/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 b/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 index 087d0d4db5715e..44bce74daa1baa 100644 --- a/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 +++ b/flang/test/Semantics/enumeration-type-intrinsics-nonenum.f90 @@ -1,7 +1,7 @@ ! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s -! With the enumeration-type feature enabled, NEXT and PREVIOUS require an -! argument of enumeration type. A non-enumeration argument must produce a -! proper diagnostic rather than an internal compiler error. +! NEXT and PREVIOUS require an argument of enumeration type. A non-enumeration +! argument must produce a proper diagnostic rather than an internal compiler +! error. subroutine test_next_nonenum() integer :: i, j diff --git a/flang/test/Semantics/enumeration-type-mod-readback.F90 b/flang/test/Semantics/enumeration-type-mod-readback.F90 index 3823931ff4a075..c9402b8d5c3b60 100644 --- a/flang/test/Semantics/enumeration-type-mod-readback.F90 +++ b/flang/test/Semantics/enumeration-type-mod-readback.F90 @@ -4,6 +4,9 @@ !RUN: not %flang_fc1 -fsyntax-only -DSTEP=3 -J%t %s 2>&1 | FileCheck --check-prefix=CHECK-PRIVTYPE %s !RUN: not %flang_fc1 -fsyntax-only -DSTEP=4 -J%t %s 2>&1 | FileCheck --check-prefix=CHECK-LEAK %s !RUN: %flang_fc1 -fsyntax-only -DSTEP=5 -J%t %s +!RUN: %flang_fc1 -fsyntax-only -DSTEP=6 -J%t %s +!RUN: %flang_fc1 -fsyntax-only -DSTEP=7 -J%t %s +!RUN: %flang_fc1 -fsyntax-only -DSTEP=8 -J%t %s ! Enumerator accessibility must survive being written to a module file and read ! back: each using unit below is compiled in a SEPARATE invocation that reloads @@ -80,3 +83,47 @@ subroutine use_renamed use m7d, only: v end subroutine #endif + +#if STEP == 6 +! Producer for the declaration forms of an enumeration type that reach a +! module file: TYPE() dummies, TYPEOF() of an enumeration entity, a component +! with an enumerator default, and TYPE IS in SELECT TYPE. +module m8 + enumeration type :: state + enumerator :: off, on + end enumeration type + type :: holder + type(state) :: s = on + end type +contains + subroutine show(x) + type(state), intent(in) :: x + end subroutine + subroutine show_typeof(x, y) + type(state), intent(in) :: x + typeof(x), intent(in) :: y + end subroutine + subroutine show_poly(u) + class(*), intent(in) :: u + select type (u) + type is (state) + end select + end subroutine +end module +#endif + +#if STEP == 7 +subroutine use_enumerator_only + use m8, only: on +end subroutine +#endif + +#if STEP == 8 +subroutine use_all + use m8 + type(holder) :: h + call show(on) + call show_typeof(off, h%s) + call show_poly(on) +end subroutine +#endif _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
