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.

Reply via email to