10 Modules [module]

10.7 Reachability [module.reach]

A translation unit U is necessarily reachable from a point P if U is a module interface unit on which the translation unit containing P has an interface dependency, or the translation unit containing P imports U, in either case prior to P ([module.import]).
[Note
:
While module interface units are reachable even when they are only transitively imported via a non-exported import declaration, namespace-scope names from such module interface units are not visible to name lookup ([basic.scope.namespace]).
— end note
]
All translation units that are necessarily reachable are reachable.
It is unspecified whether additional translation units on which the point within the program has an interface dependency are considered reachable, and under what circumstances.100
[Note
:
It is advisable to avoid depending on the reachability of any additional translation units in programs intending to be portable.
— end note
]
A declaration D is reachable if, for any point P in the instantiation context ([module.context]),
[Note
:
Whether a declaration is exported has no bearing on whether it is reachable.
— end note
]
The accumulated properties of all reachable declarations of an entity within a context determine the behavior of the entity within that context.
[Note
:
These reachable semantic properties include type completeness, type definitions, initializers, default arguments of functions or template declarations, attributes, visibility of class or enumeration member names to ordinary lookup, etc.
Since default arguments are evaluated in the context of the call expression, the reachable semantic properties of the corresponding parameter types apply in that context.
[Example
:

Translation unit #1:

export module M:A;
export struct B;

Translation unit #2:

module M:B;
struct B {
  operator int();
};

Translation unit #3:

module M:C;
import :A;
B b1;                           // error: no reachable definition of struct B

Translation unit #4:

export module M;
export import :A;
import :B;
B b2;
export void f(B b = B());

Translation unit #5:

module X;
import M;
B b3;                           // error: no reachable definition of struct B
void g() { f(); }               // error: no reachable definition of struct B
— end example
]
— end note
]
[Note
:
An entity can have reachable declarations even if it is not visible to name lookup.
— end note
]
[Example
:

Translation unit #1:

export module A;
struct X {};
export using Y = X;

Translation unit #2:

module B;
import A;
Y y;                // OK, definition of X is reachable
X x;                // error: X not visible to unqualified lookup
— end example
]
Implementations are therefore not required to prevent the semantic effects of additional translation units involved in the compilation from being observed.