diff --git a/src/basic.tex b/src/basic.tex index f594a4c..1a38779 100644 --- a/src/basic.tex +++ b/src/basic.tex @@ -1,153 +1,92 @@ %!TEX root = std.tex +\setcounter{chapter}{5} \rSec0[basic]{Basic concepts} -%gram: \rSec1[gram.basic]{Basic concepts} -%gram: - -\noindent -Modify paragraph 6/3 as follows: - -%\pnum -\resetalinea[2] -\begin{std.txt} -\alinea - An \emph{entity} is a value, object, reference, function, - enumerator, type, class member, bit-field, template, template - specialization, namespace, \added{module}, or parameter pack. -\end{std.txt} - -\noindent -Modify paragraph 6/4 as follows: - -\resetalinea[3] -\begin{std.txt} -\alinea - A \emph{name} is a use of an \grammarterm{identifier} (5.10), - \grammarterm{operator-function-id} (16.5), \grammarterm{literal-operator-id} - (16.5.8), - \grammarterm{conversion-function-id} (15.3.2), \removed{or } - \grammarterm{template-id} (17.2), \added{or \grammarterm{module-name} (10.7)} that - denotes an entity or \grammarterm{label} (9.6.4, 9.1). -\end{std.txt} - -\noindent -Add a sixth bullet to paragraph 6/8 as follows: - -\resetalinea[7] -\begin{std.txt}\color{addclr} - \begin{itemize} - \item[--] \added{they are \grammarterm{module-name}{s} composed of the same - dotted sequence of \grammarterm{identifier}{s}.} - \end{itemize} -\end{std.txt} - \rSec1[basic.def]{Declarations and definitions} Modify paragraph 6.1/1 as follows: + \begin{std.txt} - \resetalinea[0] - \alinea + \pnum[1] A declaration (Clause \ref{dcl.dcl}) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations. If so, the declaration specifies the interpretation and - \removed{attributes}\added{semantic properties} of these names. [...] + \removed{attributes}\added{semantic properties} of these names. + [...] \end{std.txt} -\noindent -Append the following two bullets to paragraph 6.1/2: +\rSec1[basic.def.odr]{One-definition rule} + +Change paragraph 6.2/1 as follows: \begin{std.txt} - \resetalinea[1] - \alinea - A declaration is a \term{definition} unless - \begin{itemize} - \item ... - \item it is an explicit specialization (17.7.3) whose \grammarterm{declaration} - is not definition\removed{.}\added{,} - \color{addclr} - \item \added{it is a \grammarterm{module-import-declaration},} - \item \added{it is a \grammarterm{proclaimed-ownership-declaration}.} - \end{itemize} - \color{addclr} -% \begin{example} -\enterexample -\begin{codeblock} - import std.io; // make names from std.io available - export module M; // toplevel declaration for M - export struct Point { // define and export Point - int x; - int y; - }; -\end{codeblock} -\exitexample + \pnum[1] + \removed{No translation unit shall contain more than one definition + of any} + \added{A} + variable, function, class type, enumeration type, or template + \added{shall not be defined where a prior definition is necessarily reachable + (\ref{module.reach}); + no diagnostic is required if the prior declaration is in another translation unit}. \end{std.txt} +Modify the end of paragraph 6.2/10 as follows -\rSec1[basic.def.odr]{One-definition rule} +\begin{std.txt} +\pnum[10] +[...] +\removed{An} +\added{A definition of an} +inline function or variable shall be \removed{defined} \added{reachable} +in every translation unit in which it is odr-used outside of a discarded statement. +\end{std.txt} -Replace paragraph 6.2/1 with: -\begin{std.txt}\color{addclr} - \resetalinea[0] - \alinea - \added{A variable, function, class type, enumeration type, or template shall not - be defined where a prior definition is reachable (\ref{basic.lookup}).} +Modify paragraph 6.2/11 as follows + +\begin{std.txt} +\pnum[11] +\removed{Exactly one} +\added{A} definition of a class is required \added{to be reachable} +\removed{in a translation unit if} \added{in every context in which} +the class is used in a way that requires the class type to be complete. \end{std.txt} -Modify opening of paragraph 6.2/6 as follows +Modify opening of paragraph 6.2/12 as follows + \begin{std.txt} - \resetalinea[5] - \alinea - There can be more than one definition of a class type (Clause 12), - enumeration type (10.2), inline function with external \added{or module} - linkage (10.1.6), - inline variable with external \added{or module} linkage (10.1.6), - class template (Clause 17), - non-static function template (17.5.6), static data member of a class - template (17.5.1.3), member function of a class template (17.5.1.1), or - template specialization for which some template parameters are not - specified (17.7, 17.5.5) in a program provided that \removed{each definition appears + \pnum[12] + There can be more than one definition of a class type (Clause 10), + enumeration type (9.6), inline function with external + linkage (9.1.6), + inline variable with external linkage (9.1.6), + class template (Clause 12), + non-static function template (12.6.6), + static data member of a class + template (12.6.1.3), member function of a class template (12.6.1.1), or + template specialization for which some template parameters are not + specified (12.8, 12.6.5) in a program provided that + \removed{each definition appears in a different translation unit} - \added{no prior definition is reachable (\ref{basic.lookup}) at the point where a definition appears}, - and provided the definitions satisfy the - following requirements. - \added{For an entity with an exported declaration, there shall be only one - definition of that entity; a diagnostic is required only if the abstract - semantics graph of the module contains a definition of the entity.} - \added{\enternote - If the definition is not in the interface unit, then at most one module unit can - have and make use of the definition. - \exitnote} - Given such an entity named \tcode{D} defined in more than one + \added{no prior definition is necessarily reachable (\ref{module.reach}) + at the point where a definition appears}, + and provided the definitions satisfy the + following requirements. + \added{There shall not be more than one definition + of an entity + that is attached to a named module (\ref{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 \end{std.txt} - - \rSec1[basic.scope]{Scope}% -\setcounter{subsection}{1} -\rSec2[basic.scope.pdecl]{Point of declaration} - -\noindent -Add a new paragraph 6.3.2/13 as follows: -\resetalinea[12] -\begin{std.txt}\color{addclr} -\alinea - \added{The point of declaration of a module is immediately after the - \term{module-name} in a \grammarterm{module-declaration}.} -\end{std.txt} - \setcounter{subsection}{5} \rSec2[basic.scope.namespace]{Namespace scope} -From end-user perspective, there are really no new lookup rules to -learn. The ``old'' rules are the ``new'' rules, with appropriate -adjustment in the definition of ``associated entities.'' - -\noindent Modify paragraph 6.3.6/1 as follows: \begin{std.txt} - \resetalinea[0] - \alinea + \pnum[1] The declarative region of a \grammarterm{namespace-definition} is its \grammarterm{namespace-body}. Entities declared in a \grammarterm{namespace-body} @@ -159,10 +98,12 @@ scope. Its potential scope includes its namespace from the name's point of declaration (6.3.2) onwards; and for each \grammarterm{using-directive} - (10.3.4) that nominates the member's namespace, the member's + (9.7.3) 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. \added{If a name $X$ (not having internal linkage) is declared + declaration. +\begin{before} +\added{If a name $X$ (not having internal linkage) is declared in a namespace $N$ in the purview of the module interface unit of a module $M$, the potential scope of $X$ includes the portion of the namespace $N$ in the purview of @@ -170,22 +111,49 @@ and, if the name $X$ is exported, in every translation unit that imports $M$ after a \grammarterm{module-import-declaration} nominating $M$. } +\end{before} +\begin{after} +\added{% +If a translation unit $Q$ is imported into a translation unit $R$ (\ref{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 +} \color{addclr} +\begin{itemize} +\item \added{$X$ does not have internal linkage, and} +\item \added{$X$ is declared after the \grammarterm{module-declaration} in $Q$ (if any), and} +\item \added{either $X$ is exported or $Q$ and $R$ are part of the same module.} +\end{itemize} +\end{after} \color{addclr} % ; and for each \term{module-import-declaration} that nominates M, % the potential scope of X includes the % portion of the potential scope of the \term{using-directive} that % follows that \term{module-import-declaration}. - \enterexample + \added{\enternote + 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. + \enterexample} \begin{codeblock} // Translation unit \#1 - export module M; + export module Q; export int sq(int i) { return i*i; } // Translation unit \#2 - import M; - int main() { return sq(9); } // OK: 'sq' from module M + export module R; + export import Q; + + // Translation unit \#3 + import R; + int main() { return sq(9); } // OK: \tcode{sq} from module \tcode{Q} \end{codeblock} + \added{ \exitexample + \exitnote} \end{std.txt} @@ -194,44 +162,41 @@ Modify paragraph 6.4/1 as follows: \begin{std.txt} - \resetalinea[0] - \alinea + \pnum[1] The name lookup rules apply uniformly to all names - (including \grammarterm{typedef-name}{s} (10.1.3), - \grammarterm{namespace-name}{s} (10.3), and - \grammarterm{class-name}{s} (12.1)) + (including \grammarterm{typedef-name}{s} (9.1.3), + \grammarterm{namespace-name}{s} (9.7), and + \grammarterm{class-name}{s} (10.1)) wherever the grammar allows such names in the context discussed by a particular rule. Name lookup associates the use of a name with a set of declarations (6.1) - \added{or citations (\ref{dcl.module.import})} of that name. - \added{For all intent and purposes of further semantic processing - requiring declarations, - a citation is replaced with the declarations contained in its declset.} + of that name. [...] Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the - \removed{attributes}\added{semantic properties} introduced by the name's - declaration used further in the expression processing (Clause 8). - + \removed{attributes}\added{semantic properties} introduced by + the name's declaration + \added{and its reachable (\ref{module.reach}) redeclarations} + used further in the expression processing (Clause 7). \end{std.txt} +% Moved to module.reach with some changes. +\begin{before} Add new paragraph 6.4/5 as follows: \begin{std.txt}\color{addclr} - \resetalinea[4] - \alinea + \pnum[5] \added{A declaration is \term{reachable} from a program point if it can be found by unqualified name lookup in its scope.} \end{std.txt} +\end{before} \setcounter{subsection}{1} \rSec2[basic.lookup.argdep]{Argument-dependent name lookup} -\noindent Modify paragraph 6.4.2/2 as follows: \begin{std.txt} - \resetalinea[1] - \alinea + \pnum[2] For each argument type \tcode{T} in the function call, there is a - set of zero or more \term{associated namespaces} (10.3) and a set of + set of zero or more \term{associated namespaces} and a set of zero or more \term{associated \removed{classes} \added{entities}} \added{(other than namespaces)} to be considered. The sets of namespaces and \removed{classes} \added{entities} are determined @@ -242,10 +207,10 @@ and \removed{classes} \added{entities} are determined in the following way: \begin{itemize} - \item[---] If \tcode{T} is a fundamental type, its associated sets + \item If \tcode{T} is a fundamental type, its associated sets of namespaces and \removed{classes} \added{entities} are both empty. - \item[---] If \tcode{T} is a class type (including unions), its + \item If \tcode{T} is a class type (including unions), its associated \removed{classes} \added{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 @@ -261,29 +226,29 @@ template arguments are members. \enternote Non-type template arguments do not contribute to the set of associated namespaces. \exitnote - \item[---] If \tcode{T} is an enumeration type, its associated + \item If \tcode{T} is an enumeration type, its associated namespace is the innermost enclosing namespace of its - declaration\added{, and its associated entities are \tcode{T}, and, + declaration\added{, and its associated entities are \tcode{T} and, if}\removed{. If} it is a class member, \removed{its associated class is} the member's class\removed{; else it has no associated class}. - \item[---] If \tcode{T} is a pointer to \tcode{U} or an array + \item If \tcode{T} is a pointer to \tcode{U} or an array of \tcode{U}, its associated namespaces and \removed{classes} \added{entities} are those associated with \tcode{U}. - \item[---] If \tcode{T} is a function type, its associated + \item If \tcode{T} is a function type, its associated namespaces and \removed{classes} \added{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 data member of + \item If \tcode{T} is a pointer to a data member of class \tcode{X}, its associated namespaces and \removed{classes} \added{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 (10.3.1), its + If an associated namespace is an inline namespace (9.7.1), its enclosing namespace is also included in the set. If an associated namespace directly contains inline namespaces, those inline namespaces are also included in the set. In addition, if the @@ -300,213 +265,351 @@ template \grammarterm{template-argument}{s}. \end{std.txt} -\noindent -Modify paragraph 6.4.2/4 as follows: +Modify paragraph 6.4.2/4 and add /5 as follows: \begin{std.txt} - \resetalinea[3] - \alinea - When considering an associated namespace, the lookup is the same as - the lookup performed when the associated namespace is used as a + \pnum[4] + When considering an associated namespace \added{\tcode{N}}, + the lookup is the same as + the lookup performed when \removed{the associated namespace} + \added{\tcode{N}} is used as a qualifier (6.4.3.2) except that: \begin{itemize} - \item[---] Any \grammarterm{using-directive}{s} in the associated - namespace are ignored. - - \item Any namespace-scope friend declaration functions or friend - function templates declared in \removed{associated} - classes \added{in the set of associated entities} are visible within + \item Any \grammarterm{using-directive}{s} in \removed{the associated + namespace} \added{\tcode{N}} are ignored. + + \item Any namespace-scope friend functions or friend + function templates (10.7.3) declared in \removed{associated} + classes \added{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 (14.3). + ordinary lookup (9.7.1.2). \item All names except those of (possibly overloaded) functions and function templates are ignored. \color{addclr} - \item[---] \added{In resolving dependent names (17.6.4), - any function or function template that is owned by a - named module \tcode{M} (10.7), that is - declared in the module interface unit of \tcode{M}, and that has - the same innermost enclosing non-inline namespace as some entity - owned by \tcode{M} in the set of associated entities, is visible - within its namespace even if it is not exported.} + \item + \added{Any declaration \tcode{D} in \tcode{N} + that is in the interface of + a named module \tcode{M} (\ref{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 + \added{If the lookup is for a dependent name + (\stdref{temp.dep}{12.7.2}, \ref{temp.dep.candidate}), + any declaration \tcode{D} in \tcode{N} + is visible + if \tcode{D} would be visible to qualified name lookup (\ref{namespace.qual}) + at any point in the instantiation context (\ref{module.context}) of the lookup, + unless \tcode{D} is declared in another translation unit, attached to the global module, + and is either discarded (\ref{module.global}) or has internal linkage.} \end{itemize} + +\pnum +\color{addclr} +\added{\enterexample} +\begin{codeblock} +// TU 1 +export module M; +namespace R { + export struct X {}; + export void f(X); +} +namespace S { + export void f(X, X); +} +\end{codeblock} + +\begin{codeblock} +// TU 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{codeblock} + +\begin{codeblock} +// TU 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{codeblock} +\added{\exitexample} +\end{std.txt} + +\setcounter{subsection}{2} +\rSec2[basic.lookup.qual]{Qualified name lookup} + +\setcounter{subsubsection}{1} +\rSec3[namespace.qual]{Namespace members} + +Change in paragraph 2: + +\begin{std.txt} +\pnum[2] +For a namespace \tcode{X} +and name \tcode{m}, +the namespace-qualified lookup set \tcode{S(X,m)} is defined as follows: +Let \tcode{S'(X,m)} be the set of all declarations of \tcode{m} in \tcode{X} +and the inline namespace set of \tcode{X} (9.7.1) +\added{whose potential scope (\stdref{basic.scope.namespace}{6.3.6}) +would include the namespace in which \tcode{m} is declared +at the location of the \grammarterm{nested-name-specifier}{}}. +If \tcode{S'(X,m)} is not empty, \tcode{S(X, m)} is \tcode{S'(X, m)}; +otherwise, \tcode{S(X, m)} is the union of \tcode{S(Ni, m)} +for all namespaces \tcode{Ni} nominated by \grammarterm{using-directives} +in \tcode{X} and its inline namespace set. \end{std.txt} \setcounter{section}{4} \rSec1[basic.link]{Program and linkage}% -\resetalinea[0] - Change the definition of \term{translation-unit} in paragraph 6.5/1 to: +\begin{bnf} +\nonterminal{translation-unit}:\br + \added{top-level-}declaration-seq\opt\br + \added{global-module-fragment\opt module-declaration top-level-declaration-seq\opt private-module-fragment\opt} +\end{bnf} -\begin{bnf}\color{addclr} - \added{\nonterminal{translation-unit}\br - toplevel-declaration-seq\opt} +\begin{bnf} +\added{\nonterminal{private-module-fragment}:\br + \terminal{module} \terminal{:} \terminal{private} \terminal{;} top-level-declaration-seq\opt} \end{bnf} \begin{bnf}\color{addclr} - \added{\nonterminal{toplevel-declaration-seq}\br - toplevel-declaration\br - toplevel-declaration-seq toplevel-declaration} + \added{\nonterminal{top-level-declaration-seq}:\br + top-level-declaration\br + top-level-declaration-seq top-level-declaration} \end{bnf} \begin{bnf}\color{addclr} - \added{\nonterminal{toplevel-declaration}\br - module-declaration\br + \added{\nonterminal{top-level-declaration}:\br + module-import-declaration\br declaration} \end{bnf} +Add new paragraphs after the grammar: +\begin{std.txt} +\pnum[1] +\added{A \grammarterm{private-module-fragment} shall appear only +in a primary module interface unit (\ref{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 +\added{A token sequence beginning with +\tcode{export}\opt{} \tcode{module} or +\tcode{export}\opt{} \tcode{import} +and not immediately followed by \tcode{::} +is never interpreted as the \grammarterm{declaration} +of a \grammarterm{top-level-declaration}.} +\end{std.txt} -\noindent Insert a new bullet between first and second bullet of paragraph 6.5/2: \begin{std.txt}\color{addclr} \begin{itemize} - \item[---] \added{When a name has \term{module linkage}, the entity it denotes + \item \added{When a name has \term{module linkage}, the entity it denotes can be referred to by names - from other scopes of the same module unit (\ref{dcl.module.unit}) + from other scopes of the same module unit (\ref{module.unit}) or from scopes of other module units of that same module.} \end{itemize} \end{std.txt} -\noindent Modify bullet (3.2) of paragraph 6.5/3 as follows: \begin{std.txt} \begin{itemize} - \item[---] a non-inline \added{non-exported} variable of non-volatile const-qualified type - that is neither explicitly declared \tcode{extern} nor - previously declared to have external \added{or module} linkage; or + \item + %a non-inline \added{non-exported} variable of non-volatile const-qualified type + %that is neither explicitly declared \tcode{extern} nor + %previously declared to have external \added{or module} linkage; or + a \removed{non-inline} variable of non-volatile const-qualified type\added{, + unless} + \begin{itemize} + \color{addclr} + \item \added{it is explicitly declared \tcode{extern}, or} + \item \added{it is inline or exported, or} + \item \added{it was previously declared and the prior declaration did + not have internal linkage; or} + \end{itemize} + \removed{that is neither explicitly declared \tcode{extern} nor + previously declared to have external linkage; or} \end{itemize} \end{std.txt} -\noindent Modify paragraph 6.5/4 as follows: -%\begin{std.txt} -% \resetalinea[3] -% \alinea -% An unnamed namespace or a namespace declared directly or -% indirectly within an unnamed namespace has internal linkage. All other -% namespaces have external linkage. -% \added{A name declared at namespace scope in the purview of a named module -% that does not have internal linkage by the previous rules and that -% is not exported has module -% linkage. The name of any class member where the enclosing class has -% a name with module linkage also has module linkage.} -% A name having namespace scope that has -% not been given internal \added{or module} linkage above has the same linkage as the enclosing -% namespace if it is the name of -%\end{std.txt} -%% New wording suggested by Hubert Tong, on December 17, 2017. + \begin{std.txt} - \resetalinea[3] - \alinea - An unnamed namespace or a namespace declared directly or - indirectly within an unnamed namespace has internal linkage. All other - namespaces have external linkage. - A name having namespace scope that has - not been given internal linkage above \removed{has the same linkage as the enclosing + \pnum[4] + An unnamed namespace or a namespace declared directly or + indirectly within an unnamed namespace has internal linkage. All other + namespaces have external linkage. + A name having namespace scope that has + not been given internal linkage above \removed{has the same linkage as the enclosing namespace if it}\added{and that} is the name of \begin{itemize} \item a variable; or \item a function; or - \item a named class (Clause 12), or an unnamed class defined in a - typedef declaration in which the class has the typedef name for - linkage purposes (10.1.3); or - \item a named enumeration (10.2), or an unnamed enumeration defined in + \item a named class (Clause 10), or an unnamed class defined in a + typedef declaration in which the class has the typedef name for + linkage purposes (9.1.3); or + \item a named enumeration (9.6), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for - linkage purposes (10.1.3); or + linkage purposes (9.1.3); or \item a template\removed{.} \end{itemize} - \color{addclr} + \begin{before}\color{addclr} \added{has the same linkage as the enclosing namespace if} \begin{itemize} \item \added{said namespace has internal linkage, or} - \item \added{the name is exported (\ref{dcl.module.interface}), - or is declared in a \grammarterm{proclaimed-ownership-declaration}, + \item \added{the name is exported (\ref{module.interface}), or} + \added{is declared in a \grammarterm{proclaimed-ownership-declaration}, or is not being declared in the purview of - a named module (\ref{dcl.module.unit});} + a named module (\ref{module.unit});} \end{itemize} \added{otherwise, the name has module linkage.} + \end{before} + \begin{after}\color{addclr} + \added{has its linkage determined as follows:} + \begin{itemize}\color{addclr} + \item \added{if the enclosing namespace has internal linkage, + the name has internal linkage;} + \item \added{otherwise, if + the declaration of the name is + attached to a named module (\ref{module.unit}) + and is not exported (\ref{module.interface}), + the name has module linkage;} + \item \added{otherwise, the name has external linkage}. + \end{itemize} + \end{after} \end{std.txt} - -\noindent Modify 6.5/6 as follows: \begin{std.txt} -\resetalinea[5] -\alinea +\pnum[6] The name of a function declared in block scope and the name of a -variable declared by a block scope extern declaration have linkage. If -there is a visible declaration of an entity with linkage having the +variable declared by a block scope extern declaration have linkage. +\added{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 having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, the block scope declaration declares that same entity and receives the linkage of the previous declaration. -\added{If that entity was exported by an imported module or if the containing block scope is in the purview of a named module, the program is -ill-formed.} If +If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching entity is found, the block scope entity receives external linkage. \end{std.txt} -\noindent -Modify paragrapgh 6.5/9 as follows: +Modify paragraph 6.5/10 and add /11 as follows: \begin{std.txt} - \resetalinea[8] - \alinea - Two names that are the same (Clause 9) and that are declared in different scopes + \pnum[10] + \addtocounter{footnote}{1} + Two + names that are the same (Clause 6) and that are declared in different scopes shall denote the same variable, function, type, template or namespace if \begin{itemize} - \item[---] both names have external \added{or module} linkage - \added{and are declared in declarations attached to the - same module}{\color{addclr}\footnote{This provision supports implementations where - exported entities in different modules have different implementation - symbols. Conversely, for other implementations, exported entities - have the same implementation symbols regardless of in which - module they are declared. Such implementations are supported - for the time being by disallowing all situations where the same names - with external linkage might appear from different modules.}}\added{,} - or else both names have internal linkage and are declared in + \item both names have external \added{or module} linkage + \added{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 - \item when both names denote functions, the parameter-typelists of the - functions (11.3.5) are identical; and + \item when both names denote functions, the parameter-type-lists of the + functions (9.2.3.5) are identical; and - \item when both names denote function templates, the signatures (17.5.6.1) - ar the same. + \item when both names denote function templates, the signatures (12.6.6.1) + are the same. \end{itemize} - \added{If two declarations - declaring entities (other than namespaces) and attached to - different modules introduce two names that are the same - and that both have external linkage, the program is ill-formed; no - diagnostic required. + \added{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. \enternote \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, either. - \exitnote - } + merely introduce synonyms. Similarly, \grammarterm{using-directive}{s} + do not declare entities. + \exitnote} + + \pnum + \added{If a declaration would redeclare a reachable declaration + attached to a different module, the program is ill-formed.} + \color{addclr} + \begin{example} + \begin{codeblock} + // \tcode{"decls.h"} + int f(); // \#1, attached to the global module + int g(); // \#2, attached to the global module + + // 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 M + export int h(); // \#3 + export int k(); // \#4 + + // other translation unit + import M; + static int h(); // error: matches \#3 + int k(); // error: matches \#4 + \end{codeblock} + \end{example} + \added{As a consequence of these rules, + all declarations of an entity are attached to the same module; + the entity is said to be \term{attached} to that module.} \end{std.txt} -\setcounter{section}{5} -\rSec1[basic.start]{Start and termination} +\setcounter{section}{7} +\rSec1[basic.exec]{Program execution} + +\setcounter{subsection}{2} +\rSec2[basic.start]{Start and termination} -\setcounter{subsection}{0} -\rSec2[basic.start.main]{\tcode{main} function} +\setcounter{subsubsection}{0} +\rSec3[basic.start.main]{\tcode{main} function} -Modify paragraph 6.6.1/1 as follows: +Modify paragraph 6.8.3.1/1 as follows: \begin{std.txt} - \resetalinea[0] - \alinea + \pnum[1] A program shall contain a global function called \tcode{main} - \added{declared in the purview of the global module}. + \added{attached to the global module}. \end{std.txt} +Modify paragraph 6.8.3.1/3 as follows: +\begin{std.txt} + \pnum[3] + ... + A program that declares a variable \tcode{main} at global scope\added{, + 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. +\end{std.txt} diff --git a/src/bg.tex b/src/bg.tex new file mode 100644 index 0000000..e4e1916 --- /dev/null +++ b/src/bg.tex @@ -0,0 +1,682 @@ +\setcounter{chapter}{0} +\rSec0[bg]{Background} + +\rSec1[bg.intro]{Introduction} + +At the Jacksonville 2018 committee meeting, +P0947R0 (``Another Take On Modules'', +hereafter referred to as \term{Atom}) +was presented. Two options were polled: + +\begin{itemize} +\item merging the Atom proposal with the Modules TS, and +\item progressing the Atom proposal as a separate TS. +\end{itemize} + +Both options passed, but the first option had stronger support. + +At Rapperswill 2018, we presented P1103R0, representing +our effort in merging the two proposals +and the remaining outstanding questions from the merge. +Many open questions were answered, and we voted to adopt the +merged proposal into the Modules TS, and +scheduled a 2-day ad-hoc meeting to discuss the remaining +open questions. + +At the Bellevue 2018 ad-hoc Modules meeting, we answered all +remaining known open design questions. This paper provides a +description for the resulting design, as well as wording +(based on the wording in P1103R0, which in turn is based on +the wording of the Modules TS) to incorporate this design +into the C++20 working draft. + +\rSec1[bg.ack]{Acknowledgements} + +This paper is based on the work of a great many people. +The author would like to thank them all, and specifically +Gabriel Dos Reis, on whose Modules TS this paper is primarily +based. + +%\rSec1[bg.conventions]{Stylistic conventions} +% +%The wording section of this document describes a ``diff of a diff.'' +%The usual convention of using text style for \added{added} and +%\removed{removed} text does not work well for such situations. +%In its place, we use block-style diffs +%showing the text of the Modules TS +%before and after this document is applied: +% +%\begin{before} +%Here is some text from the \Cpp standard +%\added{with some additions from the Modules TS}. +%\end{before} +% +%\begin{after} +%Here is some text from the \Cpp standard +%\added{with some additions from the Modules TS} +%\added{and some more from the Atom proposal}. +%\end{after} +% +%Unchanged text from the Modules TS is retained in this document so that a +%complete picture of the ``after'' wording may be obtained by simply ignoring +%the ``before'' regions. + +\rSec0[merged]{Summary of merged proposal} + +\rSec1[merged.basic]{Basics} + +\pnum +A \term{module unit} is a translation unit that forms part of a module. +Such a translation unit begins with% +\footnote{A global module fragment (\ref{merged.global.frag}) may optionally +precede the preamble.} +a preamble, +comprising a module declaration +and a sequence of imports: + +\begin{codeblock} +export@\opt@ module foo; +import a; +export import b; +// ... more imports ... +\end{codeblock} + +Within a module unit, imports may not appear after the end of the preamble. +The \tcode{export} keyword indicates that a module unit is a +\term{module interface unit}, which defines the interface for the module. +For a module \tcode{foo}, there must be exactly one +translation unit whose preamble contains \tcode{export module foo;}. +This is the \term{primary module interface unit} +for \tcode{foo}~(\ref{merged.part}). +(All other module interface units are module interface partitions; +see \ref{merged.part}.) + +\pnum +Two related but distinct notions are key to understanding module semantics: +\begin{itemize} +\item A declaration is \term{visible} in a context if it can be found by a +suitable name lookup. +\item A declaration is \term{reachable} in a context if its semantic effects +are available for use. (For example, a class type is complete in contexts +where a definition of the class is reachable.) +\end{itemize} +A declaration is reachable wherever it is visible, but the converse is not true +in general. +Imports control which namespace-scope names are visible to name lookup, +and which declarations are reachable semantically. +The behavior of an entity is determined by +the set of reachable declarations of that entity. +For example, class members and enumeration members are visible to name lookup +if there is a reachable definition of the class or enumeration. + +\pnum +A declaration can be exported by use of the \tcode{export} keyword +in a module interface unit: +\begin{codeblock} +export int a; +export { +void f(); +} +\end{codeblock} +Exported declarations in a module interface unit +are visible to name lookup +in contexts that import that module interface unit. +Non-exported declarations (excluding those with internal linkage) +in a module unit +are visible to name lookup +in contexts within the same module that import the module unit. +All declarations in transitively-imported module units +are reachable, whether or not they are exported. +\begin{example} +\begin{codeblock} +// a.cpp +export module A; // interface of module \tcode{A} +int foo() { return 1; } +export int bar(); +\end{codeblock} + +\begin{codeblock} +// a-impl.cpp +module A; // implementation of module \tcode{A}, implicitly + // considered to import the interface of \tcode{A} +// OK; \tcode{foo()} is visible here (in the same module) even though +// it was not exported from \tcode{A} +int bar() { return foo() + 1; } +\end{codeblock} + +\begin{codeblock} +// unrelated.cpp +import A; +int main() { + bar(); // OK, \tcode{bar} was exported by \tcode{A} and is visible here + foo(); // error: \tcode{foo} is not visible here +} +\end{codeblock} +\end{example} + +\pnum +If a declaration within a namespace is exported, +the enclosing namespace is also implicitly exported +(but other declarations in the namespace are not implicitly exported). +If a namespace is explicitly exported, +all declarations within that namespace definition are exported. + +\rSec1[merged.part]{Module partitions} + +\pnum +A complete module can be defined in a single source file. +However, the design, nature, and size of a module may warrant +dividing both the implementation and the interface +into multiple files. +Module partitions provide facilities to support this. + +\pnum +The module interface may be split across multiple files, +if desired. +Such files are called \term{module interface partition}{s}, and are +introduced by a module declaration containing a colon: + +\begin{codeblock} +export module foo:part; +\end{codeblock} + +\pnum +Module interface partitions behave logically like distinct modules, +except that they share ownership of contained entities +with the module that they form part of. +This allows an entity to be declared in one partition +and defined in another, +which may be necessary to resolve +dependency cycles. +It also permits code to be moved between partitions of a module +with no impact on ABI. + +\pnum +The primary module interface unit for a module is required +to transitively import and re-export all of the interface +partitions of the module. + +\pnum +When the implementation of a module is split across multiple files, +it may be desirable to share declarations between the implementation units +without including them in the module interface unit, +in order to avoid all consumers of the module +having a physical dependency on the implementation details. +(Specifically, if the implementation details change, +the module interface and its dependencies should not need to be rebuilt.) +This is made possible by \term{module implementation partition}{s}, +which are module partitions that do not form part of the module interface: + +\begin{codeblock} +module foo:part; +\end{codeblock} + +\pnum +Module implementation partitions cannot contain exported declarations; +instead, all declarations within them are visible to other translation +units in the same module that import the partition. +\begin{note} +Exportation only affects which names and declarations are visible outside +the module. +\end{note} + +\pnum +Module implementation partitions can be imported +into the interface of a module, +but cannot be exported. + +\pnum +Module interface partitions and module implementation partitions +are collectively known as \term{module partition}{s}. +Module partitions are an implementation detail of the module, +and cannot be named outside the module. +To emphasize this, an import declaration naming a module partition +cannot be given a module name, only a partition name: + +\begin{codeblock} +module foo; +import :part; // imports foo:part +import bar:part; // syntax error +import foo:part; // syntax error +\end{codeblock} + +\rSec1[merged.nonmodular]{Support for non-modular code} + +\pnum +This proposal provides several features to support +interoperation between modular code +and traditional non-modular code. + +\rSec2[merged.global.frag]{Global module fragment} + +\pnum +The merged proposal permits Modules TS-style global module fragments, +with the \tcode{module;} introducer proposed in P0713R1 +and approved by EWG: + +\begin{codeblock} +module; +#include "some-header.h" +export module foo; +// ... use declarations and macros from some-header.h ... +\end{codeblock} + +\pnum +Prior to preprocessing, only preprocessor directives can appear +in the global module fragment, but those directives can include +\tcode{\#include} directives that expand to declarations, as usual. +Declarations in the global module fragment +are not owned by the module. + +\pnum +In order to avoid bloating the interface of a module with declarations +included into its global module fragment, declarations in the global +module fragment that are not (transitively) referenced by the module unit are +discarded. +In particular, such declarations are not reachable from other translation +units that import the module unit, and cannot be found by the second phase +of two-phase name lookup for a template instantiation whose point of +instantiation is outside the module unit. +A declaration in a global module fragment is considered to be referenced if it +is named within the module unit (after the preamble), or if it is mentioned +by a referenced declaration. + +\pnum +\begin{example} +\begin{codeblock} +module; +#include "some-header.h" // defines classes \tcode{X}, \tcode{Y}, \tcode{Z} +export module foo; + +export using X = ::X; // export name \tcode{X}; retain all declarations + // of \tcode{X} from \tcode{"some-header.h"} +export Y f(); // export name \tcode{f}; retain all declarations + // of \tcode{Y} from \tcode{"some-header.h"} +// \tcode{Z} is not mentioned, so is discarded +\end{codeblock} +\end{example} + +\rSec2[merged.header.import]{Header units} + +\pnum +The merged proposal also permits Atom-style header units, +which are introduced by a special \tcode{import} syntax +that names a header file instead of a module: + +\begin{codeblock} +export module foo; +import "some-header.h"; +import ; +// ... use declarations and macros from some-header.h and ... +\end{codeblock} + +\pnum +The named header is processed as if it was a source file, +the interface of the header is extracted and made available for import, +and any macros defined by preprocessing the header are saved +so that they can be made available to importers. + +\pnum +Declarations from code in a header unit +are not owned by any module. +In particular, the same entities can be redeclared +by another header unit or by non-modular code. +Header units can be re-exported +using the regular \tcode{export import} syntax: + +\begin{codeblock} +export module foo; +export import "some-header.h"; +\end{codeblock} + +However, when a header unit is re-exported, +macros are not exported. +Only the header import syntax can import macros. + +\rSec2[merged.nonmodular.reachability]{Reachability of nonmodular declarations} + +\pnum +A declaration in a global module fragment or header unit +is reachable if it is visible. +It is unspecified whether such a declaration is also reachable +in contexts where it is not visible but is transitively +imported. +(Ideally, such a declaration would not be considered reachable +in such contexts. However, in practice, making transitively-imported +declarations unreachable would impose a severe implementation +cost for some implementations, so we leave the extent to which +this rule is enforced up to the implementation.) + +\pnum +Discarded declarations (\ref{merged.global.frag}) from the global module +fragment are never visible nor reachable from outside that module unit. + +\rSec2[merged.nonmodular.use]{Module use from non-modular code} + +\pnum +Modules and header units can be imported into non-modular code. +Such imports can appear anywhere, and are not restricted to a preamble. +This permits ``bottom-up'' modularization, +whereby a library switches to providing only a modular interface +and defining its header interface in terms of the modular interface. +Non-modular code includes translation units other than module units +(including headers imported as header units), and the global module fragment +of a module unit. + +\pnum +When a \tcode{\#include} appears within non-modular code, +if the named header file is known to correspond to a header unit, +the implementation treats the \tcode{\#include} as an import +of the corresponding header unit. +The mechanism for discovering this correspondence +is left implementation-defined; +there are multiple viable strategies here +(such as explicitly building header units and +providing them as input to downstream compilations, or +introducing accompanying files describing the header unit structure) +and we wish to encourage exploration of this space. +An implementation is also permitted to not provide any mapping mechanism, +and process each header unit independently. + +\rSec0[vs]{Comparison to prior proposals} + +\rSec1[vs.r2]{Changes since R2} + +\pnum +This section lists changes to the design of the merged modules proposal +since P1103R2. + +\begin{itemize} +\item +Addressed wording feedback from CWG and other parties. +\item +Fixed bug where an incidentally-reachable definition could render other +definitions of the same entity ill-formed: +\begin{codeblock} +// a.h +#ifndef A_H +#define A_H +class X {}; +#endif + +// b.cc +#include "a.h" +export module B; +X x; + +// c.cc +export module C; +import B; // not exported + +// d.cc +import C; +#include "a.h" // OK even if definition of X is incidentally visible + // due to semantic boundaries rule +\end{codeblock} +\item +Fixed unintended divergence from Modules TS that permitted module linkage +entities to have definitions in multiple module units +\end{itemize} + +\rSec1[vs.r1]{Changes since R1} + +\pnum +This section lists changes to the design of the merged modules proposal +since P1103R1. + +\rSec2[vs.r1.p1299r2]{P1299R2: Module preamble is unnecessarily fragile} + +\pnum +Prior revisions of this proposal prohibited macros imported from header +units from affecting the set of imports of a module. However, the +complexity of the resulting rule -- for both users and implementations +-- was not considered to be justified by the expected benefit for +tools wishing to perform dependency extraction, so this rule has been +removed. + +\pnum +In this proposal, macros imported from a header unit become available +immediately after the import as described in \ref{vs.r0.preamble}, +but unlike in R0, such macros can be expanded prior to later +imports in the preamble of a module unit. + +\rSec2[vs.r1.p1242r1]{P1242R1: Single-file modules} + +\pnum +As described in \ref{vs.ts}, this proposal removes the +Modules TS ``attendant entities'' rule. +This left a feature vacuum: +there was no longer a way to define a module entirely in a single file +without module implementation details being available outside the module. + +\pnum +In this proposal, a complete module +(with both interface and implementation) +can be defined in a single source file +by separating the interface from the implementation +with a +\begin{codeblock} +module :private; +\end{codeblock} +marker. + +\rSec1[vs.r0]{Changes since R0} + +\pnum +This section lists changes to the design of the merged modules proposal +since P1103R0. + +\rSec2[vs.r0.namespace]{Namespace export} + +\pnum +In P1103R0 and in the Modules TS, +all namespaces +(excluding anonymous namespaces and those nested within them) +that are declared in a module interface unit +have external linkage and +are exported. +Following strong EWG direction in Rapperswil, +in this document such namespace names +are only exported if they are either +explicitly exported, or +if any name within them is exported. +\begin{note} +The new approach permits implementation-detail namespace names +to be hidden from the interface of a module +despite being declared in a module interface unit. +\end{note} +\begin{example} +\begin{codeblock} +export module M; + +export namespace A {} // exported +namespace B { // exported + export int n; +} +namespace C { // not exported in this proposal, exported in TS / P1103R0 + int n; +} +\end{codeblock} +\end{example} + +\rSec2[vs.r0.templates]{Reachability in template instantiations} + +\pnum +Following discussion and direction from Bellevue, +we use a path of instantiation rule to guide +visibility and reachability of declarations +within a template instantiation, based on +the relevant rule from the Atom proposal: + +\hfill\begin{minipage}{\dimexpr\textwidth-1cm} +Within a template instantiation, the \term{path of instantiation} +is a sequence of locations within the program, +starting from the ultimate point of instantiation, +via each intervening template instantiation, +terminating at the instantiation in question. +Names are visible and semantic properties are available +within template instantiations +if they would be visible or available +at any point along the path of instantiation, +or (for points outside the current translation unit) +would be visible or available +at the end of the translation unit +containing the relevant point of instantiation. +\begin{flushright} +--- P0947R1, 7.1 Templates and two-phase name lookup +\end{flushright} +\end{minipage} + +This rule permits a template to make use of all declarations +that were visible or reachable at each point along its path of instantiation, +even if those declarations are not visible or reachable +in the template definition context nor the template instantiation context. + +\pnum +\begin{example} +\begin{codeblock} +export module A; +export template void f(T t, U u) { + t.f(); +} +\end{codeblock} + +\begin{codeblock} +module; +struct S { void f(); }; +export module B; +import A; +export template void g(U u) { S s; f(s, u); } +\end{codeblock} + +\begin{codeblock} +export module C; +import B; +export template void h(const U &u) { g(u); } +\end{codeblock} + +\begin{codeblock} +import C; +int main() { h(0); } +\end{codeblock} + +The definition of \tcode{struct S} and +the declaration of its member \tcode{f} +are not reachable from the point of instantiation +of \tcode{f}, nor from the template definition. +But this code is valid under this proposal, because +\tcode{S} is reachable from module \tcode{B}, which +is on the path of instantiation. +\end{example} + +\pnum +As described above (\ref{merged.nonmodular.reachability}), +implementations are permitted to treat additional declarations +as reachable even if they would not be reachable on the +path of instantiation, +if they are transitively imported at the +point of instantiation. +\begin{example} +\begin{codeblock} +module M; +struct S; +import C; +// unspecified whether a definition of \tcode{S} is reachable +// here or in the instantiation of \tcode{h} +void q(const S &s) { h(s); } +\end{codeblock} +\end{example} + +\pnum +The same rule applies to the set of names found by ADL: +names visible along the path of instantiation are visible to ADL. +Internal-linkage declarations within the global module are ignored. +In addition, exported declarations in the owning module of +each associated type are visible to ADL. + +\rSec2[vs.r0.preamble]{Finding the end of the preamble} + +\pnum +In R0 of this proposal, the preprocessor was burdened with finding +the end of the preamble, and making macros from header units +visible at that point. +That was problematic both for implementers (as it is a challenging rule +to implement) and for users (as code would silently do something +different from what was expected, and imports in a preamble would +behave differently from imports in non-modular code). +This proposal uses a simpler rule: +imported macros become visible immediately after the import declaration. + +\rSec1[vs.ts]{Changes to the Modules TS} + +\pnum +This section lists the ways in which valid code under the Modules TS +would become invalid or change meaning in this merged proposal. + +\pnum +A \tcode{module;} introducer is required prior to a global module fragment, +as described in P0713R1 and approved by Evolution. + +\pnum +When an entity is owned by a module and is never exported, +but is referenced by an exported part of the module interface, +the Modules TS would export the semantic properties +associated with the entity at the point of the export. +If multiple such exports give the entity different semantics, +the program is ill-formed: + +\begin{codeblock} +export module M; +struct S; +export S f(); // \tcode{S} incomplete here +struct S {}; +export S g(); // \tcode{S} complete here, error +\end{codeblock} + +Under the Atom proposal, +the semantics of such entities +are instead determined their the properties +at the end of the module interface unit. + +In this merged proposal, +the semantics of all entities owned by a module +are determined by their properties +at the end of the module interface unit +(regardless of whether they are exported). +\begin{note} +The order in which declarations appear within a module interface +has no bearing on which semantic properties are exported +in this merged proposal. +\end{note} + +The Modules TS ``attendant entities'' rule is removed, +because there are no longer any cases where it could apply. + +\pnum +Entities declared within \tcode{extern "C"} and \tcode{extern "C++"} +within a module are no longer owned by that module. +It is unclear whether this is a change from the intent of +the Modules TS. + +\pnum +Namespace names are exported less often in this proposal, as discussed above. + +\rSec1[vs.atom]{Changes relative to the Atom proposal} + +\pnum +This section lists the ways in which valid code under the Atom proposal +would become invalid or change meaning in this merged proposal. + +\pnum +The merged proposal supports global module fragments, +which interferes with the Atom proposal's goal +of making the preamble easy to identify and process +with non-compiler tools. +However, the benefits of the Atom approach are still available +to those who choose not to put code in the global module fragment. + +\pnum +The identifiers \tcode{export} and \tcode{module} are taken as keywords +by the merged proposal, +rather than making them context-sensitive as proposed by the Atom proposal. +This follows EWG's direction on this question from discussion of P0924R0. diff --git a/src/classes.tex b/src/classes.tex index 967bb4a..d39a473 100644 --- a/src/classes.tex +++ b/src/classes.tex @@ -1,17 +1,16 @@ %!TEX root = std.tex -\setcounter{chapter}{11} +\setcounter{chapter}{9} \rSec0[class]{Classes} \setcounter{section}{1} \rSec1[class.mem]{Class members} -\setcounter{subsection}{3} +\setcounter{subsection}{9} \rSec2[class.bit]{Bit-fields} -Modify paragraph 12.2.4/1 as follows: +Modify paragraph 10.2.10/1 as follows: \begin{std.txt} - \resetalinea[0] - \alinea + \pnum[1] [...] The bit-field \removed{attribute}\added{semantic property} is not part of the type of the class member. [...] -\end{std.txt} \ No newline at end of file +\end{std.txt} diff --git a/src/compat.tex b/src/compat.tex new file mode 100644 index 0000000..32c522b --- /dev/null +++ b/src/compat.tex @@ -0,0 +1,57 @@ +%!TEX root = std.tex +\setcounter{chapter}{2} +\rSec0[diff]{Compatibility}% + +\setcounter{section}{4} +\rSec1[diff.cpp17]{C++ and ISO C++ 2017}% + +\setcounter{subsection}{0} +\rSec2[diff.cpp17.lex]{Clause 5: lexical conventions}% + +\noindent +Add new entry as follows: +\begin{std.txt} +\color{addclr} +\textbf{Affected subclauses:} 5.8\\ +\textbf{Change:} \grammarterm{header-name} tokens are formed in more contexts.\\ +\textbf{Rationale:} Required for new features.\\ +\textbf{Effect on original feature:} +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} +\end{std.txt} + +\setcounter{subsection}{2} +\rSec2[diff.cpp17.dcl]{Clause 9: declarations}% + +\noindent +Add new entry as follows: +\begin{std.txt} +\color{addclr} +\textbf{Affected subclauses:} 9.11.1, 9.11.3\\ +\textbf{Change:} New identifiers with special meaning.\\ +\textbf{Rationale:} Required for new features.\\ +\textbf{Effect on original feature:} +Top-level declarations beginning with +\tcode{module} or \tcode{import} may +either be 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} +\end{std.txt} diff --git a/src/config.tex b/src/config.tex index 1758f65..3eba2ed 100644 --- a/src/config.tex +++ b/src/config.tex @@ -1,16 +1,13 @@ %!TEX root = ts.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{N4720} -\newcommand{\prevdocno}{N4689} -\newcommand{\cppver}{201703L} +\newcommand{\docno}{P1103R3} +\newcommand{\prevdocno}{P1103R2} +%\newcommand{\cppver}{201703L} %% Title -\newcommand{\doctitle}{Extensions to \Cpp for Modules} -% \newcommand{\frtitle}{\Cpp Extensions for Networking} +\newcommand{\doctitle}{Merging Modules} %% Release date -%\newcommand{\reldate}{\today} -\newcommand{\reldate}{2018-01-29} - -%% Library chapters +\newcommand{\reldate}{\today} +%\newcommand{\reldate}{2018-01-29} diff --git a/src/cover-wd.tex b/src/cover-wd.tex index 1bd9eed..6089d57 100644 --- a/src/cover-wd.tex +++ b/src/cover-wd.tex @@ -8,10 +8,9 @@ \def\hd{\begin{tabular}{ll} \textbf{Document Number:} & {\larger\docno} \\ \textbf{Date:} & \reldate \\ - \textbf{Revises:} & \prevdocno \\ - \textbf{Reply to:} & Gabriel Dos~Reis \\ - & Microsoft \\ - & gdr@microsoft.com +% \textbf{Revises:} & \prevdocno \\ + \textbf{Reply to:} & Richard Smith \smaller Google \\ + & \smaller richard@metafoo.co.uk \\ \end{tabular} } \newlength{\hdwidth} @@ -19,13 +18,7 @@ \hfill\begin{minipage}{\hdwidth}\hd\end{minipage} \endgroup -\vspace{2.5cm} \begin{center} \textbf{\Huge -Working Draft, Extensions to \Cpp for Modules} +Merging Modules} \end{center} -\vfill -\textbf{Note: this is an early draft. It's known to be incomplet and - incorrekt, and it has lots of - b\kern-1.2pta\kern1ptd\hspace{1.5em}for\kern-3ptmat\kern0.6ptti\raise0.15ex\hbox{n}g.} -\newpage diff --git a/src/declarations.tex b/src/declarations.tex index 0f40e7d..568cdfb 100644 --- a/src/declarations.tex +++ b/src/declarations.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\setcounter{chapter}{9} +\setcounter{chapter}{8} \rSec0[dcl.dcl]{Declarations}% %\indextext{declaration|(} @@ -7,7 +7,7 @@ %gram: \noindent -Add a new alternative to \term{declaration} in paragraph 10/1 as follows +Add new alternatives to \term{declaration} in paragraph 9/1 as follows \begin{std.txt} \begin{bnf} \nonterminal{declaration}:\br @@ -21,10 +21,7 @@ namespace-definition\br empty-declaration\br attribute-declaration\br - \color{addclr} - \added{export-declaration\br - module-import-declaration\br - proclaimed-ownership-declaration} + \added{export-declaration}\br \end{bnf} \end{std.txt} @@ -32,54 +29,40 @@ \setcounter{section}{0} \rSec1[dcl.spec]{Specifiers}% -\setcounter{subsection}{1} -\rSec2[dcl.fct.spec]{Function specifiers}% - -\noindent -Add a new paragraph 10.1.2/7 as follows: -\begin{std.txt} - \color{addclr} - \resetalinea[6] - \alinea - \added{An exported inline function shall be defined in the same translation - unit containing its export declaration. -% That semantic property -% is a reachable semantic property (\ref{dcl.module.reach}) even if -% the definition is not exported (\ref{dcl.module.interface}). - \enternote - 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 (10.1.5) is implicitly inline. - \exitnote} -\end{std.txt} - - \setcounter{subsection}{5} -\rSec6[dcl.inline]{The \tcode{inline} specifier}% +\rSec2[dcl.inline]{The \tcode{inline} specifier}% \noindent -Modify paragraph 10.1.6/6 as follows +Modify paragraph 9.1.6/6 as follows \begin{std.txt} - \resetalinea[5] - \alinea - \added{Some definition for} - \removed{A}\added{a}n inline function or variable shall be - \removed{defined}\added{reachable} in every translation - unit in which it is odr-used and \added{the function or variable} shall have exactly - the same definition in every case (\ref{basic.link}). + \pnum[6] + \removed{An} + \added{If an} + inline function or variable + \added{is odr-used in a} + \removed{shall be defined in every} + translation unit\added{, + a definition of it shall be reachable from the end of that translation unit,} + \removed{in which it is odr-used} and \added{it} shall have exactly + the same definition in every \added{such translation unit} \removed{case} (\ref{basic.link}). \enternote A call to the inline function or a use of the inline variable may be encountered before its definition appears in the translation unit. \exitnote - If the definition of a function or variable appears in a translation unit - before its first declaration as inline, the program is ill-formed. If a + % + If \removed{the} \added{a} definition of a function or variable + \removed{appears in a translation unit before} + \added{is reachable at the point of} + its first declaration as inline, + the program is ill-formed. If a function or variable with external \added{or module} linkage is - \removed{declared}\added{reachable via an} - inline \added{declaration} in one translation - unit, it shall be \removed{declared}\added{reachable via an} inline + declared inline in one translation + unit, + \added{there} \removed{it} shall be + \added{a reachable} \removed{declared} inline \added{declaration} in all translation units in which it - \removed{appears}\added{is reachable}; + \removed{appears}\added{is declared}; no diagnostic is required. An inline function or variable with external \added{or module} linkage shall have the same address in all translation units. @@ -92,819 +75,74 @@ \exitnote \end{std.txt} +\noindent +Add a new paragraph 9.1.6/7 as follows: +\begin{std.txt} + \color{addclr} + \pnum[7] + \added{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). + \enternote + 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 (9.1.5) is implicitly inline. + \exitnote} +\end{std.txt} + +\setcounter{subsection}{6} +\rSec2[dcl.type]{Type specifiers}% +\setcounter{subsubsection}{3} +\rSec3[dcl.spec.auto]{The \tcode{auto} specifier}% +\noindent +Add a new paragraph before 9.1.7.4/9 (``If the name of an entity with an +undeduced placeholder type appears in an expression, the program is +ill-formed.'') as follows: +\begin{std.txt} +\pnum[9] +\added{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). +\enternote +There is no restriction on the linkage of +the deduced return type. +\exitnote} +\end{std.txt} -\setcounter{section}{2} +\setcounter{section}{6} \rSec1[basic.namespace]{Namespaces}% %\indextext{namespaces|(} \noindent -Modify paragraph 10.3/1 as follows: +Add a new paragraph after 9.7/1 as follows: \begin{std.txt} - \resetalinea[0] - \alinea + \pnum[1] A namespace is an optionally-named declarative region. The name of a namespace can be used to access entities declared in that namespace; that is, the members of the namespace. Unlike other declarative regions, the definition of a namespace can be split over several parts of one or more translation units. - \added{A namespace with external linkage is always - exported regardless of whether any of its \term{namespace-definition}{s} is - introduced by \tcode{export}. - \enternote - There is no way to define a namespace with module linkage. - \exitnote - }\color{addclr} - \begin{example} - \begin{codeblock} - export module M; - namespace N { // N has external linkage and is exported - } - \end{codeblock} - \end{example} -\end{std.txt} - -\setcounter{subsection}{2} -\rSec2[namespace.udecl]{The \tcode{using} declaration} - -Modify paragraph 10.3.3/1 as follows: -\begin{std.txt} - \resetalinea[0] - \alinea - Each \grammarterm{using-declarator} in a \grammarterm{using-declaration} - introduces a set of declarations \added{and citations} into the declarative - region in which the - \grammarterm{using-declaration} appears. The set of declarations - \added{and citations} - introduced by - the \grammarterm{using-declarator} is found by performing qualified name - lookup (6.4.3, 13.2) for the name in the \grammarterm{using-declarator}, - excluding functions that are hidden as described below. If the - \grammarterm{using-declarator} does not name a constructor, the - \grammarterm{unqualified-id} is declared in the declarative region in which - the \grammarterm{using-declaration} appears as a synonym for each - declaration \added{or citation} - introduced by the \grammarterm{using-declarator}. [...] -\end{std.txt} - -\noindent -Add a new subclause 10.7 titled ``\textbf{Modules}'' as follows: - -\setcounter{section}{6} -\rSec1[dcl.module]{Modules}% - -\rSec2[dcl.module.unit]{Module units and purviews} - -\begin{std.txt}\color{addclr} - \begin{bnf}\color{addclr} - \nonterminal{module-declaration}:\br - \terminal{export}\opt {} \terminal{module} module-name attribute-specifier-seq\opt \terminal{;} - \end{bnf} - - \begin{bnf}\color{addclr} - \nonterminal{module-name}:\br - module-name-qualifier-seq\opt identifier - \end{bnf} - - \begin{bnf}\color{addclr} - \nonterminal{module-name-qualifier-seq}:\br - module-name-qualifier \terminal{.}\br - module-name-qualifier-seq identifier \terminal{.} - \end{bnf} - - \begin{bnf}\color{addclr} - \nonterminal{module-name-qualifier}:\br - identifier - \end{bnf} - - \resetalinea[0] -\alinea A \term{module unit} is a translation unit that contains -a \grammarterm{module-declaration}. A \term{named module} is the -collection of module units with the same \grammarterm{module-name}. -A translation unit shall not contain more than -one \grammarterm{module-declaration}. A \grammarterm{module-name} -has external linkage but cannot be found by name lookup. - -\alinea -A \term{module interface unit} is a module unit whose -\grammarterm{module-declaration} contains the \texttt{export} keyword; -any other module unit is a \term{module implementation unit}. A named -module shall contain exactly one module interface unit. - -\alinea -A \term{module unit purview} starts at the \grammarterm{module-declaration} -and extends to the end of the translation unit. -The \term{purview} of a named module \tcode{M} is the set of module unit purviews -of \tcode{M}'s module units. - -\alinea -The \term{global module} is the collection of all declarations -not in the purview of any module. By -extension, such declarations are said to be in the purview of the -global module. -\enternote -The global module has no name, no module interface unit, and is not - introduced by any - \grammarterm{module-declaration}. -\exitnote - -\alinea - A \term{module} is either a named module or the global module. - A \grammarterm{proclaimed-ownership-declaration} is - \term{attached} to the module it nominates; any other declaration - is attached to the module in whose purview it appears. - - \alinea -For a namespace-scope declaration $D$ of an entity (other than a -namespace), if $D$ is within a \grammarterm{proclaimed-ownership-declaration} -for a module $X$, the entity is said to be \term{owned} by $X$. -Otherwise, if $D$ is the first declaration of that entity, then that entity is said -to be \term{owned} by the module in whose purview $D$ appears. - - \alinea - If a declaration attached to some module - matches (according to the redeclaration rules) a reachable declaration - from a different module, - the program is ill-formed. - \begin{example} - \begin{codeblock} - // module interface of M - int f(); // \#1 - int g(); // \#2, owned by the global module - export module M; - export using ::f; // OK: does not declare an entity - int g(); // error: matches \#2, but appears in the purview of M - export int h(); // \#3 - export int k(); // \#4 - - // other translation unit - import M; - static int h(); // error: matches \#3 - int k(); // error: matches \#4 - \end{codeblock} - \end{example} - - \alinea - The subgraph of the abstract semantics graph $G$ of a module $M$ - generated by the nodes of $G$, excluding those introducing names - with internal linkage, is available to name lookup in the purview of every - module implementation unit of $M$. - The declsets made available by the \grammarterm{module-import-declaration}{s} - in the purview of the module - interface unit of $M$ are also available to name lookup in the purview of all - module implementation units of $M$. -\end{std.txt} - -\rSec2[dcl.module.interface]{Export declaration}% - -\begin{std.txt}\color{addclr} - \begin{bnf}\color{addclr} - \nonterminal{export-declaration}:\br - \terminal{export} declaration\br - \terminal{export} \terminal{\{} declaration-seq${}_{opt}$ \terminal{\}} - \end{bnf} - - \resetalinea[0] - \alinea - An \grammarterm{export-declaration} shall only appear - 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. - An \grammarterm{exported-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 shall not contain more than one - \tcode{export} keyword. - The \term{interface} of a module \tcode{M} is the set of all - \grammarterm{export-declaration}{s} in its purview. - - \alinea - In an \grammarterm{export-declaration} of the form - \begin{grammar} - @\tcode{export}@ @\term{declaration}@ - \end{grammar} - the \grammarterm{declaration} shall be a \grammarterm{module-import-declaration}, - or it shall declare at least one name, - and if that declaration declares an entity, the - \grammarterm{decl-specifier-seq} (if any) of the - \grammarterm{declaration} shall not contain \tcode{static}. - The \grammarterm{declaration} shall not be an - \grammarterm{unnamed-namespace-definition} - or a \grammarterm{proclaimed-ownership-declaration}. - \begin{example} - \begin{codeblock} - export int x; // error: not in the purview of a module interface unit - export module M; - namespace { - export int a; // error: export within unnamed namespace - } - 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{codeblock} - \end{example} - - If the \grammarterm{declaration} is a \grammarterm{using-declaration} - (\ref{namespace.udecl}), any entity to which the - \grammarterm{using-declarator} ultimately refers shall have been introduced - with a name having external linkage. - \begin{example} - \begin{codeblock} - int f() // f has external linkage - export module M; - export using ::f; // OK - struct S; - export using ::S; // error: S has module linkage - namespace N { - int h(); - static int h(int); // \#1 - } - export using N::h; // error: \#1 has internal linkage - \end{codeblock} - \end{example} - - - \enternote - Names introduced by \tcode{typedef} declarations are not so constrained. - \begin{example} - \begin{codeblock} - export module M; - struct S; - export using T = S; // OK: exports name T denoting type S - \end{codeblock} - \end{example} - \exitnote - - \alinea - - An \grammarterm{export-declaration} of the form - \begin{grammar} - @\tcode{export}@ @\tcode{\{} \term{declaration-seq${}_{opt}$} \tcode{\}}@ - \end{grammar} - is equivalent to a sequence of declarations formed by prefixing each - \grammarterm{declaration} of the \grammarterm{declaration-seq} (if any) with - \tcode{export}. - - \alinea - A namespace-scope or a class-scope declaration lexically - contained in an \grammarterm{export-declaration}, as well as the - entities and the names it introduces are said to be \term{exported}. - The exported declarations in the interface of a module are reachable from - any translation unit importing that module. - \enternote - Exported names have either external linkage or no linkage; see \ref{basic.link} - \exitnote -% The declarations introducing names with linkage -% other than internal linkage introduced or made reachable -% (via an \grammarterm{import-declaration}) -% in the purview of the module -% interface unit of a -% module \tcode{M} are reachable from the purview of all module -% implementation units -% of \tcode{M}. - \begin{example} - \begin{codeblock} - // Interface unit of M - export module M; - export struct X { - void f(); - struct Y { }; - }; - - namespace { - struct S { }; - } - export void f(S); // OK - struct T { }; - export T id(T); // OK - - export struct A; // A exported as incomplete - - export auto rootFinder(double a) { - return [=](double x) { return (x + a/x)/2; }; - } - - export const int n = 5; // OK: n has external linkage - - // Implementation unit of M - module M; - struct A { - int value; - }; - - // main program - import M; - int main() { - X{}.f(); // OK: X and X::f are exported - X::Y y; // OK: X::Y is exported as a complete type - auto f = rootFinder(2); // OK - return A{45}.value; // error: A is incomplete - } - \end{codeblock} - \end{example} - - - - \alinea - \enternote - Redeclaring a name in an \grammarterm{export-declaration} - cannot change the linkage of the name (10.1.1). + \pnum + \added{\enternote 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} (\ref{module.interface}). + A namespace is never attached to a module, and never has module + linkage even if it is not exported. + \exitnote} + \color{addclr} \begin{example} \begin{codeblock} - // Interface unit of 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 + 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} - \exitnote -%% If the -%% \term{export-declaration} introduces a function template or a variable -%% template then the type of the corresponding current instantiation shall -%% contain only types with external linkage. If the -%% \term{export-declaration} introduces a template alias then the aliased -%% type shall have external linkage. If the -%% \term{export-declaration} defines a class template, then all -%% non-internal members of the corresponding current instantiation shall -%% contain only types with external linkage. - -%% \alinea -%% In a \grammarterm{exported-fragment-group}, -%% each \grammarterm{fragment} is processed -%% as an exported declaration. - - \alinea - Declarations in an exported \grammarterm{namespace-definition} - or in an exported \grammarterm{linkage-specification} (10.5) - are - implicitly 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{std.txt} - - -\rSec2[dcl.module.import]{Import declaration}% - -\begin{std.txt}\color{addclr} - \begin{bnf}\color{addclr} - \nonterminal{module-import-declaration}:\br - \terminal{import} module-name attribute-specifier-seq\opt {} \terminal{;} - \end{bnf} - - \resetalinea[0] - \alinea - A \grammarterm{module-import-declaration} shall appear only at - global scope, and not in a \grammarterm{linkage-specification} - or \grammarterm{proclaimed-ownership-declaration}. - A \grammarterm{module-import-declaration} nominating a module $M$ - makes every citation and every exported declaration from the - abstract semantics graph of $M$ available, as a citation, - %makes exported declarations from the interface of the nominated module visible - to name lookup in - the current translation unit, in the same namespaces and contexts - as in $M$. - % the nominated module. - A \term{citation} for a declaration attached to a module $M$ is a pair of - $M$ and the corresponding declset from the abstract semantics graph - of $M$. -% The \grammarterm{attribute-specifier-seq} appartain to the nominated module. - \enternote - The declarations in the declsets and the entities denoted by the declsets - are not redeclared in the translation unit - containing the \grammarterm{module-import-declaration}. - \exitnote - \begin{example} - \begin{Program} - // Interface unit of M - export module M; - export namespace N { - struct A { }; - } - namespace N { - struct B { }; - export struct C { - friend void f(C) { } // exported, visible only through argument-dependent lookup - }; - } - - // Translation unit 2 - import M; - N::A a { }; // OK. - N::B b { }; // error: `B' not found in N. - void h(N::C c) { - f(c); // OK: `N::f' found via argument-dependent lookup - N::f(c); // error: `f' not found via qualified lookup in N. - } - \end{Program} - \end{example} - - \alinea - A module \tcode{M1} \term{has a dependency} on a module \tcode{M2} - if any module unit of \tcode{M1} contains a \grammarterm{module-import-declaration} - nominating \tcode{M2}. A module shall not have a dependency on - itself. - \begin{example} - \begin{codeblock} - module M; - import M; // error: cannot import M in its own unit. - \end{codeblock} - \end{example} - - \alinea - A module \tcode{M1} \term{has an interface dependency} on a module - \tcode{M2} if the module interface of \tcode{M1} contains a - \grammarterm{module-import-declaration} nominating \tcode{M2}, - or if there exists a module \tcode{M3} such that \tcode{M1} has an - interface dependency on \tcode{M3} and \tcode{M3} has an interface dependency - on \tcode{M2}. A module - shall not have an interface dependency on itself. - \begin{example} - \begin{Program} - // Interface unit of M1 - export module M1; - import M2; - - // Interface unit of M2 - export module M2; - import M3; - - // Interface unit of M3 - export module M3; - import M1; // error: cyclic interface dependency M3 -> M1 -> M2 -> M3 - \end{Program} - \end{example} - - \alinea - A translation unit has an interface dependency on a module \tcode{M} if it is - a module implementation unit of \tcode{M}, or if it contains a - \grammarterm{module-import-declaration} nominating \tcode{M}, or if it has - an interface dependency on a module that has an interface dependency on \tcode{M}. -\end{std.txt} - - -\rSec2[dcl.module.export]{Module exportation}% - -\begin{std.txt}\color{addclr} - \resetalinea[0] - \alinea - An exported - \grammarterm{module-import-declaration} nominating a module \tcode{M2} - in the purview of a module interface unit of a module \tcode{M} - makes all exported names - of \tcode{M2} visible to any translation unit importing \tcode{M}, as if - that translation unit also contains a \grammarterm{module-import-declaration} - nominating \tcode{M2}. - \enternote - A module interface unit (for a module \tcode{M}) containing a non-exported - \grammarterm{module-import-declaration} does not make the imported - names transitively visible to translation units importing the module - \tcode{M}. - \exitnote - % Wording requested by Hubert Tong on December 17, 2017. - In addition to its usual semantics, a - \grammarterm{module-import-declaration} nominating a module $M$ with - a module interface unit containing one or more exported - \grammarterm{module-import-declaration}{s} also behaves as if - it nominates each module nominated by an exported - \grammarterm{module-import-declaration} in $M$; this may in turn - lead it to be considered to nominate yet additional modules. \end{std.txt} - - -\rSec2[dcl.module.proclaim]{Proclaimed ownership declaration}% - -\begin{std.txt}\color{addclr} - \begin{bnf}\color{addclr} - \nonterminal{proclaimed-ownership-declaration}:\br - \terminal{extern} \terminal{module} module-name \terminal{:} declaration - \end{bnf} - - \resetalinea[0] - \alinea - A \grammarterm{proclaimed-ownership-declaration} shall only appear - at namespace scope. - It shall not appear directly or indirectly within an unnamed namespace. - A \grammarterm{proclaimed-ownership-declaration} has the declarative effects - of its \grammarterm{declaration}. - The \grammarterm{declaration} shall declare at - least one name, and the \grammarterm{decl-specifier-seq} (if any) - of the \grammarterm{declaration} shall not contain \tcode{static}. - The \grammarterm{declaration} shall not be a \grammarterm{namespace-definition}, - an \grammarterm{export-declaration}, - or a \grammarterm{proclaimed-ownership-declaration}. - The \grammarterm{declaration} shall not be a defining declaration - (\ref{basic.def}). - A \grammarterm{proclaimed-ownership-declaration} nominating a module $M$ - shall not appear in the purview of $M$. - - \alinea - A \grammarterm{proclaimed-ownership-declaration} asserts that the entities - introduced by the declaration are exported by the nominated module. - \enternote - A \grammarterm{proclaimed-ownership-declaration} may be used to break - circular dependencies between two modules (in possibly too finely - designed components.) - \begin{example} - \begin{codeblock} - // TU 1 - export module Ty; - extern module Sym: struct Symbol; - export struct Type { - Symbol* decl; - // ... - }; - - // TU 2 - export module Sym; - extern module Ty: struct Type; - export struct Symbol { - const char* name; - const Type* type; - // ... - }; - \end{codeblock} - \end{example} - \exitnote - - \alinea - The program is ill-formed, no diagnostic required, if the - nominated module in the - \grammarterm{proclaimed-ownership-declaration} does not export the entities - introduced by the declaration. -\end{std.txt} - -\rSec2[dcl.module.reach]{Reachability} - -\begin{std.txt}\color{addclr} - \resetalinea[0] - \alinea - When declarations from the abstract semantics graph of a module $M$ - are made available - to name lookup in another translation unit $TU$, it is necessary to - determine the interpretation of the names they introduce and their - semantic properties. Except as noted below, the - \term{reachable semantic properties} of declset $D$ - (or of the entity, if any, denoted by that declset) - of the abstract semantic graph of $M$ from $TU$ are - \begin{itemize} - \item if $D$ contains at least one exported declaration, - the semantic properties cumulatively obtained in the context - of the exported declaration (\ref{dcl.module.interface}) - members of $D$ in the module interface - unit of $M$. Furthermore, if $D$ denotes an inline function, - the property that the inline function has a definition - (\ref{dcl.fct.spec}) is a reachable semantic property, even - if that definition is not exported. Otherwise, - \item the semantic properties cumulatively obtained in the context of all - declaration members of $D$ in the module interface unit of $M$. - \end{itemize} -% Given a declset $D$ for an exported name from a module $M$, -% the \term{reachable semantic property} of any declaration in that declset -% (or of the entity, if any, designated by that declset) from a translation unit -%% For a given declaration $D$ of a name $X$ exported from a module $M$, the -%% \term{reachable semantic properties} of $D$ from a translation unit -% containing a \grammarterm{module-import-declaration} nominating $M$ are -% restricted to -% the semantic properties cumulatively obtained in -% the context of the exported declaration members of $D$ in $M$. - \enternote - These reachable semantic properties include type completeness, - type definitions, initializers, - default arguments of functions or template declarations, attributes, - visibility to normal lookup, entities that are direct targets of edges - emanating from $D$ in the abstract semantics graph of $M$, etc. - Since default arguments are evaluated in the context of the call expression, - reachable semantic properties of the corresponding parameter types apply in - that context. - \begin{example} - \begin{codeblock} - // TU 1 - struct F { int f { 42 }; }; - export module M; - export using T = F; - export struct A { int i; }; - export int f(int, A = { 3 }); - - export struct B; // exported as incomplete type - struct B { // definition not exported - operator int(); - }; - export int g(B = B{}); - export int h(int = B{}); // \#1 - - export struct S { - static constexpr int v(int); - }; - - export S j(); // S attendant entity of j() - constexpr int S::v(int x) { return 2 * x; } - - - // TU 2 - import M; - int main() { - T t { }; // OK: reachable semantic properties of T include completeness. - auto x = f(42); // OK: default argument A\{3\} evaluated here. - auto y = h(); // OK: completeness of B only checked at \#1. - auto z = g(); // error: parameter type incomplete here. - constexpr auto a = decltype(j())::v(3); // OK: S::v defined - // in the abstract semantics graph of M (\ref{dcl.fct.spec}) - } - \end{codeblock} - \end{example} - \exitnote - - \alinea - Within a module interface unit, it is necessary to determine that the - declarations being exported collectively present a coherent view of - the semantic properties of the entities they reference. This determination - is based on the semantic properties of attendant entities. - \enternote - The reachable semantics properties of an entity, the declarations of which - are made available via a \grammarterm{module-import-declaration}, are - determined by its owning module and are unaffected by the importing module. - \begin{example} - \begin{codeblock} - // module interface of M1 - export module M1; - export struct S { }; - - // module interface of M2 - import M1; - export module M2; - export S f(); // \#1 - export S* g(); // \#2 - - // elsewhere - import M2; - auto x = f(); // OK: completeness of S obtained at \#1 - auto y = *g(); // OK: completeness of S obtained at \#2 - \end{codeblock} - \end{example} - \exitnote - - For each declaration $D$ exported from the module interface unit of a module $M$, - there is a set of zero or more - \term{attendant entities} defined as follows: - \begin{itemize} - \item If $D$ is a type alias declaration, then the attendant entities - of $D$ are those determined by the aliased type at the point of the - declaration $D$. - - \item If $D$ is a \grammarterm{using-declaration}, the set of attendant entities - is the union of the sets of attendant entities of the declarations introduced by - $D$ at the point of the declaration. - - \item If $D$ is a template declaration, the set of attendant entities is - the union of the set of attendant entities - of the declaration being parameterized, the set of attendant entities - determined by the default type template arguments (if any), - and the set consisting of - the entities (if any) designated by the default template template argument, - the default non-type template arguments (if any). - - \item if $D$ has a type $T$, the set of attendant entities is the set of - attendant entities determined by $T$ at the point of declaration. - - \item Otherwise, the set of attendant entities is empty. - \end{itemize} - - The \term{set of attendant entities determined by} a type $T$ is defined as follows - (exactly one of these cases matches): - \begin{itemize} - \item If $T$ is a fundamental type, then - the set of attendant entities is empty. - - % \item If $T$ is a dependent type denoted by a \grammarterm{typename-specifier} - % where the \grammarterm{nested-name-specifier} itself denotes a dependent type, - % then the set of attendant entities is the set of attendant entities determined by - % that type. - \item If $T$ is a member of an unknown specialization, the set of - attendant entities is the set of attendant entities determined by that - unknown specialization. - - \item If $T$ is a class type owned by $M$, the set of attendant entities includes - $T$ itself, the union of the sets of the attendant entities determined - by its direct base classes owned by $M$, the sets of the - attendant entities of its data members, static data member templates, - member functions, member function templates, - the function parameters of its constructors and constructor templates. - Furthermore, if $T$ is a - class template specialization, the set of attendant entities also - includes: the class template if it is owned by $M$, - the union of the sets of attendant entities determined by the type - template-arguments, the sets of the attendant entities of the templates - used as template template-arguments, the sets of the attendant entities - determined by the types of the non-type template-arguments. - - \item If $T$ is an enumeration type owned by $M$, - the set of attendant entities is the singleton $\{T\}$. - - \item If $T$ is a reference to $U$, or a pointer to $U$, or an array of $U$, - the set of attendant entities is the set of attendant entities determined by $U$. - - \item If $T$ is a function type, the set of attendant entities is the - union of the set of attendant entities determined by the function - parameter types and the return type. - - \item if $T$ is a pointer to data member of class $X$, the set of attendant - entities is the union of the set of attendant entities of the member type - and the set of attendant entities determined by $X$. - - \item If $T$ is a pointer to member function type of a class $X$, the - set of attendant entities is the union of the set of attendant entities - determined by $X$ and the set of attendant entities determined by - the function type. - - \item Otherwise, the set of attendant entities is empty. - \end{itemize} - - If a class template $X$ is an attendant entity, then its reachable semantic - properties include all the declarations of the primary class template, - its partial specializations, and its explicit specializations in the - containing module interface unit. - If a complete class type $X$ is an attendant entity, then its reachable - semantic properties include the declarations of its nested types but - not the definitions of the types denoted by those members - unless those definitions are exported. - Furthermore, if $X$ is an attendant entity of an - exported declaration $D$, then its reachable semantic properties are - restricted to those defined by the exported declarations of $X$ - (if $X$ is introduced by an exported declaration), or by - the semantic properties of $X$ available at the point of the declaration $D$. - \enternote - If $X$ is a complete class type that is an attendant entity, its nested types - (including nested enumerations and associated enumerators) - and member class templates - are not considered attendant entities unless they are determined attendant - entities by one of the rules above. Attendant entities allow type checking - of direct member selection of an object even if that object's type isn't exported. - Declarations, such as \grammarterm{asm-declaration} or - \grammarterm{alias-declaration} or - \grammarterm{static\_assert-declaration}, - that do not declare entities do not contribute to the set of attendant entities. - \exitnote - \begin{example} - \begin{codeblock} - export module M; - export struct Foo; // Foo exported as incomplete type - struct Foo { }; - export using ::Foo; // OK: exports complete type Foo - - struct C { }; - struct S { - struct B { }; - using C = ::C; - int i : 8; - double d { }; - }; - - export S f(); // S attendant entity of f(). - - // translation unit 2 - import M; - int main() { - int x = sizeof(decltype(f())::B); // error: incomplete B - int y = sizeof(decltype(f())::C); // error: incomplete C - decltype(f()) s { }; - s.d = 3.14; // OK - return &s.i != nullptr; // error: cannot take address of bitfield - } - \end{codeblock} - \end{example} - - \alinea - If $X$ is an attendant entity of two exported declarations - designating two distinct entities, its reachable semantic properties shall - be the same at the points where the declarations occur. - \begin{example} - \begin{codeblock} - export module M; - struct S; - export S f(); // \#1 - struct S { }; - export S g(); // error: class type S has different properties from \#1 - \end{codeblock} - \end{example} - -\end{std.txt} - diff --git a/src/front.tex b/src/front.tex index 8f8abbb..723453b 100644 --- a/src/front.tex +++ b/src/front.tex @@ -1,6 +1,4 @@ %!TEX root = ts.tex -\input{cover-wd} -%\input{cover-reg} %%-------------------------------------------------- %% The table of contents, list of tables, and list of figures diff --git a/src/layout.tex b/src/layout.tex index 505bb53..4fe8c97 100644 --- a/src/layout.tex +++ b/src/layout.tex @@ -56,31 +56,11 @@ }}} \makeatother -\def\pnum{\parabullnum{Paras}{0pt}} +\newcommand{\pnum}[1][]{\ifthenelse{\equal{#1}{}}{}{\setcounter{Paras}{#1}\addtocounter{Paras}{-1}}\parabullnum{Paras}{0pt}\ignorespaces} % Leave more room for section numbers in TOC \cftsetindents{section}{1.5em}{3.0em} -% For compatibility only. We no longer need this environment. -\newenvironment{paras}{}{} - - -%% This is used to number paragraphs in ISO C++ standard text, e.g. -%% 3 blah blah ... -%% blah .... ... -\newcounter{alinea}[section] -\renewcommand{\thealinea}{\arabic{alinea}} -\newcommand{\alinea}{% - \ifhmode\par\fi\vskip.5em\noindent - \refstepcounter{alinea}% - \llap{\thealinea\hspace{2ex}}% -} - -\newcommand{\resetalinea}[1][0]{% - \setcounter{alinea}{#1}% -} - - \lstnewenvironment{grammar} {\lstset{basicstyle=\rmfamily,columns=fullflexible,escapechar=@}} {} diff --git a/src/lexical.tex b/src/lexical.tex index 3795844..e7af876 100644 --- a/src/lexical.tex +++ b/src/lexical.tex @@ -1,5 +1,6 @@ %!TEX root = ts.tex +\setcounter{chapter}{4} \rSec0[lex]{Lexical conventions} \setcounter{section}{0} @@ -7,8 +8,7 @@ Modify paragraph 5.1/2 as follows \begin{std.txt} - \resetalinea[1] - \alinea + \pnum[2] \enternote Previously translated translation units and instantiation units can be preserved individually or in libraries. The separate translation units of @@ -27,8 +27,7 @@ \noindent Modify bullet 7 of paragraph 5.2/1 as follows: \begin{std.txt} -% \resetalinea[6] -% \alinea +% \pnum[1] \begin{itemize} \item[7.] White-space characters separating tokens are no longer significant. @@ -39,9 +38,11 @@ The process of analyzing and translating the tokens may occasionally result in one token being replaced by a sequence of other tokens (17.2). \exitnote - \added{It is implementation-defined whether the source for module interface - units for modules on which the current translation unit has an interface - dependency (\ref{dcl.module.import}) is required to be available.} + \added{It is implementation-defined 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.} \enternote Source files, translation units and translated translation units need not necessarily be stored as files, nor need there be any one-to-one @@ -52,388 +53,54 @@ \end{itemize} \end{std.txt} +\begin{after} +\setcounter{section}{3} +\Sec1[lex.pptoken]{Preprocessing tokens} -Add new paragraphs as follows: -\begin{std.txt}\color{addclr} - \resetalinea[1] - \alinea - The result of processing a translation unit from phases 1 through 7 - is a directed graph called the \term{abstract semantics graph} of - the translation unit: - \begin{itemize} - \item Each vertex, called a \term{declset}, is - a citation (\ref{dcl.module.import}), or a collection of - non-local declarations and redeclarations (Clause \ref{dcl.dcl}) - declaring the same entity or other non-local declarations - of the same name that do not declare an entity. - \item A directed edge $(D_1, D_2)$ exists in the graph if and only if the - declarations contained in $D_2$ declare an entity mentioned - in a declaration contained in $D_1$. - \end{itemize} - The \term{abstract semantics graph of a module} is the subgraph of - the abstract semantics graph of its module interface unit generated - by the declsets the declarations of which are - in the purview of that module interface unit. - \enternote - The abstract semantics graphs of modules, - as appropriately restricted (\ref{dcl.module.reach}), are used in - the processing of \grammarterm{module-import-declaration}{s} - (\ref{dcl.module.import}) and module implementation units. - \exitnote - - \alinea - An entity is \term{mentioned} in a declaration $D$ if that entity is a member of the - \term{basis} of $D$, a set of entities determined as follows: - \begin{itemize} - \item If $D$ is a \grammarterm{namespace-definition}, the basis is the union - of the bases of the \grammarterm{declaration}{s} in its - \grammarterm{namespace-body}. - - \item If $D$ is a \grammarterm{nodeclspec-function-declaration}, - \begin{itemize} - \item if $D$ declares a contructor, the basis is - the union of the type-bases of the parameter types - - \item if $D$ declares a conversion function, the basis is - the type-basis of the return type - - \item otherwise, the basis is empty. - \end{itemize} - - \item If $D$ is a \grammarterm{function-definition}, the basis is - the type-basis of the function's type - - \item If $D$ is a \grammarterm{simple-declaration} - \begin{itemize} - \item if $D$ declares a \grammarterm{typedef-name}, the basis is the - type-basis of the aliased type - \item if $D$ declares a variable, the basis is the type-basis - of the type of that variable - \item if $D$ declares a function, the basis is the type-basis of the type of that function - \item if $D$ defines a class type, the basis is the union of the - type-bases of its direct base classes (if any), and the bases of - its \grammarterm{member-declaration}{s}. - \item otherwise, the basis is the empty set. - \end{itemize} - - \item If $D$ is a \grammarterm{template-declaration}, the basis is the union - of the basis of its \grammarterm{declaration}, the set - consisting of the entities (if any) designated by the default - template template arguments, the default non-type template arguments, the - type-bases of the default type template arguments. - Furthermore, if $D$ declares a - partial specialization, the basis also includes the primary template. - - \item If $D$ is an \grammarterm{explicit-instantiation} - or an \grammarterm{explicit-specialization}, the basis includes - the primary template, and all the entities in the basis of the - \grammarterm{declaration} of $D$. - - \item If $D$ is a \grammarterm{linkage-specification}, the basis is the union - of all the bases of the \grammarterm{declaration}{s} contained in $D$. - - \item If $D$ is a \grammarterm{namespace-alias-definition}, the basis is the - singleton consisting of the namespace denoted by the - \grammarterm{qualified-namespace-specifier}. - - \item If $D$ is a \grammarterm{using-declaration}, the basis is the union - of the bases of all the declarations introduced by - the \grammarterm{using-declarator}. - - \item If $D$ is a \grammarterm{using-directive}, the basis is the - singleton consisting of the norminated namespace. - - \item If $D$ is an \grammarterm{alias-declaration}, the basis is the type-basis of - its \grammarterm{defining-type-id}. - - \item Otherwise, the basis is empty. - \end{itemize} - - The \term{type-basis} of a type $T$ is - \begin{itemize} - \item If $T$ is a fundamental type, the type-basis is the empty set. - \item If $T$ is a cv-qualified type, the type-basis is the type-basis of - the unqualified type. - \item If $T$ is a member of an unknown specialization, the type-basis - is the type-basis of that specialization. - \item If $T$ is a class template specialization, the type-basis - is the union of the set consisting of the primary template and the - template template arguments (if any) and the non-dependent non-type - template arguments (if any), and the type-bases of the type - template arguments (if any). - \item If $T$ is a class type or an enumeration type, - the type-basis is the singleton $\{ T \}$. - \item If $T$ is a reference to $U$, or a pointer to $U$, or an array of $U$, the - type-basis is the type-basis of $U$. - \item If $T$ is a function type, the type-basis is the union of the - type-basis of the return type and the type-bases of the parameter types. - \item If $T$ is a pointer to data member of a class $X$, the type-basis is - the union of the type-basis of $X$ and the type-basis of member type. - \item If $T$ is a pointer to member function type of a class $X$, the - type-basis is the union of the type-basis of $X$ and the type-basis of - the function type. - \item Otherwise, the type-basis is the empty set. - \end{itemize} - -% The \term{expr-basis} of an expression $E$ is -% \begin{itemize} -% \item If $E$ is a pair of \grammarterm{expression} separated by a comma, -% the expr-basis is the union of the expr-bases of the two operands. - -% \item If $E$ is an assignment, the expr-basis is the union of the -% expr-bases of the left operand and the right operand, and the set consisting -% of the function implementing the assignment operator (if the left operand -% if of class type) and all the functions involved in the implicit conversion -% sequences applied to the operands. - -% \item If $E$ is a \grammarterm{throw-expression}, the expr-basis is the -% expr-basis of its operand. - -% \item If $E$ is a \grammarterm{conditional-expression}, the expr-basis is the -% union of the expr-bases of all the operands, and the set of functions involved -% in the implicit conversion sequences applied to the operands. - -% \item If $E$ is a binary expression, the expr-basis is the union of the -% expr-bases of the two operands, and the set of functions involved in the -% implicit conversion sequences applied to the operands, and the function -% selected by overload resolution (if any) for the operator. - -% \item If $E$ is an explicit type conversion expression, the expr-basis is -% the union of the type-basis of the target type and the expr-basis of -% the operand expression, and the set consisting of the function or constructor -% involved in performing the conversion to the target type (if any). - -% \item If $E$ is a \grammarterm{noexcept-expression}, -% the expr-basis is the expr-basis of the operand. - -% \item If $E$ is an alignof expression, -% the expr-basis is the type-basis of that operand. - -% \item If $E$ is a \grammarterm{delete-expression}, the expr-basis is -% the union of the expr-basis of the operand and the set consisting of -% the functions inolved in the implicit conversion sequence -% applied to the operand, and the deallocation function selected. - -% \item If $E$ is a \grammarterm{new-expression}, the expr-basis is -% the union of -% \begin{itemize} -% \item the expr-bases of the expressions in its -% \grammarterm{new-placement} (if any), and the set of -% functions involved in the implicit conversion sequences applied -% to those expressions (if any), and the allocation function selected -% \item the type-basis of the \grammarterm{type-specifier-seq} contained -% in the \grammarterm{new-type-id}, the expr-bases of the expressions -% contained in the \grammarterm{new-declarator} (if any), and the set -% consisting of the functions involved in the implicit conversion sequences -% applied to those expressions -% \item the expr-bases of the expressions contained in the -% \grammarterm{new-initializer} (if any), and the set consisting of the -% functions involved in the implicit conversion sequences applied -% to those expressions and the constructor selected (if any) -% \end{itemize} - -% \item If $E$ is a sizeof expression, the expr-basis is the expr-basis -% of the operand if the operand is an expression, otherwise the type-basis -% of the operand. - -% \item If $E$ is prefix expression or a postfix expression, the expr-basis -% is the expr-basis of the operand, and the set consisting of the -% operator function selected by overload resolution (if any). - -% \item If $E$ is a pointer to member expression, the expr-basis is the -% set consisting of the designated non-static member. - -% \item If $E$ is any other unary expression, the expr-basis is the -% union of the expr-basis of the operand expression, and the set -% consisting of the operator function (if any) selected by overload -% resolution and any functions involved in the implicit conversion -% sequence applied to the operand expression. - -% \item if $E$ is a \grammarterm{postfix-expression} -% \begin{itemize} -% \item and is a typeid expression, the expr-basis is the -% type-basis of the type operand if the operand is a type, or the -% expr-basis of the expression operand - -% \item and is a cast expression, the expr-basis is the union of the -% the type-basis of the target type, the expr-basis of the expression operand, -% and the set consisting of function or constructor involved in the -% conversion of the expression operand to the target type +Modify bullet 3 of paragraph 5.4/3 as follows: -% \item and is a postifx increment or decrement expression, the expr-basis is -% the expr-basis of the operand expression, and the set consisting of the -% operator function (if any) selected by overload resolution - -% \item and is a pseudo destructor call, the expr-basis is the expr-basis -% of the left-hand side of the dot or arrow operator - -% \item and is a class member access expression, the expr-basis is the union -% of the left-hand expression operand of the dot or the arrow operator, -% and (if that left-hand side is not type-dependent) the set consisting of -% the class member designated by the \grammarterm{id-expression}, the -% operator function selected by overload resolution for the member access -% operator - -% \item and is a function call expression, the expr-basis is the union of -% the expr-basis of the \grammarterm{postfix-expression}, the expr-bases -% of the arguments (if any), and the set consisting of the operator function -% implementing the call selected by overload resolution, all the functions -% involved in the implicit conversion sequences applied to each argument -% in the call - -% \item and is a subscripting expression, the expr-basis is the union of -% the expr-basis of the \grammarterm{postfix-expression}, and the expr-bases -% of each expression in the \grammarterm{expr-or-braced-init-list} - -% \item otherwise, the expr-basis is the empty set. -% \end{itemize} - -% \item If $E$ is a primay expression, -% \begin{itemize} -% \item and is a literal, the expr-basis is... -% \item and is an \grammarterm{id-expression}, the expr-basis is the set -% consisting of the designated entity (if it has namespace scope -% or class scope) or the non-static class member; otherwise the class is empty -% \item and is a parentesized expression, the expr-basis is the expr-basis -% of that expression -% \item and is a lambda expression, the expr-basis is the union of -% \begin{itemize} -% \item the type-bases in the parameter types (if any) -% \item the type-basis of the \grammarterm{trailing-return-type} (if any) -% \item the expr-basis of the \grammarterm{initializer}{s} (if any) -% in its \grammarterm{lambda-capture}. -% \end{itemize} -% \end{itemize} - -% \item Otherwise, the expr-basis is the empty set. - -% \end{itemize} - -% The \term{expr-basis} of an expression $E$ is -% \begin{itemize} -% \item If $E$ is a \grammarterm{literal} -% \begin{itemize} -% \item the set consisting of the literal operator function called, if -% $E$ is a \grammarterm{user-defined-literal}; otherwise -% \item the empty set. -% \end{itemize} - -% \item If $E$ is a parenthesized expression, the expr-basis is the expr-basis -% of that expression. - -% \item If $E$ is a \grammarterm{id-expression} -% \begin{itemize} -% \item the set consisting of the designated destructor, -% if $E$ denotes a destructor; otherwise, -% \item the union of the set consisting of the template, the template -% template-arguments (if any), the type-bases of the type -% template-argumnts (if any), the expr-bases of the non-type -% template-arguments (if any), if $E$ is a \grammarterm{template-id}; otherwise, -% \item the set consisting of the namespace scope or class scope entity -% designated by $E$ if $E$ denotes such an entity; otherwise, -% \item the empty set. -% \end{itemize} - -% \item If $E$ is a \grammarterm{lambda-expression}, the union of -% \begin{itemize} -% \item the type-bases in the parameter types (if any) -% \item the type-basis of the \grammarterm{trailing-return-type} (if any) -% \item the expr-basis of the expressions in the -% \grammarterm{initializer}{s} (if any) -% in its \grammarterm{lambda-capture}. -% \end{itemize} - -% \item If $E$ is a \grammarterm{fold-expression}, the union -% of the expr-bases of the operands, and the set of operator functions -% found by name lookup for the \grammarterm{fold-operator}{s} in the -% context of $E$. - -% \item The empty set, if $E$ is any other \grammarterm{primary-expression}. - -% \item If $E$ is a subscripting expression, the union of the expr-basis -% of the \grammarterm{postfix-expression}, the expr-bases of the -% expressions contained in the \grammarterm{expr-or-braced-init-list}, and -% the set consisting of the selected overloaded operator function (if any) -% and all functions involved in the implicit conversion sequences (if any) -% applied to those expressions. - -% \item If $E$ is a function call expression, the union of the expr-basis -% of the \grammarterm{postfix-expression}, the expr-bases of the expressions -% in the argument list, the set consisting of the selected overloaded function -% operator (if any) and the functions involved in the -% implicit conversion sequences (if any) applied to the arguments, -% and the set of functions found by name lookup in the context of $E$ if -% the \grammarterm{postfix-expression} is a dependent name. - -% \item If $E$ is an explicit type conversion using functional notation, -% the union of the type-basis of the target type, the expr-bases of the -% expressions in the \grammarterm{expression-list} or -% \grammarterm{brace-init-list}, the set consisting of the -% constructor selected (if any) and all functions involved in -% the implicit conversion sequences (if any) applied to the arguments. - -% \item If $E$ is a member selection expression, the union of the expr-basis -% of the \grammarterm{postfix-expression} and the set consisting of -% the overloaded function operator (if any) and the entity member (if any) -% designated by the \grammarterm{id-expression}. - -% \item If $E$ is a named cast expression, the union of the type-basis -% of the target type, the expr-basis of the operand expression, the -% set consisting of the function or constructor selected to perform -% the conversion and the function involved in the implicit conversion -% sequence (if any) applied to the operand. - -% \item If $E$ is a post-increment or post-decrement expression, the -% union of the expr-basis of the \grammarterm{postfix-expression}, and the -% set consisting the selected function operator (if any). - -% \item If $E$ is a pseudo destructor call, the expr-basis of -% the \grammartem{postfix-expression}. - -% \item If $E$ is a typeid expression, the expr-basis of the operand if -% that operand is an expression, otherwise the type-basis of that operand. - -% \item The empty set, if $E$ is any other -% \grammarterm{postfix-expression}. - -% \item Otherwise, the empty set. -%\end{itemize} - -\alinea -\enternote -The basis of a declaration includes neither non-fully evaluated expressions nor -entities used in those expressions. -\begin{example} - \begin{codeblock} - const int size = 2; - int ary1[size]; // \tcode{size} not in \tcode{ary1}'s basis - constexpr int identity(int x) { return x; } - int ary2[identity(2)]; // \tcode{identity} not in \tcode{ary2}'s basis +\begin{std.txt} +Otherwise, the next preprocessing token is +the longest sequence of characters +that could constitute a preprocessing token, +even if that would cause further lexical analysis to fail, +except that a \grammarterm{header-name} (5.8) +is only formed +\begin{itemize} +\item +within a \tcode{\#include} directive (19.2)\added{,} + +\item +\added{within a \grammarterm{has-include-expression}, or} + +\item +\added{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} (\ref{cpp.module}).} +\end{itemize} +\end{std.txt} +\end{after} - template struct S; - template struct S2; - constexpr int g(int); +\setcounter{section}{9} +\Sec1[lex.name]{Identifiers} - template - S> f(); // \tcode{f}'s basis: $\{ \mathtt{S}, \mathtt{S2} \}$ - \end{codeblock} -\end{example} -\exitnote +In \ref{lex.name}, add these two identifiers to Table 4, +``Identifiers with special meaning'': +\begin{std.txt} +\added{\tcode{module}}\\ +\added{\tcode{import}} \end{std.txt} - \setcounter{section}{10} \Sec1[lex.key]{Keywords} -In \ref{lex.key}, add these two keywords to Table 5 in paragraph -5.11/1: \added{module} and \added{import}. - \noindent Modify note in paragraph \ref{lex.key}/1 as follows: \begin{std.txt} - \resetalinea[0] - \alinea + \pnum[1] ... @@ -442,4 +109,4 @@ unused but \removed{are} \added{is} reserved for future use. \exitnote -\end{std.txt} \ No newline at end of file +\end{std.txt} diff --git a/src/macros.tex b/src/macros.tex index 764a582..c3e6909 100644 --- a/src/macros.tex +++ b/src/macros.tex @@ -151,6 +151,7 @@ \newcommand{\enterexample}{\EnterBlock{Example}} \newcommand{\exitexample}{\ExitBlock{example}} \newenvironment{example}[1][Example]{\EnterBlock{#1}}{\ExitBlock{example}} +\newenvironment{note}[1][Note]{\enternote}{\exitnote} %% Library function descriptions \newcommand{\Fundescx}[1]{\textit{#1}\xspace} @@ -168,7 +169,7 @@ \newcommand{\complexity}{\Fundesc{Complexity}} \newcommand{\remark}{\Fundesc{Remark}} \newcommand{\remarks}{\Fundesc{Remarks}} -\newcommand{\note}{\remark} +%\newcommand{\note}{\remark} \newcommand{\notes}{\remarks} \newcommand{\realnote}{\Fundesc{Note}} \newcommand{\realnotes}{\Fundesc{Notes}} @@ -187,6 +188,7 @@ %% Cross reference \newcommand{\xref}{\textsc{See also:}\xspace} \newcommand{\xsee}{\textsc{See:}\xspace} +\newcommand{\stdref}[2]{#2 [#1]} %% NTBS, etc. \newcommand{\NTS}[1]{\textsc{#1}\xspace} @@ -229,7 +231,7 @@ %% Double underscore \newcommand{\ungap}{\kern.5pt} -\newcommand{\unun}{\_\ungap\_} +\newcommand{\unun}{\textunderscore\ungap\textunderscore} \newcommand{\xname}[1]{\unun\ungap#1} \newcommand{\mname}[1]{\tcode{\unun\ungap#1\ungap\unun}} @@ -351,7 +353,7 @@ \newcommand{\bnfindentfirst}{\BnfIndent} \newcommand{\bnfindentinc}{\BnfInc} \newcommand{\bnfindentrest}{\BnfRest} - \begin{minipage}{.9\hsize} + \begin{minipage}{.95\hsize} \newcommand{\br}{\hfill\\} \frenchspacing } @@ -509,3 +511,19 @@ \subsubsection[#1]{\hfill[#2]}\vspace{-.3\onelineskip}\label{#2}\textbf{#1}\\% } \newcommand{\defncontext}[1]{\textlangle#1\textrangle} + +\NewEnviron{before}{} +%\newenvironment{before}{ +%\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black,title=Before] +%}{ +%\end{tcolorbox} +%} + +\newenvironment{after}{% +%\begin{tcolorbox}[colback=green!5!white,colframe=green!75!black,title=After] +}{% +%\end{tcolorbox} +} + +% Wording on which the authors disagree. +\newenvironment{undecided}{}{} diff --git a/src/modules.tex b/src/modules.tex new file mode 100644 index 0000000..896fa45 --- /dev/null +++ b/src/modules.tex @@ -0,0 +1,1055 @@ +%!TEX root = std.tex +\setcounter{chapter}{99} +\rSec0[module]{Modules}% +%\indextext{declaration|(} + +\noindent +Add a new clause between 9 and 10 titled ``\textbf{Modules}'' with contents as follows: + +\rSec1[module.unit]{Module units and purviews} + +\begin{std.txt}\color{addclr} +\begin{bnf}\color{addclr} +\nonterminal{module-declaration}:\br + \terminal{export}\opt{} \terminal{module} module-name module-partition\opt{} attribute-specifier-seq\opt{} \terminal{;} +\end{bnf} + + \begin{bnf}\color{addclr} + \nonterminal{module-name}:\br + module-name-qualifier\opt identifier + \end{bnf} + + \begin{after} + \begin{bnf}\color{addclr} + \nonterminal{module-partition}:\br + \terminal{:} module-name-qualifier\opt identifier + \end{bnf} + \end{after} + + \begin{bnf}\color{addclr} + \nonterminal{module-name-qualifier}:\br + identifier \terminal{.}\br + module-name-qualifier identifier \terminal{.} + \end{bnf} + +\pnum +A \term{module unit} is a translation unit that contains +a \grammarterm{module-declaration}. A \term{named module} is the +collection of module units with the same \grammarterm{module-name}. +%Two \grammarterm{module-name}{s} are the same if they are +%composed of the same dotted sequence of \grammarterm{identifier}{s}. +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 \term{module interface unit} is a module unit whose +\grammarterm{module-declaration} contains the \texttt{export} keyword; +any other module unit is a \term{module implementation unit}. +A named module shall contain exactly one module interface unit +with no \grammarterm{module-partition}, known as the +\term{primary module interface unit} of the module; +no diagnostic is required. + +\pnum +A \term{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 %dotted sequence of \grammarterm{identifier}{s} in their +\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 (\ref{module.import}). +No diagnostic is required for a violation of these rules. +\enternote +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. +\exitnote + +\begin{after}\color{addclr} +\pnum +\begin{example} +\begin{codeblock} +// TU 1 +export module A; +export import :Foo; +export int baz(); +\end{codeblock} + +\begin{codeblock} +// TU 2 +export module A:Foo; +import :Internals; +export int foo() { return 2 * (bar() + 1); } +\end{codeblock} + +\begin{codeblock} +// TU 3 +module A:Internals; +int bar(); +\end{codeblock} + +\begin{codeblock} +// TU 4 +module A; +import :Internals; +int bar() { return baz() - 10; } +int baz() { return 30; } +\end{codeblock} + +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} +\end{after} + +\pnum +A \term{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 \term{purview} of a named module \tcode{M} is the set of module unit purviews +of \tcode{M}'s module units. + +\pnum +The \term{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 \term{purview} of the global module. +\enternote +The global module has no name, no module interface unit, and is not +introduced by any \grammarterm{module-declaration}. +\exitnote + +\pnum + A \term{module} is either a named module or the global module. + A declaration is \term{attached} to a module as follows: + \begin{itemize}\color{addclr} + \item If the declaration + \begin{itemize}\color{addclr} + \item is a replaceable global allocation or deallocation + function (\stdref{new.delete.single}{21.6.2.1}, \stdref{new.delete.array}{21.6.2.2}), or + \item is a \grammarterm{namespace-declaration} with external linkage, or + \item appears within a \grammarterm{linkage-specification}, + \end{itemize}\color{addclr} + it is attached to the global module. + + \item Otherwise, the declaration is + attached to the module in whose purview it appears. + \end{itemize} + +% Notion of 'ownership' is unused; removed. +% \pnum +% \begin{before}\color{addclr} +%For a namespace-scope declaration $D$ of an entity (other than a +%namespace), if $D$ is within a \grammarterm{proclaimed-ownership-declaration} +%for a module $X$, the entity is said to be \term{owned} by $X$. +%Otherwise, if $D$ is the first declaration of that entity, then that entity is said +%to be \term{owned} by the module in whose purview $D$ appears. +%\end{before} +%\begin{after}\color{addclr} +%An entity introduced at namespace scope is \term{owned} by the +%module to which its first declaration is attached. +%\end{after} + + \pnum +\color{addclr} +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{codeblock} +// TU 1 +module B:Y; // does not implicitly import \tcode{B} +int y(); +\end{codeblock} + +\begin{codeblock} +// TU 2 +export module B; +import :Y; // OK, does not create interface dependency cycle +int n = y(); +\end{codeblock} + +\begin{codeblock} +// TU 3 +module B:X1; // does not implicitly import \tcode{B} +int &a = n; // error: \tcode{n} not visible here +\end{codeblock} + +\begin{codeblock} +// TU 4 +module B:X2; // does not implicitly import \tcode{B} +import B; +int &b = n; // OK +\end{codeblock} + +\begin{codeblock} +// TU 5 +module B; // implicitly imports \tcode{B} +int &c = n; // OK +\end{codeblock} +\end{example} +\end{std.txt} + +\rSec1[module.interface]{Export declaration}% + +\begin{std.txt}\color{addclr} + \begin{bnf}\color{addclr} + \nonterminal{export-declaration}:\br + \terminal{export} declaration\br + \terminal{export} \terminal{\{} declaration-seq${}_{opt}$ \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 \term{exported} if it is + \begin{itemize}\color{addclr} + \item a namespace-scope declaration declared within an + \grammarterm{export-declaration}, or + \item a \grammarterm{module-import-declaration} declared with + the \tcode{export} keyword (\ref{module.import}), or + \item a \grammarterm{namespace-definition} that contains an + exported declaration, or + \item a declaration within a header unit (\ref{module.import}) + that introduces at least one name. + \end{itemize} + The \term{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. + %\grammarterm{decl-specifier-seq} (if any) of the + %\grammarterm{declaration} shall not contain \tcode{static}, + %and the \grammarterm{declaration} shall not be an + %\grammarterm{unnamed-namespace-definition}. + + \pnum + \begin{example} + \begin{codeblock} + // \tcode{"a.h"} + export int x; + + // TU 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{codeblock} + \end{example} + + \pnum + If the declaration is a \grammarterm{using-declaration} + (9.8 [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{codeblock} +// \tcode{"b.h"} +int f(); + +// \tcode{"c.h"} +int g(); + +// TU 1 +export module X; +export int h(); + +// TU 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{codeblock} +\end{example} + \enternote + Names introduced by \tcode{typedef} declarations + and \grammarterm{alias-declaration}{s} + are not so constrained. + \begin{example} + \begin{codeblock} + export module M; + struct S; + export using T = S; // OK: exports name T denoting type S + \end{codeblock} + \end{example} + \exitnote + + \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 \term{exported} by a module + if it is introduced or redeclared + by an exported declaration in the purview of that module. + \enternote + 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. + \exitnote + \begin{example} + \begin{codeblock} + // Interface unit of 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; // A exported as incomplete + + export auto rootFinder(double a) { + return [=](double x) { return (x + a/x)/2; }; + } + + export const int n = 5; // OK: n has external linkage + + // Implementation unit of M + module M; + struct A { + int value; + }; + + // 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{codeblock} + \end{example} + + \pnum + \enternote + Redeclaring a name in an \grammarterm{export-declaration} + cannot change the linkage of the name (\ref{basic.link}). + \begin{example} + \begin{codeblock} + // Interface unit of 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{codeblock} + \end{example} + \exitnote +%% If the +%% \term{export-declaration} introduces a function template or a variable +%% template then the type of the corresponding current instantiation shall +%% contain only types with external linkage. If the +%% \term{export-declaration} introduces a template alias then the aliased +%% type shall have external linkage. If the +%% \term{export-declaration} defines a class template, then all +%% non-internal members of the corresponding current instantiation shall +%% contain only types with external linkage. + +%% \pnum +%% In a \grammarterm{exported-fragment-group}, +%% each \grammarterm{fragment} is processed +%% as an exported declaration. + +\pnum +\begin{note} +Declarations in an exported \grammarterm{namespace-definition} +or in an exported \grammarterm{linkage-specification} (10.5) +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} +\end{std.txt} + + +\rSec1[module.import]{Import declaration}% + +\begin{std.txt}\color{addclr} +\begin{before} + \begin{bnf}\color{addclr} + \nonterminal{module-import-declaration}:\br + \terminal{import} module-name attribute-specifier-seq\opt {} \terminal{;} + \end{bnf} +\end{before}\begin{after} + \begin{bnf}\color{addclr} + \nonterminal{module-import-declaration}:\br + \terminal{export}\opt{} \terminal{import} module-name attribute-specifier-seq\opt {} \terminal{;}\br + \terminal{export}\opt{} \terminal{import} module-partition attribute-specifier-seq\opt {} \terminal{;}\br + \terminal{export}\opt{} \terminal{import} header-name attribute-specifier-seq\opt {} \terminal{;} + \end{bnf} +\end{after} + + \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} \term{imports} a set of + translation units determined as described below. + \enternote + Namespace-scope names exported by the imported translation units + become visible (\ref{basic.scope.namespace}) + in the importing translation unit + and declarations within the imported translation units + become reachable (\ref{module.reach}) + in the importing translation unit + after the import declaration. + \exitnote + + \pnum + A \grammarterm{module-import-declaration} that specifies + a \grammarterm{module-name} $M$ + imports all module interface units of $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 $M$. + Such a declaration imports the so-named + module partition of $M$. + + \pnum + A \grammarterm{module-import-declaration} that specifies + a \grammarterm{header-name} $H$ imports + a synthesized \term{header unit}, + which is a translation unit formed by applying + phases 1 to 7 of translation (\stdref{lex.phases}{5.2}) + to the source file or header nominated by $H$, + which shall not contain a \grammarterm{module-declaration}. + \enternote + All declarations within a header unit are implicitly + exported (\ref{module.interface}), + and are attached to the global module (\ref{module.unit}). + \exitnote + An \term{importable header} is a member of an + implementation-defined set of headers. + $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 (\ref{cpp.include}). + \enternote + 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}. + \exitnote + A declaration of a name with internal linkage is + permitted within a header unit despite all + declarations being implicitly exported (\ref{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 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 + \color{addclr} + A module implementation unit shall not be exported. + \begin{example} + \begin{Program} +// Translation unit \#1 +module M:Part; + +// Translation unit \#2 +export module M; +export import :Part; // error: exported partition \tcode{:Part} is an implementation unit + \end{Program} + \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 M in its own unit + \end{codeblock} + \end{example} + +\color{addclr} + \pnum + A translation unit \term{has an 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{Program} + // Interface unit of M1 + export module M1; + import M2; + + // Interface unit of M2 + export module M2; + import M3; + + // Interface unit of M3 + export module M3; + import M1; // error: cyclic interface dependency M3 -> M1 -> M2 -> M3 + \end{Program} + \end{example} + +\begin{before}\color{addclr} +\pnum + A translation unit has an interface dependency on a module \tcode{M} if it is + a module implementation unit of \tcode{M}, or if it contains a + \grammarterm{module-import-declaration} nominating \tcode{M}, or if it has + an interface dependency on a module that has an interface dependency on \tcode{M}. +\end{before} +\end{std.txt} + +\rSec1[module.global]{Global module fragment} + +\begin{std.txt}\color{addclr} +\begin{bnf} +\nonterminal{global-module-fragment}:\br + \terminal{module} \terminal{;} top-level-declaration-seq\opt +\end{bnf} + +\pnum +A \grammarterm{global-module-fragment} specifies the contents of the +\term{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. +\enternote +Prior to phase 4 of translation, +only preprocessing directives can appear +in the global module fragment (\ref{cpp.glob.frag}). +\exitnote + +\pnum +A declaration $D$ is \term{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 (\stdref{basic.def.odr}{6.2}) +appearing in $S$, or + +\item +$S$ contains an expression \tcode{E} of the form + +\begin{ncsimplebnf} +postfix-expression \terminal{(} expression-list\opt{} \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 (\stdref{over.over}{11.4}) +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 \term{discarded} 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 +(\stdref{temp.point}{12.7.4.1}) are outside the module unit, +even when the instantiation context (\ref{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{codeblock} +// \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); +} + +// 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} + // \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} + +// 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{codeblock} +\end{example} +\end{std.txt} + +\rSec1[module.context]{Instantiation context} + +\begin{std.txt}\color{addclr} +\pnum +The \term{instantiation context} is a set of points within the program +that determines which names are visible to argument-dependent name lookup +(\ref{basic.lookup.argdep}) +and which declarations are reachable (\ref{module.reach}) +in the context of a particular declaration or template instantiation. + +\pnum +During the implicit definition of a defaulted special member function +(\stdref{special}{10.2.3}), +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 (\stdref{temp.point}{12.7.4.1}), +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{codeblock} +// 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; } + +// 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); +} + +// 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); +} + +// translation unit \#4 +import M1; +import M2; +void test() { + f(0); + g(0); +} +\end{codeblock} +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} +\end{std.txt} + +\rSec1[module.reach]{Reachability} + +\begin{std.txt}\color{addclr} +\pnum +A translation unit $U$ is \term{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$ (\ref{module.import}). +\enternote +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 (\ref{basic.scope.namespace}). +\exitnote + +\pnum +All translation units that are necessarily reachable are \term{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.% +\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 \term{reachable} or \term{necessarily reachable}, respectively, if, +for any point $P$ in the +instantiation context (\ref{module.context}), +\begin{itemize} +\item $D$ appears prior to $P$ in the same translation unit, or +\item $D$ is not discarded (\ref{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} +\enternote +Whether a declaration is exported has no bearing on whether it is reachable. +\exitnote + +\pnum +The accumulated properties of all reachable declarations of +an entity within a context +determine the behavior of the entity within that context. +\enternote +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{codeblock} +// 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 \tcode{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 \tcode{struct B} +void g() { f(); } // error: no reachable definition of \tcode{struct B} +\end{codeblock} +\end{example} +\exitnote + +% This is not necessarily true due to the "semantic boundaries" rule. +%\pnum +%\enternote +%The reachable semantic properties for an entity attached to a module $M$ +%are the same for all contexts outside that module in which the entity +%can be referenced, irrespective of whether $M$ is directly or indirectly +%imported. +%\exitnote + +\pnum +\enternote +An entity can have reachable declarations +even if it is not visible to name lookup. +\exitnote +\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} +\end{std.txt} diff --git a/src/notes b/src/notes new file mode 100644 index 0000000..0e775a6 --- /dev/null +++ b/src/notes @@ -0,0 +1,19 @@ +added module partitions +added "linkage specifications opt out of module ownership" +added module preamble syntax +added 'module;' introducer (p0713r1, approved at jax) +header import semantics +module import declaration shall only appear within preamble if there is a module-declaration +availability rule (effects may be available despite the declaration not being visible) +header import preprocessor effects +preamble identification + +WORDING QUESTIONS: +do we need ASG etc? can we simplify it? +do we need modules-as-entities? + +TO DISCUSS WITH EWG: +namespace export rules +ADL and path of instantiation +#export +public import or restricted import diff --git a/src/overloading.tex b/src/overloading.tex index 340c63a..973b194 100644 --- a/src/overloading.tex +++ b/src/overloading.tex @@ -1,6 +1,6 @@ %!TEX root = ts.tex -\setcounter{chapter}{15} +\setcounter{chapter}{10} \rSec0[over]{Overloading} \setcounter{section}{4} @@ -10,10 +10,9 @@ \rSec2[over.literal]{User-defined literals} \noindent -Modify paragraph 16.5.8/7 as follows: +Modify paragraph 11.5.8/7 as follows: \begin{std.txt} - \resetalinea[6] - \alinea + \pnum[7] \enternote Literal operators and literal operator templates are usually invoked implicitly through user-defined literals (5.13.8). However, except for diff --git a/src/p1103r3.pdf b/src/p1103r3.pdf new file mode 100644 index 0000000..0f50d4c Binary files /dev/null and b/src/p1103r3.pdf differ diff --git a/src/preprocessor.tex b/src/preprocessor.tex new file mode 100644 index 0000000..46995bf --- /dev/null +++ b/src/preprocessor.tex @@ -0,0 +1,282 @@ +%!TEX root = std.tex +\setcounter{chapter}{13} +\rSec0[cpp]{Preprocessing directives}% + +\begin{after} +Modify paragraph 14/5 as follows: + +\begin{std.txt} +\pnum[5] +The implementation can +process and skip sections of source files conditionally, +include other source files, +\added{import macros from header units,} +and replace macros. +These capabilities are called +\term{preprocessing}, +because conceptually they occur +before translation of the resulting translation unit. +\end{std.txt} +\end{after} + +\setcounter{section}{0} +\rSec1[cpp.cont]{Conditional inclusion}% + +Modify the grammar before 14.1/1 as follows: + +\begin{std.txt} +\begin{bnf} +\added{\nonterminal{header-name-tokens}:}\br + \added{string-literal}\br + \added{\terminal{<} h-pp-tokens \terminal{>}} +\end{bnf} + +\begin{bnf} +\nonterminal{has-include-expression}:\br + % FIXME: Need \textunderscore: underscore package does not work inside \added / \removed! + \removed{\terminal{\xname{has\textunderscore{}include}} \terminal{(} \terminal{<} h-char-sequence \terminal{>} \terminal{)}}\br + \removed{\terminal{\xname{has\textunderscore{}include}} \terminal{(} \terminal{"} q-char-sequence \terminal{"} \terminal{)}}\br + \added{\terminal{\xname{has\textunderscore{}include}} \terminal{(} header-name \terminal{)}}\br + \removed{\terminal{\xname{has\textunderscore{}include}} \terminal{(} string-literal \terminal{)}}\br + \removed{\terminal{\xname{has\textunderscore{}include}} \terminal{(} \terminal{<} h-pp-tokens \terminal{>} \terminal{)}}\br + \added{\terminal{\xname{has\textunderscore{}include}} \terminal{(} header-name-tokens \terminal{)}}\br +\end{bnf} +\end{std.txt} + +Modify paragraph 14.1/2 as follows: + +\begin{std.txt} +\pnum[2] +A \grammarterm{defined-macro-expression} evaluates to \tcode{1} +if the identifier is currently defined as a macro name +(that is, if it is predefined or if +\added{it has one or more active macro definitions (\ref{cpp.module}), +for example because} +it has been the subject of a \tcode{\#define} preprocessing directive +without an intervening \tcode{\#undef} directive with the same subject +identifier), +\tcode{0} if it is not. + +\end{std.txt} + +Modify paragraph 14.1/3 as follows: + +\begin{std.txt} +\pnum[3] +The \removed{third and fourth forms} +\added{second form} +of \grammarterm{has-include-expression} +\removed{are} \added{is} considered +only if \removed{neither of} the first \removed{or second forms matches} +\added{form does not match}, +in which case the preprocessing tokens are processed just as in normal text. +\end{std.txt} + +\setcounter{section}{1} +\rSec1[cpp.include]{Source file inclusion}% + +\begin{after} +Add a new paragraph after 14.2/6 as follows: + +\begin{std.txt} +\color{addclr} +\pnum[7] +If the header identified by the \grammarterm{header-name} +denotes an importable header (\ref{module.import}), +the preprocessing directive +is instead replaced by the \grammarterm{preprocessing-token}{s} + +\begin{bnf} +\terminal{import} header-name \terminal{;} +\end{bnf} +\end{std.txt} +\end{after} + +\noindent +Add a new subclause 14.3 titled ``\textbf{Global module fragment}'' as follows: + +\setcounter{section}{2} +\rSec1[cpp.glob.frag]{Global module fragment}% + +\begin{std.txt} +\color{addclr} +\begin{bnf} +\nonterminal{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 +(\ref{cpp.include}), and for which the second \tcode{module} +\grammarterm{preprocessing-token} was not produced by source file inclusion or +macro replacement (\stdref{cpp.replace}{14.3}). +Otherwise, the first two preprocessing tokens at the end of phase 4 of +translation shall not be \tcode{module} \tcode{;}. +\end{std.txt} + +Add a new subclause 14.4 titled ``\textbf{Header units}'' as follows: + +\setcounter{section}{3} +\rSec1[cpp.module]{Header units}% + +\begin{std.txt} +\color{addclr} +\begin{bnf} +\nonterminal{import-seq}:\br + \grammarterm{top-level-token-seq}\opt{} \terminal{export}\opt{} \terminal{import} +\end{bnf} + +\begin{bnf} +\nonterminal{top-level-token-seq}:\br + \descr{any \nonterminal{pp-balanced-token-seq} ending in \terminal{;} or \terminal{\}}} +\end{bnf} + +\begin{bnf} +\nonterminal{pp-import}:\br + \terminal{import} header-name pp-import-suffix\opt{} \terminal{;}\br + \terminal{import} header-name-tokens pp-import-suffix\opt{} \terminal{;} +\end{bnf} + +\begin{bnf} +\nonterminal{pp-import-suffix}:\br + pp-import-suffix-token\br + pp-import-suffix pp-import-suffix-token +\end{bnf} + +\begin{bnf} +\nonterminal{pp-import-suffix-token}:\br + \descr{any \grammarterm{pp-balanced-token} other than \terminal{;}} +\end{bnf} + +\begin{bnf} +\nonterminal{pp-balanced-token-seq}:\br + pp-balanced-token\br + pp-balanced-token-seq pp-balanced-token +\end{bnf} + +\begin{bnf} +\nonterminal{pp-balanced-token}:\br + pp-ldelim pp-balanced-token-seq\opt{} pp-rdelim\br + \descr{any \grammarterm{preprocessing-token} other than a \nonterminal{pp-ldelim} or \nonterminal{pp-rdelim}} +\end{bnf} + +\begin{bnf} +\nonterminal{pp-ldelim:} \descr{one of}\br + \terminal{( [ \{ <: <\%} +\end{bnf} + +\begin{bnf} +\nonterminal{pp-rdelim:} \descr{one of}\br + \terminal{) ] \} :> \%>} +\end{bnf} + +\color{addclr} +\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 +(\ref{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 (\stdref{cpp.replace}{14.3}). +The \term{point of macro import} for a \grammarterm{pp-import} is +immediately after the \tcode{;} terminating the \grammarterm{pp-import}. + +\color{addclr} +\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} + +\color{addclr} +\pnum +Each \tcode{\#define} directive encountered when preprocessing +each translation unit in a program results in a distinct +\term{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 \term{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 (\stdref{lex.key}{5.11}) +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 \term{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 \term{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 (\stdref{cpp.replace}{14.3}). +\enternote +The relative order of \grammarterm{pp-import}{s} has no bearing on whether a +particular macro definition is active. +\exitnote + +\pnum +\begin{example} +\begin{codeblock} +// translation unit 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{codeblock} + +\begin{codeblock} +// translation unit 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{codeblock} + +\begin{codeblock} +// translation unit c.h +#define Y 45 // \#4 +#define Z c // \#5 +\end{codeblock} + +\begin{codeblock} +// translation unit 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{codeblock} +\end{example} +\end{std.txt} diff --git a/src/references.tex b/src/references.tex index 873dc47..cc37c66 100644 --- a/src/references.tex +++ b/src/references.tex @@ -3,7 +3,6 @@ \rSec0[intro.refs]{Normative references} \pnum - The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. diff --git a/src/scope.tex b/src/scope.tex index 946fbfb..9d7fce2 100644 --- a/src/scope.tex +++ b/src/scope.tex @@ -1,4 +1,4 @@ - +\setcounter{chapter}{0} \rSec0[intro.scope]{Scope} \pnum diff --git a/src/templates.tex b/src/templates.tex index 4f8faa0..10606f8 100644 --- a/src/templates.tex +++ b/src/templates.tex @@ -1,20 +1,19 @@ %!TEX root = std.tex -\setcounter{chapter}{16} +\setcounter{chapter}{11} \rSec0[temp]{Templates}% %\indextext{template|(} \noindent -Modify paragraph 17/2 as follows: +Modify paragraph 12/4 as follows: \begin{std.txt} - \resetalinea[1] - \alinea + \pnum[4] A \grammarterm{template-declaration} can appear only as a namespace scope or class scope declaration. \added{Its \grammarterm{declaration} shall not be an - \grammarterm{export-declaration} or a - \grammarterm{proclaimed-ownership-declaration}.} + \grammarterm{export-declaration}.} In a function template declaration, the last component of the \grammarterm{declarator-id} shall not be a \grammarterm{template-id}. + [...] \end{std.txt} @@ -30,238 +29,236 @@ %% \noindent %% Modify second bullet of paragraph 14.6.4/1 %% \begin{std.txt} -%% \item[---] Declarations from namespace \added{partitions} associated +%% \item Declarations from namespace \added{partitions} associated %% with the types of the function arguments both from the %% instantiation context (14.6.4.1) and from the definition context. %% \end{std.txt} -\setcounter{section}{5} +\setcounter{section}{6} \rSec1[temp.res]{Name resolution} \setcounter{subsection}{3} \rSec2[temp.dep.res]{Dependent name resolution} - -Add new example to paragraph 17.6.4/1: -\begin{std.txt} - \begin{addedblock} - \enterexample - \begin{codeblock} - // Header file X.h - namespace Q { - struct X { }; - } - - // Interface unit of M1 - #include "X.h" // global module - namespace Q { - void g_impl(X, X); - } - export module M1; - export template - void g(T t) { - g_impl(t, Q::X{ }); // \#1: ADL in definition context finds Q::g_impl - } - - // Interface unit of M2 - #include "X.h" - import M1; - export module M2; - void h(Q::X x) { - g(x); // OK - } - \end{codeblock} - \exitexample -\end{addedblock} -\end{std.txt} - +\rSec3[temp.point]{Point of instantiation} \noindent -Add new paragraphs to 17.6.4: +Delete paragraph 12.7.4.1/7: \begin{std.txt} - \color{addclr} - \resetalinea[1] - \alinea - \enterexample - \begin{codeblock} - // Interface unit of Std - export module Std; - export template - void indirect_swap(Iter lhs, Iter rhs) - { - swap(*lhs, *rhs); // swap can be found only via ADL - } - - // Interface unit of M - import Std; - export module M; - - struct S { /* ...*/ }; - void swap(S&, S&); // \#1; - - void f(S* p, S* q) - { - indirect_swap(p, q); // instantiation finds \#1 via ADL - } - \end{codeblock} - \exitexample - - \alinea - \enterexample - \begin{codeblock} - // Header file X.h - struct X { /* ... */ }; - X operator+(X, X); - - // Module interface unit of F - export module F; - export template - void f(T t) { - t + t; - } - - // Module interface unit of M - #include "X.h" - import F; - export module M; - void g(X x) { - f(x); // OK: instantiates f from F - // point of instantiation: just before g(X) - } - \end{codeblock} - \exitexample - - \alinea - \enternote - \enterexample - \begin{codeblock} - // Module interface unit of A - export module A; - export template - void f(T t) { - t + t; // \#1 - } - - // Module interface unit of B - export module B; - import A; - export template - void g(T t, U u) { - f(t); - } - - // Module interface unit of C - #include // not in the purview of C - import B; - export module C; - export template - void h(T t) { - g(std::string{ }, t); - } - - // Translation unit of main() - import C; - void i() { - h(0); // ill-formed: '+' not found at \#1 - // point of instantiation of h: just before 'i()' - // point of instantiation of g: same as h's - // point of instantiation of f: same as g's - } - \end{codeblock} - \exitexample - - This example is ill-formed by this document. - It is an open question as to how often the scenario occurs in - practice, and whether to make the example well-formed or whether - additional syntax will be introduced that does not involve - modifying the header. - \exitnote - - \alinea - \enternote - \enterexample - \begin{codeblock} - // Module interface unit of M1 - #include - - export module M1; - export template - void f(T& t, U& u) { - min(t, u); // \#1 - } - - // Module interface unit of M2 - #include - struct Aux : std::ctype_base { - operator int() const; - }; - void min(Aux&, Aux&); // \#2 - - export module M2; - import M1; - export template - void g(T t) { - Aux aux; - f(aux, aux); - } - - // Elsewhere, translation unit of global module - import M2; - void h() { - g(0); - } - \end{codeblock} - In the body of the function \tcode{h}, the call to \tcode{g} triggers a request - for (implicit) instantiation of \tcode{g}. The point of instantiation of - that specialization is right before the definition of \tcode{h}. - That instantiation, in turn, requests the implicit instantiation of - \tcode{f}. The point of instantiation of that specialization - immediately preceeds that of \tcode{g}. In that context, the invocation of - \tcode{min}: (a) selects \tcode{std::min}; and (b) invokes the - implicit conversion. In particular, the declaration at {\#2} is not used - because it is neither available in the context of definition, nor in the - context of instantiation of \tcode{f}. - However, paragraph 17.6.4.2/1 of the C++ Standard formally renders the behavior - of the program undefined because the better match wasn't considered. This is - a case where it is unclear if that paragraph is too broad and needs further restrictions, - or if there ought to be a mechanism to consider all such functions. - \exitexample - \exitnote +\pnum[7] +\removed{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.} \end{std.txt} - -\rSec3[temp.point]{Point of instantiation} - \noindent -Replace paragraph 17.6.4.1/7 as follows: +Change in paragraph \ref{temp.point}/8: \begin{std.txt} - \resetalinea[6] - \alinea - \removed{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.}\added{The - instantiation context of an expression that depends on template - arguments is the context of a lookup at the point of instantiation - of the enclosing template.} +\pnum[8] +in addition to the points of instantiation described above, +\begin{itemize} +\item +for any such +specialization that has a point of instantiation within the +\added{\grammarterm{top-level-declaration-seq} of the} +translation unit, +\added{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 +\added{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} \end{std.txt} - \rSec3[temp.dep.candidate]{Candidate functions} \noindent -Modify paragraph 17.6.4.2/1 as follows +Modify paragraph 12.7.4.2/1 as follows \begin{std.txt} - \resetalinea[0] - \alinea - \ldots - - 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 external \added{or module} - linkage introduced in those namespaces in all - translation units, not just considering those declarations found in the - template definition and template instantiation contexts, then the program - has undefined behavior. +\pnum[1] +For a function call where the \grammarterm{postfix-expression} is a +dependent name, +the candidate functions are found using the usual lookup +rules \added{from the template definition context}~(\stdref{basic.lookup.unqual}{6.4.1}, \ref{basic.lookup.argdep})\added{.} +\removed{except that:} +\added{\enternote} +\begin{itemize} +\item +\removed{For the part of the lookup using unqualified name lookup (\stdref{basic.lookup.unqual}{6.4.1}), +only function declarations +from the template definition context are found.} +\item +For the part of the lookup using associated namespaces (\ref{basic.lookup.argdep}), +\removed{only} function declarations found in \removed{either the template +definition context or} the template instantiation context are found +\added{by this lookup, as described in \ref{basic.lookup.argdep}}. +\end{itemize} +\added{\exitnote} +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 external +linkage introduced in those namespaces in all +translation units, not just considering those declarations found in the +template definition and template instantiation contexts, then the program +has undefined behavior. \end{std.txt} - - +Append new paragraphs as follows: + +\begin{std.txt}\color{addclr} +\pnum[2] +\enterexample +\begin{codeblock} +// header file \tcode{"X.h"} +namespace Q { + struct X { }; +} + +// header file \tcode{"G.h"} +namespace Q { + void g_impl(X, X); +} + +// 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 +} + +// interface unit of \tcode{M2} +module; +#include "X.h" +export module M2; +import M1; +void h(Q::X x) { + g(x); // OK +} +\end{codeblock} +\exitexample + +\color{addclr} +\pnum +\enterexample +\begin{codeblock} +// 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 +} + +// 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{codeblock} +\exitexample + +\pnum +\enterexample +\begin{codeblock} +// header file \tcode{"X.h"} +struct X { /* ... */ }; +X operator+(X, X); + +// module interface unit of \tcode{F} +export module F; +export template +void f(T t) { + t + t; +} + +// 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{codeblock} +\exitexample + +\pnum +\enterexample +\begin{codeblock} +// module interface unit of \tcode{A} +export module A; +export template +void f(T t) { + cat(t, t); // \#1 + dog(t, t); // \#2 +} + +// module interface unit of \tcode{B} +export module B; +import A; +export template +void g(T t, U u) { + f(t); +} + +// \tcode{"foo.h"}, not an importable header +struct foo { + friend int cat(foo, foo); +}; +int dog(foo, foo); + +// 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); +} + +// translation unit +import C1; +void i() { + h(0); // error: \tcode{dog} not found at \#2 +} + +// \tcode{"bar.h"}, an importable header +struct bar { + friend int cat(bar, bar); +}; +int dog(bar, bar); + +// 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); +} + +// 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{codeblock} +\exitexample +\end{std.txt} diff --git a/src/ts.tex b/src/ts.tex index e1ad9e4..faadc63 100644 --- a/src/ts.tex +++ b/src/ts.tex @@ -13,27 +13,26 @@ {listings} % code listings \usepackage{longtable} % auto-breaking tables \usepackage{ltcaption} % fix captions for long tables -\usepackage{booktabs} % fancy tables \usepackage{relsize} % provide relative font size changes +\usepackage{textcomp} % provide \text{l,r}angle \usepackage{underscore} % remove special status of '_' in ordinary text -\usepackage{verbatim} % improved verbatim environment \usepackage{parskip} % handle non-indented paragraphs "properly" \usepackage{array} % new column definitions for tables \usepackage[normalem]{ulem} +\usepackage{enumitem} \usepackage{color} % define colors for strikeouts and underlines \usepackage{amsmath} % additional math symbols \usepackage{mathrsfs} % mathscr font -\usepackage{microtype} +\usepackage[final]{microtype} \usepackage{multicol} -\usepackage{xspace} -\usepackage{fixme} +\usepackage{xspace} % FIXME: removed from WP \usepackage{lmodern} \usepackage[T1]{fontenc} \usepackage[pdftex, final]{graphicx} \usepackage[pdftex, - pdftitle={C++ Technical Specification}, - pdfsubject={C++ Technical Specification}, - pdfcreator={Gabriel Dos~Reis}, + pdftitle={Merging Modules}, + pdfsubject={Merging Modules}, + pdfcreator={Richard Smith}, bookmarks=true, bookmarksnumbered=true, pdfpagelabels=true, @@ -45,7 +44,16 @@ plainpages=false ]{hyperref} \usepackage{memhfixc} % fix interactions between hyperref and memoir -\usepackage{xstring} +%\usepackage[active,header=false,handles=false,copydocumentclass=false,generate=std-gram.ext,extract-cmdline={gramSec},extract-env={bnf,simplebnf}]{extract} % Grammar extraction +\usepackage{expl3} +\usepackage{xparse} +\usepackage{environ} % FIXME: remove + +\pdfminorversion=5 +\pdfcompresslevel=9 +\pdfobjcompresslevel=2 + +\renewcommand\RSsmallest{5.5pt} % smallest font size for relsize \input{layout} \input{styles} @@ -56,27 +64,11 @@ \makeindex[libraryindex] \makeindex[impldefindex] -%%-------------------------------------------------- -%% macros specific to the Networking TS -\newcommand{\completionsig}{\Fundesc{Completion signature}} -\newcommand{\DEDUCED}{\textit{\texttt{DEDUCED}}} -\newcommand{\nativeref}{see~\ref{socket.reqmts.native}} -\newcommand{\CppXref}[1]{\texorpdfstring{C\kern-0.05em\protect\raisebox{.35ex}{\textsmaller[2]{+\kern-0.05em+}}Std}{C++Std} [#1]} -% Alternative formatting of cross-references, resolving stable name to number. -% Needs include{cxx} and CppXIV from cplusplus/draft/source/macros.tex. -% \input{cxx} -% \newcommand{\CppXref}[1]{\CppXIV \S\cxxref{#1}} - % Add two names to the library index as both #1!#2 and #2!#1 \newcommand{\indexlibrarytwo}[2]{% \indexlibrary{\idxcode{#1}!\idxcode{#2}}% \indexlibrary{\idxcode{#2}!\idxcode{#1}}% } -% Add an extensible implementation entry to the main and library name indices -\newcommand{\indexextensible}[1]{% -\indextext{extensible implementation!\idxcode{#1}}% -\indexlibrary{\idxcode{#1}!extensible implementation}% -} %%-------------------------------------------------- %% fix interaction between hyperref and other @@ -107,30 +99,44 @@ %%-------------------------------------------------- %% front matter \frontmatter -\include{front} +\input{cover-wd} +\input{front} -%%-------------------------------------------------- -%% main body of the document \mainmatter \setglobalstyles -\include{scope} -\include{references} -\include{definitions} -\include{general} +%%-------------------------------------------------- +%% part 1: design and commentary +\begin{KeepFromToc} +\part[Commentary]{Design and commentary}\label{commentary} + +\input{bg} + +\end{KeepFromToc} + +%%-------------------------------------------------- +%% part 2: wording +\part[Wording]{Wording for applying the merged modules proposal to the C++20 working draft}\label{wording} + +%\include{scope} +%\include{references} +%\include{definitions} +%\include{general} \include{lexical} \include{basic} \include{declarations} +\include{modules} \include{classes} \include{overloading} \include{templates} +\include{preprocessor} %%-------------------------------------------------- %% appendices -%\appendix -%\include{compatibility} +\appendix +\include{compat} %%-------------------------------------------------- %% back matter