diff --git a/source/basic.tex b/source/basic.tex index d302761565..1fe27cfb6a 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -99,7 +99,7 @@ one or more names into a translation unit or redeclare names introduced by previous declarations. If so, the -declaration specifies the interpretation and attributes of these names. +declaration specifies the interpretation and semantic properties of these names. A declaration may also have effects including: \begin{itemize} \item a static assertion\iref{dcl.dcl}, @@ -274,8 +274,9 @@ \rSec1[basic.def.odr]{One-definition rule} \pnum -No translation unit shall contain more than one definition of any -variable, function, class type, enumeration type, or template. +A variable, function, class type, enumeration type, or template +shall not be defined where a prior definition is necessarily reachable\iref{module.reach}; +no diagnostic is required if the prior declaration is in another translation unit. \pnum \indextext{expression!potentially evaluated}% @@ -470,7 +471,7 @@ the standard or a user-defined library, or (when appropriate) it is implicitly defined (see~\ref{class.default.ctor}, \ref{class.copy.ctor}, \ref{class.dtor}, and \ref{class.copy.assign}). -An inline function or variable shall be defined in every +A definition of an inline function or variable shall be reachable in every translation unit in which it is odr-used outside of a discarded statement. \begin{example} \begin{codeblock} @@ -490,7 +491,7 @@ \pnum \indextext{type!incomplete}% -Exactly one definition of a class is required in a translation unit if +A definition of a class is required to be reachable in every context in which the class is used in a way that requires the class type to be complete. \begin{example} The following complete translation unit is well-formed, even though it never defines \tcode{X}: @@ -548,9 +549,17 @@ static data member of a class template\iref{temp.static}, member function of a class template\iref{temp.mem.func}, or template specialization for which some template parameters are not -specified~(\ref{temp.spec}, \ref{temp.class.spec}) in a program provided -that each definition appears in a different translation unit, and -provided the definitions satisfy the following requirements. Given such +specified~(\ref{temp.spec}, \ref{temp.class.spec}) in a program +provided that +no prior definition is necessarily reachable\iref{module.reach} +at the point where a definition appears, and +provided the definitions satisfy the following requirements. +There shall not be more than one definition +of an entity +that is attached to a named module\iref{module.unit}; +no diagnostic is required unless a prior definition +is reachable at a point where a later definition appears. +Given such an entity named \tcode{D} defined in more than one translation unit, then \begin{itemize} @@ -985,7 +994,8 @@ \grammarterm{using-directive}\iref{namespace.udir} that nominates the member's namespace, the member's potential scope includes that portion of the potential scope of the \grammarterm{using-directive} that follows -the member's point of declaration. \begin{example} +the member's point of declaration. +\begin{example} \begin{codeblock} namespace N { @@ -1013,6 +1023,42 @@ \end{codeblock} \end{example} +\pnum +If a translation unit $Q$ is imported into a translation unit $R$\iref{module.import}, +the potential scope of a name $X$ declared with namespace scope in $Q$ +is extended to include the portion of the corresponding namespace +scope in $R$ following the first \grammarterm{module-import-declaration} +or \grammarterm{module-declaration} +in $R$ that imports $Q$ (directly or indirectly) if +\begin{itemize} +\item $X$ does not have internal linkage, and +\item $X$ is declared after the \grammarterm{module-declaration} in $Q$ (if any), and +\item either $X$ is exported or $Q$ and $R$ are part of the same module. +\end{itemize} +\begin{note} +A \grammarterm{module-import-declaration} imports both +the named translation unit(s) and +any modules named by exported +\grammarterm{module-import-declaration}{s} within them, +recursively. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module Q; +export int sq(int i) { return i*i; } +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module R; +export import Q; +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +import R; +int main() { return sq(9); } // OK: \tcode{sq} from module \tcode{Q} +\end{codeblocktu} +\end{example} +\end{note} + \pnum A namespace member can also be referred to after the \tcode{::} scope resolution operator\iref{expr.prim.id.qual} applied to the name of its @@ -1251,8 +1297,10 @@ are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function overload resolution (if applicable) and access -checking have succeeded are the attributes introduced by the name's -declaration used further in expression processing\iref{expr}. +checking have succeeded +are the semantic properties introduced by the name's declaration +and its reachable\iref{module.reach} redeclarations +used further in expression processing\iref{expr}. \pnum A name ``looked up in the context of an expression'' is looked up @@ -1636,51 +1684,69 @@ \end{example} \pnum -For each argument type \tcode{T} in the function call, there is a set of -zero or more \defnx{associated namespaces}{namespace!associated} -and a set of zero or more \defnx{associated classes}{class!associated} -to be considered. The sets of namespaces and classes are -determined entirely by the types of the function arguments (and the -namespace of any template template argument). Typedef names and -\grammarterm{using-declaration}{s} used to specify the types do not -contribute to this set. The sets of namespaces and classes are -determined in the following way: +For each argument type \tcode{T} in the function call, +there is a set of zero or more +\defnx{associated namespaces}{namespace!associated} +and a set of zero or more +\defnx{associated entities}{entity!associated} +(other than namespaces) +to be considered. +The sets of namespaces and entities +are determined entirely by +the types of the function arguments +(and the namespace of any template template argument). +Typedef names and \grammarterm{using-declaration}{s} +used to specify the types +do not contribute to this set. +The sets of namespaces and entities +are determined in the following way: \begin{itemize} \item If \tcode{T} is a fundamental type, its associated sets of -namespaces and classes are both empty. - -\item If \tcode{T} is a class type (including unions), its associated -classes are: the class itself; the class of which it is a member, if -any; and its direct and indirect base classes. Its associated namespaces -are the innermost enclosing namespaces of its associated classes. -Furthermore, if \tcode{T} is a class template specialization, its -associated namespaces and classes also include: the namespaces and -classes associated with the types of the template arguments provided for -template type parameters (excluding template template parameters); the -namespaces of which any template template arguments are members; and the +namespaces and entities are both empty. + +\item If \tcode{T} is a class type (including unions), +its associated entities are: +the class itself; +the class of which it is a member, if any; +and its direct and indirect base classes. +Its associated namespaces are +the innermost enclosing namespaces of its associated entities. +Furthermore, if \tcode{T} is a class template specialization, +its associated namespaces and entities also include: +the namespaces and entities +associated with the types of the template arguments +provided for template type parameters +(excluding template template parameters); +the templates used as template template arguments; +the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template -arguments are members. \begin{note} Non-type template arguments do not -contribute to the set of associated namespaces.\end{note} +arguments are members. +\begin{note} +Non-type template arguments do not +contribute to the set of associated namespaces. +\end{note} -\item If \tcode{T} is an enumeration type, its associated namespace is -the innermost enclosing namespace of its declaration. If it is a class member, its -associated class is the member's class; else it has no associated class. +\item If \tcode{T} is an enumeration type, +its associated namespace is +the innermost enclosing namespace of its declaration, and +its associated entities are \tcode{T} +and, if it is a class member, the member's class. \item If \tcode{T} is a pointer to \tcode{U} or an array of \tcode{U}, -its associated namespaces and classes are those associated with +its associated namespaces and entities are those associated with \tcode{U}. \item If \tcode{T} is a function type, its associated namespaces and -classes are those associated with the function parameter types and those +entities are those associated with the function parameter types and those associated with the return type. \item If \tcode{T} is a pointer to a member function of a class -\tcode{X}, its associated namespaces and classes are those associated +\tcode{X}, its associated namespaces and entities are those associated with the function parameter types and return type, together with those associated with \tcode{X}. \item If \tcode{T} is a pointer to a data member of class \tcode{X}, its -associated namespaces and classes are those associated with the member +associated namespaces and entities are those associated with the member type together with those associated with \tcode{X}. \end{itemize} If an associated namespace is an inline namespace\iref{namespace.def}, its @@ -1688,12 +1754,12 @@ directly contains inline namespaces, those inline namespaces are also included in the set. In addition, if the argument is the name or address of a set of -overloaded functions and/or function templates, its associated classes +overloaded functions and/or function templates, its associated entities and namespaces are the union of those associated with each of the -members of the set, i.e., the classes and namespaces associated with its +members of the set, i.e., the entities and namespaces associated with its parameter types and return type. Additionally, if the aforementioned set of overloaded functions is named with -a \grammarterm{template-id}, its associated classes and namespaces also include +a \grammarterm{template-id}, its associated entities and namespaces also include those of its type \grammarterm{template-argument}{s} and its template \grammarterm{template-argument}{s}. @@ -1709,8 +1775,8 @@ then \placeholder{Y} is empty. Otherwise \placeholder{Y} is the set of declarations found in the namespaces associated with the argument types as described below. The set of declarations found by the lookup of the name is the -union of \placeholder{X} and \placeholder{Y}. \begin{note} The namespaces and classes -associated with the argument types can include namespaces and classes +union of \placeholder{X} and \placeholder{Y}. \begin{note} The namespaces and entities +associated with the argument types can include namespaces and entities already considered by the ordinary unqualified lookup. \end{note} \begin{example} @@ -1731,22 +1797,83 @@ \end{example} \pnum -When considering an associated namespace, the lookup is the same as the -lookup performed when the associated namespace is used as a -qualifier\iref{namespace.qual} except that: +When considering an associated namespace \tcode{N}, +the lookup is the same as the +lookup performed when \tcode{N} +is used as a qualifier\iref{namespace.qual} +except that: \begin{itemize} -\item Any \grammarterm{using-directive}{s} in the associated namespace are -ignored. +\item Any \grammarterm{using-directive}{s} in \tcode{N} are ignored. \item Any namespace-scope friend functions or friend function templates\iref{class.friend} -declared in associated classes are visible within their respective +declared in classes with reachable definitions in the set of associated entities +are visible within their respective namespaces even if they are not visible during an ordinary lookup\iref{namespace.memdef}. \item All names except those of (possibly overloaded) functions and function templates are ignored. + +\item +Any declaration \tcode{D} in \tcode{N} +that is in the interface of +a named module \tcode{M}\iref{module.interface} +is visible +if there is an associated entity attached to \tcode{M} +with the same innermost enclosing non-inline namespace as \tcode{D}. + +\item +If the lookup is for a dependent name (\ref{temp.dep}, \ref{temp.dep.candidate}), +any declaration \tcode{D} in \tcode{N} +is visible +if \tcode{D} would be visible to qualified name lookup\iref{namespace.qual} +at any point in the instantiation context\iref{module.context} of the lookup, +unless \tcode{D} is declared in another translation unit, attached to the global module, +and is either discarded\iref{module.global} or has internal linkage. \end{itemize} +\pnum +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module M; +namespace R { + export struct X {}; + export void f(X); +} +namespace S { + export void f(X, X); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module N; +import M; +export R::X make(); +namespace R { static int g(X); } +template void apply(T t, U u) { + f(t, u); + g(t); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +module Q; +import N; +namespace S { + struct Z { template operator T(); }; +} +void test() { + auto x = make(); // OK, \tcode{decltype(x)} is \tcode{R::X} in module \tcode{M} + R::f(x); // ill-formed: \tcode{R} and \tcode{R::f} are not visible here + f(x); // OK, calls \tcode{R::f} from interface of \tcode{M} + f(x, S::Z()); // ill-formed: \tcode{S::f} in module \tcode{M} not considered + // even though \tcode{S} is an associated namespace + apply(x, S::Z()); // OK, \tcode{S::f} is visible in instantiation context, and + // \tcode{R::g} is visible even though it has internal linkage +} +\end{codeblocktu} +\end{example} + \rSec2[basic.lookup.qual]{Qualified name lookup} \pnum @@ -1945,7 +2072,11 @@ For a namespace \tcode{X} and name \tcode{m}, the namespace-qualified lookup set $S(X, m)$ is defined as follows: Let $S'(X, m)$ be the set of all declarations of \tcode{m} in \tcode{X} and the inline namespace set of -\tcode{X}\iref{namespace.def}. If $S'(X, m)$ is not empty, $S(X, m)$ +\tcode{X}\iref{namespace.def} +whose potential scope\iref{basic.scope.namespace} +would include the namespace in which \tcode{m} is declared +at the location of the \grammarterm{nested-name-specifier}. +If $S'(X, m)$ is not empty, $S(X, m)$ is $S'(X, m)$; otherwise, $S(X, m)$ is the union of $S(N_i, m)$ for all namespaces $N_i$ nominated by \grammarterm{using-directive}{s} in \tcode{X} and its inline namespace set. @@ -2367,9 +2498,42 @@ \begin{bnf} \nontermdef{translation-unit}\br - \opt{declaration-seq} + \opt{top-level-declaration-seq}\br + \opt{global-module-fragment} module-declaration \opt{top-level-declaration-seq} \opt{private-module-fragment} +\end{bnf} + +\begin{bnf} +\nontermdef{private-module-fragment}\br + \terminal{module} \terminal{:} \terminal{private} \terminal{;} \opt{top-level-declaration-seq} \end{bnf} +\begin{bnf} +\nontermdef{top-level-declaration-seq}\br + top-level-declaration\br + top-level-declaration-seq top-level-declaration +\end{bnf} + +\begin{bnf} +\nontermdef{top-level-declaration}\br + module-import-declaration\br + declaration +\end{bnf} + +\pnum +A \grammarterm{private-module-fragment} shall appear only +in a primary module interface unit\iref{module.unit}. +A module unit with a \grammarterm{private-module-fragment} +shall be the only module unit of its module; +no diagnostic is required. + +\pnum +A token sequence beginning with +\opt{\tcode{export}} \tcode{module} or +\opt{\tcode{export}} \tcode{import} +and not immediately followed by \tcode{::} +is never interpreted as the \grammarterm{declaration} +of a \grammarterm{top-level-declaration}. + \pnum \indextext{linkage}% \indextext{translation unit}% @@ -2384,6 +2548,11 @@ can be referred to by names from scopes of other translation units or from other scopes of the same translation unit. +\item When a name has \defnx{module linkage}{linkage!module}, +the entity it denotes +can be referred to by names from other scopes of the same module unit\iref{module.unit} or +from scopes of other module units of that same module. + \item When a name has \indextext{linkage!internal}\defn{internal linkage}, the entity it denotes can be referred to by names from other scopes in the same translation @@ -2405,18 +2574,21 @@ \begin{itemize} \item a variable, variable template, function, or function template that is - explicitly declared \tcode{static}; or, + explicitly declared \tcode{static}; or \item - a non-inline non-template variable of non-volatile const-qualified type - that is - neither explicitly declared \tcode{extern} nor previously - declared to have external linkage; or + a non-template variable of non-volatile const-qualified type, unless + \begin{itemize} + \item it is explicitly declared \tcode{extern}, or + \item it is inline or exported, or + \item it was previously declared and the prior declaration did + not have internal linkage; or + \end{itemize} \item a data member of an anonymous union. \end{itemize} \begin{note} An instantiated variable template that has const-qualified type -can have external linkage, even if not declared \tcode{extern}. +can have external or module linkage, even if not declared \tcode{extern}. \end{note} \pnum @@ -2424,7 +2596,7 @@ unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not been given internal linkage above -has the same linkage as the enclosing namespace if it is the name of +and that is the name of \begin{itemize} \item a variable; or \item a function; or @@ -2436,7 +2608,22 @@ a named enumeration\iref{dcl.enum}, or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes\iref{dcl.typedef}; or -\item a template. +\item a template +\end{itemize} +has its linkage determined as follows: +\begin{itemize} +\item +if the enclosing namespace has internal linkage, +the name has internal linkage; +\item +otherwise, +if the declaration of the name is +attached to a named module\iref{module.unit} +and is not exported\iref{module.interface}, +the name has module linkage; +\item +otherwise, +the name has external linkage. \end{itemize} \pnum @@ -2448,8 +2635,12 @@ member. \pnum -The name of a function declared in block scope and the name of a variable declared by a -block scope \tcode{extern} declaration have linkage. If there is a visible declaration +The name of a function declared in block scope and +the name of a variable declared by a block scope \tcode{extern} declaration +have linkage. +If such a declaration is attached to a named module, +the program is ill-formed. +If there is a visible declaration of an entity with linkage, ignoring entities declared outside the innermost enclosing namespace scope, such that the block scope declaration would be @@ -2518,8 +2709,10 @@ in different scopes shall denote the same variable, function, type, template or namespace if \begin{itemize} -\item both names have external linkage or else both names have internal -linkage and are declared in the same translation unit; and +\item both names have external or module linkage +and are declared in declarations attached to the same module, +or else both names have internal linkage +and are declared in the same translation unit; and \item both names refer to members of the same namespace or to members, not by inheritance, of the same class; and @@ -2530,6 +2723,48 @@ \item when both names denote function templates, the signatures\iref{temp.over.link} are the same. \end{itemize} +If multiple declarations of the same name with external linkage +would declare the same entity except that +they are attached to different modules, +the program is ill-formed; no diagnostic is required. +\begin{note} +\grammarterm{using-declaration}{s}, +typedef declarations, +and \grammarterm{alias-declaration}{s} +do not declare entities, but merely introduce synonyms. +Similarly, +\grammarterm{using-directive}{s} +do not declare entities. +\end{note} + +\pnum +If a declaration would redeclare a reachable declaration +attached to a different module, the program is ill-formed. +\begin{example} +\begin{codeblocktu}{\tcode{"decls.h"}} +int f(); // \#1, attached to the global module +int g(); // \#2, attached to the global module +\end{codeblocktu} + +\begin{codeblocktu}{Module interface of \tcode{M}} +module; +#include "decls.h" +export module M; +export using ::f; // OK: does not declare an entity, exports \#1 +int g(); // error: matches \#2, but attached to \tcode{M} +export int h(); // \#3 +export int k(); // \#4 +\end{codeblocktu} + +\begin{codeblocktu}{Other translation unit} +import M; +static int h(); // error: matches \#3 +int k(); // error: matches \#4 +\end{codeblocktu} +\end{example} +As a consequence of these rules, +all declarations of an entity are attached to the same module; +the entity is said to be \defnx{attached}{attached!entity} to that module. \pnum \indextext{consistency!type declaration}% @@ -5717,7 +5952,8 @@ \pnum \indextext{program!start|(}% -A program shall contain a global function called \tcode{main}. +A program shall contain a global function called \tcode{main} +attached to the global module. Executing a program starts a main thread of execution~(\ref{intro.multithread}, \ref{thread.threads}) in which the \tcode{main} function is invoked, and in which variables of static storage duration @@ -5771,9 +6007,11 @@ deleted or that declares \tcode{main} to be \tcode{inline}, \tcode{static}, or \tcode{constexpr} is ill-formed. The \tcode{main} function shall not be declared with a -\grammarterm{linkage-specification}\iref{dcl.link}. A program that -declares a variable \tcode{main} at global scope or that declares the name -\tcode{main} with C language linkage (in any namespace) is ill-formed. +\grammarterm{linkage-specification}\iref{dcl.link}. +A program that declares a variable \tcode{main} at global scope, +or that declares a function \tcode{main} at global scope attached to a named module, +or that declares the name \tcode{main} with C language linkage (in any namespace) +is ill-formed. The name \tcode{main} is not otherwise reserved. \begin{example} Member functions, classes, and enumerations can be called \tcode{main}, as can entities in other diff --git a/source/classes.tex b/source/classes.tex index 2d62692deb..f4ed78d86f 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2876,7 +2876,7 @@ A bit-field shall not be a static member. \indextext{bit-field!type of}% A bit-field shall have integral or enumeration type; -the bit-field attribute is not part of the type of the class member. +the bit-field semantic property is not part of the type of the class member. The \grammarterm{constant-expression} shall be an integral constant expression with a value greater than or equal to zero and is called the \defn{width} of the bit-field. diff --git a/source/compatibility.tex b/source/compatibility.tex index 1e448b4849..bb53ff732e 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -1791,6 +1791,20 @@ \rSec2[diff.cpp17.lex]{\ref{lex}: lexical conventions} +\diffref{lex.header} +\change \grammarterm{header-name} tokens are formed in more contexts. +\rationale Required for new features. +\effect When the identifier \tcode{import} +is followed by a \tcode{<} character, +a \grammarterm{header-name} token may be formed. +\begin{example} +\begin{codeblock} +template class import {}; +import f(); // ill-formed; previously well-formed +::import g(); // OK +\end{codeblock} +\end{example} + \diffref{lex.key} \change New keywords. \rationale Required for new features. @@ -1862,6 +1876,25 @@ \rSec2[diff.cpp17.basic]{\ref{basic}: basics} +\diffref{basic.link,module.unit,module.import} +\change New identifiers with special meaning. +\rationale Required for new features. +\effect Top-level declarations beginning with +\tcode{module} or \tcode{import} may +be either ill-formed or interpreted differently +in this International Standard. +\begin{example} +\begin{codeblock} +class module; +module *m1; // ill-formed; previously well-formed +::module *m2; // OK + +class import {}; +import j1; // was variable declaration; now \grammarterm{import-declaration} +::import j2; // variable declaration +\end{codeblock} +\end{example} + \diffref{intro.races} \change Except for the initial release operation, a release sequence consists solely of atomic read-modify-write operations. diff --git a/source/declarations.tex b/source/declarations.tex index f23d73225e..436abdb33d 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -25,6 +25,7 @@ deduction-guide\br explicit-instantiation\br explicit-specialization\br + export-declaration\br linkage-specification\br namespace-definition\br empty-declaration\br @@ -1031,27 +1032,46 @@ been declared inline. \pnum -An inline function or variable shall be defined in every translation unit in which -it is odr-used and shall have exactly the same definition in every -case\iref{basic.def.odr}. +If an inline function or variable +is odr-used in a translation unit, +a definition of it shall be reachable from the end of that translation unit, +and it shall have exactly the same definition +in every such translation unit\iref{basic.def.odr}. \begin{note} A call to the inline function or a use of the inline variable may be encountered before its definition appears in the translation unit. \end{note} -If the definition of a function or variable appears in a translation unit before its +If a definition of a function or variable is reachable +at the point of its first declaration as inline, the program is ill-formed. If a function or variable -with external linkage is declared inline in one translation unit, it -shall be declared inline in all translation units in which it appears; -no diagnostic is required. An inline function or variable with external -linkage shall have the same address in all translation units. +with external or module linkage +is declared inline in one translation unit, +there shall be a reachable inline declaration +in all translation units in which it is declared; +no diagnostic is required. +An inline function or variable +with external or module linkage +shall have the same address in all translation units. \begin{note} A \tcode{static} local variable in an inline -function with external linkage always refers to the same object. +function with external or module linkage +always refers to the same object. A type defined within the body of an inline -function with external linkage is the +function with external or module linkage is the same type in every translation unit. \end{note} +\pnum +An exported inline function or variable +shall be defined in the translation unit +containing its exported declaration, +outside the \grammarterm{private-module-fragment} (if any). +\begin{note} +There is no restriction on the linkage (or absence thereof) +of entities that the function body of an exported inline function +can reference. A constexpr function\iref{dcl.constexpr} is implicitly inline. +\end{note} + \rSec2[dcl.type]{Type specifiers}% \indextext{specifier!type|see{type specifier}} @@ -1709,6 +1729,17 @@ \end{codeblock} \end{example} +\pnum +An exported function +with a declared return type that uses a placeholder type +shall be defined in the translation unit +containing its exported declaration, +outside the \grammarterm{private-module-fragment} (if any). +\begin{note} +There is no restriction on the linkage of +the deduced return type. +\end{note} + \pnum If the name of an entity with an undeduced placeholder type appears in an expression, the program is ill-formed. Once a @@ -6642,6 +6673,25 @@ the definition of a namespace can be split over several parts of one or more translation units. +\pnum +\begin{note} +A namespace name with external linkage is exported +if any of its \term{namespace-definition}{s} is exported, +or if it contains any +\grammarterm{export-declaration}{s}\iref{module.interface}. +A namespace is never attached to a module, +and never has module linkage +even if it is not exported. +\end{note} +\begin{example} +\begin{codeblock} +export module M; +namespace N1 {} // \tcode{N1} is not exported +export namespace N2 {} // \tcode{N2} is exported +namespace N3 { export int n; } // \tcode{N3} is exported +\end{codeblock} +\end{example} + \pnum The outermost declarative region of a translation unit is a namespace; see~\ref{basic.scope.namespace}. diff --git a/source/lex.tex b/source/lex.tex index b623fef534..acf98690d9 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -42,8 +42,9 @@ \begin{note} Previously translated translation units and instantiation units can be preserved individually or in libraries. The separate translation units of a program communicate\iref{basic.link} by (for -example) calls to functions whose identifiers have external linkage, -manipulation of objects whose identifiers have external linkage, or +example) +calls to functions whose identifiers have external or module linkage, +manipulation of objects whose identifiers have external or module linkage, or manipulation of data files. Translation units can be separately translated and then later linked to produce an executable program\iref{basic.link}. \end{note}% @@ -139,7 +140,18 @@ semantically analyzed and translated as a translation unit. \begin{note} The process of analyzing and translating the tokens may occasionally result in one token being replaced by a sequence of other -tokens\iref{temp.names}.\end{note} \begin{note} Source files, translation +tokens\iref{temp.names}.\end{note} +It is +\impldef{whether the sources for +module units and header units +on which the current translation unit has an interface +dependency are required to be available during translation} +whether the sources for +module units and header units +on which the current translation unit has an interface +dependency (\ref{module.unit}, \ref{module.import}) +are required to be available. +\begin{note} Source files, translation units and translated translation units need not necessarily be stored as files, nor need there be any one-to-one correspondence between these entities and any external representation. The description is conceptual @@ -324,7 +336,20 @@ characters that could constitute a preprocessing token, even if that would cause further lexical analysis to fail, except that a \grammarterm{header-name}\iref{lex.header} is only formed -within a \tcode{\#include} directive\iref{cpp.include}. +\begin{itemize} +\item +within a \tcode{\#include} directive\iref{cpp.include}, + +\item +within a \grammarterm{has-include-expression}, or + +\item +outside of any preprocessing directive, +if applying phase 4 of translation to the sequence +of preprocessing tokens produced thus far +is valid and +results in an \grammarterm{import-seq}\iref{cpp.module}. +\end{itemize} \end{itemize} \begin{example} @@ -638,14 +663,17 @@ \grammarterm{identifier} has a special meaning is resolved to interpret the token as a regular \grammarterm{identifier}. -\begin{floattable}{Identifiers with special meaning}{tab:identifiers.special} -{llll} -\topline -\tcode{audit} & -\tcode{axiom} & -\tcode{final} & +\begin{multicolfloattable}{Identifiers with special meaning}{tab:identifiers.special} +{lll} +\tcode{audit} \\ +\tcode{axiom} \\ +\columnbreak +\tcode{import} \\ +\tcode{final} \\ +\columnbreak +\tcode{module} \\ \tcode{override} \\ -\end{floattable} +\end{multicolfloattable} \pnum \indextext{\idxcode{_}|see{character, underscore}}% @@ -765,8 +793,8 @@ \tcode{while} \\ \end{multicolfloattable} -\begin{note} The \tcode{export} and \tcode{register} keywords are unused but -are reserved for future use.\end{note} +\begin{note} The \tcode{register} keyword is unused but +is reserved for future use.\end{note} \pnum Furthermore, the alternative representations shown in diff --git a/source/macros.tex b/source/macros.tex index f50fbb775b..39da8a743f 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -407,6 +407,26 @@ \lstnewenvironment{codeblock}{\CodeBlockSetup}{} +% Left-align listings titles +\makeatletter +\def\lst@maketitle{\@makeleftcaption\lst@title@dropdelim} +\long\def\@makeleftcaption#1#2{% + \vskip\abovecaptionskip + \sbox\@tempboxa{#1: #2}% + \ifdim \wd\@tempboxa >\hsize + #1: #2\par + \else + \global \@minipagefalse + \hb@xt@\hsize{%\hfil -- REMOVED + \box\@tempboxa\hfil}% + \fi + \vskip\belowcaptionskip}% +\makeatother + +\lstnewenvironment{codeblocktu}[1]{% +\lstset{title={%\parabullnum{Bullets1}{0pt} +#1:}}\CodeBlockSetup}{} + % An environment for command / program output that is not C++ code. \lstnewenvironment{outputblock}{\lstset{language=}}{} diff --git a/source/modules.tex b/source/modules.tex new file mode 100644 index 0000000000..679690a901 --- /dev/null +++ b/source/modules.tex @@ -0,0 +1,982 @@ +%!TEX root = std.tex +\rSec0[module]{Modules}% + +\gramSec[gram.module]{Modules} + +\rSec1[module.unit]{Module units and purviews} + +\begin{bnf} +\nontermdef{module-declaration}\br + \opt{\terminal{export}} \terminal{module} module-name \opt{module-partition} \opt{attribute-specifier-seq} \terminal{;} +\end{bnf} + +\begin{bnf} +\nontermdef{module-name}\br + \opt{module-name-qualifier} identifier +\end{bnf} + +\begin{bnf} +\nontermdef{module-partition}\br + \terminal{:} \opt{module-name-qualifier} identifier +\end{bnf} + +\begin{bnf} +\nontermdef{module-name-qualifier}\br + identifier \terminal{.}\br + module-name-qualifier identifier \terminal{.} +\end{bnf} + +\pnum +A \defn{module unit} is a translation unit that contains +a \grammarterm{module-declaration}. +A \defnadj{named}{module} is the +collection of module units with the same \grammarterm{module-name}. +The identifiers \tcode{module} and \tcode{import} +shall not appear as \grammarterm{identifier}{s} +in a \grammarterm{module-name} or \grammarterm{module-partition}. +The optional \grammarterm{attribute-specifier-seq} +appertains to the \grammarterm{module-declaration}. + +\pnum +A \defn{module interface unit} is a module unit whose +\grammarterm{module-declaration} contains the \tcode{export} keyword; +any other module unit is a \defn{module implementation unit}. +A named module shall contain exactly one module interface unit +with no \grammarterm{module-partition}, known as the +\defn{primary module interface unit} of the module; +no diagnostic is required. + +\pnum +A \defn{module partition} is +a module unit whose \grammarterm{module-declaration} contains +a \grammarterm{module-partition}. +A named module shall not contain multiple module partitions with +the same \grammarterm{module-partition}. +All module partitions of a module +that are module interface units +shall be directly or indirectly exported +by the primary module interface unit\iref{module.import}. +No diagnostic is required for a violation of these rules. +\begin{note} +Module partitions can be imported only by +other module units in the same module. +The division of a module into module units +is not visible outside the module. +\end{note} + +\pnum +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module A; +export import :Foo; +export int baz(); +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module A:Foo; +import :Internals; +export int foo() { return 2 * (bar() + 1); } +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +module A:Internals; +int bar(); +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#4} +module A; +import :Internals; +int bar() { return baz() - 10; } +int baz() { return 30; } +\end{codeblocktu} + +Module \tcode{A} contains four translation units: +\begin{itemize} +\item a primary module interface unit, +\item a module partition \tcode{A:Foo}, which is a module interface unit +forming part of the interface of module \tcode{A}, +\item a module partition \tcode{A:Internals}, which does not contribute +to the external interface of module \tcode{A}, and +\item a module implementation unit providing +a definition of \tcode{bar} and \tcode{baz}, +which cannot be imported because +it does not have a partition name. +\end{itemize} +\end{example} + +\pnum +A \defnadj{module unit}{purview} is +the sequence of \grammarterm{token}{s} +starting at the \grammarterm{module-declaration} +and extending to the end of the translation unit. +The \defnx{purview}{purview!named module} +of a named module \tcode{M} is the set of module unit purviews +of \tcode{M}'s module units. + +\pnum +The \defnadj{global}{module} is the collection of all +\grammarterm{global-module-fragment}{s} +and all translation units that are not module units. +Declarations appearing in such a context +are said to be in the \defnx{purview}{purview!global module} of the global module. +\begin{note} +The global module has no name, no module interface unit, and is not +introduced by any \grammarterm{module-declaration}. +\end{note} + +\pnum +A \defn{module} is either a named module or the global module. +A declaration is \defnx{attached}{attached!declaration} to a module as follows: +\begin{itemize} +\item If the declaration +\begin{itemize} +\item is a replaceable global allocation or deallocation +function (\ref{new.delete.single}, \ref{new.delete.array}), or +\item is a \grammarterm{namespace-declaration} with external linkage, or +\item appears within a \grammarterm{linkage-specification}, +\end{itemize} +it is attached to the global module. + +\item Otherwise, the declaration is +attached to the module in whose purview it appears. +\end{itemize} + +\pnum +A \grammarterm{module-declaration} +that contains neither \tcode{export} +nor a \grammarterm{module-partition} +implicitly imports the primary module interface unit of the module +as if by a \grammarterm{module-import-declaration}. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +module B:Y; // does not implicitly import \tcode{B} +int y(); +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module B; +import :Y; // OK, does not create interface dependency cycle +int n = y(); +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +module B:X1; // does not implicitly import \tcode{B} +int &a = n; // error: \tcode{n} not visible here +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#4} +module B:X2; // does not implicitly import \tcode{B} +import B; +int &b = n; // OK +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#5} +module B; // implicitly imports \tcode{B} +int &c = n; // OK +\end{codeblocktu} +\end{example} + +\rSec1[module.interface]{Export declaration}% + +\begin{bnf} +\nontermdef{export-declaration}\br + \terminal{export} declaration\br + \terminal{export} \terminal{\{} \opt{declaration-seq} \terminal{\}} +\end{bnf} + +\pnum +An \grammarterm{export-declaration} shall appear only +at namespace scope and only in the purview of a module interface unit. +An \grammarterm{export-declaration} shall not appear directly +or indirectly within an unnamed namespace +or a \grammarterm{private-module-fragment}. +An \grammarterm{export-declaration} +has the declarative effects of its \grammarterm{declaration} +or its \grammarterm{declaration-seq} (if any). +An \grammarterm{export-declaration} does not +establish a scope and its \grammarterm{declaration} +or \grammarterm{declaration-seq} +shall not contain an \grammarterm{export-declaration}. + +\pnum +A declaration is \defnx{exported}{declaration!exported} if it is +\begin{itemize} +\item a namespace-scope declaration declared within an + \grammarterm{export-declaration}, or +\item a \grammarterm{module-import-declaration} declared with + the \tcode{export} keyword\iref{module.import}, or +\item a \grammarterm{namespace-definition} that contains an + exported declaration, or +\item a declaration within a header unit\iref{module.import} + that introduces at least one name. +\end{itemize} +The \defnx{interface}{module!interface} of a module \tcode{M} +is the set of all exported declarations within its purview. +\begin{example} +\begin{codeblock} +export module M; +namespace A { // exported + export int f(); // exported + int g(); // not exported +} +\end{codeblock} +The interface of \tcode{M} comprises \tcode{A} and \tcode{A::f}. +\end{example} + +\pnum +An exported declaration shall declare at least one name. +If the declaration is not within a header unit, +it shall not declare a name with internal linkage. + +\pnum +\begin{example} +\begin{codeblocktu}{Source file \tcode{"a.h"}} +export int x; +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#1} +module; +#include "a.h" // error: declaration of \tcode{x} is not in the + // purview of a module interface unit +export module M; +export namespace {} // error: does not introduce any names +export namespace { + int a1; // error: export of name with internal linkage +} +namespace { + export int a2; // error: export of name with internal linkage +} +export static int b; // error: b explicitly declared static +export int f(); // OK +export namespace N { } // OK +export using namespace N; // error: does not declare a name +\end{codeblocktu} +\end{example} + +\pnum +If the declaration is a \grammarterm{using-declaration}\iref{namespace.udecl} +and is not within a header unit, +all entities to which all of the +\grammarterm{using-declarator}{s} ultimately refer (if any) +shall have been introduced with a name having external linkage. +\begin{example} +\begin{codeblocktu}{Source file \tcode{"b.h"}} +int f(); +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"c.h"}} +int g(); +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#1} +export module X; +export int h(); +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +module; +#include "b.h" +export module M; +import "c.h"; +import X; +export using ::f, ::g, ::h; // OK +struct S; +export using ::S; // error: \tcode{S} has module linkage +namespace N { + export int h(); + static int h(int); // \#1 +} +export using N::h; // error: \#1 has internal linkage +\end{codeblocktu} +\end{example} +\begin{note} +These constraints do not apply to +type names introduced by \tcode{typedef} declarations +and \grammarterm{alias-declaration}{s}. +\begin{example} +\begin{codeblock} +export module M; +struct S; +export using T = S; // OK, exports name \tcode{T} denoting type \tcode{S} +\end{codeblock} +\end{example} +\end{note} + +\pnum +A redeclaration of an exported declaration of an entity +is implicitly exported. +An exported redeclaration of a non-exported declaration +of an entity is ill-formed. +\begin{example} +\begin{codeblock} +export module M; +struct S { int n; }; +typedef S S; +export typedef S S; // OK, does not redeclare an entity +export struct S; // error: exported declaration follows non-exported declaration +\end{codeblock} +\end{example} + +\pnum +A name is \defnx{exported}{name!exported} by a module +if it is introduced or redeclared +by an exported declaration in the purview of that module. +\begin{note} +Exported names have either external linkage or no linkage; see \ref{basic.link}. +Namespace-scope names exported by a module are visible to name lookup +in any translation unit importing that module; see \ref{basic.scope.namespace}. +Class and enumeration member names are visible to name lookup in any +context in which a definition of the type is reachable. +\end{note} +\begin{example} +\begin{codeblocktu}{Interface unit of \tcode{M}} +export module M; +export struct X { + static void f(); + struct Y { }; +}; + +namespace { + struct S { }; +} +export void f(S); // OK +struct T { }; +export T id(T); // OK + +export struct A; // \tcode{A} exported as incomplete + +export auto rootFinder(double a) { + return [=](double x) { return (x + a/x)/2; }; +} + +export const int n = 5; // OK, \tcode{n} has external linkage +\end{codeblocktu} + +\begin{codeblocktu}{Implementation unit of \tcode{M}} +module M; +struct A { + int value; +}; +\end{codeblocktu} + +\begin{codeblocktu}{Main program} +import M; +int main() { + X::f(); // OK, \tcode{X} is exported and definition of \tcode{X} is reachable + X::Y y; // OK, \tcode{X::Y} is exported as a complete type + auto f = rootFinder(2); // OK + return A{45}.value; // error: \tcode{A} is incomplete +} +\end{codeblocktu} +\end{example} + +\pnum +\begin{note} +Redeclaring a name in an \grammarterm{export-declaration} +cannot change the linkage of the name\iref{basic.link}. +\begin{example} +\begin{codeblocktu}{Interface unit of \tcode{M}} +export module M; +static int f(); // \#1 +export int f(); // error: \#1 gives internal linkage +struct S; // \#2 +export struct S; // error: \#2 gives module linkage +namespace { + namespace N { + extern int x; // \#3 + } +} +export int N::x; // error: \#3 gives internal linkage +\end{codeblocktu} +\end{example} +\end{note} + +\pnum +\begin{note} +Declarations in an exported \grammarterm{namespace-definition} +or in an exported \grammarterm{linkage-specification}\iref{dcl.link} +are exported and subject to the rules of exported declarations. +\begin{example} +\begin{codeblock} +export module M; +export namespace N { + int x; // OK + static_assert(1 == 1); // error: does not declare a name +} +\end{codeblock} +\end{example} +\end{note} + +\rSec1[module.import]{Import declaration}% + +\begin{bnf} +\nontermdef{module-import-declaration}\br + \opt{\terminal{export}} \terminal{import} module-name \opt{attribute-specifier-seq} \terminal{;}\br + \opt{\terminal{export}} \terminal{import} module-partition \opt{attribute-specifier-seq} \terminal{;}\br + \opt{\terminal{export}} \terminal{import} header-name \opt{attribute-specifier-seq} \terminal{;} +\end{bnf} + +\pnum +In a module unit, all \grammarterm{module-import-declaration}{s} +shall precede all other \grammarterm{top-level-declaration}{s} in +the \grammarterm{top-level-declaration-seq} of the +\grammarterm{translation-unit} +and of the \grammarterm{private-module-fragment} (if any). +The optional \grammarterm{attribute-specifier-seq} +appertains to the \grammarterm{module-import-declaration}. + +\pnum +A \grammarterm{module-import-declaration} \defnx{imports}{import} a set of +translation units determined as described below. +\begin{note} +Namespace-scope names exported by the imported translation units +become visible\iref{basic.scope.namespace} +in the importing translation unit +and declarations within the imported translation units +become reachable\iref{module.reach} +in the importing translation unit +after the import declaration. +\end{note} + +\pnum +A \grammarterm{module-import-declaration} that specifies +a \grammarterm{module-name} \tcode{M} +imports all module interface units of \tcode{M}. + +\pnum +A \grammarterm{module-import-declaration} that specifies +a \grammarterm{module-partition} shall only appear after +the \grammarterm{module-declaration} in a module unit of +some module \tcode{M}. +Such a declaration imports the so-named +module partition of \tcode{M}. + +\pnum +A \grammarterm{module-import-declaration} that specifies +a \grammarterm{header-name} \tcode{H} imports +a synthesized \defn{header unit}, +which is a translation unit formed by applying +phases 1 to 7 of translation\iref{lex.phases} +to the source file or header nominated by \tcode{H}, +which shall not contain a \grammarterm{module-declaration}. +\begin{note} +All declarations within a header unit are implicitly +exported\iref{module.interface}, +and are attached to the global module\iref{module.unit}. +\end{note} +An \defnadj{importable}{header} is a member of an +\impldef{how the set of importable headers is determined} +set of headers. +\tcode{H} shall identify an importable header. +Two +\grammarterm{module-import-declaration}{s} +import the same header unit if and only if +their \grammarterm{header-name}{s} identify the same +header or source file\iref{cpp.include}. +\begin{note} +A \grammarterm{module-import-declaration} nominating +a \grammarterm{header-name} is also recognized by the +preprocessor, and results in macros defined at the +end of phase 4 of translation of the header unit +being made visible as described in \ref{cpp.module}. +\end{note} +A declaration of a name with internal linkage is +permitted within a header unit despite all +declarations being implicitly exported\iref{module.interface}. +If such a declaration declares an entity +that is odr-used outside the +header unit, or by a template +instantiation whose point of instantiation is outside +the header unit, the program is ill-formed. + +\pnum +When a \grammarterm{module-import-declaration} imports +a translation unit $T$, it also imports +all translation units imported by +exported \grammarterm{module-import-declaration}{s} +in $T$; such translation units are +said to be \defnx{exported}{module!exported} by $T$. +When a \grammarterm{module-import-declaration} in a module unit imports +another module unit of the same module, it also imports +all translation units imported by +all \grammarterm{module-import-declaration}{s} +in that module unit. +These rules may in turn lead to the importation of yet more +translation units. + +\pnum +A module implementation unit shall not be exported. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +module M:Part; +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module M; +export import :Part; // error: exported partition \tcode{:Part} is an implementation unit +\end{codeblocktu} +\end{example} + +\pnum +A module implementation unit of a module \tcode{M} +that is not a module partition +shall not contain a \grammarterm{module-import-declaration} +nominating \tcode{M}. +\begin{example} +\begin{codeblock} +module M; +import M; // error: cannot import \tcode{M} in its own unit +\end{codeblock} +\end{example} + +\pnum +A translation unit has an \defn{interface dependency} on a module unit \tcode{U} +if it contains a \grammarterm{module-declaration} or +\grammarterm{module-import-declaration} that imports \tcode{U} or if it has +an interface dependency on a module unit that has an interface dependency on \tcode{U}. +A translation unit shall not have an interface dependency on itself. +\begin{example} +\begin{codeblocktu}{Interface unit of \tcode{M1}} +export module M1; +import M2; +\end{codeblocktu} + +\begin{codeblocktu}{Interface unit of \tcode{M2}} +export module M2; +import M3; +\end{codeblocktu} + +\begin{codeblocktu}{Interface unit of \tcode{M3}} +export module M3; +import M1; // error: cyclic interface dependency $\mathtt{M3} \rightarrow \mathtt{M1} \rightarrow \mathtt{M2} \rightarrow \mathtt{M3}$ +\end{codeblocktu} +\end{example} + +\rSec1[module.global]{Global module fragment} + +\begin{bnf} +\nontermdef{global-module-fragment}\br + \terminal{module} \terminal{;} \opt{top-level-declaration-seq} +\end{bnf} + +\pnum +A \grammarterm{global-module-fragment} specifies the contents of the +\defn{global module fragment} for a module unit. +The global module fragment can be used to provide declarations +that are attached to the global module and usable within the module unit. +\begin{note} +Prior to phase 4 of translation, +only preprocessing directives can appear +in the global module fragment\iref{cpp.glob.frag}. +\end{note} + +\pnum +A declaration $D$ is \defn{decl-reachable} from a declaration $S$ +in the same translation unit if: +\begin{itemize} +\item +$D$ does not declare a function or function template and +$S$ contains an +\grammarterm{id-expression}, +\grammarterm{namespace-name}, +\grammarterm{type-name}, +\grammarterm{template-name}, or +\grammarterm{concept-name} +naming $D$, or + +\item +$D$ declares a function or function template that +is named by an expression\iref{basic.def.odr} +appearing in $S$, or + +\item +$S$ contains an expression \tcode{E} of the form + +\begin{ncsimplebnf} +postfix-expression \terminal{(} \opt{expression-list} \terminal{)} +\end{ncsimplebnf} +whose \grammarterm{postfix-expression} denotes a dependent name, +or for an operator expression whose operator denotes a dependent name, +and $D$ is found by name lookup for the corresponding name +in an expression synthesized from \tcode{E} +by replacing each type-dependent argument or operand +with a value of a placeholder type +with no associated namespaces or entities, or + +\item +$S$ contains an expression that +takes the address of an overloaded function\iref{over.over} +whose set of overloads contains $D$ and +for which the target type is dependent, or + +\item +there exists a declaration $M$ that is not a \grammarterm{namespace-definition} +for which $M$ is decl-reachable from $S$ and either +\begin{itemize} +\item +$D$ is decl-reachable from $M$, or +\item +$D$ redeclares the entity declared by $M$ or +$M$ redeclares the entity declared by $D$, +and $D$ is neither a friend declaration +nor a block-scope declaration, or +\item +$D$ declares a namespace $N$ and $M$ is a member of $N$, or +\item +one of $M$ and $D$ declares a class or class template $C$ +and the other declares a member or friend of $C$, or +\item +one of $D$ and $M$ declares an enumeration $E$ +and the other declares an enumerator of $E$, or +\item +$D$ declares a function or variable and $M$ is declared in $D$,% +\footnote{A declaration can appear within a \grammarterm{lambda-expression} +in the initializer of a variable.} or +\item +one of $M$ and $D$ declares a template and the other declares +a partial or explicit specialization or +an implicit or explicit instantiation of that template, or +\item +one of $M$ and $D$ declares a class or enumeration type +and the other introduces a typedef name for linkage purposes for that type. +\end{itemize} +\end{itemize} +In this determination, it is unspecified +\begin{itemize} +\item +whether a reference to an +\grammarterm{alias-declaration}, +\tcode{typedef} declaration, +\grammarterm{using-declaration}, or +\grammarterm{namespace-alias-declaration} +is replaced by the declarations they name +prior to this determination, + +\item +whether a \grammarterm{simple-template-id} +that does not denote a dependent type +and whose \grammarterm{template-name} names an alias template +is replaced by its denoted type +prior to this determination, + +\item +whether a \grammarterm{decltype-specifier} +that does not denote a dependent type +is replaced by its denoted type +prior to this determination, +and + +\item +whether a non-value-dependent constant expression +is replaced by the result of constant evaluation +prior to this determination. +\end{itemize} + +\pnum +A declaration \tcode{D} in a global module fragment of a module unit +is \defnx{discarded}{discarded!declaration} if \tcode{D} +is not decl-reachable from any \grammarterm{top-level-declaration} +in the \grammarterm{top-level-declaration-seq} +of the \grammarterm{translation unit}. +\begin{note} +A discarded declaration is neither reachable +nor visible to name lookup outside the module unit, +nor in template instantiations whose points of instantiation\iref{temp.point} +are outside the module unit, +even when the instantiation context\iref{module.context} +includes the module unit. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} +const int size = 2; +int ary1[size]; // unspecified whether \tcode{size} is decl-reachable from \tcode{ary1} +constexpr int identity(int x) { return x; } +int ary2[identity(2)]; // unspecified whether \tcode{identity} is decl-reachable from \tcode{ary2} + +template struct S; +template struct S2; +constexpr int g(int); + +template +S> f(); // \tcode{S}, \tcode{S2}, \tcode{g}, and \tcode{::} are decl-reachable from \tcode{f} + +template +void h() noexcept(g(N) == N); // \tcode{g} and \tcode{::} are decl-reachable from \tcode{h} +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblocktu}{Source file \tcode{"foo.h"}} +namespace N { + struct X {}; + int d(); + int e(); + inline int f(X, int = d()) { return e(); } + int g(X); + int h(X); +} +\end{codeblocktu} + +\begin{codeblocktu}{Module \tcode{M} interface} +module; +#include "foo.h" +export module M; +template int use_f() { + N::X x; // \tcode{N::X}, \tcode{N}, and \tcode{::} are decl-reachable from \tcode{use_f} + return f(x, 123); // \tcode{N::f} is decl-reachable from \tcode{use_f}, + // \tcode{N::e} is indirectly decl-reachable from \tcode{use_f} + // because it is decl-reachable from \tcode{N::f}, and + // \tcode{N::d} is decl-reachable from \tcode{use_f} + // because it is decl-reachable from \tcode{N::f} + // even though it is not used in this call +} +template int use_g() { + N::X x; // \tcode{N::X}, \tcode{N}, and \tcode{::} are decl-reachable from \tcode{use_f} + return g((T(), x)); // \tcode{N::g} is not decl-reachable from \tcode{use_g} +} +template int use_h() { + N::X x; // \tcode{N::X}, \tcode{N}, and \tcode{::} are decl-reachable from \tcode{use_h} + return h((T(), x)); // \tcode{N::h} is not decl-reachable from \tcode{use_h}, but + // \tcode{N::h} is decl-reachable from \tcode{use_h} +} +int k = use_h(); + // \tcode{use_h} is decl-reachable from \tcode{k}, so + // \tcode{N::h} is decl-reachable from \tcode{k} +\end{codeblocktu} + +\begin{codeblocktu}{Module \tcode{M} implementation} +module M; +int a = use_f(); // OK +int b = use_g(); // error: no viable function for call to \tcode{g}; + // \tcode{g} is not decl-reachable from purview of + // module \tcode{M}{'s} interface, so is discarded +int c = use_h(); // OK +\end{codeblocktu} +\end{example} + +\rSec1[module.context]{Instantiation context} + +\pnum +The \defn{instantiation context} is a set of points within the program +that determines which names are visible +to argument-dependent name lookup\iref{basic.lookup.argdep} +and which declarations are reachable\iref{module.reach} +in the context of a particular declaration or template instantiation. + +\pnum +During the implicit definition of +a defaulted special member function\iref{special}, +the instantiation context is the union of +the instantiation context from the definition of the class and +the instantiation context of the program construct that +resulted in the implicit definition of the special member function. + +\pnum +During the implicit instantiation of a template +whose point of instantiation is specified as +that of an enclosing specialization\iref{temp.point}, +the instantiation context is the union of +the instantiation context of the enclosing specialization and, +if the template is defined in a module interface unit of a module $M$ +and the point of instantiation is not in a module interface unit of $M$, +the point at the end of the +\grammarterm{top-level-declaration-seq} of the +primary module interface unit of $M$ +(prior to the \grammarterm{private-module-fragment}, if any). + +\pnum +During the implicit instantiation of a template +that is implicitly instantiated because it is referenced +from within the implicit definition of a defaulted special member function, +the instantiation context is the instantiation context of +the defaulted special member function. + +\pnum +During the instantiation of any other template specialization, +the instantiation context comprises the point of instantiation +of the template. + +\pnum +In any other case, the instantiation context +at a point within the program +comprises that point. + +\pnum +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module stuff; +export template void foo(T, U u) { auto v = u; } +export template void bar(T, U u) { auto v = *u; } +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module M1; +import "defn.h"; // provides \tcode{struct X \{\};} +import stuff; +export template void f(T t) { + X x; + foo(t, x); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +export module M2; +import "decl.h"; // provides \tcode{struct X;} (not a definition) +import stuff; +export template void g(T t) { + X *x; + bar(t, x); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#4} +import M1; +import M2; +void test() { + f(0); + g(0); +} +\end{codeblocktu} +The call to \tcode{f(0)} is valid; +the instantiation context of \tcode{foo} comprises +\begin{itemize} +\item the point at the end of translation unit \#1, +\item the point at the end of translation unit \#2, and +\item the point of the call to \tcode{f(0)}, +\end{itemize} +so the definition of \tcode{X} is reachable (\ref{module.reach}). + +It is unspecified whether the call to \tcode{g(0)} is valid: +the instantiation context of \tcode{bar} comprises +\begin{itemize} +\item the point at the end of translation unit \#1, +\item the point at the end of translation unit \#3, and +\item the point of the call to \tcode{g(0)}, +\end{itemize} +so the definition of \tcode{X} is not necessarily reachable, +as described in \ref{module.reach}. +\end{example} + +\rSec1[module.reach]{Reachability} + +\indextext{necessarily reachable|see{reachable!necessarily}} +\pnum +A translation unit $U$ is +\defnx{necessarily reachable}{reachable!necessarily!translation unit} +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$ (\ref{module.import}). +\begin{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\iref{basic.scope.namespace}. +\end{note} + +\pnum +All translation units that are necessarily reachable are +\defnx{reachable}{reachable!translation unit}. +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.% +\footnote{Implementations are therefore not required to prevent the semantic +effects of additional translation units involved in the compilation from being +observed.} +\begin{note} +It is advisable to avoid +depending on the reachability of any additional translation units +in programs intending to be portable. +\end{note} + +\pnum +A declaration $D$ is +\defnx{reachable}{reachable!declaration} or +\defnx{necessarily reachable}{reachable!necessarily!declaration}, +respectively, if, +for any point $P$ in the +instantiation context\iref{module.context}, +\begin{itemize} +\item $D$ appears prior to $P$ in the same translation unit, or +\item $D$ is not discarded\iref{module.global}, +appears in a translation unit that is +reachable or necessarily reachable from $P$, respectively, +and +either does not appear within a \grammarterm{private-module-fragment} +or appears in a \grammarterm{private-module-fragment} +of the module containing $P$. +\end{itemize} +\begin{note} +Whether a declaration is exported has no bearing on whether it is reachable. +\end{note} + +\pnum +The accumulated properties of all reachable declarations of +an entity within a context +determine the behavior of the entity within that context. +\begin{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. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module M:A; +export struct B; +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +module M:B; +struct B { + operator int(); +}; +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +module M:C; +import :A; +B b1; // error: no reachable definition of \tcode{struct B} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#4} +export module M; +export import :A; +import :B; +B b2; +export void f(B b = B()); +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#5} +module X; +import M; +B b3; // error: no reachable definition of \tcode{struct B} +void g() { f(); } // error: no reachable definition of \tcode{struct B} +\end{codeblocktu} +\end{example} +\end{note} + +\pnum +\begin{note} +An entity can have reachable declarations +even if it is not visible to name lookup. +\end{note} +\begin{example} +\begin{codeblock} +export module A; +struct X {}; +export using Y = X; + +module B; +import A; +Y y; // OK, definition of \tcode{X} is reachable +X x; // ill-formed: \tcode{X} not visible to unqualified lookup +\end{codeblock} +\end{example} diff --git a/source/overloading.tex b/source/overloading.tex index 2e1b9b2e32..26a6c0013a 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -3583,8 +3583,9 @@ the constraints described above, they are ordinary namespace-scope functions and function templates. In particular, they are looked up like ordinary functions and function templates and they follow the same overload resolution rules. Also, -they can be declared \tcode{inline} or \tcode{constexpr}, they may have internal -or external linkage, they can be called explicitly, their addresses can be +they can be declared \tcode{inline} or \tcode{constexpr}, +they may have internal, module, or external linkage, +they can be called explicitly, their addresses can be taken, etc. \end{note} \pnum diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 8bc6ecba14..50696f5bcc 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -161,6 +161,7 @@ The implementation can process and skip sections of source files conditionally, include other source files, +import macros from header units, and replace macros. These capabilities are called \defn{preprocessing}, @@ -205,13 +206,17 @@ h-pp-tokens h-preprocessing-token \end{bnf} +\begin{bnf} +\nontermdef{header-name-tokens}\br + string-literal\br + \terminal{<} h-pp-tokens \terminal{>} +\end{bnf} + \indextext{\idxxname{has_include}}% \begin{bnf} \nontermdef{has-include-expression}\br - \terminal{\xname{has_include} ( <} h-char-sequence \terminal{> )}\br - \terminal{\xname{has_include} ( "} q-char-sequence \terminal{" )}\br - \terminal{\xname{has_include} (} string-literal \terminal{)}\br - \terminal{\xname{has_include} ( <} h-pp-tokens \terminal{> )} + \terminal{\xname{has_include}} \terminal{(} header-name \terminal{)}\br + \terminal{\xname{has_include}} \terminal{(} header-name-tokens \terminal{)} \end{bnf} \indextext{\idxxname{has_cpp_attribute}}% @@ -238,7 +243,9 @@ if the identifier is currently defined as a macro name (that is, if it is predefined -or if it has been the subject of a +or if it has one or more active macro definitions\iref{cpp.module}, +for example because +it has been the subject of a \tcode{\#define} preprocessing directive without an intervening @@ -246,8 +253,8 @@ directive with the same subject identifier), \tcode{0} if it is not. \pnum -The third and fourth forms of \grammarterm{has-include-expression} -are considered only if neither of the first or second forms matches, +The second form of \grammarterm{has-include-expression} +is considered only if the first form does not match, in which case the preprocessing tokens are processed just as in normal text. \pnum @@ -611,6 +618,15 @@ directive in another file, up to an \impldef{nesting limit for \tcode{\#include} directives} nesting limit. +\pnum +If the header identified by the \grammarterm{header-name} +denotes an importable header\iref{module.import}, +the preprocessing directive +is instead replaced by the \grammarterm{preprocessing-token}{s} +\begin{ncbnf} +\terminal{import} header-name \terminal{;} +\end{ncbnf} + \pnum \begin{note} Although an implementation may provide a mechanism for making arbitrary @@ -646,6 +662,188 @@ \end{codeblock} \end{example} +\rSec1[cpp.glob.frag]{Global module fragment} + +\begin{bnf} +\nontermdef{pp-global-module-fragment}\br + \terminal{module} \terminal{;} pp-balanced-token-seq \terminal{module} +\end{bnf} + +\pnum +If the first two preprocessing tokens at the start of phase 4 of translation +are \tcode{module} \tcode{;}, +the result of preprocessing shall begin with +a \grammarterm{pp-global-module-fragment} +for which all \grammarterm{preprocessing-token}{s} +in the \grammarterm{pp-balanced-token-seq} +were produced directly or indirectly by source file inclusion\iref{cpp.include}, +and for which the second \tcode{module} \grammarterm{preprocessing-token} +was not produced by source file inclusion or +macro replacement\iref{cpp.replace}. +Otherwise, +the first two preprocessing tokens at the end of phase 4 of translation +shall not be \tcode{module} \tcode{;}. + +\rSec1[cpp.module]{Header units} +\indextext{header unit!preprocessing}% +\indextext{macro import|(}% + +\begin{bnf} +\nontermdef{import-seq}\br + \opt{top-level-token-seq} \opt{\terminal{export}} \terminal{import} +\end{bnf} + +\begin{bnf} +\nontermdef{top-level-token-seq}\br + \descr{any \grammarterm{pp-balanced-token-seq} ending in \terminal{;} or \terminal{\}}} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-import}\br + \terminal{import} header-name \opt{pp-import-suffix} \terminal{;}\br + \terminal{import} header-name-tokens \opt{pp-import-suffix} \terminal{;} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-import-suffix}\br + pp-import-suffix-token\br + pp-import-suffix pp-import-suffix-token +\end{bnf} + +\begin{bnf} +\nontermdef{pp-import-suffix-token}\br + \descr{any \grammarterm{pp-balanced-token} other than \terminal{;}} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-balanced-token-seq}\br + pp-balanced-token\br + pp-balanced-token-seq pp-balanced-token +\end{bnf} + +\begin{bnf} +\nontermdef{pp-balanced-token}\br + pp-ldelim \opt{pp-balanced-token-seq} pp-rdelim\br + \descr{any \grammarterm{preprocessing-token} other than a \grammarterm{pp-ldelim} or \grammarterm{pp-rdelim}} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-ldelim} \descr{one of}\br + \terminal{( [ \{ <: <\%} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-rdelim} \descr{one of}\br + \terminal{) ] \} :> \%>} +\end{bnf} + +\pnum +A sequence of \grammarterm{preprocessing-token}{s} +matching the form of a \grammarterm{pp-import} +instructs the preprocessor to import macros +from the header unit\iref{module.import} +denoted by the \grammarterm{header-name}. +A \grammarterm{pp-import} is only recognized +when the sequence of tokens +produced by phase 4 of translation +up to the \tcode{import} token +forms an \grammarterm{import-seq}, +and the \tcode{import} token is not within +the \grammarterm{header-name-tokens} or \grammarterm{pp-import-suffix} +of another \grammarterm{pp-import}. +The \tcode{;} \grammarterm{preprocessing-token} +terminating a \grammarterm{pp-import} +shall not have been produced by +macro replacement\iref{cpp.replace}. +The \defnadj{point of}{macro import} for a \grammarterm{pp-import} is +immediately after the \tcode{;} terminating the \grammarterm{pp-import}. + +\pnum +In the second form of \grammarterm{pp-import}, +a \grammarterm{header-name} token is formed as if +the \grammarterm{header-name-tokens} +were the \grammarterm{pp-tokens} of a \tcode{\#include} directive. +The \grammarterm{header-name-tokens} are replaced by +the \grammarterm{header-name} token. +\begin{note} +This ensures that imports are treated consistently by +the preprocessor and later phases of translation. +\end{note} + +\pnum +Each \tcode{\#define} directive encountered when preprocessing +each translation unit in a program results in a distinct +\defn{macro definition}. +Importing macros from a header unit makes macro definitions +from a translation unit visible in other translation units. +Each macro definition has at most one point of definition in +each translation unit and at most one point of undefinition, as follows: +\begin{itemize} +\item +The \defnx{point of definition}{macro definition!point of definition} +of a macro definition within a translation unit +is the point at which its \tcode{\#define} directive occurs (in the translation +unit containing the \tcode{\#define} directive), or, +if the macro name is not lexically identical to a keyword\iref{lex.key} +or to the \grammarterm{identifier}{s} \tcode{module} or \tcode{import}, +the first point +of macro import of a translation unit containing a point of definition for the +macro definition, if any (in any other translation unit). + +\item +The \defnx{point of undefinition}{macro definition!point of undefinition} +of a macro definition within a translation unit +is the first point at which a \tcode{\#undef} directive naming the macro occurs +after its point of definition, or the first point +of macro import of a translation unit containing a point of undefinition for the +macro definition, whichever (if any) occurs first. +\end{itemize} + +\pnum +A macro directive is \defnx{active}{macro definition!active} at a source location +if it has a point of definition in that translation unit preceding the location, +and does not have a point of undefinition in that translation unit preceding +the location. + +\pnum +If a macro would be replaced or redefined, and multiple macro definitions +are active for that macro name, the active macro definitions shall all be +valid redefinitions of the same macro\iref{cpp.replace}. +\begin{note} +The relative order of \grammarterm{pp-import}{s} has no bearing on whether a +particular macro definition is active. +\end{note} + +\pnum +\begin{example} +\begin{codeblocktu}{Importable header \tcode{"a.h"}} +#define X 123 // \#1 +#define Y 45 // \#2 +#define Z a // \#3 +#undef X // point of undefinition of \#1 in \tcode{"a.h"} +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"b.h"}} +import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"b.h"} +#define X 456 // OK, \#1 is not active +#define Y 6 // error: \#2 is active +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"c.h"}} +#define Y 45 // \#4 +#define Z c // \#5 +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"d.h"}} +import "a.h"; // point of definition of \#1, \#2, and \#3, point of undefinition of \#1 in \tcode{"d.h"} +import "c.h"; // point of definition of \#4 and \#5 in \tcode{"d.h"} +int a = Y; // OK, active macro definitions \#2 and \#3 are valid redefinitions +int c = Z; // error: active macro definitions \#2 and \#3 are not valid redefinitions of \tcode{Z} +\end{codeblocktu} +\end{example} + +\indextext{macro import|)}% + \rSec1[cpp.replace]{Macro replacement}% \indextext{macro!replacement|(}% \indextext{replacement!macro|see{macro, replacement}}% diff --git a/source/std.tex b/source/std.tex index a87c75c129..1d9c01fb5a 100644 --- a/source/std.tex +++ b/source/std.tex @@ -106,6 +106,7 @@ \include{expressions} \include{statements} \include{declarations} +\include{modules} \include{classes} \include{overloading} \include{templates} diff --git a/source/templates.tex b/source/templates.tex index 1af8343a13..9643f0ab24 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -130,6 +130,8 @@ A \grammarterm{template-declaration} can appear only as a namespace scope or class scope declaration. +Its \grammarterm{declaration} shall not be an +\grammarterm{export-declaration}. In a function template declaration, the last component of the \grammarterm{declarator-id} shall not be a @@ -5391,19 +5393,28 @@ point for the specialization or specializations specified by the explicit instantiation. -\pnum -The instantiation context of an expression that depends on the template -arguments is the set of declarations with external linkage declared prior to the -point of instantiation of the template specialization in the same translation -unit. - \pnum A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition -to the points of instantiation described above, for any such specialization -that has a point of instantiation within the translation unit, the end of the -translation unit is also considered a point of instantiation. +to the points of instantiation described above, +\begin{itemize} +\item +for any such +specialization that has a point of instantiation within the +\grammarterm{top-level-declaration-seq} of the +translation unit, +prior to the \grammarterm{private-module-fragment} (if any), +the point after the \grammarterm{top-level-declaration-seq} +of the \grammarterm{translation-unit} +is also considered a point of instantiation, +and +\item +for any such specialization that has a point of instantiation +within the \grammarterm{private-module-fragment}, +the end of the translation unit is also +considered a point of instantiation. +\end{itemize} A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple @@ -5419,19 +5430,13 @@ For a function call where the \grammarterm{postfix-expression} is a dependent name, the candidate functions are found using the usual lookup -rules~(\ref{basic.lookup.unqual}, \ref{basic.lookup.argdep}) except that: - -\begin{itemize} -\item -For the part of the lookup using unqualified name lookup\iref{basic.lookup.unqual}, -only function declarations -from the template definition context are found. -\item +rules from the template definition context +(\ref{basic.lookup.unqual}, \ref{basic.lookup.argdep}). +\begin{note} For the part of the lookup using associated namespaces\iref{basic.lookup.argdep}, -only function declarations found in either the template -definition context or the template instantiation context are found. -\end{itemize} - +function declarations found in the template instantiation context +are found by this lookup, as described in \ref{basic.lookup.argdep}. +\end{note} If the call would be ill-formed or would find a better match had the lookup within the associated namespaces considered all the function declarations with @@ -5439,6 +5444,166 @@ not just considering those declarations found in the template definition and template instantiation contexts, then the program has undefined behavior. +\pnum +\begin{example} +\begin{codeblocktu}{Source file \tcode{"X.h"}} +namespace Q { + struct X { }; +} +\end{codeblocktu} + +\begin{codeblocktu}{Source file \tcode{"G.h"}} +namespace Q { + void g_impl(X, X); +} +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{M1}} +module; +#include "X.h" +#include "G.h" +export module M1; +export template +void g(T t) { + g_impl(t, Q::X{ }); // ADL in definition context finds \tcode{Q::g_impl}, \tcode{g_impl} not discarded +} +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{M2}} +module; +#include "X.h" +export module M2; +import M1; +void h(Q::X x) { + g(x); // OK +} +\end{codeblocktu} +\end{example} + +\pnum +\begin{example} +\begin{codeblocktu}{Module interface unit of \tcode{Std}} +export module Std; +export template +void indirect_swap(Iter lhs, Iter rhs) +{ + swap(*lhs, *rhs); // \tcode{swap} not found by unqualified lookup, can be found only via ADL +} +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{M}} +export module M; +import Std; + +struct S { /* ...*/ }; +void swap(S&, S&); // \#1 + +void f(S* p, S* q) +{ + indirect_swap(p, q); // finds \#1 via ADL in instantiation context +} +\end{codeblocktu} +\end{example} + +\pnum +\begin{example} +\begin{codeblocktu}{Source file \tcode{"X.h"}} +struct X { /* ... */ }; +X operator+(X, X); +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{F}} +export module F; +export template +void f(T t) { + t + t; +} +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{M}} +module; +#include "X.h" +export module M; +import F; +void g(X x) { + f(x); // OK: instantiates \tcode{f} from \tcode{F}, + // \tcode{operator+} is visible in instantiation context +} +\end{codeblocktu} +\end{example} + +\pnum +\begin{example} +\begin{codeblocktu}{Module interface unit of \tcode{A}} +export module A; +export template +void f(T t) { + cat(t, t); // \#1 + dog(t, t); // \#2 +} +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{B}} +export module B; +import A; +export template +void g(T t, U u) { + f(t); +} +\end{codeblocktu} + +\begin{codeblocktu}{Source file \tcode{"foo.h"}, not an importable header} +struct foo { + friend int cat(foo, foo); +}; +int dog(foo, foo); +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{C1}} +module; +#include "foo.h" // \tcode{dog} not referenced, discarded +export module C1; +import B; +export template +void h(T t) { + g(foo{ }, t); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit} +import C1; +void i() { + h(0); // error: \tcode{dog} not found at \#2 +} +\end{codeblocktu} + +\begin{codeblocktu}{Importable header \tcode{"bar.h"}} +struct bar { + friend int cat(bar, bar); +}; +int dog(bar, bar); +\end{codeblocktu} + +\begin{codeblocktu}{Module interface unit of \tcode{C2}} +module; +#include "bar.h" // imports header unit \tcode{"bar.h"} +export module C2; +import B; +export template +void j(T t) { + g(bar{ }, t); +} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit} +import C2; +void k() { + j(0); // OK, \tcode{dog} found in instantiation context: + // visible at end of module interface unit of \tcode{C2} +} +\end{codeblocktu} +\end{example} + \rSec2[temp.inject]{Friend names declared within a class template} \pnum