https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119983
--- Comment #5 from Nathaniel Shead <nshead at gcc dot gnu.org> ---
(In reply to gap mman from comment #4)
> (In reply to Nathaniel Shead from comment #2)
> > Thanks for the report! As Andrew noted, the ICE is fixed for 14.3 by
> > r14-10825-g01d3a974fe3474c37cd52b595c29dddafad954dc.
> >
> > The code is ill-formed, however:
> >
> > export module M;
> > struct {} instance;
> >
> > is not legal in a module interface, because of
> > https://eel.is/c++draft/basic.link#15.2 (the type of the unnamed struct is
> > TU-local), https://eel.is/c++draft/basic.link#14 (the declaration of the
> > variable exposes the TU-local type), and
> > https://eel.is/c++draft/basic.link#17 (the variable is not TU-local, so this
> > is ill-formed).
> >
> > We don't check this in GCC 14 (so 14.3 will accept this code), but for GCC
> > 15 we properly implement https://wg21.link/p1815 and so error in this case:
> >
> > <source>:2:11: error: 'instance' exposes TU-local entity 'struct<unnamed>'
> > 2 | struct {} instance;
> > | ^~~~~~~~
> > <source>:2:8: note: '<unnamed struct>' has no name and is not defined within
> > a class, function, or initializer
> > 2 | struct {} instance;
> > | ^
>
> Thank you for answering. I'm only using this variable within the TU.
>
> Am I correct in understanding the problem as the following: The instance,
> even though not visible outside of the module,
This is the issue: 'instance' *would* be visible outside of this TU, such as in
e.g. a module implementation unit, but the unnamed struct would not be, which
would cause issues.
> doesn't have internal linkage
> but names a TU local entity (the unnamed type), which causes exposure and is
> therefore ill formed. To fix, either name the type to make it not TU local
> or make the variable have internal linkage (adding `static` as in the
> example).
And yes, by adding 'static', or wrapping in an unnamed namespace, 'instance'
would no longer be accessible in other TUs, so there's no reason to complain
anymore.
>
> As for a fix in current GCC14.2 I'm using, my only bet is naming this type?
Naming the type is probably the most straight-forward workaround, yes.
> I'm actually declaring it `constexpr`(which, unfortunately, is explicitly
> defined as exposure)
> ```
> constexpr struct
> {
> void aRandomFunc()
> {
>
> }
> } variableWithNamelessType{};
> ```
>
> I also noticed something I didn't quite understand in GCC14.2. If I declare
> this as `static constexpr` and use it in an exported function, then I'm
> fine; but if the function is templatized, then I get "references internal
> linkage entity". https://godbolt.org/z/3rKn3v7rq In GCC 15 both works, which
> I believe should be the correct behavior?
Within a non-inline templated function it's actually still problematic, but
only if an importer attempts to instantiate it; this is the behaviour mandated
by the standard. You can experiment with '-Wtemplate-names-tu-local' (also
enabled by '-Wextra') to see more.
For a non-inline non-template function it's OK because we don't emit the bodies
of such functions, so the entity is not exposed.