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.

Reply via email to