https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122908
--- Comment #6 from Nathaniel Shead <nshead at gcc dot gnu.org> --- (In reply to Bernardo Negri from comment #5) > I don't quite understand what you mean by "recursively finds": I admit I do > not know much about the C++ standard (or C++ in general), but from the links > you sent, what I could interpret is: > > 1. internalLink has internal linkage, which means it is TU-local > 2. Class::testFn (the template) names internalLink in its body, which means > testFn is an exposure. Exposures in the global module fragment are allowed, > however. What makes you say that? Within a module interface unit, only in a private module fragment is an exposure allowed, by https://eel.is/c++draft/basic.link#17. > 3. friendFn<int> (the instantiation of the template in the module purview) > names Class. > > However, I'd argue that because neither Class nor Class::testFn are TU-local > because they are not marked static and do not have internal linkage. Correct. > Therefore, I don't see what is the problem with friendFn<int> naming Class. > Exposures only happen when something in module purview name TU-local > entities outside the function body (and a few other exceptions), and I don't > think either Class or testFn are TU-local. I simply don't see where the > standard says being TU-local is a transitive property. > No, an exposure in the GMF is still an exposure. This is deprecated in normal headers but ill-formed in a module interface unit. To see why, consider // a.cpp module; static int x = 0; inline int foo() { return ++x; } export module M; export using ::foo; export int bar() { return foo(); } // b.cpp import M; import std; int main() { std::cout << foo() << ':'; std::cout << bar() << ':'; std::cout << foo() << '\n'; } If we assume that the exposure of 'x' is not, in fact, an exposure, because it's only referenced by non-purview entities, then this should be legal. But 'x' is only referenceable from 'a.cpp'; the definition of 'foo()' expanded into 'b.cpp' cannot possibly name it (since it's in a different TU), and so the perhaps expected result of '1:2:3' is not possible. In fact, strictly by the standard, GCC is being _permissive_ here; we only forbid exposures that might actually cause issues, and ignore discarded entities (https://eel.is/c++draft/module.global.frag#4), but the standard doesn't actually care about whether an entity is discarded as to whether it's an exposure.
