https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122908
Nathaniel Shead <nshead at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |nshead at gcc dot gnu.org
--- Comment #4 from Nathaniel Shead <nshead at gcc dot gnu.org> ---
So:
- 'Class::testFn' is an inline function, because it is defined in the body of
'Class' and 'Class' is not attached to a named module.
- 'modFn' is not an inline function, so its body is not checked for exposures;
this is why when 'Class' is changed to a non-template everything is fine, since
nothing in the module purview exposes it.
- But the 'Class<int>' performs an instantiation of the template within the
module purview. This instantiation pushes 'friendFn' into the module purview
(see https://eel.is/c++draft/temp.friend#2), and because it's a unique friend
function definition associated with 'Class<int>' (since it's defined in the
class body) we treat this as naming 'Class<int>', that then recursively finds
the exposing declaration 'Class::testFn'.
This last step is possibly the most dubious by standardese, but I don't see a
good way of avoiding it. We need to emit the context ('Class<int>') in the
general case to handle access and requires-clauses if 'friendFn' is a function
template, for instance, so even attempting to clear DECL_FRIEND_CONTEXT on
non-template friends here seems to just be kicking the can down the road (and
maybe there's a context where it's still necessary even that I'm not thinking
of right now).
The other approach might be to rework friend instantiations to not emit hidden
bindings for them. This is tricky to do however because it's hard to know
whether a declaration came purely from friend instantiation (e.g. if it merged
with a forward decl or an import). And irrespective of this I don't think this
is justifiable by the standard wording currently, which should apply to all
non-discarded purview entities, and doesn't say "except hidden bindings" or
whatever (https://eel.is/c++draft/basic.link#17).
--
Perhaps there's a diagnostic improvement here for GM exposures to walk up the
dep chain and find which purview declaration exposed it. We don't currently
track this information at all and it would be quite expensive to reconstruct,
but seems occasionally worthwhile for trickier cases like this. But most of
the time this seems to me it would just be a huge amount of extra noise.
I'll leave this open for the time being and maybe I'll come back to it in GCC17
timeframe for exploring the diagnostic issue, but I don't think there's an
actual bug here really.