diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -1356,10 +1356,8 @@ }; // R828 access-id -> access-name | generic-spec -struct AccessId { - UNION_CLASS_BOILERPLATE(AccessId); - std::variant> u; -}; +// "access-name" is ambiguous with "generic-spec", so that's what's parsed +WRAPPER_CLASS(AccessId, common::Indirection); // R827 access-stmt -> access-spec [[::] access-id-list] struct AccessStmt { diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -758,8 +758,8 @@ Parser{})))) // R828 access-id -> access-name | generic-spec -TYPE_PARSER(construct(indirect(genericSpec)) || - construct(name)) // initially ambiguous with genericSpec +// "access-name" is ambiguous with "generic-spec" +TYPE_PARSER(construct(indirect(genericSpec))) // R829 allocatable-stmt -> ALLOCATABLE [::] allocatable-decl-list TYPE_PARSER(construct("ALLOCATABLE" >> maybe("::"_tok) >> diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -7102,24 +7102,12 @@ defaultAccess_ = accessAttr; } else { for (const auto &accessId : accessIds) { - common::visit( - common::visitors{ - [=](const parser::Name &y) { - Resolve(y, SetAccess(y.source, accessAttr)); - }, - [=](const Indirection &y) { - auto info{GenericSpecInfo{y.value()}}; - const auto &symbolName{info.symbolName()}; - if (auto *symbol{FindInScope(symbolName)}) { - info.Resolve(&SetAccess(symbolName, accessAttr, symbol)); - } else if (info.kind().IsName()) { - info.Resolve(&SetAccess(symbolName, accessAttr)); - } else { - Say(symbolName, "Generic spec '%s' not found"_err_en_US); - } - }, - }, - accessId.u); + GenericSpecInfo info{accessId.v.value()}; + auto *symbol{FindInScope(info.symbolName())}; + if (!symbol && !info.kind().IsName()) { + symbol = &MakeSymbol(info.symbolName(), Attrs{}, GenericDetails{}); + } + info.Resolve(&SetAccess(info.symbolName(), accessAttr, symbol)); } } return false; diff --git a/flang/test/Semantics/modfile51.f90 b/flang/test/Semantics/modfile51.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/modfile51.f90 @@ -0,0 +1,21 @@ +! RUN: %python %S/test_modfile.py %s %flang_fc1 +! Allow a generic spec that is not a name to be declared on an +! accessibility control statement +module m + public :: assignment(=) + public :: read(unformatted) + public :: operator(.eq.) + public :: operator(.smooth.) +end module + +!Expect: m.mod +!module m +!interface assignment(=) +!end interface +!interface read(unformatted) +!end interface +!interface operator(.eq.) +!end interface +!interface operator(.smooth.) +!end interface +!end