From cdec7c1fc0ca5bee244f6fb4e6fb5f1acf44ba07 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 15 Nov 2020 11:21:20 +0100 Subject: [PATCH 01/60] P1787R6 Declarations and where to find them --- source/basic.tex | 72 +++++++++++++++++++++++++++++++++++++----------- source/intro.tex | 11 ++++---- source/lex.tex | 14 ++++++---- 3 files changed, 69 insertions(+), 28 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index f078e90b75..ee46d02bc0 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -40,18 +40,55 @@ pack. \pnum -A \defn{name} is a use of an \grammarterm{identifier}\iref{lex.name}, +A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, \grammarterm{operator-function-id}\iref{over.oper}, -\grammarterm{literal-operator-id}\iref{over.literal}, -\grammarterm{conversion-function-id}\iref{class.conv.fct}, or -\grammarterm{template-id}\iref{temp.names} that denotes an entity or -label~(\ref{stmt.goto}, \ref{stmt.label}). +\grammarterm{literal-operator-id}\iref{over.literal}, or +\grammarterm{conversion-function-id}\iref{class.conv.fct}. \pnum -Every name that denotes an entity is introduced by a -\defn{declaration}. Every name that denotes a label is introduced -either by a \tcode{goto} statement\iref{stmt.goto} or a -\grammarterm{labeled-statement}\iref{stmt.label}. +Every name is introduced by a \defn{declaration}, which is a +\begin{itemize} +\item +\grammarterm{declaration}, +\grammarterm{block-declaration}, or +\grammarterm{member-declaration} (\ref{dcl.pre}, \ref{class.mem}), +\item +\grammarterm{init-declarator}\iref{dcl.decl}, +\item +\grammarterm{identifier} +in a structured binding declaration\iref{dcl.struct.bind}, +\item +\grammarterm{init-capture}\iref{expr.prim.lambda.capture}, +\item +\grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, +\item +\grammarterm{member-declarator}\iref{class.mem}, +\item +\grammarterm{using-declarator}\iref{namespace.udecl}, +\item +\grammarterm{parameter-declaration}\iref{dcl.fct}, +\item +\grammarterm{type-parameter}\iref{temp.param}, +\item +\grammarterm{elaborated-type-specifier} +that introduces a name\iref{dcl.type.elab}, +\item +\grammarterm{class-specifier}\iref{class.pre}, +\item +\grammarterm{enum-specifier} or +\grammarterm{enumerator-definition}\iref{dcl.enum}, +\item +\grammarterm{exception-declaration}\iref{except.pre}, or +\item +implicit declaration of an injected-class-name\iref{class.pre}. +\end{itemize} +\begin{note} +The interpretation of a \grammarterm{for-range-declaration} produces +one or more of the above\iref{stmt.ranged}. +\end{note} +An entity $E$ is denoted by the name (if any) +that is introduced by a declaration of $E$ or +by a \grammarterm{typedef-name} introduced by a declaration specifying $E$. \pnum A \defn{variable} is introduced by the @@ -80,9 +117,7 @@ \item they are \grammarterm{operator-function-id}{s} formed with the same operator, or \item they are \grammarterm{conversion-function-id}{s} formed -with the same type, or -\item they are \grammarterm{template-id}{s} that refer to the same class, -function, or variable\iref{temp.type}, or +with equivalent\iref{temp.over.link} types, or \item they are \grammarterm{literal-operator-id}{s}\iref{over.literal} formed with the same literal suffix identifier. \end{itemize} @@ -101,11 +136,14 @@ \indextext{declaration!definition versus}% \indextext{declaration}% \indextext{declaration!name}% -A declaration\iref{dcl.dcl} may introduce -one or more names into a translation -unit or redeclare names introduced by previous declarations. +A declaration\iref{dcl.dcl} may (re)introduce +one or more names and/or entities into a translation +unit. If so, the declaration specifies the interpretation and semantic properties of these names. +A declaration of an entity or \grammarterm{typedef-name} $X$ is +a redeclaration of $X$ +if another declaration of $X$ is reachable from it\iref{module.reach}. A declaration may also have effects including: \begin{itemize} \item a static assertion\iref{dcl.pre}, @@ -148,7 +186,7 @@ specifier (this usage is deprecated; see \ref{depr.static.constexpr}), \item \indextext{declaration!class name}% -it is introduced by an \grammarterm{elaborated-type-specifier}\iref{class.name}, +it is an \grammarterm{elaborated-type-specifier}\iref{class.name}, \item it is an \indextext{declaration!opaque enum}% @@ -389,6 +427,8 @@ \end{itemize} \pnum +A variable is named by an expression +if the expression is an \grammarterm{id-expression} that denotes it. A variable \tcode{x} whose name appears as a potentially-evaluated expression $E$ is \defnx{odr-used}{odr-use} by $E$ unless diff --git a/source/intro.tex b/source/intro.tex index a91c950d9b..fbc90fb5fc 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -564,7 +564,7 @@ \defncontext{function} name, parameter-type-list, -and enclosing namespace (if any) +and enclosing namespace \begin{defnote} Signatures are used as a basis for @@ -585,7 +585,7 @@ \defncontext{function template} name, parameter-type-list, -enclosing namespace (if any), +enclosing namespace, return type, \grammarterm{template-head}, and @@ -813,10 +813,9 @@ consistent with the descriptions in the library Clauses. \pnum -The names defined in the library have namespace -scope\iref{basic.namespace}. A \Cpp{} translation -unit\iref{lex.phases} obtains access to these names by including the -appropriate standard library header or importing +A \Cpp{} translation unit\iref{lex.phases} +obtains access to the names defined in the library by +including the appropriate standard library header or importing the appropriate standard library named header unit\iref{using.headers}. \pnum diff --git a/source/lex.tex b/source/lex.tex index 9bce034663..3e39f30b11 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -1933,12 +1933,14 @@ \pnum A \grammarterm{user-defined-literal} is treated as a call to a literal operator or -literal operator template\iref{over.literal}. To determine the form of this call for a -given \grammarterm{user-defined-literal} \placeholder{L} with \grammarterm{ud-suffix} \placeholder{X}, -the \grammarterm{literal-operator-id} whose literal suffix identifier is \placeholder{X} is -looked up in the context of \placeholder{L} using the rules for unqualified name -lookup\iref{basic.lookup.unqual}. Let \placeholder{S} be the set of declarations found by -this lookup. \placeholder{S} shall not be empty. +literal operator template\iref{over.literal}. +To determine the form of this call for +a given \grammarterm{user-defined-literal} \placeholder{L} +with \grammarterm{ud-suffix} \placeholder{X}, +first let \placeholder{S} be the set of declarations +found by unqualified lookup for the \grammarterm{literal-operator-id} +whose literal suffix identifier is \placeholder{X}\iref{basic.lookup.unqual}. +\placeholder{S} shall not be empty. \pnum If \placeholder{L} is a \grammarterm{user-defined-integer-literal}, let \placeholder{n} be the literal From 60d12b4f6f3994bab7f73cbaa72cf3e29b813f7b Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 15 Nov 2020 23:05:32 +0100 Subject: [PATCH 02/60] basic.scope.scope --- source/basic.tex | 279 +++++++++++++++++++++++++++------------- source/declarations.tex | 2 +- source/expressions.tex | 8 +- source/xrefdelta.tex | 1 + 4 files changed, 198 insertions(+), 92 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index ee46d02bc0..e0600277de 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -32,7 +32,6 @@ \indextext{storage class}% \indextext{scope}% \indextext{linkage}% -\indextext{region!declarative}% An \defn{entity} is a value, object, reference, structured binding, function, enumerator, type, @@ -486,30 +485,30 @@ \pnum A local entity\iref{basic.pre} -is \defn{odr-usable} in a declarative region\iref{basic.scope.declarative} if: +is \defn{odr-usable} in a scope\iref{basic.scope.scope} if: \begin{itemize} \item either the local entity is not \tcode{*this}, or an enclosing class or non-lambda function parameter scope exists and, if the innermost such scope is a function parameter scope, it corresponds to a non-static member function, and \item -for each intervening declarative region\iref{basic.scope.declarative} +for each intervening scope\iref{basic.scope.scope} between the point at which the entity is introduced and the region (where \tcode{*this} is considered to be introduced within the innermost enclosing class or non-lambda function definition scope), either: \begin{itemize} -\item the intervening declarative region is a block scope, or -\item the intervening declarative region is the function parameter scope of a \grammarterm{lambda-expression} +\item the intervening scope is a block scope, or +\item the intervening scope is the function parameter scope of a \grammarterm{lambda-expression} that has a \grammarterm{simple-capture} naming the entity or has a \grammarterm{capture-default}, and the block scope of the \grammarterm{lambda-expression} -is also an intervening declarative region. +is also an intervening scope. \end{itemize} \end{itemize} If a local entity is odr-used -in a declarative region in which it is not odr-usable, +in a scope in which it is not odr-usable, the program is ill-formed. \begin{example} \begin{codeblock} @@ -794,101 +793,207 @@ \rSec1[basic.scope]{Scope}% \indextext{scope|(} -\rSec2[basic.scope.declarative]{Declarative regions and scopes}% -\indextext{scope!declarations and|(} +\rSec2[basic.scope.scope]{General} \pnum -\indextext{name!scope of}% -Every name is introduced in some portion of program text called a -\indextext{region!declarative}% -\indextext{scope!potential}% -\defn{declarative region}, which is the largest part of the program -in which that name is valid, that is, in which that name may -be used as an unqualified name to refer to the same entity. In general, -each particular name is valid only within some possibly discontiguous -portion of program text called its \defn{scope}. To determine the -scope of a declaration, it is sometimes convenient to refer to the -\defn{potential scope} of a declaration. The scope of a declaration -is the same as its potential scope unless the potential scope contains -another declaration of the same name. In that case, the potential scope -of the declaration in the inner (contained) declarative region is -excluded from the scope of the declaration in the outer (containing) -declarative region. +The declarations in a program appear in a number of scopes +that are in general discontiguous. +The global scope contains the entire program; +every other scope $S$ is introduced by a +declaration, +\grammarterm{parameter-declaration-clause}, +\grammarterm{statement}, or \grammarterm{handler} +(as described in the following subclauses of \ref{basic.scope}) +ppearing in another scope which thereby contains $S$. +An \defnadj{enclosing}{scope} at a program point is any scope that contains it; +the smallest such scope is said to be the \defnadj{immediate}{scope} +at that point. +A scope \defnx{intervenes}{intervene} +between a program point $P$ and a scope $S$ +(that does not contain $P$) if it is or contains $S$ but does not contain $P$. \pnum +Unless otherwise specified: +\begin{itemize} +\item +The smallest scope that contains a scope $S$ is the parent scope of $S$. +\item +No two declarations (re)introduce the same entity. +\item +A declaration inhabits the immediate scope at its locus\iref{basic.scope.pdecl}. +\item +A declaration's target scope is the scope it inhabits. +\item +Any names (re)introduced by a declaration are bound to it in its target scope. +\end{itemize} +An entity belongs to a scope $S$ +if $S$ is the target scope of a declaration of the entity. +\begin{note} +Special cases include that: +\begin{itemize} +\item +Template parameter scopes are parents +only to other template parameter scopes\iref{basic.scope.temp}. +\item +Corresponding declarations with appropriate linkage +declare the same entity\iref{basic.link}. +\item +The declaration in a \grammarterm{template-declaration} +inhabits the same scope as the \grammarterm{template-declaration}. +\item +Friend declarations and +declarations of qualified names and +template specializations do not bind names\iref{dcl.meaning}; +those with qualified names target a specified scope, and +other friend declarations and +certain \grammarterm{elaborated-type-specifier}s\iref{dcl.type.elab} +target a larger enclosing scope. +\item +Block-scope extern declarations target a larger enclosing scope +but bind a name in their immediate scope. +\item +The names of unscoped enumerators are bound +in the two innermost enclosing scopes\iref{dcl.enum}. +\item +A class's name is also bound in its own scope\iref{class.pre}. +\item +The names of the members of an anonymous union are bound in +the union's parent scope\iref{class.union.anon}. +\end{itemize} +\end{note} + +\pnum +Two declarations \defn{correspond} +if they (re)introduce the same name, +both declare constructors, or +both declare destructors, +unless +\begin{itemize} +\item +either is a \grammarterm{using-declarator}, or +\item +one declares a type (not a \grammarterm{typedef-name}) and the other declares a +variable, +non-static data member other than of an anonymous union\iref{class.union.anon}, +enumerator, +function, or +function template, or +\item +each declares a function or function template, except when +\begin{itemize} +\item +both declare functions with the same parameter-type-list +\begin{footnote} +An implicit object parameter\iref{over.match.funcs} +is not part of the parameter-type-list. +\end{footnote}, +equivalent\iref{temp.over.link} trailing \grammarterm{requires-clauses} +(if any, except as specified in \ref{temp.friend}), and, +if both are non-static members, +the same \grammarterm{cv-qualifier}s (if any) and +\grammarterm{ref-qualifier} (if both have one), or +\item +both declare function templates with equivalent +parameter-type-lists, +return types (if any), +\grammarterm{template-head}s, and +trailing \grammarterm{requires-clauses} (if any), and, +if both are non-static members, +the same \grammarterm{cv-qualifier}s (if any) and +\grammarterm{ref-qualifier} (if both have one). +\end{itemize} +\end{itemize} +\begin{note} +Declarations can correspond even if neither binds a name. \begin{example} -In \begin{codeblock} -int j = 24; -int main() { - int i = j, j; - j = 42; -} +struct A { +friend void f(); // \#1 +}; +struct B { + friend void f() {} // corresponds to, and defines, \#1 +}; \end{codeblock} -the identifier \tcode{j} is declared twice as a name (and used twice). -The declarative region of the first \tcode{j} includes the entire -example. The potential scope of the first \tcode{j} begins immediately -after that \tcode{j} and extends to the end of the program, but its -(actual) scope excludes the text between the \tcode{,} and the -\tcode{\}}. The declarative region of the second declaration of -\tcode{j} (the \tcode{j} immediately before the semicolon) includes all -the text between \tcode{\{} and \tcode{\}}, but its potential scope -excludes the declaration of \tcode{i}. The scope of the second -declaration of \tcode{j} is the same as its potential scope. \end{example} +\end{note} +\begin{example} +\begin{codeblock} +typedef int Int; +enum E : int { a }; +void f(int); // \#1 +void f(Int) {} // defines \#1 +void f(E) {} // OK: another overload -\pnum -The names declared by a declaration are introduced into the scope in -which the declaration occurs, except that the presence of a -\tcode{friend} specifier\iref{class.friend}, certain uses of the -\grammarterm{elaborated-type-specifier}\iref{dcl.type.elab}, and -\grammarterm{using-directive}{s}\iref{namespace.udir} alter this general -behavior. +struct X { + static void f(); + void f() const; // error: redeclaration + void g(); + void g() const; // OK + void g() &; // error: redeclaration +}; +\end{codeblock} +\end{example} \pnum -Given a set of declarations in a single declarative region, each of -which specifies the same unqualified name, -\begin{itemize} -\item they shall all refer to the same entity, or all refer to functions -and function templates; or -\item exactly one declaration shall declare a class name or enumeration -name that is not a typedef name and the other declarations shall -all refer to the same variable, non-static data member, or enumerator, -or all refer to functions and function templates; -in this case the class name or enumeration name is -hidden\iref{basic.scope.hiding}. -\begin{note} -A structured binding\iref{dcl.struct.bind}, -namespace name\iref{basic.namespace}, or -class template name\iref{temp.pre} -must be unique in its declarative region. -\end{note} -\end{itemize} +Two declarations \defn{potentially conflict} +if they correspond and +cause their shared name to denote different entities\iref{basic.link}. +The program is ill-formed +if, in any scope, a name is bound to two declarations +that potentially conflict and one precedes the other\iref{basic.lookup}. \begin{note} -These restrictions apply to the declarative region into which -a name is introduced, which is not necessarily the same as the region in -which the declaration occurs. In particular, -\grammarterm{elaborated-type-specifier}{s}\iref{dcl.type.elab} and -friend declarations\iref{class.friend} can introduce a (possibly not -visible) name into an enclosing namespace; these restrictions apply to -that region. Local extern declarations\iref{basic.link} can introduce -a name into the declarative region where the declaration appears and -also introduce a (possibly not visible) name into an enclosing -namespace; these restrictions apply to both regions. +Overload resolution can consider potentially conflicting declarations +found in multiple scopes +(e.g. via \grammarterm{using-directive}s or for operator functions), +in which case it is often ambiguous. \end{note} +\begin{example} +\begin{codeblock} +void f() { + int x,y; + void x(); // error: different entity for \tcode{x} + int y; // error: redefinition +} +enum { f }; // error: different entity for \tcode{::f} +namespace A {} +namespace B = A; +namespace B = A; // OK: no effect +namespace B = B; // OK: no effect +namespace A = B; // OK: no effect +namespace B {} // error: different entity for \tcode{B} +\end{codeblock} +\end{example} \pnum -For a given declarative region \placeholder{R} -and a point \placeholder{P} outside \placeholder{R}, -the set of \defnx{intervening}{region!declarative!intervening} declarative regions -between \placeholder{P} and \placeholder{R} -comprises all declarative regions -that are or enclose \placeholder{R} and do not enclose \placeholder{P}. +A declaration is \defn{nominable} +in a class, class template, or namespace $E$ at a point $P$ if +it precedes $P$, +it does not inhabit a block scope, and +its target scope is the scope associated with $E$ or, +if $E$ is a namespace, +any element of the inline namespace set of $E$\iref{namespace.def}. +\begin{example} +\begin{codeblock} +namespace A { + void f() {void g();} + inline namespace B { + struct S { + friend void h(); + static int i; + }; + } +} +\end{codeblock} +At the end of this example, +the declarations of \tcode{f}, \tcode{B}, \tcode{S}, and \tcode{h} +are nominable in \tcode{A}, but those of \tcode{g} and \tcode{i} are not. +\end{example} \pnum -\begin{note} -The name lookup rules are summarized in~\ref{basic.lookup}. -\end{note} +When instantiating a templated entity\iref{temp.pre}, +any scope $S$ introduced by any part of the template definition is considered +to be introduced by the instantiated entity and +to contain the instantiations of any declarations that inhabit $S$. \rSec2[basic.scope.pdecl]{Point of declaration} @@ -2248,7 +2353,7 @@ \end{example} \pnum -A class member name hidden by a name in a nested declarative region or +A class member name hidden by a name in a nested scope or by the name of a derived class member can still be found if qualified by the name of its class followed by the \tcode{::} operator. @@ -2810,7 +2915,7 @@ outside the innermost enclosing namespace scope, such that the block scope declaration would be a (possibly ill-formed) redeclaration -if the two declarations appeared in the same declarative region, +if the two declarations appeared in the same scope, the block scope declaration declares that same entity and receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching diff --git a/source/declarations.tex b/source/declarations.tex index 8cb10c99ee..999f0258a0 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -6508,7 +6508,7 @@ A structured binding declaration introduces the \grammarterm{identifier}{s} $\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc$ of the -\grammarterm{identifier-list} as names\iref{basic.scope.declarative} +\grammarterm{identifier-list} as names of \defn{structured binding}{s}. Let \cv{} denote the \grammarterm{cv-qualifier}{s} in the \grammarterm{decl-specifier-seq} and diff --git a/source/expressions.tex b/source/expressions.tex index 43df35d164..3bc6417b9a 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1391,7 +1391,7 @@ The result is the entity denoted by the identifier. If the entity is a local entity and naming it from outside of an unevaluated operand -within the declarative region where the \grammarterm{unqualified-id} appears +within the scope where the \grammarterm{unqualified-id} appears would result in some intervening \grammarterm{lambda-expression} capturing it by copy\iref{expr.prim.lambda.capture}, the type of the expression is @@ -2082,7 +2082,7 @@ behaves as if it declares and explicitly captures a variable of the form ``\tcode{auto} \grammarterm{init-capture} \tcode{;}'' -whose declarative region is the \grammarterm{lambda-expression}'s +whose scope is the \grammarterm{lambda-expression}'s \grammarterm{compound-statement}, except that: \begin{itemize} \item if the capture is by copy (see below), the non-static data member @@ -2135,7 +2135,7 @@ \end{itemize} If an expression potentially references a local entity -within a declarative region in which it is odr-usable, +within a scope in which it is odr-usable, and the expression would be potentially evaluated if the effect of any enclosing \tcode{typeid} expressions\iref{expr.typeid} were ignored, the entity is said to be \defnx{implicitly captured}{capture!implicit} @@ -2417,7 +2417,7 @@ An \grammarterm{init-capture} containing an ellipsis is a pack expansion that introduces an \grammarterm{init-capture} pack\iref{temp.variadic} -whose declarative region is +whose scope is the \grammarterm{lambda-expression}'s \grammarterm{compound-statement}. \begin{example} \begin{codeblock} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 7b6af45f59..f140b0574d 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -24,6 +24,7 @@ %\movedxrefs{old.label}{new place (eg \tref{blah})} \movedxref{re.def}{intro.refs} +\movedxref{basic.scope.declarative}{basic.scope.scope} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From 70ea7f274311f9b9dff13e6eb14a45840b44f2d7 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 16 Nov 2020 09:00:25 +0100 Subject: [PATCH 03/60] basic.scope.pdecl --- source/basic.tex | 141 +++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 79 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index e0600277de..39d950e4d1 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -997,14 +997,13 @@ \rSec2[basic.scope.pdecl]{Point of declaration} -\indextext{declaration!point of|(}% +\indextext{declaration!point of|see{locus}}% +\indextext{scope!declarations and|see{locus}}% +\indextext{locus|(}% \pnum -\indextext{name!point of declaration|see{declaration, point of}}% -\indextext{point of!declaration|see{declaration, point of}}% -The \defnx{point of declaration}{declaration!point of} for a name is immediately after its -complete declarator\iref{dcl.decl} and before its -\grammarterm{initializer} (if any), except as noted below. +The \defn{locus} of a declaration\iref{basic.pre} that is a declarator +is immediately after the complete declarator\iref{dcl.decl}. \begin{example} \begin{codeblock} unsigned char x = 12; @@ -1018,8 +1017,8 @@ \pnum \begin{note} \indextext{name hiding}% -A name from an outer scope remains visible up -to the point of declaration of the name that hides it. +A name from an outer scope remains visible up to +the locus of the declaration that hides it. \begin{example} \begin{codeblock} const int i = 2; @@ -1030,25 +1029,22 @@ \end{note} \pnum -The point of declaration for a class or class template first declared by a -\grammarterm{class-specifier} is immediately after the \grammarterm{identifier} or -\grammarterm{simple-template-id} (if any) in its \grammarterm{class-head}\iref{class.pre}. -The point of declaration for an enumeration is -immediately after the \grammarterm{identifier} (if any) in either its -\grammarterm{enum-specifier}\iref{dcl.enum} or its first -\grammarterm{opaque-enum-declaration}\iref{dcl.enum}, whichever comes first. -The point of declaration of an alias or alias template immediately -follows the \grammarterm{defining-type-id} to which the -alias refers. +The locus of a \grammarterm{class-specifier} is immediately after +the \grammarterm{identifier} or \grammarterm{simple-template-id} (if any) +in its \grammarterm{class-head}\iref{class.pre}. +The locus of +an \grammarterm{enum-specifier} or \grammarterm{opaque-enum-declaration} +is immediately after the \grammarterm{identifier} (if any) +in it\iref{dcl.enum}. +The locus of an \grammarterm{alias-declaration} is immediately after it. \pnum -The point of declaration of a \grammarterm{using-declarator} that does not name a -constructor is immediately after the \grammarterm{using-declarator}\iref{namespace.udecl}. +The locus of a \grammarterm{using-declarator} +that does not name a constructor +is immediately after the \grammarterm{using-declarator}\iref{namespace.udecl}. \pnum -\indextext{declaration!enumerator point of}% -The point of declaration for an enumerator is immediately after its -\grammarterm{enumerator-definition}. +The locus of an \grammarterm{enumerator-definition} is immediately after it. \begin{example} \begin{codeblock} const int x = 12; @@ -1059,77 +1055,47 @@ \end{example} \pnum -After the point of declaration of a class member, the member name can be -looked up in the scope of its class. \begin{note} +After the declaration of a class member, the member name can be +found in the scope of its class. \indextext{type!incomplete}% -This is true even if the class is an incomplete class. For example, +This is true even if the class is an incomplete class. +\begin{example} \begin{codeblock} struct X { enum E { z = 16 }; - int b[X::z]; // OK + int b[X::z]; // OK }; \end{codeblock} +\end{example} \end{note} \pnum -The point of declaration of a class first declared in an -\grammarterm{elaborated-type-specifier} is as follows: -\begin{itemize} -\item for a declaration of the form -\begin{ncbnf} -class-key \opt{attribute-specifier-seq} identifier \terminal{;} -\end{ncbnf} -the \grammarterm{identifier} is declared to be a -\grammarterm{class-name} in the scope that contains the declaration, -otherwise -\item for an \grammarterm{elaborated-type-specifier} of the form -\begin{ncbnf} -class-key identifier -\end{ncbnf} -if the -\grammarterm{elaborated-type-specifier} is used in the -\grammarterm{decl-specifier-seq} or \grammarterm{parameter-declaration-clause} -of a function defined in namespace scope, the \grammarterm{identifier} is -declared as a \grammarterm{class-name} in the namespace that contains the -declaration; otherwise, except as a friend declaration, the -\grammarterm{identifier} is declared in the smallest namespace or block -scope that contains the declaration. -\begin{note} -These rules also apply within templates. -\end{note} -\begin{note} -Other -forms of \grammarterm{elaborated-type-specifier} do not declare a new name, -and therefore must refer to an existing \grammarterm{type-name}. -See~\ref{basic.lookup.elab} and~\ref{dcl.type.elab}. -\end{note} -\end{itemize} +The locus of an \grammarterm{elaborated-type-specifier} +that is a declaration\iref{dcl.type.elab} is immediately after it. \pnum -The point of declaration for an -injected-class-name\iref{class.pre} is immediately following -the opening brace of the class definition. +The locus of an injected-class-name declaration\iref{class.pre} +is immediately following the opening brace of the class definition. \pnum -The point of declaration for a function-local predefined -variable\iref{dcl.fct.def.general} is immediately before the -\grammarterm{function-body} of a function definition. +The locus of the implicit declaration of +a function-local predefined variable\iref{dcl.fct.def.general} +is immediately before +the \grammarterm{function-body} of its function's definition. \pnum -The point of declaration of a structured binding\iref{dcl.struct.bind} +The locus of the declaration of a structured binding\iref{dcl.struct.bind} is immediately after the \grammarterm{identifier-list} of the structured binding declaration. \pnum -The point of declaration for the variable or the structured bindings -declared in the \grammarterm{for-range-declaration} +The locus of a \grammarterm{for-range-declaration} of a range-based \tcode{for} statement\iref{stmt.ranged} is immediately after the \grammarterm{for-range-initializer}. \pnum -The point of declaration for a template parameter is immediately after its complete -\grammarterm{template-parameter}. +The locus of a \grammarterm{template-parameter} is immediately after it. \begin{example} \begin{codeblock} typedef unsigned char T; @@ -1140,23 +1106,40 @@ \end{codeblock} \end{example} +\pnum +The locus of a \grammarterm{concept-definition} +is immediately after its concept-name\iref{temp.concept}. +\begin{note} +The \grammarterm{constraint-expression} cannot use +the \grammarterm{concept-name}. +\end{note} + +\pnum +The locus of a \grammarterm{namespace-definition} +with an \grammarterm{identifier} +is immediately after the \grammarterm{identifier}. +\begin{note} +An identifier is invented +for an \grammarterm{unnamed-namespace-definition}\iref{namespace.unnamed}. +\end{note} + \pnum \begin{note} -Friend declarations refer to functions or classes that are -members of the nearest enclosing namespace, but they do not introduce -new names into that namespace\iref{namespace.memdef}. Function -declarations at block scope and variable declarations with the -\tcode{extern} specifier at block scope refer to declarations that are -members of an enclosing namespace, but they do not introduce new names -into that scope. +Friend declarations can introduce functions or classes +that belong to the nearest enclosing namespace or block scope, +but they do not bind names anywhere\iref{class.friend}. +Function declarations at block scope and +variable declarations with the \tcode{extern} specifier at block scope +declare entities +that belong to the nearest enclosing namespace, +but they do not bind names in it. \end{note} \pnum \begin{note} For point of instantiation of a template, see~\ref{temp.point}. \end{note} -\indextext{scope!declarations and|)}% -\indextext{declaration!point of|)} +\indextext{locus|)} \rSec2[basic.scope.block]{Block scope} From f052452fe7d130a99ef631fca9df706912228823 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 16 Nov 2020 22:34:35 +0100 Subject: [PATCH 04/60] basic.scope.block --- source/basic.tex | 70 +++++++++++++++++++++++++++++-------------- source/statements.tex | 11 ------- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 39d950e4d1..e60d3340ae 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1143,30 +1143,54 @@ \rSec2[basic.scope.block]{Block scope} -\pnum -\indextext{scope!block}% \indextext{local scope|see{scope, block}}% -A name declared in a block\iref{stmt.block} is local to that block; it has -\defnx{block scope}{block (statement)!scope}. -Its potential scope begins at its point of -declaration\iref{basic.scope.pdecl} and ends at the end of its block. -A variable declared at block scope is a \defnadj{local}{variable}. - -\pnum -\indextext{scope!exception declaration}% -The name declared in an \grammarterm{exception-declaration} -is local to the -\grammarterm{handler} and shall not be redeclared in the outermost block of the -\grammarterm{handler}. - -\pnum -Names declared in the \grammarterm{init-statement}, the \grammarterm{for-range-declaration}, and in the -\grammarterm{condition} of \tcode{if}, \tcode{while}, \tcode{for}, and -\tcode{switch} statements are local to the \tcode{if}, \tcode{while}, -\tcode{for}, or \tcode{switch} statement (including the controlled -statement), and shall not be redeclared in a subsequent condition of -that statement nor in the outermost block (or, for the \tcode{if} -statement, any of the outermost blocks) of the controlled statement. + +\pnum +Each +\begin{itemize} +\item +selection or iteration statement (\ref{stmt.select}, \ref{stmt.iter}), +\item +substatement of such a statement, +\item +\indextext{scope!\idxgram{handler}}% +\grammarterm{handler}\iref{except.pre}, or +\item +compound statement\iref{stmt.block} +that is not the \grammarterm{compound-statement} of a \grammarterm{handler} +\end{itemize} +introduces a \defnadj{block}{scope} +that includes that statement or \grammarterm{handler}. +\begin{note} +A substatement that is also a block has only one scope. +\end{note} +A variable that belongs to a block scope is a \defn{block variable}. +\begin{example} +\begin{codeblock} +int i = 42; +int a[10]; + +for (int i = 0; i < 10; i++) + a[i] = i; + +int j = i; // \tcode{j = 42} +\end{codeblock} +\end{example} + +\pnum +If a declaration whose target scope is the block scope $S$ of a +\begin{itemize} +\item +\grammarterm{compound-statement} of a \grammarterm{lambda-expression}, +\grammarterm{function-body}, or \grammarterm{function-try-block}, +\item +substatement of a selection or iteration statement, or +\item +\grammarterm{handler} of a \grammarterm{function-try-block} +\end{itemize} +potentially conflicts with a declaration +whose target scope is the parent scope of $S$, +the program is ill-formed. \begin{example} \begin{codeblock} if (int x = f()) { diff --git a/source/statements.tex b/source/statements.tex index 895fd3c682..74f7486979 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -614,17 +614,6 @@ \indextext{\idxcode{for}!scope of declaration in}% If the \grammarterm{init-statement} is a declaration, the scope of the name(s) declared extends to the end of the \tcode{for} statement. -\begin{example} -\begin{codeblock} -int i = 42; -int a[10]; - -for (int i = 0; i < 10; i++) - a[i] = i; - -int j = i; // \tcode{j = 42} -\end{codeblock} -\end{example} \rSec2[stmt.ranged]{The range-based \tcode{for} statement}% \indextext{statement!range based for@range based \tcode{for}} From 322ab634bb2dabf29bbc64e44c5c3e693d4f0c24 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 16 Nov 2020 23:01:09 +0100 Subject: [PATCH 05/60] basic.scope.param --- source/basic.tex | 58 ++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index e60d3340ae..cf9793867e 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1204,29 +1204,45 @@ \rSec2[basic.scope.param]{Function parameter scope} -\pnum -\indextext{scope!function parameter}% \indextext{scope!function prototype|see{scope, function parameter}}% \indextext{parameter!scope of}% -A function parameter -(including one appearing in a -\grammarterm{lambda-declarator}) -or function-local predefined variable\iref{dcl.fct.def} -has \defn{function parameter scope}. -The potential scope of a parameter -or function-local predefined variable -begins at its point of declaration. If -the nearest enclosing function declarator -is not the declarator of a function definition, -the potential scope ends at the end of that function declarator. -Otherwise, if -the function has a \grammarterm{function-try-block} the potential scope -ends at the end of the last associated handler. -Otherwise the potential scope ends -at the end of the outermost block of the function definition. A -parameter name shall not be redeclared in the outermost block of the -function definition nor in the outermost block of any handler associated -with a \grammarterm{function-try-block}. + +\pnum +A \grammarterm{parameter-declaration-clause} $P$ introduces +a \defnadj{function parameter}{scope} that includes $P$. +\begin{note} +A function parameter cannot be used for its value +within the \grammarterm{parameter-declaration-clause}\iref{dcl.fct.default}. +\end{note} +\begin{itemize} +\item +If $P$ is associated with a \grammarterm{declarator} and +is preceded by a (possibly-parenthesized) \grammarterm{noptr-declarator} of +the form +\grammarterm{declarator-id} \opt{\grammarterm{attribute-specifier-seq}}, +its scope extends to the end of the nearest enclosing +\grammarterm{init-declarator}, +\grammarterm{member-declarator}, +\grammarterm{declarator} of a \grammarterm{parameter-declaration} or +a \grammarterm{nodeclspec-function-declaration}, or +\grammarterm{function-definition}, +but does not include the locus of the associated \grammarterm{declarator}. +\begin{note} +In this case, $P$ declares the parameters of a function +(or a function or template parameter declared with function type). +A member function's parameter scope is nested within its class's scope. +\end{note} +\item +If $P$ is associated with a \grammarterm{lambda-declarator}, +its scope extends to the end of the \grammarterm{compound-statement} +in the \grammarterm{lambda-expression}. +\item +If $P$ is associated with a \grammarterm{requirement-parameter-list}, +its scope extends to the end of the \grammarterm{requirement-body} of the requires-expression. +\item +If $P$ is associated with a \grammarterm{deduction-guide}, +its scope extends to the end of the \grammarterm{deduction-guide}. +\end{itemize} \rSec2[basic.funscope]{Function scope} From 3c70279116bb6bb69be49a17969a73795296aab6 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 16 Nov 2020 23:09:45 +0100 Subject: [PATCH 06/60] basic.funscope --- source/basic.tex | 8 -------- source/xrefdelta.tex | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index cf9793867e..051047c6ee 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1244,14 +1244,6 @@ its scope extends to the end of the \grammarterm{deduction-guide}. \end{itemize} -\rSec2[basic.funscope]{Function scope} - -\pnum -\indextext{label!scope of}% -Labels\iref{stmt.label} have \defnx{function scope}{scope!function} and -may be used anywhere in the function in which they are declared. Only -labels have function scope. - \rSec2[basic.scope.namespace]{Namespace scope} \pnum diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index f140b0574d..e474b5603e 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -25,6 +25,7 @@ \movedxref{re.def}{intro.refs} \movedxref{basic.scope.declarative}{basic.scope.scope} +\movedxref{basic.funscope}{stmt.label} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From a9c57becf97813f0203b296f4cd9133c223539c4 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 16 Nov 2020 23:14:56 +0100 Subject: [PATCH 07/60] basic.scope.namespace --- source/basic.tex | 102 ++++++++--------------------------------------- 1 file changed, 17 insertions(+), 85 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 051047c6ee..25aa06cb87 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1247,98 +1247,30 @@ \rSec2[basic.scope.namespace]{Namespace scope} \pnum -\indextext{scope!namespace}% -The declarative region of a \grammarterm{namespace-definition} is its -\grammarterm{namespace-body}. Entities declared in a -\grammarterm{namespace-body} are said to be \defn{members} of the -namespace, and names introduced by these declarations into the -declarative region of the namespace are said to be \defn{member -names} of the namespace. A namespace member name has namespace scope. -Its potential scope includes its namespace from the name's point of -declaration\iref{basic.scope.pdecl} onwards; and for each -\grammarterm{using-directive}\iref{namespace.udir} that nominates the -member's namespace, the member's potential scope includes that portion -of the potential scope of the \grammarterm{using-directive} that follows -the member's point of declaration. +Any \grammarterm{namespace-definition} for a namespace $N$ introduces +a \defnadj{namespace}{scope} +that includes the \grammarterm{namespace-body} +for every \grammarterm{namespace-definition} for $N$. +For each non-friend redeclaration or specialization +whose target scope is or is contained by the scope, +the portion after the +\grammarterm{declarator-id}, +\grammarterm{class-head-name}, or +\grammarterm{enum-head-name} +is also included in the scope. +The global scope is +the namespace scope of the global namespace\iref{basic.namespace}. \begin{example} \begin{codeblock} -namespace N { - int i; - int g(int a) { return a; } - int j(); - void q(); -} -namespace { int l=1; } -// the potential scope of \tcode{l} is from its point of declaration to the end of the translation unit - -namespace N { - int g(char a) { // overloads \tcode{N::g(int)} - return l+a; // \tcode{l} is from unnamed namespace - } - - int i; // error: duplicate definition - int j(); // OK: duplicate function declaration - - int j() { // OK: definition of \tcode{N::j()} - return g(i); // calls \tcode{N::g(int)} +namespace Q { + namespace V { void f(); } + void V::f() { // in the scope of \tcode{V} + void h(); // declares \tcode{Q::V::h} } - int q(); // error: different return type } \end{codeblock} \end{example} -\pnum -If a translation unit $Q$ is imported into a translation unit $R$\iref{module.import}, -the potential scope of a name $X$ declared with namespace scope in $Q$ -is extended to include the portion of the corresponding namespace -scope in $R$ following the first \grammarterm{module-import-declaration} -or \grammarterm{module-declaration} -in $R$ that imports $Q$ (directly or indirectly) if -\begin{itemize} -\item $X$ does not have internal linkage, and -\item $X$ is declared after the \grammarterm{module-declaration} in $Q$ (if any), and -\item either $X$ is exported or $Q$ and $R$ are part of the same module. -\end{itemize} -\begin{note} -A \grammarterm{module-import-declaration} imports both -the named translation unit(s) and -any modules named by exported -\grammarterm{module-import-declaration}{s} within them, -recursively. -\begin{example} -\begin{codeblocktu}{Translation unit \#1} -export module Q; -export int sq(int i) { return i*i; } -\end{codeblocktu} - -\begin{codeblocktu}{Translation unit \#2} -export module R; -export import Q; -\end{codeblocktu} - -\begin{codeblocktu}{Translation unit \#3} -import R; -int main() { return sq(9); } // OK: \tcode{sq} from module \tcode{Q} -\end{codeblocktu} -\end{example} -\end{note} - -\pnum -A namespace member can also be referred to after the \tcode{::} scope -resolution operator\iref{expr.prim.id.qual} applied to the name of its -namespace or the name of a namespace which nominates the member's -namespace in a \grammarterm{using-directive}; see~\ref{namespace.qual}. - -\pnum -The outermost declarative region of a translation unit is also a -namespace, called the \defnadj{global}{namespace}. A name declared in -the global namespace has \defnadj{global}{namespace scope} (also called -\defnadj{global}{scope}). The potential scope of such a name begins at -its point of declaration\iref{basic.scope.pdecl} and ends at the end -of the translation unit that is its declarative region. -A name with global namespace scope is said to be a -\defnadj{global}{name}. - \rSec2[basic.scope.class]{Class scope} \indextext{scope!class}% From f59e4f4bbed2def706d39ee3e8e18978b5d7c1d5 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 16 Nov 2020 23:21:31 +0100 Subject: [PATCH 08/60] basic.scope.class --- source/basic.tex | 80 ++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 60 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 25aa06cb87..9eb4cf0685 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1272,74 +1272,34 @@ \end{example} \rSec2[basic.scope.class]{Class scope} -\indextext{scope!class}% - -\pnum -The potential scope of a name declared in a class consists not -only of the declarative region following the name's point of -declaration, but also of all complete-class contexts\iref{class.mem} -of that class. - -\pnum -A name \tcode{N} used in a class \tcode{S} shall refer to the same -declaration in its context and when re-evaluated in the completed scope -of \tcode{S}. No diagnostic is required for a violation of this rule. - -\pnum -A name declared within a member function hides a declaration of -the same name whose scope extends to or past the end of the member -function's class. - -\pnum -The potential scope of a declaration in a class that extends to or past the -end of a class definition also extends to the regions defined by its -member definitions, even if the members are defined lexically outside -the class (this includes static data member definitions, nested class -definitions, and member function definitions, including the member function -body and any portion of the -declarator part of such definitions which follows the \grammarterm{declarator-id}, -including a \grammarterm{parameter-declaration-clause} and any default -arguments\iref{dcl.fct.default}). \pnum +Any declaration of a class or class template $C$ introduces +a \defnadj{class}{scope} +that includes the \grammarterm{member-specification} of +the \grammarterm{class-specifier} for $C$ (if any). +For each non-friend redeclaration or specialization +whose target scope is or is contained by the scope, +the portion after the +\grammarterm{declarator-id}, +\grammarterm{class-head-name}, or +\grammarterm{enum-head-name} is also included in the scope. +\begin{note} +Lookup from a program point +before the \grammarterm{class-specifier} of a class +will find no bindings in the class scope. \begin{example} \begin{codeblock} -typedef int c; -enum { i = 1 }; - -class X { - char v[i]; // error: \tcode{i} refers to \tcode{::i} but when reevaluated is \tcode{X::i} - int f() { return sizeof(c); } // OK: \tcode{X::c} - char c; - enum { i = 2 }; -}; - -typedef char* T; -struct Y { - T a; // error: \tcode{T} refers to \tcode{::T} but when reevaluated is \tcode{Y::T} - typedef long T; - T b; +template +struct B { + D::type x; // \#1 }; -typedef int I; -class D { - typedef I I; // error, even though no reordering involved -}; +struct A { using type=int; }; +struct C : A, B {}; // error at \#1: \tcode{C::type} not found \end{codeblock} \end{example} - -\pnum -The name of a class member shall only be used as follows: -\begin{itemize} -\item in the scope of its class (as described above) or a class derived\iref{class.derived} -from its class, -\item after the \tcode{.} operator applied to an expression of the type -of its class\iref{expr.ref} or a class derived from its class, -\item after the \tcode{->} operator applied to a pointer to an object of -its class\iref{expr.ref} or a class derived from its class, -\item after the \tcode{::} scope resolution operator\iref{expr.prim.id.qual} -applied to the name of its class or a class derived from its class. -\end{itemize} +\end{note} \rSec2[basic.scope.enum]{Enumeration scope}% \indextext{enumeration scope}% From 545491cdbd956a0b9d7dfd0827c5ae26dd406a3a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 16 Nov 2020 23:23:48 +0100 Subject: [PATCH 09/60] basic.scope.enum --- source/basic.tex | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 9eb4cf0685..f94c3cdbea 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1295,21 +1295,19 @@ D::type x; // \#1 }; -struct A { using type=int; }; +struct A { using type = int; }; struct C : A, B {}; // error at \#1: \tcode{C::type} not found \end{codeblock} \end{example} \end{note} \rSec2[basic.scope.enum]{Enumeration scope}% -\indextext{enumeration scope}% -\indextext{scope!enumeration} \pnum -The name of a scoped enumerator\iref{dcl.enum} has -\defn{enumeration scope}. Its potential scope begins at -its point of declaration and terminates at the end of the -\grammarterm{enum-specifier}. +Any declaration of an enumeration $E$ introduces +an \defnadj{enumeration}{scope} +that includes the \grammarterm{enumerator-list} of +the \grammarterm{enum-specifier} for $E$ (if any). \rSec2[basic.scope.temp]{Template parameter scope}% \indextext{template parameter scope}% From aae25976e9a7bbd43458c045df37a462e6a4568f Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 17 Nov 2020 07:59:06 +0100 Subject: [PATCH 10/60] basic.scope.temp --- source/basic.tex | 90 ++++++++---------------------------------------- 1 file changed, 15 insertions(+), 75 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index f94c3cdbea..3525bd8735 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1310,86 +1310,26 @@ the \grammarterm{enum-specifier} for $E$ (if any). \rSec2[basic.scope.temp]{Template parameter scope}% -\indextext{template parameter scope}% -\indextext{scope!template parameter}% \pnum -The declarative region of the name of a template parameter of a template -\grammarterm{template-parameter} is the smallest \grammarterm{template-parameter-list} -in which the name was introduced. - -\pnum -The declarative region of the name of a template parameter of a template is the smallest -\grammarterm{template-declaration} in which the name was introduced. Only template -parameter names belong to this declarative region; any other kind of name introduced by -the \grammarterm{declaration} of a \grammarterm{template-declaration} is instead -introduced into the same declarative region where it would be introduced as a result of -a non-template declaration of the same name. -\begin{example} -\begin{codeblock} -namespace N { - template struct A { }; // \#1 - template void f(U) { } // \#2 - struct B { - template friend int g(struct C*); // \#3 - }; -} -\end{codeblock} -The declarative regions of \tcode{T}, \tcode{U} and \tcode{V} are the -\grammarterm{template-declaration}{s} on lines \#1, \#2, and \#3, -respectively. But the names \tcode{A}, \tcode{f}, \tcode{g} and \tcode{C} all belong to -the same declarative region --- namely, the \grammarterm{namespace-body} of \tcode{N}. -(\tcode{g} is still considered to belong to this declarative region in spite of its -being hidden during qualified and unqualified name lookup.) -\end{example} - -\pnum -The potential scope of a template parameter name begins at its point of -declaration\iref{basic.scope.pdecl} and ends at the end of its declarative region. -\begin{note} -This implies that a \grammarterm{template-parameter} can be used in the -declaration of subsequent \grammarterm{template-parameter}{s} and their default -arguments but cannot be used in preceding \grammarterm{template-parameter}{s} or their -default arguments. For example, -\begin{codeblock} -template class X { @\commentellip@ }; -template void f(T* p = new T); -\end{codeblock} - -This also implies that a \grammarterm{template-parameter} can be used in the -specification of base classes. For example, -\begin{codeblock} -template class X : public Array { @\commentellip@ }; -template class Y : public T { @\commentellip@ }; -\end{codeblock} -The use of a template parameter as a base class implies that a class used as a template -argument must be defined and not just declared when the class template is instantiated. -\end{note} - -\pnum -The declarative region of the name of a template parameter is nested within the -immediately-enclosing declarative region. -\begin{note} -As a result, a -\grammarterm{template-parameter} hides any entity with the same name in an enclosing -scope\iref{basic.scope.hiding}. -\begin{example} -\begin{codeblock} -typedef int N; -template class T> struct A; -\end{codeblock} -Here, \tcode{X} is a non-type template parameter of type \tcode{int} and \tcode{Y} is a -non-type template parameter of the same type as the second template parameter of -\tcode{A}. -\end{example} -\end{note} +Each template \grammarterm{template-parameter} introduces +a \defnadj{template parameter}{scope} +that includes the \grammarterm{template-head} of +the \grammarterm{template-parameter}. \pnum +Each \grammarterm{template-declaration} $D$ introduces +a template parameter scope +that extends from the beginning of its \grammarterm{template-parameter-list} +to the end of the \grammarterm{template-declaration}. +Any declaration outside the \grammarterm{template-parameter-list} +that would inhabit that scope instead inhabits the same scope as $D$. +The parent scope of any scope $S$ that is not a template parameter scope +is the smallest scope that contains $S$ and is not a template parameter scope. \begin{note} -Because the name of a template parameter cannot be redeclared within its -potential scope\iref{temp.local}, a template parameter's scope is often its potential -scope. However, it is still possible for a template parameter name to be hidden; -see~\ref{temp.local}. +Therefore, only template parameters belong to a template parameter scope, and +only template parameter scopes have +a template parameter scope as a parent scope. \end{note} \rSec2[basic.scope.hiding]{Name hiding} From de690f05de3dc31928f26b252c78abf824beaf4f Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 17 Nov 2020 08:00:41 +0100 Subject: [PATCH 11/60] basic.scope.hiding --- source/basic.tex | 44 +++----------------------------------------- source/classes.tex | 4 ++-- source/templates.tex | 2 +- source/xrefdelta.tex | 1 + 4 files changed, 7 insertions(+), 44 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 3525bd8735..24e556bc6e 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1332,44 +1332,6 @@ a template parameter scope as a parent scope. \end{note} -\rSec2[basic.scope.hiding]{Name hiding} - -\pnum -\indextext{scope name hiding and}% -\indextext{name hiding}% -\indextext{hiding|see{name hiding}}% -A declaration of a name in a nested declarative region -hides a declaration of the same name in an enclosing declarative region; -see \ref{basic.scope.declarative} and \ref{basic.lookup.unqual}. - -\pnum -\indextext{name hiding}% -If a class name\iref{class.name} or enumeration name\iref{dcl.enum} and -a variable, data member, function, or enumerator -are declared in the same declarative region (in any order) with the -same name (excluding declarations made visible -via \grammarterm{using-directive}{s}\iref{basic.lookup.unqual}), -the class or enumeration name is hidden wherever the variable, data member, -function, or enumerator name is visible. - -\pnum -In a member function definition, the declaration of a name -at block scope -hides -the declaration of a member of the class with the same name; -see~\ref{basic.scope.class}. The declaration of a member in a derived -class\iref{class.derived} hides the declaration of a member of -a base class of the same name; see~\ref{class.member.lookup}. - -\pnum -During the lookup of a name qualified by a namespace name, declarations -that would otherwise be made visible by a \grammarterm{using-directive} can -be hidden by declarations with the same name in the namespace containing -the \grammarterm{using-directive}; see~\ref{namespace.qual}. - -\pnum -\indextext{visibility}% -If a name is in scope and is not hidden it is said to be \defn{visible}.% \indextext{scope|)} \rSec1[basic.lookup]{Name lookup}% @@ -2077,7 +2039,7 @@ whose declaration is visible in global scope because of a \grammarterm{using-directive}\iref{namespace.qual}. The use of \tcode{::} allows a global name to be referred to even if its identifier has been -hidden\iref{basic.scope.hiding}. +hidden\iref{basic.lookup}. \pnum A name prefixed by a \grammarterm{nested-name-specifier} that @@ -2150,7 +2112,7 @@ \item the lookup for a name specified in a \grammarterm{using-declaration}\iref{namespace.udecl} also finds class or enumeration names hidden within the same -scope\iref{basic.scope.hiding}. +scope\iref{basic.lookup}. \end{itemize} \pnum @@ -2450,7 +2412,7 @@ An \grammarterm{elaborated-type-specifier}\iref{dcl.type.elab} may be used to refer to a previously declared \grammarterm{class-name} or \grammarterm{enum-name} even though the name has been hidden by a non-type -declaration\iref{basic.scope.hiding}. +declaration\iref{basic.lookup}. \pnum If the \grammarterm{elaborated-type-specifier} has no diff --git a/source/classes.tex b/source/classes.tex index 51b5d73007..024a192a59 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -3518,7 +3518,7 @@ \indextext{base class}% \indextext{derivation|see{inheritance}}% During the lookup for a base class name, non-type names are -ignored\iref{basic.scope.hiding}. +ignored\iref{basic.lookup}. A class \tcode{B} is a base class of a class \tcode{D} if it is a direct base class of \tcode{D} or a direct base class of one of \tcode{D}'s base classes. @@ -4612,7 +4612,7 @@ \pnum \begin{note} Access to members and base classes is controlled, not their -visibility\iref{basic.scope.hiding}. +visibility\iref{basic.lookup}. Names of members are still visible, and implicit conversions to base classes are still considered, when those members and base classes are inaccessible. diff --git a/source/templates.tex b/source/templates.tex index d886adc6a8..85c1a689e2 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4889,7 +4889,7 @@ \grammarterm{template-parameter}, the base class name or member name hides the \grammarterm{template-parameter} -name\iref{basic.scope.hiding}. +name\iref{basic.lookup}. \begin{example} \begin{codeblock} struct A { diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index e474b5603e..d0176d20e0 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -26,6 +26,7 @@ \movedxref{re.def}{intro.refs} \movedxref{basic.scope.declarative}{basic.scope.scope} \movedxref{basic.funscope}{stmt.label} +\movedxref{basic.scope.hiding}{basic.lookup} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From fe7218d35df72842356631fcf7e0eb812410a74c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 17 Nov 2020 08:25:42 +0100 Subject: [PATCH 12/60] basic.lookup.general --- source/basic.tex | 94 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 24e556bc6e..09dd3fdc5b 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1336,9 +1336,10 @@ \rSec1[basic.lookup]{Name lookup}% +\indextext{lookup!name|(} + \rSec2[basic.lookup.general]{General}% -\indextext{scope!name lookup and|(}% -\indextext{lookup!name|(}% +\indextext{scope!name lookup and|see{lookup, name}}% \pnum The name lookup rules apply uniformly to all names (including @@ -1348,36 +1349,98 @@ such names in the context discussed by a particular rule. Name lookup associates the use of a name with a set of declarations\iref{basic.def} of that name. +Unless otherwise specified, +the program is ill-formed if no declarations are found. If the declarations found by name lookup all denote functions or function templates, the declarations are said to form an \defn{overload set}. -The declarations found by name lookup shall either -all denote the same entity or form an overload set. +Otherwise, +if the declarations found by name lookup do not all denote the same entity, +they are \defn{ambiguous} and the program is ill-formed. Overload resolution~(\ref{over.match}, \ref{over.over}) takes place after name lookup has succeeded. The access rules\iref{class.access} are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function overload resolution (if applicable) and access checking have succeeded -are the semantic properties introduced by the name's declaration -and its reachable\iref{module.reach} redeclarations -used further in expression processing\iref{expr}. +are the semantic properties introduced by the declarations +used in further processing. \pnum -A name ``looked up in the context of an expression'' is looked up -in the scope where the expression is found. +A program point $P$ is said to follow +any declaration in the same translation unit +whose locus\iref{basic.scope.pdecl} is before $P$. +\begin{note} +The declaration might appear in a scope that does not contain $P$. +\end{note} +A declaration $X$ \defnx{precedes}{precede} +a program point $P$ in a translation unit $L$ +if $P$ follows $X$, $X$ inhabits a class scope and is reachable from $P$, or +else $X$ appears in a translation unit $D$ and +\begin{itemize} +\item +$P$ follows +a \grammarterm{module-import-declaration} or \grammarterm{module-declaration} +that imports $D$ (directly or indirectly), and +\item +$X$ appears after the \grammarterm{module-declaration} in $D$ (if any) and +before the \grammarterm{private-module-fragment} in $D$ (if any), and +\item +either $X$ is exported or else $D$ and $L$ are part of the same module and +$X$ does not inhabit a namespace with internal linkage or +declare a name with internal linkage. +\begin{note} +Names declared by a \grammarterm{using-declaration} have no linkage. +\end{note} +\end{itemize} +\begin{note} +A \grammarterm{module-import-declaration} imports both +the named translation unit(s) and +any modules named by exported +\grammarterm{module-import-declaration}{s} within them, +recursively. +\begin{example} +\begin{codeblocktu}{Translation unit \#1} +export module Q; +export int sq(int i) { return i*i; } +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#2} +export module R; +export import Q; +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \#3} +import R; +int main() { return sq(9); } // OK: \tcode{sq} from module \tcode{Q} +\end{codeblocktu} +\end{example} +\end{note} \pnum -The injected-class-name of a class\iref{class.pre} is also -considered to be a member of that class for the purposes of name hiding -and lookup. +A \defnadj{single}{search} in a scope $S$ +for a name $N$ from a program point $P$ +finds all declarations that precede $P$ +to which any name that is the same as $N$\iref{basic.pre} is bound in $S$. +If any such declaration is a \grammarterm{using-declarator} +whose terminal name\iref{expr.prim.id.unqual} +is not dependent\iref{temp.dep.type}, +it is replaced by the declarations named by +the \grammarterm{using-declarator}\iref{namespace.udecl}. \pnum +In certain contexts, only certain kinds of declarations are included. +After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found. \begin{note} -\ref{basic.link} discusses linkage issues. The notions of -scope, point of declaration and name hiding are discussed -in~\ref{basic.scope}. +A type (but not a \grammarterm{typedef-name} or template) +is therefore hidden by any other entity in its scope. \end{note} +However, if a lookup is type-only, only declarations of types and +templates whose specializations are types are considered; +furthermore, if declarations +of a \grammarterm{typedef-name} and of the type to which it refers are found, +the declaration of the \grammarterm{typedef-name} is discarded +instead of the type declaration. \rSec2[basic.lookup.unqual]{Unqualified name lookup} @@ -2593,7 +2656,6 @@ \grammarterm{nested-name-specifier}{} only namespace names are considered.% \indextext{lookup!name|)}% -\indextext{scope!name lookup and|)} \rSec1[basic.link]{Program and linkage}% \indextext{linkage|(} From 136df788d3b2bdfbabb98b456114803a02eeca68 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 17 Nov 2020 21:34:18 +0100 Subject: [PATCH 13/60] class.member.lookup --- source/basic.tex | 241 +++++++++++++++++++++++++++++++++++++++++- source/classes.tex | 258 --------------------------------------------- 2 files changed, 239 insertions(+), 260 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 09dd3fdc5b..7ce1d4b2db 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1442,6 +1442,243 @@ the declaration of the \grammarterm{typedef-name} is discarded instead of the type declaration. +\rSec2[class.member.lookup]{Member name lookup}% +\indextext{lookup!member name}% +\indextext{ambiguity!base class member}% +\indextext{ambiguity!member access} + +\pnum +A \defn{search} in a scope $X$ for a name $N$ from a program point $P$ +is a single search in $X$ for $N$ from $P$ +unless $X$ is the scope of a class or class template $T$, in which case the +following steps define the result of the search. +\begin{note} +The result differs only +if $N$ is a \grammarterm{conversion-function-id} or +if the single search would find nothing. +\end{note} + +\pnum +The \defn{lookup set} for $N$ in $C$, called $S(N,C)$, +consists of two component sets: +the \term{declaration set}, a set of members named $N$; and +the \term{subobject set}, +a set of subobjects where declarations of these members were found +(possibly via \grammarterm{using-declaration}{s}). +In the declaration set, type declarations (including injected-class-names) +are replaced by the types they designate. $S(N,C)$ is calculated as follows: + +\pnum +The declaration set is the result of +a single search in the scope of $C$ for $N$ +from immediately after the \grammarterm{class-specifier} of $C$ +if $P$ is in a complete-class context of $C$ or +from $P$ otherwise. +If the resulting declaration set is not empty, the subobject set +contains $C$ itself, and calculation is complete. + +\pnum +Otherwise (i.e., $C$ does not contain a declaration of $N$ +or the resulting declaration set is empty), $S(N,C)$ is initially empty. +Calculate the lookup set for $N$ +in each direct non-dependent\iref{temp.dep.type} base class subobject $B_i$, and +merge each such lookup set $S(N,B_i)$ in turn into $S(N,C)$. +\begin{note} +If $T$ is incomplete, +only base classes whose \grammarterm{base-specifier} appears before $P$ +are considered. +If $T$ is an instantiated class, its base classes are not dependent. +\end{note} + +\pnum +The following steps define the result of merging lookup set $S(N,B_i)$ +into the intermediate $S(N,C)$: + +\begin{itemize} +\item If each of the subobject members of $S(N,B_i)$ is a base class +subobject of at least one of the subobject members of $S(N,C)$, or if +$S(N,B_i)$ is empty, $S(N,C)$ is unchanged and the merge is complete. +Conversely, if each of the subobject members of $S(N,C)$ is a base class +subobject of at least one of the subobject members of $S(N,B_i)$, or if +$S(N,C)$ is empty, the new $S(N,C)$ is a copy of $S(N,B_i)$. + +\item Otherwise, if the declaration sets of $S(N,B_i)$ and $S(N,C)$ +differ, the merge is ambiguous: the new $S(N,C)$ is a lookup set with an +invalid declaration set and the union of the subobject sets. In +subsequent merges, an invalid declaration set is considered different +from any other. + +\item Otherwise, the new $S(N,C)$ is a lookup set with the shared set of +declarations and the union of the subobject sets. +\end{itemize} + +\pnum +The result of the search is the declaration set of $S(N,T)$. +If it is an invalid set, the program is ill-formed. +If it differs from the result of a search in $T$ for $N$ +from immediately after the \grammarterm{class-specifier} of $T$, +the program is ill-formed, no diagnostic required. +\begin{example} +\begin{codeblock} +struct A { int x; }; // S(x,A) = \{ \{ \tcode{A::x} \}, \{ \tcode{A} \} \} +struct B { float x; }; // S(x,B) = \{ \{ \tcode{B::x} \}, \{ \tcode{B} \} \} +struct C: public A, public B { }; // S(x,C) = \{ invalid, \{ \tcode{A} in \tcode{C}, \tcode{B} in \tcode{C} \} \} +struct D: public virtual C { }; // S(x,D) = S(x,C) +struct E: public virtual C { char x; }; // S(x,E) = \{ \{ \tcode{E::x} \}, \{ \tcode{E} \} \} +struct F: public D, public E { }; // S(x,F) = S(x,E) +int main() { + F f; + f.x = 0; // OK, lookup finds \tcode{E::x} +} +\end{codeblock} + +$S(\tcode{x},\tcode{F})$ is unambiguous because the \tcode{A} and \tcode{B} base +class subobjects of \tcode{D} are also base class subobjects of \tcode{E}, so +$S(\tcode{x},\tcode{D})$ is discarded in the first merge step. +\end{example} + +\pnum +If $N$ is a non-dependent \grammarterm{conversion-function-id}, +conversion function templates that are members of $T$ are considered. +For each such template $F$, the lookup set $S(t,T)$ is constructed, +considering a function template declaration to have the name $t$ +only if it corresponds to a declaration of $F$\iref{basic.scope.scope}. +The members of the declaration set of each such lookup set, +which shall not be an invalid set, are included in the result. +\begin{note} +Overload resolution will discard those +that cannot convert to the type specified by $N$\iref{temp.over}. +\end{note} + +\pnum +\begin{note} +A static member, a nested type or an enumerator defined in a base class +\tcode{T} can unambiguously be found even if an object has more than one +base class subobject of type \tcode{T}. Two base class subobjects share +the non-static member subobjects of their common virtual base classes. +\end{note} +\begin{example} +\begin{codeblock} +struct V { + int v; +}; +struct A { + int a; + static int s; + enum { e }; +}; +struct B : A, virtual V { }; +struct C : A, virtual V { }; +struct D : B, C { }; + +void f(D* pd) { + pd->v++; // OK: only one \tcode{v} (virtual) + pd->s++; // OK: only one \tcode{s} (static) + int i = pd->e; // OK: only one \tcode{e} (enumerator) + pd->a++; // error: ambiguous: two \tcode{a}{s} in \tcode{D} +} +\end{codeblock} +\end{example} + +\pnum +\begin{note} +\indextext{dominance!virtual base class}% +When virtual base classes are used, a hidden declaration can be reached +along a path through the subobject lattice that does not pass through +the hiding declaration. This is not an ambiguity. The identical use with +non-virtual base classes is an ambiguity; in that case there is no +unique instance of the name that hides all the others. +\end{note} +\begin{example} +\begin{codeblock} +struct V { int f(); int x; }; +struct W { int g(); int y; }; +struct B : virtual V, W { + int f(); int x; + int g(); int y; +}; +struct C : virtual V, W { }; + +struct D : B, C { void glorp(); }; +\end{codeblock} + +\begin{importgraphic} +{Name lookup} +{class.lookup} +{figname.pdf} +\end{importgraphic} + +As illustrated in \fref{class.lookup}, +the names declared in \tcode{V} and the left-hand instance of \tcode{W} +are hidden by those in \tcode{B}, but the names declared in the +right-hand instance of \tcode{W} are not hidden at all. +\begin{codeblock} +void D::glorp() { + x++; // OK: \tcode{B::x} hides \tcode{V::x} + f(); // OK: \tcode{B::f()} hides \tcode{V::f()} + y++; // error: \tcode{B::y} and \tcode{C}'s \tcode{W::y} + g(); // error: \tcode{B::g()} and \tcode{C}'s \tcode{W::g()} +} +\end{codeblock} +\end{example} +\indextext{ambiguity!class conversion}% + +\pnum +An explicit or implicit conversion from a pointer to or +an expression designating an object +of a +derived class to a pointer or reference to one of its base classes shall +unambiguously refer to a unique object representing the base class. +\begin{example} +\begin{codeblock} +struct V { }; +struct A { }; +struct B : A, virtual V { }; +struct C : A, virtual V { }; +struct D : B, C { }; + +void g() { + D d; + B* pb = &d; + A* pa = &d; // error: ambiguous: \tcode{C}'s \tcode{A} or \tcode{B}'s \tcode{A}? + V* pv = &d; // OK: only one \tcode{V} subobject +} +\end{codeblock} +\end{example} + +\pnum +\begin{note} +Even if the result of name lookup is unambiguous, use of a name found in +multiple subobjects might still be +ambiguous~(\ref{conv.mem}, \ref{expr.ref}, \ref{class.access.base}). +\end{note} +\begin{example} +\begin{codeblock} +struct B1 { + void f(); + static void f(int); + int i; +}; +struct B2 { + void f(double); +}; +struct I1: B1 { }; +struct I2: B1 { }; + +struct D: I1, I2, B2 { + using B1::f; + using B2::f; + void g() { + f(); // Ambiguous conversion of \tcode{this} + f(0); // Unambiguous (static) + f(0.0); // Unambiguous (only one \tcode{B2}) + int B1::* mpB1 = &D::i; // Unambiguous + int D::* mpD = &D::i; // Ambiguous conversion + } +}; +\end{codeblock} +\end{example} + \rSec2[basic.lookup.unqual]{Unqualified name lookup} \pnum @@ -1485,7 +1722,7 @@ template int h(T); } -int x = f(N::A()); // OK: lookup of \tcode{f} finds nothing, \tcode{f} treated as template name +int x = f(N::A()); // OK: lookup of \tcode{f} finds nothing, $N$ treated as template name int y = g(N::A()); // OK: lookup of \tcode{g} finds a function, \tcode{g} treated as template name int z = h(N::A()); // error: \tcode{h<} does not begin a \grammarterm{template-id} \end{codeblock} @@ -1499,7 +1736,7 @@ friend void f(A &); operator int(); void g(A a) { - int i = f(a); // \tcode{f} is the typedef, not the friend function: equivalent to \tcode{int(a)} + int i = f(a); // $N$ is the typedef, not the friend function: equivalent to \tcode{int(a)} } }; } diff --git a/source/classes.tex b/source/classes.tex index 024a192a59..bb5fc221b3 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -4257,264 +4257,6 @@ destroyed) from such a constructor (or destructor) is undefined.% \indextext{derived class|)} -\rSec1[class.member.lookup]{Member name lookup}% -\indextext{lookup!member name}% -\indextext{ambiguity!base class member}% -\indextext{ambiguity!member access} - -\pnum -Member name lookup determines the meaning of a name -(\grammarterm{id-expression}) in a class scope\iref{basic.scope.class}. -Name lookup can result in an ambiguity, in which case the -program is ill-formed. For an \grammarterm{unqualified-id}, name lookup -begins in the class scope of \tcode{this}; for a -\grammarterm{qualified-id}, name lookup begins in the scope of the -\grammarterm{nested-name-specifier}. Name lookup takes place before access -control~(\ref{basic.lookup}, \ref{class.access}). - -\pnum -The following steps define the result of name lookup for a member name -\tcode{f} in a class scope \tcode{C}. - -\pnum -The \term{lookup set} for \tcode{f} in \tcode{C}, called $S(f,C)$, -consists of two component sets: the \term{declaration set}, a set of -members named \tcode{f}; and the \term{subobject set}, a set of -subobjects where declarations of these members (possibly including -\grammarterm{using-declaration}{s}) were found. In the declaration set, -\grammarterm{using-declaration}{s} are replaced by the -set of designated members that are not hidden or overridden by members of the -derived class\iref{namespace.udecl}, -and type declarations (including injected-class-names) are -replaced by the types they designate. $S(f,C)$ is calculated as follows: - -\pnum -If \tcode{C} contains a declaration of the name \tcode{f}, the -declaration set contains every declaration of \tcode{f} declared in -\tcode{C} that satisfies the requirements of the language construct in -which the lookup occurs. -\begin{note} -Looking up a name in an -\grammarterm{elaborated-type-specifier}\iref{basic.lookup.elab} or -\grammarterm{base-specifier}\iref{class.derived}, for instance, -ignores all non-type declarations, while looking up a name in a -\grammarterm{nested-name-specifier}\iref{basic.lookup.qual} ignores -function, variable, and enumerator declarations. As another example, -looking up a name in a -\grammarterm{using-declaration}\iref{namespace.udecl} includes the -declaration of a class or enumeration that would ordinarily be hidden by -another declaration of that name in the same scope. -\end{note} -If the resulting declaration set is not empty, the subobject set -contains \tcode{C} itself, and calculation is complete. - -\pnum -Otherwise (i.e., \tcode{C} does not contain a declaration of \tcode{f} -or the resulting declaration set is empty), $S(f,C)$ is initially empty. -If \tcode{C} has base classes, calculate the lookup set for \tcode{f} in -each direct base class subobject $B_i$, and merge each such lookup set -$S(f,B_i)$ in turn into $S(f,C)$. - -\pnum -The following steps define the result of merging lookup set $S(f,B_i)$ -into the intermediate $S(f,C)$: - -\begin{itemize} -\item If each of the subobject members of $S(f,B_i)$ is a base class -subobject of at least one of the subobject members of $S(f,C)$, or if -$S(f,B_i)$ is empty, $S(f,C)$ is unchanged and the merge is complete. -Conversely, if each of the subobject members of $S(f,C)$ is a base class -subobject of at least one of the subobject members of $S(f,B_i)$, or if -$S(f,C)$ is empty, the new $S(f,C)$ is a copy of $S(f,B_i)$. - -\item Otherwise, if the declaration sets of $S(f,B_i)$ and $S(f,C)$ -differ, the merge is ambiguous: the new $S(f,C)$ is a lookup set with an -invalid declaration set and the union of the subobject sets. In -subsequent merges, an invalid declaration set is considered different -from any other. - -\item Otherwise, the new $S(f,C)$ is a lookup set with the shared set of -declarations and the union of the subobject sets. -\end{itemize} - -\pnum -The result of name lookup for \tcode{f} in \tcode{C} is the declaration -set of $S(f,C)$. If it is an invalid set, the program is ill-formed. -\begin{example} -\begin{codeblock} -struct A { int x; }; // S(x,A) = \{ \{ \tcode{A::x} \}, \{ \tcode{A} \} \} -struct B { float x; }; // S(x,B) = \{ \{ \tcode{B::x} \}, \{ \tcode{B} \} \} -struct C: public A, public B { }; // S(x,C) = \{ invalid, \{ \tcode{A} in \tcode{C}, \tcode{B} in \tcode{C} \} \} -struct D: public virtual C { }; // S(x,D) = S(x,C) -struct E: public virtual C { char x; }; // S(x,E) = \{ \{ \tcode{E::x} \}, \{ \tcode{E} \} \} -struct F: public D, public E { }; // S(x,F) = S(x,E) -int main() { - F f; - f.x = 0; // OK, lookup finds \tcode{E::x} -} -\end{codeblock} - -$S(x,F)$ is unambiguous because the \tcode{A} and \tcode{B} base -class subobjects of \tcode{D} are also base class subobjects of \tcode{E}, so -$S(x,D)$ is discarded in the first merge step. -\end{example} - -\pnum -\indextext{access control!overload resolution and}% -If the name of an overloaded function is unambiguously found, -overload resolution\iref{over.match} also takes place before access -control. -\indextext{overloading!resolution!scoping ambiguity}% -Ambiguities can often be resolved by qualifying a name with its class name. -\begin{example} -\begin{codeblock} -struct A { - int f(); -}; - -\end{codeblock} -\begin{codeblock} -struct B { - int f(); -}; - -\end{codeblock} -\begin{codeblock} -struct C : A, B { - int f() { return A::f() + B::f(); } -}; -\end{codeblock} -\end{example} - -\pnum -\begin{note} -A static member, a nested type or an enumerator defined in a base class -\tcode{T} can unambiguously be found even if an object has more than one -base class subobject of type \tcode{T}. Two base class subobjects share -the non-static member subobjects of their common virtual base classes. -\end{note} -\begin{example} -\begin{codeblock} -struct V { - int v; -}; -struct A { - int a; - static int s; - enum { e }; -}; -struct B : A, virtual V { }; -struct C : A, virtual V { }; -struct D : B, C { }; - -void f(D* pd) { - pd->v++; // OK: only one \tcode{v} (virtual) - pd->s++; // OK: only one \tcode{s} (static) - int i = pd->e; // OK: only one \tcode{e} (enumerator) - pd->a++; // error: ambiguous: two \tcode{a}{s} in \tcode{D} -} -\end{codeblock} -\end{example} - -\pnum -\begin{note} -\indextext{dominance!virtual base class}% -When virtual base classes are used, a hidden declaration can be reached -along a path through the subobject lattice that does not pass through -the hiding declaration. This is not an ambiguity. The identical use with -non-virtual base classes is an ambiguity; in that case there is no -unique instance of the name that hides all the others. -\end{note} -\begin{example} -\begin{codeblock} -struct V { int f(); int x; }; -struct W { int g(); int y; }; -struct B : virtual V, W { - int f(); int x; - int g(); int y; -}; -struct C : virtual V, W { }; - -struct D : B, C { void glorp(); }; -\end{codeblock} - -\begin{importgraphic} -{Name lookup} -{class.lookup} -{figname.pdf} -\end{importgraphic} - -As illustrated in \fref{class.lookup}, -the names declared in \tcode{V} and the left-hand instance of \tcode{W} -are hidden by those in \tcode{B}, but the names declared in the -right-hand instance of \tcode{W} are not hidden at all. -\begin{codeblock} -void D::glorp() { - x++; // OK: \tcode{B::x} hides \tcode{V::x} - f(); // OK: \tcode{B::f()} hides \tcode{V::f()} - y++; // error: \tcode{B::y} and \tcode{C}'s \tcode{W::y} - g(); // error: \tcode{B::g()} and \tcode{C}'s \tcode{W::g()} -} -\end{codeblock} -\end{example} -\indextext{ambiguity!class conversion}% - -\pnum -An explicit or implicit conversion from a pointer to or -an expression designating an object -of a -derived class to a pointer or reference to one of its base classes shall -unambiguously refer to a unique object representing the base class. -\begin{example} -\begin{codeblock} -struct V { }; -struct A { }; -struct B : A, virtual V { }; -struct C : A, virtual V { }; -struct D : B, C { }; - -void g() { - D d; - B* pb = &d; - A* pa = &d; // error: ambiguous: \tcode{C}'s \tcode{A} or \tcode{B}'s \tcode{A}? - V* pv = &d; // OK: only one \tcode{V} subobject -} -\end{codeblock} -\end{example} - -\pnum -\begin{note} -Even if the result of name lookup is unambiguous, use of a name found in -multiple subobjects might still be -ambiguous~(\ref{conv.mem}, \ref{expr.ref}, \ref{class.access.base}). -\end{note} -\begin{example} -\begin{codeblock} -struct B1 { - void f(); - static void f(int); - int i; -}; -struct B2 { - void f(double); -}; -struct I1: B1 { }; -struct I2: B1 { }; - -struct D: I1, I2, B2 { - using B1::f; - using B2::f; - void g() { - f(); // Ambiguous conversion of \tcode{this} - f(0); // Unambiguous (static) - f(0.0); // Unambiguous (only one \tcode{B2}) - int B1::* mpB1 = &D::i; // Unambiguous - int D::* mpD = &D::i; // Ambiguous conversion - } -}; -\end{codeblock} -\end{example} - \rSec1[class.access]{Member access control}% \rSec2[class.access.general]{General}% From 09fa30e0e8987f14d26dad659fac14872243b480 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 17 Nov 2020 22:00:34 +0100 Subject: [PATCH 14/60] basic.lookup.unqual --- source/basic.tex | 421 +++++++++-------------------------------------- 1 file changed, 80 insertions(+), 341 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 7ce1d4b2db..4170b6d5d8 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1681,372 +1681,111 @@ \rSec2[basic.lookup.unqual]{Unqualified name lookup} -\pnum \indextext{lookup!unqualified name}% \indextext{name!unqualified}% -In all the cases listed in~\ref{basic.lookup.unqual}, the scopes are -searched for a declaration in the order listed in each of the respective -categories; name lookup ends as soon as a declaration is found for the -name. If no declaration is found, the program is ill-formed. - -\pnum -The declarations from the namespace nominated by a -\grammarterm{using-directive} become visible in a namespace enclosing the -\grammarterm{using-directive}; see~\ref{namespace.udir}. For the purpose of -the unqualified name lookup rules described -in~\ref{basic.lookup.unqual}, the declarations from the namespace -nominated by the \grammarterm{using-directive} are considered members of -that enclosing namespace. - -\pnum -The lookup for an unqualified name used as the -\grammarterm{postfix-expression} of a function call is described -in~\ref{basic.lookup.argdep}. -\begin{note} -For purposes of determining -(during parsing) whether an expression is a -\grammarterm{postfix-expression} for a function call, the usual name lookup -rules apply. -In some cases -a name followed by \tcode{<} is treated as a \grammarterm{template-name} -even though name lookup did not find a \grammarterm{template-name} -(see \ref{temp.names}). -For example, -\begin{codeblock} -int h; -void g(); -namespace N { - struct A {}; - template int f(T); - template int g(T); - template int h(T); -} - -int x = f(N::A()); // OK: lookup of \tcode{f} finds nothing, $N$ treated as template name -int y = g(N::A()); // OK: lookup of \tcode{g} finds a function, \tcode{g} treated as template name -int z = h(N::A()); // error: \tcode{h<} does not begin a \grammarterm{template-id} -\end{codeblock} - -The rules in~\ref{basic.lookup.argdep} have no effect on -the syntactic interpretation of an expression. For example, -\begin{codeblock} -typedef int f; -namespace N { - struct A { - friend void f(A &); - operator int(); - void g(A a) { - int i = f(a); // $N$ is the typedef, not the friend function: equivalent to \tcode{int(a)} - } - }; -} -\end{codeblock} -Because the expression is not a function call, the argument-dependent -name lookup\iref{basic.lookup.argdep} does not apply and the friend -function \tcode{f} is not found. -\end{note} - -\pnum -A name used in global scope, outside of any function, class or -user-declared namespace, shall be declared before its use in global -scope. \pnum -A name used in a user-declared namespace outside of the definition of -any function or class shall be declared before its use in that namespace -or before its use in a namespace enclosing its namespace. - -\pnum -In the definition of a function that is a member of namespace \tcode{N}, -a name used after the function's -\grammarterm{declarator-id} -\begin{footnote} -This refers to unqualified names -that occur, for instance, in -a type or default argument in the -\grammarterm{parameter-declaration-clause} or used in the function body. -\end{footnote} -shall be -declared before its use in the block in which it is used or in one of -its enclosing blocks\iref{stmt.block} or shall be declared before its -use in namespace \tcode{N} or, if \tcode{N} is a nested namespace, shall -be declared before its use in one of \tcode{N}'s enclosing namespaces. -\begin{example} -\begin{codeblock} -namespace A { - namespace N { - void f(); - } -} -void A::N::f() { - i = 5; - // The following scopes are searched for a declaration of \tcode{i}: - // 1) outermost block scope of \tcode{A::N::f}, before the use of \tcode{i} - // 2) scope of namespace \tcode{N} - // 3) scope of namespace \tcode{A} - // 4) global scope, before the definition of \tcode{A::N::f} -} -\end{codeblock} -\end{example} - -\pnum -A name used in the definition of a class \tcode{X} -\begin{footnote} -This -refers to unqualified names following the class name; -such a name might be used in a \grammarterm{base-specifier} or -in the \grammarterm{member-specification} of the class definition. -\end{footnote} -outside of a complete-class context\iref{class.mem} of \tcode{X} -shall be declared in one of the following ways: -\begin{itemize} -\item before its use in class \tcode{X} or be a member of a base class -of \tcode{X}\iref{class.member.lookup}, or -\item if \tcode{X} is a nested class of class -\tcode{Y}\iref{class.nest}, before the definition of \tcode{X} in -\tcode{Y}, or shall be a member of a base class of \tcode{Y} (this -lookup applies in turn to \tcode{Y}'s enclosing classes, starting with -the innermost enclosing class), -\begin{footnote} -This lookup applies whether the -definition of \tcode{X} is -nested within \tcode{Y}'s definition or whether \tcode{X}'s definition -appears in a namespace scope enclosing \tcode{Y}'s -definition\iref{class.nest}. -\end{footnote} -or -\item if \tcode{X} is a local class\iref{class.local} or is a nested -class of a local class, before the definition of class \tcode{X} in a -block enclosing the definition of class \tcode{X}, or -\item if \tcode{X} is a member of namespace \tcode{N}, or is a nested -class of a class that is a member of \tcode{N}, or is a local class or a -nested class within a local class of a function that is a member of -\tcode{N}, before the definition of class \tcode{X} in namespace -\tcode{N} or in one of \tcode{N}'s enclosing namespaces. -\end{itemize} -\begin{example} -\begin{codeblock} -namespace M { - class B { }; -} - -\end{codeblock} -\begin{codeblock} -namespace N { - class Y : public M::B { - class X { - int a[i]; - }; - }; -} - -// The following scopes are searched for a declaration of \tcode{i}: -// 1) scope of class \tcode{N::Y::X}, before the use of \tcode{i} -// 2) scope of class \tcode{N::Y}, before the definition of \tcode{N::Y::X} -// 3) scope of \tcode{N::Y}'s base class \tcode{M::B} -// 4) scope of namespace \tcode{N}, before the definition of \tcode{N::Y} -// 5) global scope, before the definition of \tcode{N} -\end{codeblock} -\end{example} +A \grammarterm{using-directive} is +\term{active} in a scope $S$ at a program point $P$ +if it precedes $P$ and inhabits either $S$ or +the scope of a namespace nominated by a \grammarterm{using-directive} +that is active in $S$ at $P$. \begin{note} -When looking for a prior declaration of a class -or function introduced by a friend declaration, scopes outside -of the innermost enclosing namespace scope are not considered; -see~\ref{namespace.memdef}. -\end{note} -\begin{note} -\ref{basic.scope.class} -further describes the restrictions on the use of names in a class -definition. \ref{class.nest} further describes the restrictions on the -use of names in nested class definitions. \ref{class.local} further -describes the restrictions on the use of names in local class -definitions. +A \grammarterm{using-directive} is exported if and only if +it appears in a header unit. \end{note} \pnum -For the members of a class \tcode{X}, a name used -in a complete-class context\iref{class.mem} of \tcode{X} or -in the definition of a class member outside of the definition of \tcode{X}, -following the member's -\grammarterm{declarator-id} -\begin{footnote} -That is, an unqualified name that occurs, -for instance, in a -type in the -\grammarterm{parameter-declaration-clause} or in the -\grammarterm{noexcept-specifier}. -\end{footnote}% -, shall be declared in one of the -following ways: +An unqualified search in a scope $S$ from a program point $P$ +includes the results of searches from $P$ in \begin{itemize} -\item before its use in the block in which it is used or in an enclosing -block\iref{stmt.block}, or - -\item shall be a member of class \tcode{X} or be a member of a base -class of \tcode{X}\iref{class.member.lookup}, or - -\item if \tcode{X} -is a nested class of class \tcode{Y}\iref{class.nest}, shall be a -member of \tcode{Y}, or shall be a member of a base class of \tcode{Y} -(this lookup applies in turn to \tcode{Y}'s enclosing classes, starting -with the innermost enclosing class), -\begin{footnote} -This lookup applies whether -the member function is defined -within the definition of class \tcode{X} or whether the member function -is defined in a namespace scope enclosing \tcode{X}'s definition. -\end{footnote} -or - -\item if \tcode{X} is a local class\iref{class.local} or is a nested -class of a local class, before the definition of class \tcode{X} in a -block enclosing the definition of class \tcode{X}, or - -\item if \tcode{X} is a member of namespace \tcode{N}, or is a nested -class of a class that is a member of \tcode{N}, or is a local class or a -nested class within a local class of a function that is a member of -\tcode{N}, before the use of the name, in namespace \tcode{N} -or in one of \tcode{N}'s enclosing namespaces. +\item +$S$, and +\item +for any scope $U$ that contains $P$ and is or is contained by $S$, +each namespace contained by $S$ that is nominated by +a \grammarterm{using-directive} that is active in $U$ at $P$. \end{itemize} -\begin{example} -\begin{codeblock} -class B { }; -namespace M { - namespace N { - class X : public B { - void f(); - }; - } -} -void M::N::X::f() { - i = 16; -} - -// The following scopes are searched for a declaration of \tcode{i}: -// 1) outermost block scope of \tcode{M::N::X::f}, before the use of \tcode{i} -// 2) scope of class \tcode{M::N::X} -// 3) scope of \tcode{M::N::X}'s base class \tcode{B} -// 4) scope of namespace \tcode{M::N} -// 5) scope of namespace \tcode{M} -// 6) global scope, before the definition of \tcode{M::N::X::f} -\end{codeblock} -\end{example} +If no declarations are found, +the results of the unqualified search are +the results of an unqualified search in the parent scope of $S$, if any, +from $P$. \begin{note} -\ref{class.mfct} and~\ref{class.static} further -describe the restrictions on the use of names in member function -definitions. \ref{class.nest} further describes the restrictions on the -use of names in the scope of nested classes. \ref{class.local} further -describes the restrictions on the use of names in local class -definitions. -\end{note} - -\pnum -Name lookup for a name used in the definition of a friend -function\iref{class.friend} defined inline in the class granting -friendship shall proceed as described for lookup in member function -definitions. If the friend function is not defined in the class -granting friendship, name lookup in the friend function -definition shall proceed as described for lookup in namespace member -function definitions. - -\pnum -In a friend declaration naming a member function, a name used in -the function declarator and not part of a \grammarterm{template-argument} -in the \grammarterm{declarator-id} is first looked up in the scope of the -member function's class\iref{class.member.lookup}. If it is not found, -or if the name is part of a -\grammarterm{template-argument} in -the \grammarterm{declarator-id}, the look up is -as described for unqualified names in the definition of the class -granting friendship. -\begin{example} -\begin{codeblock} -struct A { - typedef int AT; - void f1(AT); - void f2(float); - template void f3(); -}; -struct B { - typedef char AT; - typedef float BT; - friend void A::f1(AT); // parameter type is \tcode{A::AT} - friend void A::f2(BT); // parameter type is \tcode{B::BT} - friend void A::f3(); // template argument is \tcode{B::AT} -}; -\end{codeblock} -\end{example} +When a class scope is searched, +the scopes of its base classes are also searched\iref{class.member.lookup}. +If it inherits from a single base, +it is as if the scope of the base immediately contains +the scope of the derived class. +Template parameter scopes +that are associated with one scope in the chain of parents +are also considered\iref{temp.local}. +\end{note} \pnum -During the lookup for a name used as a default -argument\iref{dcl.fct.default} in a function -\grammarterm{parameter-declaration-clause} or used in the -\grammarterm{expression} of a \grammarterm{mem-initializer} for a -constructor\iref{class.base.init}, the function parameter names are -visible and hide the names of entities declared in the block, class or -namespace scopes containing the function declaration. -\begin{note} -\ref{dcl.fct.default} further describes the restrictions on the use of -names in default arguments. \ref{class.base.init} further describes the -restrictions on the use of names in a \grammarterm{ctor-initializer}. -\end{note} +\defnx{Unqualified name lookup}{name lookup!unqualified} +from a program point performs an unqualified search in its immediate scope. \pnum -During the lookup of a name used in the -\grammarterm{constant-expression} of an \grammarterm{enumerator-definition}, -previously declared \grammarterm{enumerator}{s} of the enumeration are visible -and hide the names of entities declared in the block, class, or namespace -scopes containing the \grammarterm{enum-specifier}. +An \defnadj{unqualified}{name} is a name +that does not follow a \grammarterm{nested-name-specifier} or +the \tcode{.} or \tcode{->} in a class member access expression\iref{expr.ref}, +possibly after a \keyword{template} keyword or \tcode{\~}. +Unless otherwise specified, +such a name undergoes unqualified name lookup from the point where it appears. \pnum -A name used in the definition of a \tcode{static} data member of class -\tcode{X}\iref{class.static.data} (after the \grammarterm{qualified-id} -of the static member) is looked up as if the name was used in a member -function of \tcode{X}. -\begin{note} -\ref{class.static.data} further -describes the restrictions on the use of names in the definition of a -\tcode{static} data member. -\end{note} +An unqualified name that is a component name\iref{expr.prim.id.unqual} of +a \grammarterm{type-specifier} or \grammarterm{ptr-operator} of +a \grammarterm{conversion-type-id} is looked up in the same fashion +as the \grammarterm{conversion-function-id} in which it appears. +If that lookup finds nothing, it undergoes unqualified name lookup; +in each case, only names +that denote types or templates whose specializations are types are considered. \pnum -If a variable member of a namespace is defined outside of the scope of -its namespace then any name that appears in the definition of the -member (after the \grammarterm{declarator-id}) is looked up as if the -definition of the member occurred in its namespace. +In a friend declaration \grammarterm{declarator} +whose \grammarterm{declarator-id} is a \grammarterm{qualified-id} +whose lookup context is\iref{basic.lookup.qual} a class or namespace $S$, +lookup for an unqualified name +that appears after the \grammarterm{declarator-id} +performs a search in the scope associated with $S$. +If that lookup finds nothing, it undergoes unqualified name lookup. \begin{example} \begin{codeblock} -namespace N { - int i = 4; - extern int j; +using I = int; +using D = double; +namespace A { + inline namespace N {using C = char; } + using F = float; + void f(I); + void f(D); + void f(C); + void f(F); +} +struct X0 {using F = float; }; +struct W { + using D = void; + struct X : X0 { + void g(I); + void g(::D); + void g(F); + }; +}; +namespace B { + typedef short I, F; + class Y { + friend void A::f(I); // error: no \tcode{void A::f(short)} + friend void A::f(D); // OK + friend void A::f(C); // error: \tcode{A::N::C} not found + friend void A::f(F); // OK + friend void X::g(I); // error: no \tcode{void X::g(short)} + friend void X::g(D); // OK + friend void X::g(F); // OK + }; } - -int i = 2; - -int N::j = i; // \tcode{N::j == 4} \end{codeblock} \end{example} -\pnum -A name used in the handler for a \grammarterm{function-try-block}\iref{except.pre} -is looked up as if the name was used in the -outermost block of the function definition. In particular, the function -parameter names shall not be redeclared in the -\grammarterm{exception-declaration} nor in the outermost block of a handler -for the \grammarterm{function-try-block}. Names declared in the outermost -block of the function definition are not found when looked up in the -scope of a handler for the \grammarterm{function-try-block}. -\begin{note} -But -function parameter names are found. -\end{note} - -\pnum -\begin{note} -The rules for name lookup in template definitions are -described in~\ref{temp.res}. -\end{note} - \rSec2[basic.lookup.argdep]{Argument-dependent name lookup}% \indextext{lookup!argument-dependent} From cdba829be16a3cd826d448b050cdfd2e6f254231 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 18:00:03 +0100 Subject: [PATCH 15/60] basic.lookup.argdep --- source/basic.tex | 239 +++++++++++++++++++++++++---------------------- 1 file changed, 127 insertions(+), 112 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 4170b6d5d8..5efa44d3ea 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1791,14 +1791,22 @@ \pnum When the \grammarterm{postfix-expression} in -a function call\iref{expr.call} is an \grammarterm{unqualified-id}, other namespaces not considered -during the usual unqualified lookup\iref{basic.lookup.unqual} may be -searched, and in those namespaces, namespace-scope friend function or -function template declarations\iref{class.friend} not otherwise -visible may be found. -These modifications to the search depend on the types of the arguments -(and for template template arguments, the namespace of the template -argument). +a function call\iref{expr.call} is an \grammarterm{unqualified-id} +and unqualified lookup\iref{basic.lookup.unqual} +for the name in the \grammarterm{unqualified-id} does not find any +\begin{itemize} +\item +declaration of a class member, or +\item +function declaration inhabiting a block scope, or +\item +declaration not of a function or function template +\end{itemize} +then lookup for the name also includes the result of +\defnadj{argument-dependent}{lookup} in a set of associated namespaces +that depends on the types of the arguments +(and for template template arguments, the namespace of the template argument), +as specified below. \begin{example} \begin{codeblock} namespace N { @@ -1814,156 +1822,141 @@ \end{codeblock} \end{example} +\pnum +\begin{note} +For purposes of determining +(during parsing) whether an expression is a +\grammarterm{postfix-expression} for a function call, the usual name lookup +rules apply. +In some cases +a name followed by \tcode{<} is treated as a \grammarterm{template-name} +even though name lookup did not find a \grammarterm{template-name} +(see \ref{temp.names}). +For example, +\begin{codeblock} +int h; +void g(); +namespace N { + struct A {}; + template int f(T); + template int g(T); + template int h(T); +} + +int x = f(N::A()); // OK: lookup of \tcode{f} finds nothing, $N$ treated as template name +int y = g(N::A()); // OK: lookup of \tcode{g} finds a function, \tcode{g} treated as template name +int z = h(N::A()); // error: \tcode{h<} does not begin a \grammarterm{template-id} +\end{codeblock} + +The rules have no effect on the syntactic interpretation of an expression. +For example, +\begin{codeblock} +typedef int f; +namespace N { + struct A { + friend void f(A &); + operator int(); + void g(A a) { + int i = f(a); // $N$ is the typedef, not the friend function: equivalent to \tcode{int(a)} + } + }; +} +\end{codeblock} +Because the expression is not a function call, +argument-dependent name lookup does not apply and +the friend function \tcode{f} is not found. +\end{note} + \pnum For each argument type \tcode{T} in the function call, -there is a set of zero or more -\defnx{associated namespaces}{namespace!associated} -and a set of zero or more -\defnx{associated entities}{entity!associated} -(other than namespaces) +there is a set of zero or more \defnx{associated entities}{entity!associated} to be considered. -The sets of namespaces and entities -are determined entirely by +The set of entities is determined entirely by the types of the function arguments -(and the namespace of any template template argument). +(and any template template arguments). Typedef names and \grammarterm{using-declaration}{s} used to specify the types do not contribute to this set. -The sets of namespaces and entities -are determined in the following way: +The set entities +is determined in the following way: \begin{itemize} -\item If \tcode{T} is a fundamental type, its associated sets of -namespaces and entities are both empty. +\item If \tcode{T} is a fundamental type, its associated set of +entities is empty. \item If \tcode{T} is a class type (including unions), its associated entities are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. -Its associated namespaces are -the innermost enclosing namespaces of its associated entities. Furthermore, if \tcode{T} is a class template specialization, -its associated namespaces and entities also include: -the namespaces and entities +its associated entities also include: +the entities associated with the types of the template arguments -provided for template type parameters -(excluding template template parameters); -the templates used as template template arguments; -the namespaces of which any template template arguments are members; and the -classes of which any member templates used as template template +provided for template type parameters; +the templates used as template template arguments; and +the classes of which any member templates used as template template arguments are members. \begin{note} Non-type template arguments do not -contribute to the set of associated namespaces. +contribute to the set of associated entities. \end{note} \item If \tcode{T} is an enumeration type, -its associated namespace is -the innermost enclosing namespace of its declaration, and its associated entities are \tcode{T} and, if it is a class member, the member's class. \item If \tcode{T} is a pointer to \tcode{U} or an array of \tcode{U}, -its associated namespaces and entities are those associated with -\tcode{U}. +its associated entities are those associated with \tcode{U}. -\item If \tcode{T} is a function type, its associated namespaces and +\item If \tcode{T} is a function type, its associated entities are those associated with the function parameter types and those associated with the return type. \item If \tcode{T} is a pointer to a member function of a class -\tcode{X}, its associated namespaces and entities are those associated +\tcode{X}, its associated entities are those associated with the function parameter types and return type, together with those associated with \tcode{X}. \item If \tcode{T} is a pointer to a data member of class \tcode{X}, its -associated namespaces and entities are those associated with the member +associated entities are those associated with the member type together with those associated with \tcode{X}. \end{itemize} -If an associated namespace is an inline namespace\iref{namespace.def}, its -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 argument is the name or address of an overload set, +In addition, if the argument is an overload set or the address of such a set, its associated entities -and namespaces are the union of those associated with each of the -members of the set, i.e., the entities and namespaces associated with its +are the union of those associated with each of the +members of the set, i.e., the entities associated with its parameter types and return type. Additionally, if the aforementioned overload set is named with -a \grammarterm{template-id}, its associated entities and namespaces also include -those of its type \grammarterm{template-argument}{s} and its template -\grammarterm{template-argument}{s}. +a \grammarterm{template-id}, its associated entities also include +its template \grammarterm{template-argument}{s} and +those associated with its type \grammarterm{template-argument}s. \pnum -Let \placeholder{X} be the lookup set produced by unqualified -lookup\iref{basic.lookup.unqual} and let \placeholder{Y} be the lookup set produced -by argument dependent lookup (defined as follows). If \placeholder{X} contains +The associated namespaces for a call are +the innermost enclosing non-inline namespaces for its associated entities +as well as every element of the inline namespace set of those namespaces. +Argument-dependent lookup finds +all declarations of functions and function templates that \begin{itemize} -\item a declaration of a class member, or -\item a block-scope function declaration that is not a \grammarterm{using-declaration}, or -\item a declaration that is neither a function nor a function template -\end{itemize} -then \placeholder{Y} is empty. Otherwise \placeholder{Y} is the set of declarations -found in the namespaces associated with the argument types as described -below. The set of declarations found by the lookup of the name is the -union of \placeholder{X} and \placeholder{Y}. -\begin{note} -The namespaces and entities -associated with the argument types can include namespaces and entities -already considered by the ordinary unqualified lookup. -\end{note} -\begin{example} -\begin{codeblock} -namespace NS { - class T { }; - void f(T); - void g(T, int); -} -NS::T parm; -void g(NS::T, float); -int main() { - f(parm); // OK: calls \tcode{NS::f} - extern void g(NS::T, float); - g(parm, 1); // OK: calls \tcode{g(NS::T, float)} -} -\end{codeblock} -\end{example} - -\pnum -When considering an associated namespace \tcode{N}, -the lookup is the same as the -lookup performed when \tcode{N} -is used as a qualifier\iref{namespace.qual} -except that: -\begin{itemize} -\item Any \grammarterm{using-directive}{s} in \tcode{N} are ignored. - -\item All names except those of (possibly overloaded) functions and -function templates are ignored. - -\item Any namespace-scope friend functions or friend function templates\iref{class.friend} -declared in classes with reachable definitions in the set of associated entities -are visible within their respective -namespaces even if they are not visible during an ordinary -lookup\iref{namespace.memdef}. - \item -Any exported declaration \tcode{D} in \tcode{N} -declared within the purview of -a named module \tcode{M}\iref{module.interface} -is visible -if there is an associated entity attached to \tcode{M} -with the same innermost enclosing non-inline namespace as \tcode{D}. - +are found by a search of any associated namespace, or \item -If the lookup is for a dependent name (\ref{temp.dep}, \ref{temp.dep.candidate}), -any declaration \tcode{D} in \tcode{N} -is visible -if \tcode{D} would be visible to qualified name lookup\iref{namespace.qual} -at any point in the instantiation context\iref{module.context} of the lookup, -unless \tcode{D} is declared in another translation unit, attached to the global module, -and is either discarded\iref{module.global.frag} or has internal linkage. +are declared as a friend\iref{class.friend} of any class +with a reachable definition in the set of associated entities, or +\item +are exported, +are attached to a named module \tcode{M}\iref{module.interface}, +do not appear in the translation unit containing the point of the lookup, and +have the same innermost enclosing non-inline namespace scope as +a declaration of an associated entity attached to \tcode{M}. \end{itemize} +If the lookup is for a dependent name (\ref{temp.dep}, \ref{temp.dep.candidate}), +the above lookup is also performed +from each point in the instantiation context\iref{module.context} of the lookup, +additionally ignoring any declaration that +appears in another translation unit, +is attached to the global module, and +is either discarded\iref{module.global.frag} or has internal linkage. \pnum \begin{example} @@ -2007,6 +2000,28 @@ \end{codeblocktu} \end{example} +\pnum +\begin{note} +The associated namespace can include namespaces +already considered by ordinary unqualified lookup. +\end{note} +\begin{example} +\begin{codeblock} +namespace NS { + class T { }; + void f(T); + void g(T, int); +} +NS::T parm; +void g(NS::T, float); +int main() { + f(parm); // OK: calls \tcode{NS::f} + extern void g(NS::T, float); + g(parm, 1); // OK: calls \tcode{g(NS::T, float)} +} +\end{codeblock} +\end{example} + \rSec2[basic.lookup.qual]{Qualified name lookup} \rSec3[basic.lookup.qual.general]{General} From 348e5a45e327bbdef3f724fe604363fbdfc1c286 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 18:28:10 +0100 Subject: [PATCH 16/60] basic.lookup.qual.general --- source/basic.tex | 185 +++++++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 62 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 5efa44d3ea..ca7adf5c61 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2030,19 +2030,15 @@ \indextext{lookup!qualified name|(}% \indextext{name!qualified}% \indextext{qualification!explicit}% -The name of a class or namespace member -or enumerator can be referred to after the -\tcode{::} scope resolution operator\iref{expr.prim.id.qual} applied to a -\grammarterm{nested-name-specifier} that denotes its class, -namespace, or enumeration. -If a -\tcode{::} scope resolution -operator -in a \grammarterm{nested-name-specifier} is not preceded by a \grammarterm{decltype-specifier}, -lookup of the name preceding that \tcode{::} considers only namespaces, types, and -templates whose specializations are types. If the -name found does not designate a namespace or a class, enumeration, or dependent type, -the program is ill-formed. +Lookup of an \grammarterm{identifier} +followed by a \tcode{::} scope resolution operator +considers only +namespaces, types, and templates whose specializations are types. +If a name, \grammarterm{template-id}, or \grammarterm{decltype-specifier} +is followed by a \tcode{::}, +it shall designate a namespace, class, enumeration, or dependent type, +and the \tcode{::} is never interpreted as +a complete \grammarterm{nested-name-specifier}. \begin{example} \begin{codeblock} class A { @@ -2051,62 +2047,130 @@ }; int main() { int A; - A::n = 42; // OK - A b; // error: \tcode{A} does not name a type + A::n = 42; // OK + A b; // error: \tcode{A} does not name a type +} +template struct B : A {}; +namespace N { + template void B(); + int f() { + return B<0>::n; // error: N::B<0> is not a type + } } \end{codeblock} \end{example} +\indextext{operator!scope resolution}% +\indextext{scope resolution operator|see{operator, scope resolution}}% + \pnum -\begin{note} -Multiply qualified names, such as \tcode{N1::N2::N3::n}, can -be used to refer to members of nested classes\iref{class.nest} or -members of nested namespaces. +A member-qualified name is +the (unique) component name\iref{expr.prim.id.unqual}, if any, of +\begin{itemize} +\item +an \grammarterm{unqualified-id} or +\item +a \grammarterm{nested-name-specifier} of the form +\grammarterm{type-name} \tcode{::} or \grammarterm{namespace-name} \tcode{::} +\end{itemize} +in the \grammarterm{id-expression} of a class member access expression\iref{expr.ref}. +A \defnadj{qualified}{name} is a member-qualified name or the terminal name of +a \grammarterm{qualified-id}, +a \grammarterm{using-declarator}, +a \grammarterm{typename-specifier}, +a \grammarterm{qualified-namespace-specifier}, or +a \grammarterm{nested-name-specifier}, +\grammarterm{elaborated-type-specifier}, or +\grammarterm{class-or-decltype} +that has a \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. +The \defn{lookup context} of a member-qualified name is +the type of its associated object expression +(considered dependent if the object expression is type-dependent). +The lookup context of any other qualified name is +the type, template, or namespace +nominated by the preceding \grammarterm{nested-name-specifier}. +\begin{note} +When parsing a class member access, +the name following the \tcode{->} or \tcode{.} is +a qualified name even though it is not yet known of which kind. \end{note} +\begin{example} +In +\begin{codeblock} + N::C::m.Base::f() +\end{codeblock} +\tcode{Base} is a member-qualified name; +the other qualified names are \tcode{C}, \tcode{m}, and \tcode{f}. +\end{example} \pnum -In a declaration in which the \grammarterm{declarator-id} is a -\grammarterm{qualified-id}, names used before the \grammarterm{qualified-id} -being declared are looked up in the defining namespace scope; names -following the \grammarterm{qualified-id} are looked up in the scope of the -member's class or namespace. +Qualified name lookup in a class, namespace, or enumeration performs +a search of the scope associated with it\iref{class.member.lookup} +except as specified below. +Unless otherwise specified, +a qualified name undergoes qualified name lookup in its lookup context +from the point where it appears +unless the lookup context either +is dependent and is not the current instantiation\iref{temp.dep.type} or +is not a class or class template. +If nothing is found by qualified lookup for a member-qualified name +that is the terminal name of a \grammarterm{nested-name-specifier} and +is not dependent, it undergoes unqualified lookup. +\begin{note} +During lookup for a template specialization, no names are dependent. +\end{note} \begin{example} \begin{codeblock} -class X { }; -class C { - class X { }; - static const int number = 50; - static X arr[number]; +int f(); +struct A { + int B, C; + template using D = void; + using T = void; + void f(); }; -X C::arr[number]; // error: - // equivalent to \tcode{::X} \tcode{C::arr[C::number];} - // and not to \tcode{C::X} \tcode{C::arr[C::number];} +using B = A; +template using C = A; +template using D = A; +template using X = A; + +template +void g(T *p) { // as instantiated for \tcode{g}: + p->X<0>::f(); // error: \tcode{A::X} not found in \tcode{((p->X) < 0) > ::f()} + p->template X<0>::f(); // OK: \tcode{::X} found in definition context + p->B::f(); // OK: non-type \tcode{A::B} ignored + p->template C<0>::f(); // error: \tcode{A::C} is not a template + p->template D<0>::f(); // error: \tcode{A::D<0>} is not a class type + p->T::f(); // error: \tcode{A::T} is not a class type +} +template void g(A*); \end{codeblock} \end{example} \pnum -\indextext{operator!scope resolution}% -\indextext{scope resolution operator|see{operator, scope resolution}}% -A name prefixed by the unary scope operator \tcode{::}\iref{expr.prim.id.qual} -is looked up in global scope, in the translation unit where it is used. -The name shall be declared in global namespace scope or shall be a name -whose declaration is visible in global scope because of a -\grammarterm{using-directive}\iref{namespace.qual}. The use of \tcode{::} -allows a global name to be referred to even if its identifier has been -hidden\iref{basic.lookup}. - -\pnum -A name prefixed by a \grammarterm{nested-name-specifier} that -nominates an enumeration type shall represent an \grammarterm{enumerator} -of that enumeration. - -\pnum -In a \grammarterm{qualified-id} of the form: - -\begin{ncbnf} -\opt{nested-name-specifier} type-name \terminal{::} \terminal{\~} type-name -\end{ncbnf} -the second \grammarterm{type-name} is looked up in the same scope as the first. +If a qualified name $Q$ follows a \tcode{\~}: +\begin{itemize} +\item +If $Q$ is a member-qualified name, +it undergoes unqualified lookup as well as qualified lookup. +\item +Otherwise, its \grammarterm{nested-name-specifier} $N$ shall nominate a type. +If $N$ has another \grammarterm{nested-name-specifier} $S$, +$Q$ is looked up as if its lookup context were that nominated by $S$. +\item +Otherwise, if the terminal name of $N$ is a member-qualified name $M$, +$Q$ is looked up as if $\tcode{\~}Q$ appeared in place of $M$ (as above). +\item +Otherwise, $Q$ undergoes unqualified lookup. +\item +Each lookup for $Q$ considers only +types (if $Q$ is not followed by a \tcode{<}) and +templates whose specializations are types. +If it finds nothing or is ambiguous, it is discarded. +\item +The \grammarterm{type-name} that is or contains $Q$ +shall refer to its (original) lookup context (ignoring cv-qualification) under +the interpretation established by at least one (successful) lookup performed. +\end{itemize} \begin{example} \begin{codeblock} struct C { @@ -2115,23 +2179,20 @@ typedef int I1, I2; extern int* p; extern int* q; -p->C::I::~I(); // \tcode{I} is looked up in the scope of \tcode{C} -q->I1::~I2(); // \tcode{I2} is looked up in the scope of the postfix-expression - +void f() { + p->C::I::~I(); // \tcode{I} is looked up in the scope of \tcode{C} + q->I1::~I2(); // \tcode{I2} is found by unqualified lookup +} struct A { ~A(); }; typedef A AB; int main() { AB* p; - p->AB::~AB(); // explicitly calls the destructor for \tcode{A} + p->AB::~AB(); // explicitly calls the destructor for \tcode{A} } \end{codeblock} \end{example} -\begin{note} -\ref{basic.lookup.classref} describes how name -lookup proceeds after the \tcode{.} and \tcode{->} operators. -\end{note} \rSec3[class.qual]{Class members} From 11710cb5fa1340377111828183e7b2f6c5f69f60 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 21:18:51 +0100 Subject: [PATCH 17/60] class.qual --- source/basic.tex | 70 +++++++++--------------------------------------- 1 file changed, 12 insertions(+), 58 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index ca7adf5c61..708fde6af3 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2196,70 +2196,29 @@ \rSec3[class.qual]{Class members} -\pnum \indextext{lookup!class member}% -If the \grammarterm{nested-name-specifier} of a \grammarterm{qualified-id} -nominates a class, the name specified after the -\grammarterm{nested-name-specifier} is looked up in the scope of the -class\iref{class.member.lookup}, except for the cases listed below. -The name shall represent one or more members of that class or of one of -its base classes\iref{class.derived}. -\begin{note} -A class member -can be referred to using a \grammarterm{qualified-id} at any point in its -potential scope\iref{basic.scope.class}. -\end{note} -The exceptions to -the name lookup rule above are the following: -\begin{itemize} -\item the lookup for a destructor is as specified -in~\ref{basic.lookup.qual}; - -\item a \grammarterm{conversion-type-id} of a -\grammarterm{conversion-function-id} is looked up -in the same manner as a \grammarterm{conversion-type-id} in a class member -access (see~\ref{basic.lookup.classref}); - -\item the names in a \grammarterm{template-argument} of a -\grammarterm{template-id} are looked up in the context in which the entire -\grammarterm{postfix-expression} occurs; - -\item the lookup for a name specified in a -\grammarterm{using-declaration}\iref{namespace.udecl} also finds class or -enumeration names hidden within the same -scope\iref{basic.lookup}. -\end{itemize} \pnum -In a lookup in which function names are not ignored +In a lookup for a qualified name whose lookup context is a class $C$ +in which function names are not ignored \begin{footnote} Lookups in which function names are ignored include names appearing in a \grammarterm{nested-name-specifier}, an \grammarterm{elaborated-type-specifier}, or a \grammarterm{base-specifier}. \end{footnote} -and the \grammarterm{nested-name-specifier} nominates a class \tcode{C}: \begin{itemize} -\item if the name specified after the \grammarterm{nested-name-specifier}, -when looked up in \tcode{C}, is the injected-class-name of \tcode{C}\iref{class.pre}, or -\item -in a \grammarterm{using-declarator} of -a \grammarterm{using-declaration}\iref{namespace.udecl} that is a \grammarterm{member-declaration}, -if the name specified after the \grammarterm{nested-name-specifier} is the same as the -\grammarterm{identifier} or the \grammarterm{simple-template-id}'s -\grammarterm{template-name} in the last component of the \grammarterm{nested-name-specifier}, +\item +if the search finds the injected-class-name of \tcode{C}\iref{class.pre} or +\item +if the qualified name is dependent and +is the terminal name of a \grammarterm{using-declarator}\iref{namespace.udecl} +that names a constructor \end{itemize} -the name is instead considered to name the -constructor of class \tcode{C}. -\begin{note} -For example, the constructor -is not an acceptable lookup result in an -\grammarterm{elaborated-type-specifier} so the constructor would not be -used in place of the injected-class-name. -\end{note} -Such a constructor -name shall be used only in the \grammarterm{declarator-id} of a declaration -that names a constructor or in a \grammarterm{using-declaration}. +the name is instead considered to name the constructor of class \tcode{C}. +Such a constructor name shall be used only +in the \grammarterm{declarator-id} of a (friend) declaration of a constructor or +in a \grammarterm{using-declaration}. \begin{example} \begin{codeblock} struct A { A(); }; @@ -2274,11 +2233,6 @@ \end{codeblock} \end{example} -\pnum -A class member name hidden by a name in a nested scope or -by the name of a derived class member can still be found if qualified by -the name of its class followed by the \tcode{::} operator. - \rSec3[namespace.qual]{Namespace members} \pnum From a62e0c373159090835a878b468ed972130fa3031 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 21:30:55 +0100 Subject: [PATCH 18/60] namespace.qual --- source/basic.tex | 101 +++++++---------------------------------------- 1 file changed, 15 insertions(+), 86 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 708fde6af3..2f1531ca40 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2236,40 +2236,17 @@ \rSec3[namespace.qual]{Namespace members} \pnum -\indextext{lookup!namespace member}% -If the \grammarterm{nested-name-specifier} of a \grammarterm{qualified-id} -nominates a namespace (including the case where the -\grammarterm{nested-name-specifier} is \tcode{::}, i.e., nominating -the global namespace), the name specified after the -\grammarterm{nested-name-specifier} is looked up in the scope of the -namespace. -The names in a \grammarterm{template-argument} of a -\grammarterm{template-id} are looked up in the context in which the -entire \grammarterm{postfix-expression} occurs. - -\pnum -For a namespace \tcode{X} and name \tcode{m}, the namespace-qualified lookup set -$S(X, m)$ is defined as follows: Let $S'(X, m)$ be the set of all -declarations of \tcode{m} in \tcode{X} and the inline namespace set of -\tcode{X}\iref{namespace.def} -whose potential scope\iref{basic.scope.namespace} -would include the namespace in which \tcode{m} is declared -at the location of the \grammarterm{nested-name-specifier}. -If $S'(X, m)$ is not empty, $S(X, m)$ -is $S'(X, m)$; otherwise, $S(X, m)$ is the union of $S(N_i, m)$ for -all namespaces $N_i$ nominated by \grammarterm{using-directive}{s} in -\tcode{X} and its inline namespace set. - -\pnum -Given \tcode{X::m} (where \tcode{X} is a user-declared namespace), or -given \tcode{::m} (where \tcode{X} is the global namespace), if -$S(X, m)$ is the empty set, the program is ill-formed. Otherwise, if -$S(X, m)$ has exactly one member, or if the context of the reference is -a \grammarterm{using-declaration}\iref{namespace.udecl}, $S(X, m)$ -is the -required set of declarations of \tcode{m}. Otherwise if the use of -\tcode{m} is not one that allows a unique declaration to be chosen from -$S(X, m)$, the program is ill-formed. +Qualified name lookup in a namespace $N$ additionally searches +every element of the inline namespace set of $N$\iref{namespace.def}. +If nothing is found, +the results of the lookup are the results of qualified name lookup +in each namespace nominated by a \grammarterm{using-directive} +that precedes the point of the lookup and +inhabits $N$ or an element of its inline namespace set. +\begin{note} +If a \grammarterm{using-directive} refers to a namespace +that has already been considered, it does not affect the result. +\end{note} \begin{example} \begin{codeblock} int x; @@ -2398,13 +2375,10 @@ \end{example} \pnum -During the lookup of a qualified namespace member name, if the lookup -finds more than one declaration of the member, and if one declaration -introduces a class name or enumeration name and the other declarations -introduce either the same variable, the same enumerator, or a set of -functions, the non-type name hides the class or enumeration name if and -only if the declarations are from the same namespace; otherwise (the -declarations are from different namespaces), the program is ill-formed. +\begin{note} +Class and enumeration declarations are not discarded +because of other declarations found in other searches. +\end{note} \begin{example} \begin{codeblock} namespace A { @@ -2426,51 +2400,6 @@ \end{codeblock} \end{example} -\pnum -In a declaration for a namespace member in which the -\grammarterm{declarator-id} is a \grammarterm{qualified-id}, given that the -\grammarterm{qualified-id} for the namespace member has the form -\begin{ncbnf} -nested-name-specifier unqualified-id -\end{ncbnf} -the -\grammarterm{unqualified-id} shall name a member of the namespace -designated by the \grammarterm{nested-name-specifier} -or of an element of the inline namespace set\iref{namespace.def} of that namespace. -\begin{example} -\begin{codeblock} -namespace A { - namespace B { - void f1(int); - } - using namespace B; -} -void A::f1(int){ } // error: \tcode{f1} is not a member of \tcode{A} -\end{codeblock} -\end{example} -However, in such namespace member declarations, the -\grammarterm{nested-name-specifier} may rely on \grammarterm{using-directive}{s} -to implicitly provide the initial part of the -\grammarterm{nested-name-specifier}. -\begin{example} -\begin{codeblock} -namespace A { - namespace B { - void f1(int); - } -} - -namespace C { - namespace D { - void f1(int); - } -} - -using namespace A; -using namespace C::D; -void B::f1(int){ } // OK, defines \tcode{A::B::f1(int)} -\end{codeblock} -\end{example} \indextext{lookup!qualified name|)}% \rSec2[basic.lookup.elab]{Elaborated type specifiers}% From 3e9ed5c5962018fa3276401c256e13fdf430fa71 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 21:38:10 +0100 Subject: [PATCH 19/60] basic.lookup.elab --- source/basic.tex | 55 ++++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 2f1531ca40..0c2c7916fa 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2407,43 +2407,24 @@ \indextext{type specifier!elaborated} \pnum -An \grammarterm{elaborated-type-specifier}\iref{dcl.type.elab} may be -used to refer to a previously declared \grammarterm{class-name} or -\grammarterm{enum-name} even though the name has been hidden by a non-type -declaration\iref{basic.lookup}. - -\pnum -If the \grammarterm{elaborated-type-specifier} has no -\grammarterm{nested-name-specifier}, and unless the -\grammarterm{elaborated-type-specifier} appears in a declaration with the -following form: -\begin{ncbnf} -class-key \opt{attribute-specifier-seq} identifier \terminal{;} -\end{ncbnf} -the \grammarterm{identifier} is looked up according -to~\ref{basic.lookup.unqual} but ignoring any non-type names that have -been declared. If the \grammarterm{elaborated-type-specifier} is introduced -by the \tcode{enum} keyword and this lookup does not find a previously -declared \grammarterm{type-name}, the \grammarterm{elaborated-type-specifier} -is ill-formed. If the \grammarterm{elaborated-type-specifier} is introduced -by the \grammarterm{class-key} and this lookup does not find a previously -declared \grammarterm{type-name}, or if the -\grammarterm{elaborated-type-specifier} appears in a declaration with the -form: -\begin{ncbnf} -class-key \opt{attribute-specifier-seq} identifier \terminal{;} -\end{ncbnf} -the \grammarterm{elaborated-type-specifier} is a declaration that -introduces the \grammarterm{class-name} as described -in~\ref{basic.scope.pdecl}. - -\pnum -If the \grammarterm{elaborated-type-specifier} has a -\grammarterm{nested-name-specifier}, qualified name lookup is performed, as -described in~\ref{basic.lookup.qual}, but ignoring any non-type names -that have been declared. If the name lookup does not find a previously -declared \grammarterm{type-name}, the \grammarterm{elaborated-type-specifier} -is ill-formed. +If the \grammarterm{class-key} or \keyword{enum} keyword +in an \grammarterm{elaborated-type-specifier} +is followed by an \grammarterm{identifier} +that is not followed by \tcode{::}, +lookup for the \grammarterm{identifier} is type-only. +\begin{note} +In general, the recognition of an \grammarterm{elaborated-type-specifier} +depends on the following tokens. +If the \grammarterm{identifier} is followed by \tcode{::}, +see \ref{basic.lookup.qual}. +\end{note} + +\pnum +If the terminal name of the \grammarterm{elaborated-type-specifier} +is a qualified name, +lookup for it is type-only. +If the name lookup does not find a previously declared \grammarterm{type-name}, +the \grammarterm{elaborated-type-specifier} is ill-formed. \pnum \begin{example} From 64868d736505dcf455fd4285761da73be055b423 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 21:39:58 +0100 Subject: [PATCH 20/60] basic.lookup.classref --- source/basic.tex | 103 ---------------------------------------- source/declarations.tex | 4 +- source/expressions.tex | 4 +- source/statements.tex | 2 +- source/templates.tex | 2 +- source/xrefdelta.tex | 1 + 6 files changed, 7 insertions(+), 109 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 0c2c7916fa..e5bf796cba 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2459,109 +2459,6 @@ \end{example} \indextext{lookup!elaborated type specifier|)}% -\rSec2[basic.lookup.classref]{Class member access} - -\pnum -\indextext{lookup!class member}% -In a class member access expression\iref{expr.ref}, if the \tcode{.} -or \tcode{->} token is immediately followed by an \grammarterm{identifier} -followed by a \tcode{<}, the identifier is looked up to determine -whether the \tcode{<} is the beginning of a template argument -list\iref{temp.names} or a less-than operator. The identifier is first -looked up in the class of the object expression\iref{class.member.lookup}. -If the identifier is not found, -it is then looked up in the context of the entire -\grammarterm{postfix-expression} and shall name a template -whose specializations are types. - -\pnum -If the \grammarterm{id-expression} in a class member -access\iref{expr.ref} is an \grammarterm{unqualified-id}, and the type of -the object expression is of a class type \tcode{C}, the -\grammarterm{unqualified-id} is looked up -in the scope of class \tcode{C}\iref{class.member.lookup}. - -\pnum -If the \grammarterm{unqualified-id} is \tcode{\~}\grammarterm{type-name}, the -\grammarterm{type-name} is looked up in the context of the entire -\grammarterm{postfix-expression}. If the type \tcode{T} of the object -expression is of a class type \tcode{C}, the \grammarterm{type-name} is -also looked up in the scope of class \tcode{C}. At least one of the -lookups shall find a name that refers to \cv{}~\tcode{T}. -\begin{example} -\begin{codeblock} -struct A { }; - -struct B { - struct A { }; - void f(::A* a); -}; - -void B::f(::A* a) { - a->~A(); // OK: lookup in \tcode{*a} finds the injected-class-name -} -\end{codeblock} -\end{example} - -\pnum -If the \grammarterm{id-expression} in a class member access is a -\grammarterm{qualified-id} of the form -\begin{codeblock} -@\placeholder{class-name-or-namespace-name}@::... -\end{codeblock} -the \tcode{\placeholder{class-name-or-namespace-name}} following the \tcode{.} or -\tcode{->} operator is -first looked up in the class of the object expression\iref{class.member.lookup} -and the name, if found, -is used. Otherwise it is looked up in the context of the entire -\grammarterm{postfix-expression}. -\begin{note} -See~\ref{basic.lookup.qual}, which -describes the lookup of a name before \tcode{::}, which will only find a type -or namespace name. -\end{note} - -\pnum -If the \grammarterm{qualified-id} has the form -\begin{codeblock} -::@\placeholder{class-name-or-namespace-name}@::... -\end{codeblock} -the \tcode{\placeholder{class-name-or-namespace-name}} is looked up in global scope -as a \grammarterm{class-name} or \grammarterm{namespace-name}. - -\pnum -If the \grammarterm{nested-name-specifier} contains a -\grammarterm{simple-template-id}\iref{temp.names}, the names in its -\grammarterm{template-argument}{s} are looked up in the context in which the -entire \grammarterm{postfix-expression} occurs. - -\pnum -If the \grammarterm{id-expression} is a \grammarterm{conversion-function-id}, -its \grammarterm{conversion-type-id} -is first looked up -in the class of the object expression\iref{class.member.lookup} -and the name, if -found, is used. Otherwise it is looked up in the context -of the entire \grammarterm{postfix-expression}. -In each of these lookups, only names that denote types or templates whose -specializations are types are considered. -\begin{example} -\begin{codeblock} -struct A { }; -namespace N { - struct A { - void g() { } - template operator T(); - }; -} - -int main() { - N::A a; - a.operator A(); // calls \tcode{N::A::operator N::A} -} -\end{codeblock} -\end{example} - \rSec2[basic.lookup.udir]{Using-directives and namespace aliases} \pnum diff --git a/source/declarations.tex b/source/declarations.tex index 999f0258a0..b2e71964fc 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -6386,7 +6386,7 @@ \pnum The \grammarterm{unqualified-id} \tcode{get_return_object_on_allocation_failure} is looked up in the scope of the promise type by class member access -lookup\iref{basic.lookup.classref}. +lookup\iref{basic.lookup.qual}. If any declarations are found, then the result of a call to an allocation function used to obtain storage for the coroutine state is assumed to return \tcode{nullptr} if it fails to obtain storage, @@ -6576,7 +6576,7 @@ Let \tcode{i} be an index prvalue of type \tcode{std::size_t} corresponding to $\tcode{v}_\tcode{i}$. The \grammarterm{unqualified-id} \tcode{get} is looked up -in the scope of \tcode{E} by class member access lookup\iref{basic.lookup.classref}, +in the scope of \tcode{E} by class member access lookup\iref{basic.lookup.qual}, and if that finds at least one declaration that is a function template whose first template parameter is a non-type parameter, diff --git a/source/expressions.tex b/source/expressions.tex index 3bc6417b9a..aca6af59ff 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -3300,7 +3300,7 @@ member of that class. \end{note} \begin{note} -\ref{basic.lookup.classref} describes how names are looked up after the +\ref{basic.lookup.qual} describes how names are looked up after the \tcode{.} and \tcode{->} operators. \end{note} @@ -4450,7 +4450,7 @@ or a final suspend point\iref{dcl.fct.def.coroutine}. Otherwise, the \grammarterm{unqualified-id} \tcode{await_transform} is looked up within the scope of \tcode{P} by class member access -lookup\iref{basic.lookup.classref}, +lookup\iref{basic.lookup.qual}, and if this lookup finds at least one declaration, then \placeholder{a} is \mbox{\placeholder{p}\tcode{.await_transform(}\grammarterm{cast-expression}\tcode{)}}; otherwise, \placeholder{a} is the \grammarterm{cast-expression}. diff --git a/source/statements.tex b/source/statements.tex index 74f7486979..9a1262aea3 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -660,7 +660,7 @@ \item if the \grammarterm{for-range-initializer} is an expression of class type \tcode{C}, the \grammarterm{unqualified-id}{s} \tcode{begin} and \tcode{end} are looked up in the scope of \tcode{C} -as if by class member access lookup\iref{basic.lookup.classref}, and if +as if by class member access lookup\iref{basic.lookup.qual}, and if both find at least one declaration, \exposid{begin-expr} and \exposid{end-expr} are \tcode{\exposid{range}.begin()} and \tcode{\exposid{range}.end()}, respectively; diff --git a/source/templates.tex b/source/templates.tex index 85c1a689e2..45efc303f5 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -5214,7 +5214,7 @@ An \grammarterm{id-expression} denoting the member in a class member access expression\iref{expr.ref} for which the type of the object expression is the current instantiation, and the \grammarterm{id-expression}, when looked -up\iref{basic.lookup.classref}, refers to at least one member of a class +up\iref{basic.lookup.qual}, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof. \begin{note} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index d0176d20e0..8e0c3e60c9 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -27,6 +27,7 @@ \movedxref{basic.scope.declarative}{basic.scope.scope} \movedxref{basic.funscope}{stmt.label} \movedxref{basic.scope.hiding}{basic.lookup} +\movedxref{basic.lookup.classref}{basic.lookup.qual} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From b50d0ca9a44b8aa59a34ae1f336553f40f5e315c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 22:11:02 +0100 Subject: [PATCH 21/60] basic.link --- source/basic.tex | 182 +++++++++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 92 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index e5bf796cba..8137e3d59e 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -2517,8 +2517,9 @@ \indextext{\idxcode{const}!linkage of}% \indextext{linkage!\idxcode{inline} and}% \indextext{\idxcode{inline}!linkage of}% -A name having namespace scope\iref{basic.scope.namespace} has internal -linkage if it is the name of +The name of an entity +that belongs to a namespace scope\iref{basic.scope.namespace} +has internal linkage if it is the name of \begin{itemize} \item a variable, variable template, function, or function template that is @@ -2542,7 +2543,7 @@ \pnum 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 +The name of an entity that belongs to a namespace scope that has not been given internal linkage above and that is the name of \begin{itemize} @@ -2579,74 +2580,35 @@ \end{itemize} \pnum -In addition, a member function, static data member, a named class or -enumeration of class scope, or an unnamed class or enumeration defined -in a class-scope typedef declaration such that the class or enumeration -has the typedef name for linkage purposes\iref{dcl.typedef}, has -the same linkage, if any, as the name of the class of which it is a -member. +In addition, +a member function, +static data member, +a named class or enumeration that inhabits a class scope, or +an unnamed class or enumeration defined in a typedef declaration +that inhabits a class scope +such that the class or enumeration +has the typedef name for linkage purposes\iref{dcl.typedef}, +has the same linkage, if any, as the name of the class of which it is a member. \pnum -The name of a function declared in block scope and -the name of a variable declared by a block scope \tcode{extern} declaration -have linkage. -If such a declaration is attached to a named module, -the program is ill-formed. -If there is a visible declaration -of an entity with linkage, ignoring entities declared -outside the innermost enclosing namespace scope, -such that the block scope declaration would be -a (possibly ill-formed) redeclaration -if the two declarations appeared in the same scope, -the block scope declaration declares -that same entity and receives the linkage of the previous declaration. 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. -If, within a translation unit, the same entity is declared with both -internal and external linkage, the program is ill-formed. \begin{example} \begin{codeblock} static void f(); extern "C" void h(); static int i = 0; // \#1 -void g() { +void q() { extern void f(); // internal linkage + extern void g(); // \tcode{::g}, external linkage extern void h(); // C language linkage int i; // \#2: \tcode{i} has no linkage { extern void f(); // internal linkage - extern int i; // \#3: external linkage, ill-formed + extern int i; // \#3: internal linkage } } \end{codeblock} -Without the declaration at line \#2, -the declaration at line \#3 would link with the declaration at line \#1. -Because the declaration with internal linkage is hidden, however, -\#3 is given external linkage, making the program ill-formed. -\end{example} - -\pnum -When a block scope declaration of an entity with linkage is not found to -refer to some other declaration, then that entity is a member of the -innermost enclosing namespace. However such a declaration does not -introduce the member name in its namespace scope. -\begin{example} -\begin{codeblock} -namespace X { - void p() { - q(); // error: \tcode{q} not yet declared - extern void q(); // \tcode{q} is a member of namespace \tcode{X} - } - - void middle() { - q(); // error: \tcode{q} not yet declared - } - - void q() { @\commentellip@ } // definition of \tcode{X::q} -} - -void q() { @\commentellip@ } // some other, unrelated \tcode{q} -\end{codeblock} +Even though the declaration at line \#2 hides the declaration at line \#1, +the declaration at line \#3 still redeclares \#1 and receives internal linkage. \end{example} \pnum @@ -2656,42 +2618,38 @@ linkage. \pnum -Two names that are the same\iref{basic.pre} and that are declared -in different scopes shall denote the same variable, function, -type, template or namespace if +Two declarations of entities declare the same entity +if, considering declarations of unnamed types to introduce their names +for linkage purposes, if any (\ref{dcl.typedef}, \ref{dcl.enum}), +they correspond\iref{basic.scope.scope}, +have the same target scope that is not a function or template parameter scope, +and either \begin{itemize} -\item both names have external or module linkage -and are declared in declarations attached to the same module, -or else both names have internal linkage -and are declared in the same translation unit; and - -\item both names refer to members of the same namespace or to members, -not by inheritance, of the same class; and - -\item when both names denote functions or function templates, -the signatures~(\ref{defns.signature}, \ref{defns.signature.templ}) -are the same. - +\item +they appear in the same translation unit, or +\item +they both declare names with module linkage and are attached to the same module, or +\item +they both declare names with external linkage. \end{itemize} -If multiple declarations of the same name with external linkage -would declare the same entity except that -they are attached to different modules, -the program is ill-formed; no diagnostic is required. \begin{note} -\grammarterm{using-declaration}{s}, -typedef declarations, -and \grammarterm{alias-declaration}{s} -do not declare entities, but merely introduce synonyms. -Similarly, -\grammarterm{using-directive}{s} -do not declare entities. -Enumerators do not have linkage, -but might serve as the name of an enumeration with linkage\iref{dcl.enum}. +There are other circumstances in which declarations declare the same entity +(\ref{dcl.link}, \ref{temp.type}, \ref{temp.class.spec}). \end{note} \pnum -If a declaration would redeclare a reachable declaration -attached to a different module, the program is ill-formed. +If a declaration $H$ that declares a name with internal linkage +precedes a declaration $D$ in another translation unit $U$ and +would declare the same entity as $D$ if it appeared in $U$, +the program is ill-formed. +\begin{note} +Such an $H$ can appear only in a header unit. +\end{note} + +\pnum +If two declarations of an entity are +attached to different modules, the program is ill-formed; +no diagnostic is required if neither is reachable from the other. \begin{example} \begin{codeblocktu}{\tcode{"decls.h"}} int f(); // \#1, attached to the global module @@ -2721,13 +2679,53 @@ \pnum \indextext{consistency!type declaration}% \indextext{declaration!multiple}% -After all adjustments of types (during which -typedefs\iref{dcl.typedef} are replaced by their definitions), the -types specified by all declarations referring to a given variable or -function shall be identical, except that declarations for an array +For any two declarations of an entity: +\begin{itemize} +\item +If one declares it to be a variable or function, +the other shall declare it as one of the same type. +\item +If one declares it to be an enumerator, the other shall do so. +\item +If one declares it to be a namespace, the other shall do so. +\item +If one declares it to be a type, +the other shall declare it to be a type of the same kind\iref{dcl.type.elab}. +\item +If one declares it to be a class template, +the other shall do so with the same kind and +an equivalent \grammarterm{template-head}\iref{temp.over.link}. +\begin{note} +The declarations can supply different default template arguments. +\end{note} +\item +If one declares it to be a function template or +a (partial specialization of a) variable template, +the other shall declare it to be one +with an equivalent \grammarterm{template-head} and type. +\item +If one declares it to be an alias template, +the other shall declare it to be one with +an equivalent \grammarterm{template-head} and \grammarterm{defining-type-id}. +\item +If one declares it to be a concept, the other shall do so. +\end{itemize} +Types are compared after all adjustments of types (during which +typedefs\iref{dcl.typedef} are replaced by their definitions); +declarations for an array object can specify array types that differ by the presence or absence of -a major array bound\iref{dcl.array}. A violation of this rule on type -identity does not require a diagnostic. +a major array bound\iref{dcl.array}. +No diagnostic is required if neither declaration is reachable from the other. +\begin{example} +\begin{codeblock} +int f(int x, int x); // error: different entities for \tcode{x} +void g(); // \#1 +void g(int); // OK: different entity from \#1 +int g(); // error: same entity as \#1 with different type +void h(); // \#2 +namespace h {} // error: same entity as \#2, but not a function +\end{codeblock} +\end{example} \pnum \begin{note} From 9a6f2017e7803354b64a3e1683ba6a68b2c7b09a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 22:34:23 +0100 Subject: [PATCH 22/60] basic.* (rest) --- source/basic.tex | 92 +++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 8137e3d59e..b6725a025f 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -3319,9 +3319,9 @@ Before the lifetime of an object has started but after the storage which the object will occupy has been allocated \begin{footnote} -For example, before the -construction of a global object -that is initialized via a user-provided constructor\iref{class.cdtor}. +For example, before the dynamic initialization of +an object with static storage duration\iref{basic.start.dynamic}. + \end{footnote} or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of @@ -3664,12 +3664,11 @@ \pnum \indextext{object!local static@local \tcode{static}}% -The keyword \tcode{static} can be used to declare a local variable with +The keyword \tcode{static} can be used to declare a block variable with static storage duration. \begin{note} -\ref{stmt.dcl} describes the -initialization of local \tcode{static} variables; \ref{basic.start.term} -describes the destruction of local \tcode{static} variables. +\ref{stmt.dcl} and \ref{basic.start.term} describe the +initialization and destruction of such variables. \end{note} \pnum @@ -3698,7 +3697,7 @@ \pnum \indextext{storage duration!local object}% -Block-scope variables +Variables that belong to a block or parameter scope and are not explicitly declared \tcode{static}, \tcode{thread_local}, or \tcode{extern} have \defnadj{automatic}{storage duration}. The storage for these entities lasts until the block in which they are created exits. @@ -3799,10 +3798,9 @@ \pnum \indextext{function!allocation}% -An allocation function shall be a class member function or a global -function; a program is ill-formed if an allocation function is declared -in a namespace scope other than global scope or declared static in -global scope. The return type shall be \tcode{void*}. The first +An allocation function that is not a class member function +shall belong to the global scope and not have a name with internal linkage. +The return type shall be \tcode{void*}. The first parameter shall have type \tcode{std::size_t}\iref{support.types}. The first parameter shall not have an associated default argument\iref{dcl.fct.default}. The value of the first parameter @@ -3810,7 +3808,7 @@ function can be a function template. Such a template shall declare its return type and first parameter as specified above (that is, template parameter types shall not be used in the return type and first parameter -type). Template allocation functions shall have two or more parameters. +type). Allocation function templates shall have two or more parameters. \pnum An allocation function attempts to allocate the requested amount of @@ -3901,10 +3899,8 @@ \pnum \indextext{function!deallocation}% -Deallocation functions shall be class member functions or global -functions; a program is ill-formed if deallocation functions are -declared in a namespace scope other than global scope or declared static -in global scope. +A deallocation function that is not a class member function +shall belong to the global scope and not have a name with internal linkage. \pnum A deallocation function @@ -5289,7 +5285,7 @@ \pnum \begin{note} -See~\ref{dcl.fct} and~\ref{class.this} regarding function +See~\ref{dcl.fct} and~\ref{over.match.funcs} regarding function types that have \grammarterm{cv-qualifier}{s}. \end{note} @@ -6319,8 +6315,8 @@ \pnum \indextext{program!startup|(}% -A program shall contain a global function called \tcode{main} -attached to the global module. +A program shall contain exactly one function called \tcode{main} +that belongs to the global scope. Executing a program starts a main thread of execution~(\ref{intro.multithread}, \ref{thread.threads}) in which the \tcode{main} function is invoked. \indextext{implementation!freestanding}% @@ -6330,14 +6326,14 @@ \begin{note} In a freestanding environment, startup and termination is \impldef{startup and termination in freestanding environment}; startup contains the -execution of constructors for objects of namespace scope with static storage duration; +execution of constructors for non-local objects with static storage duration; termination contains the execution of destructors for objects with static storage duration. \end{note} \pnum -An implementation shall not predefine the \tcode{main} function. This -function shall not be overloaded. Its type shall have \Cpp{} language linkage +An implementation shall not predefine the \tcode{main} function. +Its type shall have \Cpp{} language linkage and it shall have a declared return type of type \tcode{int}, but otherwise its type is \impldef{parameters to \tcode{main}}. \indextext{\idxcode{main} function!implementation-defined parameters to}% @@ -6380,9 +6376,12 @@ The function \tcode{main} shall not be a coroutine\iref{dcl.fct.def.coroutine}. The \tcode{main} function shall not be declared with a \grammarterm{linkage-specification}\iref{dcl.link}. -A program that declares a variable \tcode{main} at global scope, -or that declares 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) +A program +that declares a variable \tcode{main} that belongs to the global scope, or +that declares a function \tcode{main} that belongs to the global scope and +is attached to a named module, or +that declares an entity named \tcode{main} +with C language linkage (in any namespace) is ill-formed. The name \tcode{main} is not otherwise reserved. @@ -6441,8 +6440,8 @@ All static initialization strongly happens before\iref{intro.races} any dynamic initialization. \begin{note} -The dynamic initialization of non-local variables is described -in~\ref{basic.start.dynamic}; that of local static variables is described +The dynamic initialization of non-block variables is described +in~\ref{basic.start.dynamic}; that of static block variables is described in~\ref{stmt.dcl}. \end{note} @@ -6465,7 +6464,7 @@ \end{itemize} \begin{note} As a consequence, if the initialization of an object \tcode{obj1} refers to an -object \tcode{obj2} of namespace scope potentially requiring dynamic initialization and defined +object \tcode{obj2} potentially requiring dynamic initialization and defined later in the same translation unit, it is unspecified whether the value of \tcode{obj2} used will be the value of the fully initialized \tcode{obj2} (because \tcode{obj2} was statically initialized) or will be the value of \tcode{obj2} merely zero-initialized. For example, @@ -6480,13 +6479,13 @@ \end{codeblock} \end{note} -\rSec3[basic.start.dynamic]{Dynamic initialization of non-local variables} +\rSec3[basic.start.dynamic]{Dynamic initialization of non-block variables} \pnum -\indextext{initialization!dynamic non-local}% +\indextext{initialization!dynamic non-block}% \indextext{start!program}% \indextext{initialization!order of}% -Dynamic initialization of a non-local variable with static storage duration is +Dynamic initialization of a non-block variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization, is partially-ordered if the variable is an inline variable that is not an implicitly or explicitly instantiated @@ -6507,7 +6506,7 @@ in either case prior to \tcode{E}. \pnum -Dynamic initialization of non-local variables \tcode{V} and \tcode{W} +Dynamic initialization of non-block variables \tcode{V} and \tcode{W} with static storage duration are ordered as follows: \begin{itemize} \item @@ -6555,20 +6554,20 @@ \indextext{non-initialization odr-use|see{odr-use, non-initialization}}% A \defnx{non-initialization odr-use}{odr-use!non-initialization} is an odr-use\iref{basic.def.odr} not caused directly or indirectly by -the initialization of a non-local static or thread storage duration variable. +the initialization of a non-block static or thread storage duration variable. \pnum \indextext{evaluation!unspecified order of}% It is \impldef{dynamic initialization of static variables before \tcode{main}} whether the dynamic initialization of a -non-local non-inline variable with static storage duration +non-block non-inline variable with static storage duration is sequenced before the first statement of \tcode{main} or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized. \begin{footnote} -A non-local variable with static storage duration +A non-block variable with static storage duration having initialization with side effects is initialized in this case, even if it is not itself odr-used~(\ref{basic.def.odr}, \ref{basic.stc.static}). @@ -6620,7 +6619,7 @@ \pnum It is \impldef{dynamic initialization of static inline variables before \tcode{main}} whether the dynamic initialization of a -non-local inline variable with static storage duration +non-block inline variable with static storage duration is sequenced before the first statement of \tcode{main} or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use @@ -6631,7 +6630,7 @@ \pnum It is \impldef{dynamic initialization of thread-local variables before entry} whether the dynamic initialization of a -non-local non-inline variable with thread storage duration +non-block non-inline variable with thread storage duration is sequenced before the first statement of the initial function of a thread or is deferred. If it is deferred, the initialization associated with the entity for thread \placeholder{t} @@ -6643,7 +6642,7 @@ \pnum If the initialization of -a non-local variable with static or thread storage duration +a non-block variable with static or thread storage duration exits via an exception, the function \tcode{std::terminate} is called\iref{except.terminate}.% \indextext{program!startup|)} @@ -6685,20 +6684,23 @@ If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized. For an object of array or class -type, all subobjects of that object are destroyed before any block-scope -object with static storage duration initialized during the construction +type, all subobjects of that object are destroyed before any block +variable with static storage duration initialized during the construction of the subobjects is destroyed. If the destruction of an object with static or thread storage duration exits via an exception, the function \tcode{std::terminate} is called\iref{except.terminate}. \pnum -If a function contains a block-scope object of static or thread storage duration that has been +If a function contains a block variable of static or thread storage duration that has been destroyed and the function is called during the destruction of an object with static or thread storage duration, the program has undefined behavior if the flow of control -passes through the definition of the previously destroyed block-scope object. Likewise, the -behavior is undefined if the block-scope object is used indirectly (i.e., through a -pointer) after its destruction. +passes through the definition of the previously destroyed block variable. +\begin{note} +Likewise, the behavior is undefined +if the block variable is used indirectly (e.g., through a pointer) +after its destruction. +\end{note} \pnum \indextext{\idxcode{atexit}}% From 8e6a8132cde086e4af0fb7a7aa5ed4fbfc7be57a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 18 Nov 2020 23:27:18 +0100 Subject: [PATCH 23/60] expr.prim --- source/expressions.tex | 252 ++++++++++++++++++++++++----------------- 1 file changed, 148 insertions(+), 104 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index aca6af59ff..ca5fd0784a 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1196,17 +1196,25 @@ \pnum \indextext{\idxcode{this}}% The keyword \tcode{this} names a pointer to the object for which a non-static member -function\iref{class.this} is invoked or a non-static data member's +function\iref{class.mfct.non-static} is invoked or a non-static data member's initializer\iref{class.mem} is evaluated. +\pnum +The \defnadj{current}{class} at a program point is +the class associated with the innermost class scope containing that point. +\begin{note} +A \grammarterm{lambda-expression} does not introduce a class scope. +\end{note} + \pnum If a declaration declares a member function or member function template of a class \tcode{X}, the expression \tcode{this} is a prvalue of type ``pointer to -\grammarterm{cv-qualifier-seq} \tcode{X}'' between the optional +\grammarterm{cv-qualifier-seq} \tcode{X}'' +wherever \tcode{X} is the current class +between the optional \grammarterm{cv-qualifier-seq} and the end of the \grammarterm{function-definition}, -\grammarterm{member-declarator}, or \grammarterm{declarator}. It shall not appear -before the optional \grammarterm{cv-qualifier-seq} and it shall not appear within -the declaration of a static member function (although its type and value category +\grammarterm{member-declarator}, or \grammarterm{declarator}. It shall not appear within +the declaration of a static member function of the current class (although its type and value category are defined within a static member function as they are within a non-static member function). \begin{note} @@ -1233,9 +1241,10 @@ \pnum Otherwise, if a \grammarterm{member-declarator} declares a non-static data member\iref{class.mem} of a class \tcode{X}, the expression \tcode{this} is -a prvalue of type ``pointer to \tcode{X}'' within the -optional default member initializer\iref{class.mem}. It shall not appear elsewhere -in the \grammarterm{member-declarator}. +a prvalue of type ``pointer to \tcode{X}'' +wherever \tcode{X} is the current class +within the +optional default member initializer\iref{class.mem}. \pnum The expression \tcode{this} shall not appear in any other context. @@ -1286,6 +1295,31 @@ operators\iref{expr.ref}. \end{note} +\pnum +If an \grammarterm{id-expression} $E$ denotes +a member $M$ of an anonymous union\iref{class.union.anon} $U$: +\begin{itemize} +\item +If $U$ is a non-static data member, +$E$ refers to $M$ as a member of the lookup context of the terminal name of $E$ (after any transformation to +a class member access expression\iref{class.mfct.non-static}). +\begin{example} +\tcode{o.x} is interpreted as \tcode{o.$u$.x}, +where $u$ names the anonymous union member. +\end{example} +\item +Otherwise, $E$ is interpreted as a class member access\iref{expr.ref} +that designates the member subobject $M$ of +the anonymous union variable for $U$. +\begin{note} +Under this interpretation, $E$ no longer denotes a non-static data member. +\end{note} +\begin{example} +\tcode{N::x} is interpreted as \tcode{N::$u$.x}, +where $u$ names the anonymous union variable. +\end{example} +\end{itemize} + \pnum An \grammarterm{id-expression} that denotes a non-static data member or non-static member function of a class can only be used: @@ -1388,7 +1422,20 @@ \end{note} \pnum -The result is the entity denoted by the identifier. +A \defnadj{component}{name} of an \grammarterm{unqualified-id} $U$ is $U$ +if it is a name or the component name of the \grammarterm{template-id} or \grammarterm{type-name} of $U$, if any. +\begin{note} +Other constructs that contain names to look up can have several component names +(\ref{expr.prim.id.qual}, \ref{dcl.type.simple}, \ref{dcl.type.elab}, +\ref{dcl.mptr}, \ref{namespace.udecl}, \ref{temp.param}, \ref{temp.names}, +\ref{temp.res}). +\end{note} +The \defnadj{terminal}{name} of a construct is +the component name of that construct that appears lexically last. + +\pnum +The result is the entity denoted by +the \grammarterm{unqualified-id}\iref{basic.lookup.unqual}. If the entity is a local entity and naming it from outside of an unevaluated operand within the scope where the \grammarterm{unqualified-id} appears @@ -1458,65 +1505,86 @@ \end{bnf} \pnum -The type denoted by a \grammarterm{decltype-specifier} in a -\grammarterm{nested-name-specifier} shall be a class or enumeration -type. +\indextext{name!component}% +The component names of a \grammarterm{qualified-id} are those of +its \grammarterm{nested-name-specifier} and \grammarterm{unqualified-id}. +The component names of a \grammarterm{nested-name-specifier} are +its \grammarterm{identifier} (if any) and those of its +\grammarterm{type-name}, +\grammarterm{namespace-name}, +\grammarterm{simple-template-id}, and/or +\grammarterm{nested-name-specifier}. \pnum -A \grammarterm{nested-name-specifier} that denotes a class, optionally -followed by the keyword \keyword{template}\iref{temp.names}, and then -followed by the name of a member of either that class\iref{class.mem} -or one of its base classes\iref{class.derived}, is a -\indextext{id!qualified}% -\grammarterm{qualified-id};~\ref{class.qual} describes name lookup for -class members that appear in \grammarterm{qualified-id}{s}. The result is the -member. The type of the result is the type of the member. The result is -an lvalue if the member is a static member function or a data member and a -prvalue otherwise. -\begin{note} -A class member can be referred to using a \grammarterm{qualified-id} at any -point in its potential scope\iref{basic.scope.class}. -\end{note} -Where -\grammarterm{type-name} \tcode{::\~}~\grammarterm{type-name} is used, -the two \grammarterm{type-name}{s} shall refer to the same type -(ignoring cv-qualifications); -this notation denotes the destructor of the type so named\iref{expr.prim.id.dtor}. -The \grammarterm{unqualified-id} in a \grammarterm{qualified-id} -shall not be of the form \tcode{\~}\grammarterm{decltype-specifier}. - -\pnum -The \grammarterm{nested-name-specifier} \tcode{::} names the global namespace. -A \grammarterm{nested-name-specifier} that names a -namespace\iref{basic.namespace}, optionally followed by the keyword -\keyword{template}\iref{temp.names}, and then followed by the name of a member -of that namespace (or the name of a member of a namespace made visible by a -\grammarterm{using-directive}), is a -\indextext{id!qualified}% -\grammarterm{qualified-id};~\ref{namespace.qual} describes name lookup for -namespace members that appear in \grammarterm{qualified-id}{s}. The result is -the member. The type of the result is the type of the member. The result -is an lvalue if the member is a function, a variable, or a structured binding\iref{dcl.struct.bind} and a prvalue otherwise. - -\pnum -A \grammarterm{nested-name-specifier} that denotes an -enumeration\iref{dcl.enum}, followed by the name of an -enumerator of that enumeration, is a \grammarterm{qualified-id} -that refers to the enumerator. The result is the enumerator. The type -of the result is the type of the enumeration. The result is a prvalue. - -\pnum -In a \grammarterm{qualified-id}, if the -\grammarterm{unqualified-id} -is a -\grammarterm{conversion-function-id}, its \grammarterm{conversion-type-id} -is first looked up in the class denoted by -the \grammarterm{nested-name-specifier} of the \grammarterm{qualified-id} and -the name, if found, is used. -Otherwise, it is looked up in the context in which -the entire \grammarterm{qualified-id} occurs. -In each of these lookups, only names that denote types or -templates whose specializations are types are considered. +A \grammarterm{nested-name-specifier} is \defn{declarative} if it is part of +\begin{itemize} +\item +a \grammarterm{class-head-name}, +\item +an \grammarterm{enum-head-name}, +\item +a \grammarterm{qualified-id} +that is the \grammarterm{id-expression} of a \grammarterm{declarator-id}, or +\item +a declarative \grammarterm{nested-name-specifier}. +\end{itemize} +A declarative \grammarterm{nested-name-specifier} +shall not have a \grammarterm{decltype-specifier}. +A declaration that uses a declarative \grammarterm{nested-name-specifier} +shall be a friend declaration or +inhabit a scope that contains the entity being redeclared or specialized. + +\pnum +The \grammarterm{nested-name-specifier} \tcode{::} nominates +the global namespace. +A \grammarterm{nested-name-specifier} with a \grammarterm{decltype-specifier} +nominates the type denoted by the \grammarterm{decltype-specifier}, +which shall be a class or enumeration type. +If a \grammarterm{nested-name-specifier} $N$ +is declarative and +has a \grammarterm{simple-template-id} with a template argument list $A$ +that involves a template parameter, +let $T$ be the template nominated by $N$ without $A$. +$T$ shall be a class template. +\begin{itemize} +\item +If $A$ is the template argument list\iref{temp.arg} of +the corresponding \grammarterm{template-head} $H$\iref{temp.mem}, +$N$ nominates the primary template of $T$; +$H$ shall be equivalent to +the \grammarterm{template-head} of $T$\iref{temp.over.link}. +\item +Otherwise, $N$ nominates the partial specialization\iref{temp.class.spec} of $T$ +whose template argument list is equivalent to $A$\iref{temp.over.link}; +the program is ill-formed if no such partial specialization exists. +\end{itemize} +Any other \grammarterm{nested-name-specifier} nominates +the entity denoted by its +\grammarterm{type-name}, +\grammarterm{namespace-name}, +\grammarterm{identifier}, or +\grammarterm{simple-template-id}. +If the \grammarterm{nested-name-specifier} is not declarative, +the entity shall not be a template. + +\pnum +A \grammarterm{qualified-id} shall not be of the form +\grammarterm{nested-name-specifier} \opt{\keyword{template}} \tcode{\~} +\grammarterm{decltype-specifier} +nor of the form +\grammarterm{decltype-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}. + +\pnum +The result of a \grammarterm{qualified-id} is +the entity it denotes\iref{basic.lookup.qual}. +The type of the expression is the type of the result. +The result is an lvalue if the member is +a function, +a variable, +a structured binding\iref{dcl.struct.bind}, +a static member function, or +a data member +and a prvalue otherwise. \rSec3[expr.prim.id.dtor]{Destruction} @@ -1727,11 +1795,6 @@ It is an immediate function\iref{dcl.constexpr} if the corresponding \grammarterm{lambda-expression}{'s} \grammarterm{parameter-declaration-clause} is followed by \tcode{consteval}. -\begin{note} -Names referenced in -the \grammarterm{lambda-declarator} are looked up in the context in which the -\grammarterm{lambda-expression} appears. -\end{note} \begin{example} \begin{codeblock} auto ID = [](auto a) { return a; }; @@ -1915,13 +1978,9 @@ \end{example} \pnum -The \grammarterm{lambda-expression}'s \grammarterm{compound-statement} yields the -\grammarterm{function-body}\iref{dcl.fct.def} of the function call operator, but for -purposes of name lookup\iref{basic.lookup}, determining the type and value of -\tcode{this}\iref{class.this} and transforming \grammarterm{id-expression}{s} -referring to non-static class members into class member access expressions using -\tcode{(*this)}~(\ref{class.mfct.non-static}), the \grammarterm{compound-statement} is -considered in the context of the \grammarterm{lambda-expression}. +The \grammarterm{lambda-expression}'s \grammarterm{compound-statement} yields +the \grammarterm{function-body}\iref{dcl.fct.def} of the function call operator, +but it is not within the scope of the closure type. \begin{example} \begin{codeblock} struct S1 { @@ -2054,9 +2113,8 @@ the corresponding class scope\iref{basic.scope.class}. \pnum -The \grammarterm{identifier} in a \grammarterm{simple-capture} is looked up using the -usual rules for unqualified name lookup\iref{basic.lookup.unqual}; each such lookup -shall find a local entity. +The \grammarterm{identifier} in a \grammarterm{simple-capture} +shall denote a local entity\iref{basic.lookup.unqual}. The \grammarterm{simple-capture}{s} \tcode{this} and \tcode{* this} denote the local entity \tcode{*this}. An entity that is designated by a @@ -2078,12 +2136,11 @@ \end{example} \pnum +An \grammarterm{init-capture} inhabits the scope of +the \grammarterm{lambda-expression}'s \grammarterm{compound-statement}. An \grammarterm{init-capture} without ellipsis -behaves as if it declares and explicitly captures a -variable of -the form ``\tcode{auto} \grammarterm{init-capture} \tcode{;}'' -whose scope is the \grammarterm{lambda-expression}'s -\grammarterm{compound-statement}, except that: +behaves as if it declares and explicitly captures a variable of +the form ``\tcode{auto} \grammarterm{init-capture} \tcode{;}'', except that: \begin{itemize} \item if the capture is by copy (see below), the non-static data member declared for the capture and the variable are treated as two different ways @@ -2191,8 +2248,8 @@ \pnum An entity is \defn{captured} if it is captured explicitly or implicitly. An entity -captured by a \grammarterm{lambda-expression} is odr-used\iref{basic.def.odr} in the scope -containing the \grammarterm{lambda-expression}. +captured by a \grammarterm{lambda-expression} is odr-used\iref{basic.def.odr} by +the \grammarterm{lambda-expression}. \begin{note} As a consequence, if a \grammarterm{lambda-expression} explicitly captures an entity that is not odr-usable, @@ -2415,10 +2472,8 @@ expansion\iref{temp.variadic}. \indextext{init-capture pack@\fakegrammarterm{init-capture} pack}% An \grammarterm{init-capture} containing an ellipsis is a pack -expansion that introduces an -\grammarterm{init-capture} pack\iref{temp.variadic} -whose scope is -the \grammarterm{lambda-expression}'s \grammarterm{compound-statement}. +expansion that declares an +\grammarterm{init-capture} pack\iref{temp.variadic}. \begin{example} \begin{codeblock} template @@ -2523,7 +2578,7 @@ \begin{bnf} \nontermdef{requirement-parameter-list}\br - \terminal{(} \opt{parameter-declaration-clause} \terminal{)} + \terminal{(} parameter-declaration-clause \terminal{)} \end{bnf} \begin{bnf} @@ -2580,9 +2635,6 @@ \grammarterm{parameter-declaration-clause}\iref{dcl.fct}. A local parameter of a \grammarterm{requires-expression} shall not have a default argument. -Each name introduced by a local parameter is in scope from the point -of its declaration until the closing brace of the -\grammarterm{requirement-body}. These parameters have no linkage, storage, or lifetime; they are only used as notation for the purpose of defining \grammarterm{requirement}s. The \grammarterm{parameter-declaration-clause} of a @@ -2597,14 +2649,6 @@ \end{codeblock} \end{example} -\pnum -\indextext{requirement}% -The \grammarterm{requirement-body} contains -a sequence of \grammarterm{requirement}s. -These \grammarterm{requirement}s may refer to local -parameters, template parameters, and any other declarations visible from the -enclosing context. - \pnum The substitution of template arguments into a \grammarterm{requires-expression} may result in the formation of invalid types or expressions in its From be747ecbdafcc644477e9e31eef8b1f9900186f3 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 19 Nov 2020 00:28:27 +0100 Subject: [PATCH 24/60] expr.* (rest) --- source/expressions.tex | 127 +++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 54 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index ca5fd0784a..24e15b54c6 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -3066,7 +3066,7 @@ \end{codeblock} \end{example} If the function is a non-static member -function, the \tcode{this} parameter of the function\iref{class.this} +function, the \tcode{this} parameter of the function\iref{expr.prim.this} is initialized with a pointer to the object of the call, converted as if by an explicit type conversion\iref{expr.cast}. \begin{note} @@ -3093,7 +3093,7 @@ The access of the constructor, conversion functions or destructor is checked at the point of call in the calling function. If a constructor or destructor for a function parameter throws an exception, the search -for a handler starts in the scope of the calling function; in +for a handler starts in the calling function; in particular, if the function called has a \grammarterm{function-try-block}\iref{except.pre} with a handler that could handle the exception, this handler is not considered. @@ -3287,7 +3287,7 @@ \indextext{arrow operator|see{operator, class member access}}% A postfix expression followed by a dot \tcode{.} or an arrow \tcode{->}, optionally followed by the keyword -\keyword{template}\iref{temp.names}, and then followed by an +\keyword{template}, and then followed by an \grammarterm{id-expression}, is a postfix expression. The postfix expression before the dot or arrow is evaluated; \begin{footnote} @@ -3300,6 +3300,13 @@ the result of that evaluation, together with the \grammarterm{id-expression}, determines the result of the entire postfix expression. +\begin{note} +If the keyword \keyword{template} is used, +the following unqualified name +is considered to refer to a template\iref{temp.names}. +If a \grammarterm{simple-template-id} results and is followed by a \tcode{::}, +the \grammarterm{id-expression} is a \grammarterm{qualified-id}. +\end{note} \pnum \indextext{type!incomplete}% @@ -3332,16 +3339,8 @@ The class type shall be complete unless the class member access appears in the definition of that class. \begin{note} -If the class is incomplete, -lookup in the complete class type is required to refer -to the same declaration\iref{basic.scope.class}. -\end{note} -The \grammarterm{id-expression} shall name a member of the class or of one of -its base classes. -\begin{note} -Because the name of a class is inserted in its class scope\iref{class}, -the name of a class is also considered a nested -member of that class. +The program is ill-formed if the result differs from that +when the class is complete\iref{class.member.lookup}. \end{note} \begin{note} \ref{basic.lookup.qual} describes how names are looked up after the @@ -3384,7 +3383,7 @@ \tcode{mutable} member, then the type of \tcode{E1.E2} is ``\cvqual{cq12} \cvqual{vq12} \tcode{T}''. -\item If \tcode{E2} is a (possibly overloaded) member function, +\item If \tcode{E2} is an overload set, function overload resolution\iref{over.match} is used to select the function to which \tcode{E2} refers. The type of \tcode{E1.E2} is the type of \tcode{E2} @@ -4360,9 +4359,9 @@ \pnum \indextext{overloaded function!address of}% \begin{note} -The address of an overloaded function\iref{over} can be taken -only in a context that uniquely determines which version of the -overloaded function is referred to (see~\ref{over.over}). +The address of an overload set\iref{over} can be taken +only in a context that uniquely determines +which function is referred to (see~\ref{over.over}). Since the context might determine whether the operand is a static or non-static member function, the context can also affect whether the expression has type ``pointer to function'' or ``pointer to member @@ -4474,7 +4473,7 @@ An \grammarterm{await-expression} shall not appear in a default argument\iref{dcl.fct.default}. An \grammarterm{await-expression} shall not appear in the initializer of -a block-scope variable with static or thread storage duration. +a block variable with static or thread storage duration. A context within a function where an \grammarterm{await-expression} can appear is called a \term{suspension context} of the function. @@ -4488,14 +4487,14 @@ object\iref{dcl.fct.def.coroutine} of the enclosing coroutine and \tcode{P} is the type of that object. -\item \placeholder{a} is the \grammarterm{cast-expression} if +\item Unless the \grammarterm{await-expression} was implicitly produced by a \grammarterm{yield-expression}\iref{expr.yield}, an initial suspend point, -or a final suspend point\iref{dcl.fct.def.coroutine}. -Otherwise, the \grammarterm{unqualified-id} \tcode{await_transform} is -looked up within the scope of \tcode{P} by class member access -lookup\iref{basic.lookup.qual}, -and if this lookup finds at least one declaration, then \placeholder{a} is +or a final suspend point\iref{dcl.fct.def.coroutine}, +a search is performed for the name \tcode{await_transform} +in the scope of \tcode{P} \iref{class.member.lookup}. +If this search is performed and finds at least one declaration, +then \placeholder{a} is \mbox{\placeholder{p}\tcode{.await_transform(}\grammarterm{cast-expression}\tcode{)}}; otherwise, \placeholder{a} is the \grammarterm{cast-expression}. @@ -5040,13 +5039,14 @@ \pnum \indextext{operator!scope resolution}% -If the \grammarterm{new-expression} begins with a unary \tcode{::} -operator, the allocation function's name is looked up in the global -scope. Otherwise, if the allocated type is a class type \tcode{T} or -array thereof, the allocation function's name is looked up in the scope -of \tcode{T}. If this lookup fails to find the name, or if the allocated -type is not a class type, the allocation function's name is looked up in -the global scope. +If the \grammarterm{new-expression} +does not begin with a unary \tcode{::} operator and +the allocated type is a class type \tcode{T} or array thereof, +a search is performed for the allocation function's name in the scope +of \tcode{T}\iref{class.member.lookup}. +Otherwise, or if nothing is found, +the allocation function's name is looked up by +searching for it in the global scope. \pnum An implementation is allowed to omit a call to a replaceable global allocation @@ -5280,7 +5280,7 @@ \pnum If the \grammarterm{new-expression} creates an object or an array of objects of class type, access and ambiguity control are done for the -allocation function, the deallocation function\iref{class.free}, and +allocation function, the deallocation function\iref{basic.stc.dynamic.deallocation}, and the constructor\iref{class.ctor} selected for the initialization (if any). If the \grammarterm{new-expression} creates an array of objects of class type, the destructor is potentially @@ -5307,13 +5307,14 @@ \end{note} \pnum -If the \grammarterm{new-expression} begins with a unary \tcode{::} -operator, the deallocation function's name is looked up in the global -scope. Otherwise, if the allocated type is a class type \tcode{T} or an -array thereof, the deallocation function's name is looked up in the -scope of \tcode{T}. If this lookup fails to find the name, or if the -allocated type is not a class type or array thereof, the deallocation -function's name is looked up in the global scope. +If the \grammarterm{new-expression} does not begin with +a unary \tcode{::} operator and +the allocated type is a class type \tcode{T} or an array thereof, +a search is performed for the deallocation function's name +in the scope of \tcode{T}. +Otherwise, or if nothing is found, +the deallocation function's name is looked up by +searching for it in the global scope. \pnum A declaration of a placement deallocation function matches the @@ -5502,27 +5503,45 @@ called as described above. \pnum +If a deallocation function is called, +it is \tcode{operator delete} for a single-object delete expression or +\tcode{operator delete[]} for an array delete expression. \begin{note} -An implementation provides default definitions of the global -deallocation functions \tcode{operator delete} for -non-arrays\iref{new.delete.single} and \indextext{\idxcode{operator delete}}% -\tcode{operator delete[]} for arrays\iref{new.delete.array}. A \Cpp{} -program can provide alternative definitions of these +An implementation provides default definitions of the global +deallocation functions (\ref{new.delete.single}, \ref{new.delete.array}). +A \Cpp{} program can provide alternative definitions of these functions\iref{replacement.functions}, and/or class-specific versions\iref{class.free}. \end{note} \pnum -When the keyword \tcode{delete} in a \grammarterm{delete-expression} is -preceded by the unary \tcode{::} operator, the deallocation function's name is looked -up in global scope. Otherwise, the lookup considers class-specific deallocation -functions\iref{class.free}. If no class-specific deallocation function is found, -the deallocation function's name is looked up in global scope. +If the keyword \tcode{delete} in a \grammarterm{delete-expression} +is not preceded by the unary \tcode{::} operator and the type of the operand is +a pointer to a (possibly cv-qualified) class type \tcode{T}: +\begin{itemize} +\item +If \tcode{T} has a virtual destructor, +the deallocation function is the one selected at the point of definition of +the dynamic type's virtual destructor\iref{class.dtor}. +\item +Otherwise, +a search is performed for the deallocation function's name +in the scope of \tcode{T}. +\end{itemize} +Otherwise, or if nothing is found, +the deallocation function's name is looked up by +searching for it in the global scope. +In any case, any declarations +other than of usual deallocation functions\iref{basic.stc.dynamic.deallocation} +are discarded. +\begin{note} +If only a placement deallocation function is found in a class, +the program is ill-formed because the lookup set is empty\iref{basic.lookup}. +\end{note} \pnum -If deallocation function lookup finds more than one usual -deallocation function, +If more than one deallocation function is found, the function to be called is selected as follows: \begin{itemize} \item @@ -5539,7 +5558,7 @@ If exactly one function remains, that function is selected and the selection process terminates. \item -If the deallocation functions have class scope, +If the deallocation functions belong to a class scope, the one without a parameter of type \tcode{std::size_t} is selected. \item If the type is complete @@ -7433,7 +7452,7 @@ \pnum An expression or conversion is in an \defn{immediate function context} if it is potentially evaluated and -its innermost non-block scope is +its innermost enclosing non-block scope is a function parameter scope of an immediate function. An expression or conversion is an \defn{immediate invocation} if it is a potentially-evaluated explicit or implicit invocation of @@ -7525,7 +7544,7 @@ that is potentially constant evaluated, or \item -a variable whose name appears as a potentially constant evaluated expression +a variable named by a potentially constant evaluated expression that is either a constexpr variable or is of non-volatile const-qualified integral type or of reference type. \end{itemize} From 09cc3716da587e450b5f3c1e557ae205482cfb3b Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 20 Nov 2020 00:12:07 +0100 Subject: [PATCH 25/60] stmt.stmt --- source/statements.tex | 201 ++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 136 deletions(-) diff --git a/source/statements.tex b/source/statements.tex index 9a1262aea3..9576e40749 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -87,18 +87,6 @@ the \grammarterm{decl-specifier-seq}, the type of the identifier being declared is deduced from the initializer as described in~\ref{dcl.spec.auto}. -\pnum -\indextext{statement!declaration in \tcode{if}}% -\indextext{statement!declaration in \tcode{switch}}% -\begin{note} -A name introduced in a \grammarterm{selection-statement} or -\grammarterm{iteration-statement} outside of any substatement -is in scope from its point of -declaration until the end of the statement's substatements. -Such a name cannot be redeclared in the outermost block of -any of the substatements\iref{basic.scope.block}. -\end{note} - \pnum The value of a \grammarterm{condition} that is an initialized declaration in a statement other than a \tcode{switch} statement is the value of the @@ -119,9 +107,9 @@ ``the condition'' where the usage is unambiguous. \pnum -If a \grammarterm{condition} can be syntactically resolved as either an -expression or the declaration of a block-scope name, it is interpreted as a -declaration. +If a \grammarterm{condition} can be syntactically resolved +as either an expression or a declaration, +it is interpreted as the latter. \pnum In the \grammarterm{decl-specifier-seq} of a \grammarterm{condition}, each @@ -143,23 +131,14 @@ \opt{attribute-specifier-seq} \keyword{default} \terminal{:} statement \end{bnf} -The optional \grammarterm{attribute-specifier-seq} appertains to the label. An -\defn{identifier label} declares the identifier. The only use of an -identifier label is as the target of a +The optional \grammarterm{attribute-specifier-seq} appertains to the label. \indextext{statement!\idxcode{goto}}% -\tcode{goto}. +The only use of a label with an \grammarterm{identifier} is +as the target of a \tcode{goto}. \indextext{label!scope of}% -The scope of a label is the function in which it appears. Labels shall -not be redeclared within a function. A label can be used in a -\tcode{goto} statement before its declaration. -\indextext{name space!label}% -Labels have their own name space and do not interfere with other -identifiers. -\begin{note} -A label can have the same name as another declaration in the same scope or a -\grammarterm{template-parameter} from an enclosing scope. Unqualified name -lookup\iref{basic.lookup.unqual} ignores labels. -\end{note} +No two labels in a function shall have the same \grammarterm{identifier}. +A label can be used in a \tcode{goto} statement +before its introduction by a \grammarterm{labeled-statement}. \pnum \indextext{label!\idxcode{case}}% @@ -213,8 +192,8 @@ statement-seq statement \end{bnf} -A compound statement defines a block scope\iref{basic.scope}. \begin{note} +A compound statement defines a block scope\iref{basic.scope}. A declaration is a \grammarterm{statement}\iref{stmt.dcl}. \end{note} @@ -243,26 +222,11 @@ \pnum \indextext{scope!\idxgram{selection-statement}}% -The substatement in a \grammarterm{selection-statement} (each substatement, -in the \tcode{else} form of the \tcode{if} statement) implicitly defines -a block scope\iref{basic.scope}. If the substatement in a -\grammarterm{selection-statement} is a single statement and not a -\grammarterm{compound-statement}, it is as if it was rewritten to be a -\grammarterm{compound-statement} containing the original substatement. -\begin{example} -\begin{codeblock} -if (x) - int i; -\end{codeblock} -can be equivalently rewritten as -\begin{codeblock} -if (x) { - int i; -} -\end{codeblock} - -Thus after the \tcode{if} statement, \tcode{i} is no longer in scope. -\end{example} +\begin{note} +Each \grammarterm{selection-statement} and +each substatement of a \grammarterm{selection-statement} +has a block scope\iref{basic.scope.block}. +\end{note} \rSec2[stmt.if]{The \tcode{if} statement}% \indextext{statement!\idxcode{if}} @@ -348,9 +312,8 @@ \bnfindent \keyword{if} \opt{\keyword{constexpr}} \terminal{(} condition \terminal{)} statement \keyword{else} statement\br \terminal{\}} \end{ncsimplebnf} -except that names declared in the \grammarterm{init-statement} are in -the same declarative region as those declared in the -\grammarterm{condition}. +except that the \grammarterm{init-statement} is +in the same scope as the \grammarterm{condition}. \rSec2[stmt.switch]{The \tcode{switch} statement}% \indextext{statement!\idxcode{switch}} @@ -429,9 +392,9 @@ \bnfindent \keyword{switch} \terminal{(} condition \terminal{)} statement\br \terminal{\}} \end{ncsimplebnf} -except that names declared in the \grammarterm{init-statement} are in -the same declarative region as those declared in the -\grammarterm{condition}.% +except that the \grammarterm{init-statement} is in +the same scope as the \grammarterm{condition}. + \indextext{statement!selection|)} \rSec1[stmt.iter]{Iteration statements}% @@ -491,25 +454,9 @@ int i; } \end{codeblock} - Thus after the \tcode{while} statement, \tcode{i} is no longer in scope. \end{example} -\pnum -If a name introduced in an -\grammarterm{init-statement} or \grammarterm{for-range-declaration} -is redeclared in the outermost block of the substatement, the program is ill-formed. -\begin{example} -\begin{codeblock} -void f() { - for (int i = 0; i < 10; ++i) - int i = 0; // error: redeclaration - for (int i : { 1, 2, 3 }) - int i = 1; // error: redeclaration -} -\end{codeblock} -\end{example} - \rSec2[stmt.while]{The \tcode{while} statement}% \indextext{statement!\idxcode{while}} @@ -521,10 +468,7 @@ \pnum \indextext{statement!declaration in \tcode{while}}% -When the condition of a \tcode{while} statement is a declaration, the scope of -the variable that is declared extends from its point of -declaration\iref{basic.scope.pdecl} to the end of the \tcode{while} -\grammarterm{statement}. A \tcode{while} statement is equivalent to +A \tcode{while} statement is equivalent to \begin{ncsimplebnf} \exposid{label} \terminal{:}\br \terminal{\{}\br @@ -587,9 +531,9 @@ \bnfindent \terminal{\}}\br \terminal{\}} \end{ncsimplebnf} -except that names declared in the \grammarterm{init-statement} are in -the same declarative region as those declared in the -\grammarterm{condition}, and except that a +except that the \grammarterm{init-statement} is +in the same scope as the \grammarterm{condition}, and +except that a \indextext{statement!\tcode{continue} in \tcode{for}}% \tcode{continue} in \grammarterm{statement} (not enclosed in another iteration statement) will execute \grammarterm{expression} before @@ -609,12 +553,6 @@ makes the implied \tcode{while} clause equivalent to \tcode{while(true)}. -\pnum -\indextext{statement!declaration in \tcode{for}}% -\indextext{\idxcode{for}!scope of declaration in}% -If the \grammarterm{init-statement} is a declaration, the scope of the -name(s) declared extends to the end of the \tcode{for} statement. - \rSec2[stmt.ranged]{The range-based \tcode{for} statement}% \indextext{statement!range based for@range based \tcode{for}} @@ -657,18 +595,19 @@ the array bound. If \tcode{R} is an array of unknown bound or an array of incomplete type, the program is ill-formed; -\item if the \grammarterm{for-range-initializer} is an expression of -class type \tcode{C}, the \grammarterm{unqualified-id}{s} -\tcode{begin} and \tcode{end} are looked up in the scope of \tcode{C} -as if by class member access lookup\iref{basic.lookup.qual}, and if -both find at least one declaration, \exposid{begin-expr} and -\exposid{end-expr} are \tcode{\exposid{range}.begin()} and \tcode{\exposid{range}.end()}, +\item if the \grammarterm{for-range-initializer} is +an expression of class type \tcode{C} and +searches in the scope of \tcode{C}\iref{class.member.lookup} +for the names \tcode{begin} and \tcode{end} +each find at least one declaration, +\exposid{begin-expr} and \exposid{end-expr} are +\tcode{\exposid{range}.begin()} and \tcode{\exposid{range}.end()}, respectively; \item otherwise, \exposid{begin-expr} and \exposid{end-expr} are \tcode{begin(\exposid{range})} and \tcode{end(\exposid{range})}, respectively, -where \tcode{begin} and \tcode{end} are looked -up in the associated namespaces\iref{basic.lookup.argdep}. +where \tcode{begin} and \tcode{end} undergo +argument-dependent lookup\iref{basic.lookup.argdep}. \begin{note} Ordinary unqualified lookup\iref{basic.lookup.unqual} is not performed. @@ -718,20 +657,11 @@ \pnum \indextext{local variable!destruction of}% \indextext{scope!destructor and exit from}% +\begin{note} On exit from a scope (however accomplished), objects with automatic storage duration\iref{basic.stc.auto} that have been constructed in that scope are destroyed in the reverse order of their construction. -\begin{note} -For temporaries, -see~\ref{class.temporary}. -\end{note} -Transfer out of a loop, out of a block, or back -past -an initialized variable with automatic storage duration involves the -destruction of objects with automatic storage duration that are in -scope at the point transferred from but not at the point transferred to. -(See~\ref{stmt.dcl} for transfers into blocks). -\begin{note} +For temporaries, see~\ref{class.temporary}. However, the program can be terminated (by calling \indextext{\idxcode{exit}}% \indexlibraryglobal{exit}% @@ -929,46 +859,46 @@ \indextext{statement!declaration} \pnum -A declaration statement introduces one or more new identifiers into a +A declaration statement introduces one or more new names into a block; it has the form \begin{bnf} \nontermdef{declaration-statement}\br block-declaration \end{bnf} - +\begin{note} If an identifier introduced by a declaration was previously declared in an outer block, \indextext{declaration hiding|see{name hiding}}% \indextext{name hiding}% \indextext{block (statement)!structure}% -the outer declaration is hidden for the remainder of the block, after -which it resumes its force. +the outer declaration is hidden +for the remainder of the block\iref{basic.lookup.unqual}, +after which it resumes its force. +\end{note} \pnum \indextext{block (statement)!initialization in}% \indextext{initialization!automatic}% -Variables with automatic storage duration\iref{basic.stc.auto} are -initialized each time their \grammarterm{declaration-statement} is executed. -\indextext{local variable!destruction of}% -Variables with automatic storage duration declared in the block are -destroyed on exit from the block\iref{stmt.jump}. +A variable with automatic storage duration\iref{basic.stc.auto} +is \defn{active} everywhere in the scope to which it belongs +after its \grammarterm{init-declarator}. \pnum \indextext{initialization!jump past}% \indextext{\idxcode{goto}!initialization and}% -It is possible to transfer into a block, but not in a way that bypasses -declarations with initialization (including ones in \grammarterm{condition}s -and \grammarterm{init-statement}s). -A program that jumps +Upon each transfer of control (including sequential execution of statements) +within a function from point $P$ to point $Q$, +all variables that are active at $P$ and not at $Q$ are destroyed in the reverse order of their construction. +Then, all variables that are active at $Q$ but not at $P$ are initialized in declaration order; +unless all such variables have vacuous initialization\iref{basic.life}, +the transfer of control shall not be a jump \begin{footnote} The transfer from the condition of a \tcode{switch} statement to a \tcode{case} label is considered a jump in this respect. -\end{footnote} -from a point where a variable with automatic storage duration is -not in scope to a point where it is in scope is ill-formed unless -the variable has vacuous initialization\iref{basic.life}. -In such a case, the variables with vacuous initialization -are constructed in the order of their declaration. +\end{footnote}. +When a \grammarterm{declaration-statement} is executed, +$P$ and $Q$ are the points immediately before and after it; +when a function returns, $Q$ is after its body. \begin{example} \begin{codeblock} void f() { @@ -990,7 +920,7 @@ \indextext{initialization!dynamic block-scope}% \indextext{initialization!local \tcode{static}}% \indextext{initialization!local \tcode{thread_local}}% -Dynamic initialization of a block-scope variable with +Dynamic initialization of a block variable with static storage duration\iref{basic.stc.static} or thread storage duration\iref{basic.stc.thread} is performed the first time control passes through its declaration; such a variable is @@ -1022,11 +952,11 @@ \pnum \indextext{\idxcode{static}!destruction of local}% -A block-scope object with static or thread storage duration will be -destroyed if and only if it was constructed. +An object associated with +a block variable with static or thread storage duration +will be destroyed if and only if it was constructed. \begin{note} -\ref{basic.start.term} describes the order in which block-scope objects with -static and thread storage duration are destroyed. +\ref{basic.start.term} describes the order in which such objects are destroyed. \end{note} \rSec1[stmt.ambig]{Ambiguity resolution}% @@ -1096,13 +1026,12 @@ disambiguation. Class templates are instantiated as necessary to determine if a qualified name is a \grammarterm{type-name}. Disambiguation precedes parsing, and a statement disambiguated as a declaration may be -an ill-formed declaration. If, during parsing, a name in a template -parameter is bound differently than it would be bound during a trial -parse, the program is ill-formed. No diagnostic is required. -\begin{note} -This can occur only when the name is declared earlier in the -declaration. -\end{note} +an ill-formed declaration. +If, during parsing, lookup finds +that a name in a template argument is bound to +(part of) the declaration being parsed, +the program is ill-formed. +No diagnostic is required. \begin{example} \begin{codeblock} struct T1 { From 646674c519ebbefccaaa755a7f5477e1fb70caee Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 20 Nov 2020 00:31:18 +0100 Subject: [PATCH 26/60] dcl.dcl first part --- source/declarations.tex | 144 ++++++++++------------------------------ 1 file changed, 36 insertions(+), 108 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index b2e71964fc..3d3f078773 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -126,11 +126,8 @@ \pnum \indextext{declaration}% \indextext{scope}% -A declaration occurs in a scope\iref{basic.scope}; the scope rules are -summarized in~\ref{basic.lookup}. A declaration that declares a function -or defines a class, namespace, template, or function also has one or -more scopes nested within it. These nested scopes, in turn, can have -declarations nested within them. Unless otherwise stated, utterances in +Certain declarations contain one or more scopes\iref{basic.scope.scope}. +Unless otherwise stated, utterances in \ref{dcl.dcl} about components in, of, or contained by a declaration or subcomponent thereof refer only to those components of the declaration that are \emph{not} nested within scopes nested within @@ -141,19 +138,18 @@ \indextext{declarator}% In a \grammarterm{simple-declaration}, the optional \grammarterm{init-declarator-list} can be omitted only when declaring a -class\iref{class} or enumeration\iref{dcl.enum}, that is, +class\iref{class.pre} or enumeration\iref{dcl.enum}, that is, when the \grammarterm{decl-specifier-seq} contains either a \grammarterm{class-specifier}, an \grammarterm{elaborated-type-specifier} with a \grammarterm{class-key}\iref{class.name}, or an \grammarterm{enum-specifier}. In these cases and whenever a \grammarterm{class-specifier} or \grammarterm{enum-specifier} is present in the \grammarterm{decl-specifier-seq}, the identifiers in these specifiers -are among the names being declared by the declaration (as +are also declared (as \grammarterm{class-name}{s}, \grammarterm{enum-name}{s}, or \grammarterm{enumerator}{s}, depending on the syntax). In such cases, -the \grammarterm{decl-specifier-seq} shall introduce one or more names into -the program, or shall redeclare a name introduced by a previous -declaration. +the \grammarterm{decl-specifier-seq} shall (re)introduce one or more names into +the program. \begin{example} \begin{codeblock} enum { }; // error @@ -201,25 +197,30 @@ \grammarterm{assignment-expression} is of array or non-union class type. \pnum -Each \grammarterm{init-declarator} in the \grammarterm{init-declarator-list} -contains exactly one \grammarterm{declarator-id}, which is the name -declared by that \grammarterm{init-declarator} and hence one of the names -declared by the declaration. The -\grammarterm{defining-type-specifier}{s}\iref{dcl.type} in the -\grammarterm{decl-specifier-seq} and the recursive \grammarterm{declarator} -structure of the \grammarterm{init-declarator} describe a -type\iref{dcl.meaning}, which is then associated with the name being -declared by the \grammarterm{init-declarator}. +If a \grammarterm{declarator-id} is a name, the +\grammarterm{init-declarator} and (hence) the declaration introduce that name. +\begin{note} +Otherwise, the \grammarterm{declarator-id} is +a \grammarterm{qualified-id} or +names a destructor or +its \grammarterm{unqualified-id} is a \grammarterm{template-id} and +no name is introduced. +\end{note} +The \grammarterm{defining-type-specifier}{s}\iref{dcl.type} in +the \grammarterm{decl-specifier-seq} and +the recursive \grammarterm{declarator} structure +describe a type\iref{dcl.meaning}, +which is then associated with the \grammarterm{declarator-id}. \pnum If the \grammarterm{decl-specifier-seq} contains the \tcode{typedef} -specifier, the declaration is called a \defnx{typedef declaration}{declaration!typedef} and the name -of each \grammarterm{init-declarator} -is declared to be a \grammarterm{typedef-name}, synonymous with its +specifier, the declaration is called a \defnx{typedef declaration}{declaration!typedef}, +each \grammarterm{declarator-id} must be an \grammarterm{identifier} +and is declared to be a \grammarterm{typedef-name}, synonymous with its associated type\iref{dcl.typedef}. If the \grammarterm{decl-specifier-seq} contains no \tcode{typedef} specifier, the declaration is called a \defnx{function declaration}{declaration!function} if -the type associated with the name is a function type\iref{dcl.fct} and +the type associated with a \grammarterm{declarator-id} is a function type\iref{dcl.fct} and an \defnx{object declaration}{declaration!object} otherwise. \pnum @@ -354,10 +355,7 @@ \tcode{typedef} specifier in the same \grammarterm{decl-specifier-seq} and the \grammarterm{init-declarator-list} or \grammarterm{member-declarator-list} of the declaration shall not be -empty (except for an anonymous union declared in a named namespace or in the -global namespace, which shall be declared -\indextext{specifier!\idxcode{static}}% -\tcode{static}\iref{class.union.anon}). The +empty (except for an anonymous union declared in a namespace scope\iref{class.union.anon}). The \grammarterm{storage-class-specifier} applies to the name declared by each \grammarterm{init-declarator} in the list and not to any names declared by other specifiers. @@ -421,10 +419,11 @@ \end{note} \pnum -The linkages implied by successive declarations for a given entity shall -agree. That is, within a given scope, each declaration declaring the -same variable name or the same overloading of a function name shall imply -the same linkage. +All declarations for a given entity shall give its name the same linkage. +\begin{note} +The linkage given by some declarations is affected by previous declarations. +Overloads are distinct entities. +\end{note} \begin{example} \begin{codeblock} static char* f(); // \tcode{f()} has internal linkage @@ -599,7 +598,7 @@ \pnum A \grammarterm{typedef-name} can also be introduced by an \grammarterm{alias-declaration}. The \grammarterm{identifier} following the -\tcode{using} keyword becomes a \grammarterm{typedef-name} +\tcode{using} keyword is not looked up; it becomes a \grammarterm{typedef-name} and the optional \grammarterm{attribute-specifier-seq} following the \grammarterm{identifier} appertains to that \grammarterm{typedef-name}. Such a \grammarterm{typedef-name} has the same @@ -618,75 +617,6 @@ a class or enumeration if the \grammarterm{alias-declaration} is the \grammarterm{declaration} of a \grammarterm{template-declaration}. -\pnum -\indextext{redefinition!\idxcode{typedef}}% -In a given non-class scope, a \tcode{typedef} specifier can be used to -redeclare the name of any type declared in that scope to refer to the -type to which it already refers. -\begin{example} -\begin{codeblock} -typedef struct s { @\commentellip@ } s; -typedef int I; -typedef int I; -typedef I I; -\end{codeblock} -\end{example} - -\pnum -In a given class scope, a \tcode{typedef} specifier can be used to -redeclare any \grammarterm{class-name} declared in that scope that is not -also a \grammarterm{typedef-name} to refer to the type to which it already -refers. -\begin{example} -\begin{codeblock} -struct S { - typedef struct A { } A; // OK - typedef struct B B; // OK - typedef A A; // error -}; -\end{codeblock} -\end{example} - -\pnum -If a \tcode{typedef} specifier is used to redeclare in a given scope an -entity that can be referenced using an \grammarterm{elaborated-type-specifier}, -the entity can continue to be referenced by an -\grammarterm{elaborated-type-specifier} or as an enumeration or class name -in an enumeration or class definition respectively. -\begin{example} -\begin{codeblock} -struct S; -typedef struct S S; -int main() { - struct S* p; // OK -} -struct S { }; // OK -\end{codeblock} -\end{example} - -\pnum -In a given scope, a \tcode{typedef} specifier shall not be used to -redeclare the name of any type declared in that scope to refer to a -different type. -\begin{example} -\begin{codeblock} -class complex { @\commentellip@ }; -typedef int complex; // error: redefinition -\end{codeblock} -\end{example} - -\pnum -Similarly, in a given scope, a class or enumeration shall not be -declared with the same name as a \grammarterm{typedef-name} that is -declared in that scope and refers to a type other than the class or -enumeration itself. -\begin{example} -\begin{codeblock} -typedef int complex; -class complex { @\commentellip@ }; // error: redefinition -\end{codeblock} -\end{example} - \pnum \indextext{class name!\idxcode{typedef}}% A \grammarterm{simple-template-id} is only a \grammarterm{typedef-name} @@ -1097,13 +1027,11 @@ \begin{note} An inline function or variable with external or module linkage -has the same address in all translation units. -A \tcode{static} local variable in an inline -function with external or module linkage -always refers to the same object. -A type defined within the body of an inline -function with external or module linkage is the -same type in every translation unit. +can be defined in multiple translation units\iref{basic.def.odr}, +but is one entity with one address. +A type or \tcode{static} variable +defined in the body of such a function +is therefore a single entity. \end{note} \pnum From 25c38432114d4b87b8594e1c60c4a136bfd53e48 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 20 Nov 2020 20:18:53 +0100 Subject: [PATCH 27/60] [dcl.pre] Turn 'must' into a note. --- source/declarations.tex | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index 3d3f078773..b866d28d59 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -214,10 +214,15 @@ \pnum If the \grammarterm{decl-specifier-seq} contains the \tcode{typedef} -specifier, the declaration is called a \defnx{typedef declaration}{declaration!typedef}, -each \grammarterm{declarator-id} must be an \grammarterm{identifier} -and is declared to be a \grammarterm{typedef-name}, synonymous with its -associated type\iref{dcl.typedef}. If the +specifier, the declaration is called a \defnx{typedef declaration}{declaration!typedef} +and each \grammarterm{declarator-id} +is declared to be a \grammarterm{typedef-name}, synonymous with its +associated type\iref{dcl.typedef}. +\begin{note} +Such a \grammarterm{declarator-id} is an \grammarterm{identifier} +(\ref{class.conv.fct}). +\end{note} +If the \grammarterm{decl-specifier-seq} contains no \tcode{typedef} specifier, the declaration is called a \defnx{function declaration}{declaration!function} if the type associated with a \grammarterm{declarator-id} is a function type\iref{dcl.fct} and From ecfd378e9d09feb63c5283291eb8711cce15ef05 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 20 Nov 2020 22:33:48 +0100 Subject: [PATCH 28/60] safety --- source/declarations.tex | 565 ++++++++++++++++++++++++---------------- 1 file changed, 339 insertions(+), 226 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index b866d28d59..adc4f335f9 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -1292,6 +1292,17 @@ typedef-name \end{bnf} +\pnum +\indextext{component name} +The component names of a \grammarterm{simple-type-specifier} are those of its +\grammarterm{nested-name-specifier}, +\grammarterm{type-name}, +\grammarterm{simple-template-id}, +\grammarterm{template-name}, and/or +\grammarterm{type-constraint} +(if it is a \grammarterm{placeholder-type-specifier}). +The component name of a \grammarterm{type-name} is the first name in it. + \pnum \indextext{type specifier!\idxcode{char}}% \indextext{type specifier!\idxcode{char8_t}}% @@ -1419,11 +1430,16 @@ \keyword{enum} \opt{nested-name-specifier} identifier \end{bnf} +\pnum +\indextext{component name}% +The component names of an \grammarterm{elaborated-type-specifier} are +its \grammarterm{identifier} (if any) and +those of its \grammarterm{nested-name-specifier} and +\grammarterm{simple-template-id} (if any). + \pnum \indextext{class name!elaborated}% \indextext{name!elaborated!\idxcode{enum}}% -An \grammarterm{attribute-specifier-seq} shall not appear in an \grammarterm{elaborated-type-specifier} -unless the latter is the sole constituent of a declaration. If an \grammarterm{elaborated-type-specifier} is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit specialization\iref{temp.expl.spec}, an explicit @@ -1432,21 +1448,50 @@ \begin{ncsimplebnf} class-key \opt{attribute-specifier-seq} identifier \terminal{;}\br -\keyword{friend} class-key \terminal{\opt{::}} identifier \terminal{;}\br -\keyword{friend} class-key \terminal{\opt{::}} simple-template-id \terminal{;}\br -\keyword{friend} class-key nested-name-specifier identifier \terminal{;}\br -\keyword{friend} class-key nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{;} +class-key \opt{attribute-specifier-seq} simple-template-id \terminal{;} \end{ncsimplebnf} -In the first case, the \grammarterm{attribute-specifier-seq}, if any, appertains -to the class being declared; the attributes in the -\grammarterm{attribute-specifier-seq} are thereafter considered attributes of -the class whenever it is named. +In the first case, +it declares the \grammarterm{identifier} as a \grammarterm{class-name}. +The second case shall appear only +in an \grammarterm{explicit-specialization}\iref{temp.expl.spec} or +in a \grammarterm{template-declaration} +(where it declares a partial specialization\iref{temp.decls}). +The \grammarterm{attribute-specifier-seq}, if any, appertains +to the class or template being declared. + +\pnum +Otherwise, the \grammarterm{elaborated-type-specifier} shall not have +an \grammarterm{attribute-specifier-seq}. +If it contains a \grammarterm{identifier} +but no \grammarterm{nested-name-specifier} and +(unqualified) lookup for the \grammarterm{identifier} finds nothing, +it shall not be introduced by the \keyword{enum} keyword and +declares the \grammarterm{identifier} as a \grammarterm{class-name}. +Its target scope is the nearest enclosing namespace or block scope. + +\pnum +If it appears with the \keyword{friend} specifier as an entire declaration, +the declaration shall have one of the following forms: +\begin{ncsimplebnf} +\keyword{friend} class-key \opt{nested-name-specifier} identifier \terminal{;}\br +\keyword{friend} class-key simple-template-id \terminal{;}\br +\keyword{friend} class-key nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{;} +\end{ncsimplebnf} +Any unqualified lookup for the \grammarterm{identifier} (in the first case) +does not consider scopes that contain the target scope; no name is bound. +\begin{note} +A \grammarterm{using-directive} in the target scope is ignored +if it refers to a namespace not contained by that scope. +\ref{basic.lookup.elab} describes how name lookup proceeds +in an \grammarterm{elaborated-type-specifier}. +\end{note} \pnum \begin{note} -\ref{basic.lookup.elab} describes how name lookup proceeds for the -\grammarterm{identifier} in an \grammarterm{elaborated-type-specifier}. +An \grammarterm{elaborated-type-specifier} can be used to refer to +a previously declared \grammarterm{class-name} or \grammarterm{enum-name} +even if the name has been hidden by a non-type declaration. \end{note} If the \grammarterm{identifier} or \grammarterm{simple-template-id} resolves to a \grammarterm{class-name} or @@ -1517,9 +1562,8 @@ an unparenthesized class member access\iref{expr.ref}, \tcode{decltype($E$)} is the -type of the entity named by $E$. If there is no such entity, or -if $E$ names a set of overloaded functions, the program is -ill-formed; +type of the entity named by $E$. +If there is no such entity, the program is ill-formed; \item otherwise, if $E$ is an xvalue, \tcode{decltype($E$)} is \tcode{T\&\&}, where \tcode{T} is the type @@ -1739,8 +1783,8 @@ \end{note} \pnum -If the name of an entity with an undeduced placeholder type appears in an -expression, the program is ill-formed. Once a +If a variable or function with an undeduced placeholder type is named by an +expression\iref{basic.def.odr}, the program is ill-formed. Once a non-discarded \tcode{return} statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other \tcode{return} statements. @@ -1780,19 +1824,17 @@ \end{example} \pnum -Redeclarations or specializations of a function or function template with a -declared return type that uses a placeholder type shall also use that -placeholder, not a deduced type. -Similarly, -redeclarations or specializations of a function or function template with a -declared return type that does not use a placeholder type -shall not use a placeholder. +If a function or function template has +a declared return type that uses a placeholder type, +redeclarations or specializations (respectively) of it shall use that +placeholder, not a deduced type; +otherwise, they shall not use a placeholder. \begin{example} \begin{codeblock} auto f(); auto f() { return 42; } // return type is \tcode{int} auto f(); // OK -int f(); // error: cannot be overloaded with \tcode{auto f()} +int f(); // error: \tcode{auto} and \tcode{int} don't match decltype(auto) f(); // error: \tcode{auto} and \tcode{decltype(auto)} don't match template auto g(T t) { return t; } // \#1 @@ -2041,7 +2083,7 @@ A declarator declares a single variable, function, or type, within a declaration. The \grammarterm{init-declarator-list} -appearing in a declaration +appearing in a \grammarterm{simple-declaration} is a comma-separated sequence of declarators, each of which can have an initializer. @@ -2058,34 +2100,28 @@ \end{bnf} \pnum -The three components of a -\grammarterm{simple-declaration} -are the -attributes\iref{dcl.attr}, the -specifiers -(\grammarterm{decl-specifier-seq}; -\ref{dcl.spec}) and the declarators -(\grammarterm{init-declarator-list}). -The specifiers indicate the type, storage class or other properties of -the entities being declared. -The declarators specify the names of these entities -and (optionally) modify the type of the specifiers with operators such as -\tcode{*} -(pointer -to) -and -\tcode{()} -(function returning). -Initial values can also be specified in a declarator; -initializers are discussed in~\ref{dcl.init} and~\ref{class.init}. +In all contexts, a \grammarterm{declarator} is interpreted as given below. +Where an \grammarterm{abstract-declarator} can be used (or omitted) +in place of a \grammarterm{declarator} (\ref{dcl.fct}, \ref{except.pre}), +it is as if a unique identifier were included in +the appropriate place\iref{dcl.name}. +The preceding specifiers indicate +the type, storage class or other properties +of the entity or entities being declared. +Each declarator specifies one entity and +(optionally) names it and/or +modifies the type of the specifiers with operators such as +\tcode{*} (pointer to) and \tcode{()} (function returning). +\begin{note} +An \grammarterm{init-declarator} can also specify an initializer\iref{dcl.init}. +\end{note} \pnum -Each -\grammarterm{init-declarator} -in a declaration is analyzed separately as if it was in a declaration by itself. +Each \grammarterm{init-declarator} or \grammarterm{member-declarator} +in a declaration is analyzed separately as if it were in a declaration by itself. \begin{note} A declaration with several declarators is usually equivalent to the corresponding -sequence of declarations each with a single declarator. That is +sequence of declarations each with a single declarator. That is, \begin{codeblock} T D1, D2, ... Dn; \end{codeblock} @@ -2094,7 +2130,8 @@ T D1; T D2; ... T Dn; \end{codeblock} where \tcode{T} is a \grammarterm{decl-specifier-seq} -and each \tcode{Di} is an \grammarterm{init-declarator}. +and each \tcode{Di} is +an \grammarterm{init-declarator} or \grammarterm{member-declarator}. One exception is when a name introduced by one of the \grammarterm{declarator}{s} hides a type name used by the \grammarterm{decl-specifier}{s}, so that when the same @@ -2419,44 +2456,151 @@ \pnum \indextext{declaration!type}% -A declarator contains exactly one -\grammarterm{declarator-id}; -it names the identifier that is declared. -An -\grammarterm{unqualified-id} -occurring in -a -\grammarterm{declarator-id} -shall be a simple -\grammarterm{identifier} -except for the declaration of some special functions~(\ref{class.ctor}, -\ref{class.conv}, \ref{class.dtor}, \ref{over.oper}) and -for the declaration of template specializations -or partial specializations\iref{temp.spec}. -When the -\grammarterm{declarator-id} -is qualified, the declaration shall refer to a previously declared member -of the class or namespace to which the qualifier refers (or, -in the case of a namespace, -of an element of the inline namespace -set of that namespace\iref{namespace.def}) or to a specialization thereof; the member -shall not merely have been introduced by a -\grammarterm{using-declaration} -in the scope of the class or namespace nominated by the -\grammarterm{nested-name-specifier} -of the -\grammarterm{declarator-id}. -The \grammarterm{nested-name-specifier} of a qualified \grammarterm{declarator-id} shall not -begin with a \grammarterm{decltype-specifier}. -\begin{note} -If the qualifier is the global -\tcode{::} -scope resolution operator, the -\grammarterm{declarator-id} -refers to a name declared in the global namespace scope. +A declarator contains exactly one \grammarterm{declarator-id}; +it names the entity that is declared. +If the \grammarterm{unqualified-id} occurring in a \grammarterm{declarator-id} +is a \grammarterm{template-id}, +the declarator shall appear in the \grammarterm{declaration} of a +\grammarterm{template-declaration}\iref{temp.decls}, +\grammarterm{explicit-specialization}\iref{temp.expl.spec}, or +\grammarterm{explicit-instantiation}\iref{temp.explicit}. +\begin{note} +An \grammarterm{unqualified-id} that is not an \grammarterm{identifier} +is used to declare certain functions +(\ref{class.conv.fct}, \ref{class.dtor}, \ref{over.oper}, \ref{over.literal}). \end{note} The optional \grammarterm{attribute-specifier-seq} following a \grammarterm{declarator-id} appertains to the entity that is declared. +\pnum +If the declaration is a friend declaration: +\begin{itemize} +\item +The declarator binds no name. +\item +If the \grammarterm{id-expression} $E$ in a \grammarterm{declarator-id} is +a \grammarterm{qualified-id} or a \grammarterm{template-id}: +\begin{itemize} + \item +If the friend declaration is not a template declaration, +then in the lookup for the terminal name of $E$: +\begin{itemize} + \item +if the \grammarterm{unqualified-id} in $E$ is a \grammarterm{template-id}, +all function declarations are discarded; + \item +otherwise, +if the \grammarterm{declarator} corresponds\iref{basic.scope.scope} to +any declaration found of a non-template function, +all function template declarations are discarded; + \item +each remaining function template is replaced with the specialization chosen by +deduction from the friend declaration\iref{temp.deduct.decl} or +discarded if deduction fails. +\end{itemize} + \item +The \grammarterm{declarator} shall correspond to +one or more declarations found by the lookup; +they shall all have the same target scope, and +the target scope of the declarator is that scope. +\end{itemize} +\item +Otherwise, the terminal name of $E$ is not looked up. +The declaration's target scope is the innermost enclosing namespace scope; +if the declaration is contained by a block scope, +it shall correspond to a declaration that inhabits the innermost block scope. +\end{itemize} + +\pnum +Otherwise: +\begin{itemize} +\item +If the \grammarterm{id-expression} in a \grammarterm{declarator-id} is +a \grammarterm{qualified-id} $Q$, +let $S$ be its lookup context\iref{basic.lookup.qual}; +the declaration shall inhabit a namespace scope. +\item +Otherwise, let $S$ be the entity associated with the scope inhabited by +the \grammarterm{declarator}. +\item +If the \grammarterm{declarator} declares +an explicit instantiation or a partial or explicit specialization, +the \grammarterm{declarator} binds no name. +If it declares a class member, +the terminal name of the \grammarterm{declarator-id} is not looked up; +otherwise, only those lookup results that are nominable in $S$ +are considered when identifying +any function template specialization being declared\iref{temp.deduct.decl}. +\begin{example} +\begin{codeblock} +namespace N { + inline namespace O { + template void f(T); // \#1 + template void g(T) {} + } + namespace P { + template void f(T*); // \#2, more specialized than \#1 + template int g; + } + using P::f,P::g; +} +template<> void N::f(int*) {} // OK: \#2 is not nominable +template void N::g(int); // error: lookup is ambiguous +\end{codeblock} +\end{example} +\item +Otherwise, +the terminal name of the \grammarterm{declarator-id} is not looked up. +If it is a qualified name, +the \grammarterm{declarator} shall correspond to +one or more declarations nominable in $S$; +all the declarations shall have the same target scope and +the target scope of the \grammarterm{declarator} is that scope. +\begin{example} +\begin{codeblock} +namespace Q { + namespace V { + void f(); + } + void V::f() { @\commentellip@ } // OK + void V::g() { @\commentellip@ } // error: \tcode{g()} is not yet a member of \tcode{V} + namespace V { + void g(); + } +} + +namespace R { + void Q::V::g() { @\commentellip@ } // error: \tcode{R} doesn't enclose \tcode{Q} +} +\end{codeblock} +\end{example} +\item +If the declaration inhabits a block scope $S$ and +declares a function\iref{dcl.fct} or uses the \keyword{extern} specifier, +the declaration shall not be attached to a named module\iref{module.unit}; +its target scope is the innermost enclosing namespace scope, +but the name is bound in $S$. +\begin{example} +\begin{codeblock} +namespace X { + void p() { + q(); // error: \tcode{q} not yet declared + extern void q(); // \tcode{q} is a member of namespace \tcode{X} + extern void r(); // \tcode{r} is a member of namespace \tcode{X} + } + + void middle() { + q(); // error: \tcode{q} not found + } + + void q() { @\commentellip@ } // definition of \tcode{X::q} +} + +void q() { @\commentellip@ } // some other, unrelated \tcode{q} +void X::r() { @\commentellip@ } // error: \tcode{r} cannot be declared by \grammarterm{qualified-id} +\end{codeblock} +\end{example} +\end{itemize} + \pnum A \tcode{static}, @@ -2472,12 +2616,12 @@ specifier or an \grammarterm{explicit-specifier} applies directly to each \grammarterm{declarator-id} -in an \grammarterm{init-declarator-list} or \grammarterm{member-declarator-list}; +in a declaration; the type specified for each \grammarterm{declarator-id} depends on both the \grammarterm{decl-specifier-seq} and its \grammarterm{declarator}. \pnum -Thus, a declaration of a particular identifier has the form +Thus, (for each declarator) a declaration has the form \begin{codeblock} T D \end{codeblock} @@ -2525,7 +2669,7 @@ \tcode{D} where \tcode{D} -is an unadorned identifier the type of this identifier is +is an unadorned name the type of the declared entity is ``\tcode{T}''. \pnum @@ -2564,12 +2708,12 @@ \begin{ncsimplebnf} \terminal{*} \opt{attribute-specifier-seq} \opt{cv-qualifier-seq} \terminal{D1} \end{ncsimplebnf} -and the type of the identifier in the declaration +and the type of the contained \grammarterm{declarator-id} in the declaration \tcode{T} \tcode{D1} is ``\placeholder{derived-declarator-type-list} \tcode{T}'', -then the type of the identifier of +the type of the \grammarterm{declarator-id} of \tcode{D} is ``\placeholder{derived-declarator-type-list} \grammarterm{cv-qualifier-seq} pointer to \tcode{T}''. @@ -2670,12 +2814,12 @@ \terminal{\&} \opt{attribute-specifier-seq} \terminal{D1}\br \terminal{\&\&} \opt{attribute-specifier-seq} \terminal{D1} \end{ncsimplebnf} -and the type of the identifier in the declaration +and the type of the contained \grammarterm{declarator-id} in the declaration \tcode{T} \tcode{D1} is ``\placeholder{derived-declarator-type-list} \tcode{T}'', -then the type of the identifier of +the type of the \grammarterm{declarator-id} in \tcode{D} is ``\placeholder{derived-declarator-type-list} reference to \tcode{T}''. @@ -2846,6 +2990,11 @@ \indextext{declarator!pointer-to-member}% \indextext{pointer to member}% +\pnum +\indextext{component name}% +The component names of a \grammarterm{ptr-operator} are +those of its \grammarterm{nested-name-specifier}, if any. + \pnum In a declaration \tcode{T} @@ -2859,12 +3008,12 @@ and the \grammarterm{nested-name-specifier} denotes a class, -and the type of the identifier in the declaration +and the type of the contained \grammarterm{declarator-id} in the declaration \tcode{T} \tcode{D1} is ``\placeholder{derived-declarator-type-list} \tcode{T}'', -then the type of the identifier of +the type of the \grammarterm{declarator-id} in \tcode{D} is ``\placeholder{derived-declarator-type-list} \grammarterm{cv-qualifier-seq} pointer to member of class \grammarterm{nested-name-specifier} of type @@ -3051,7 +3200,7 @@ and the type of the array is ``array of \tcode{N} \tcode{U}''. \pnum -Furthermore, if there is a preceding declaration of the entity in the same +Furthermore, if there is a reachable declaration of the entity that inhabits the same scope in which the bound was specified, an omitted array bound is taken to be the same as in that earlier declaration, and similarly for the definition of a static data member of a class. @@ -3332,10 +3481,7 @@ \indextext{type!function}% The type of a function is determined using the following rules. The type of each parameter (including function parameter packs) is -determined from its own -\grammarterm{decl-specifier-seq} -and -\grammarterm{declarator}. +determined from its own \grammarterm{parameter-declaration}\iref{dcl.decl}. After determining the type of each parameter, any parameter \indextext{array!parameter of type}% of type ``array of \tcode{T}'' or @@ -3356,6 +3502,21 @@ For example, \tcode{int(*)(const int p, decltype(p)*)} and \tcode{int(*)(int, const int*)} are identical types. \end{note} +\begin{example} +\begin{codeblock} +void f(char*); // \#1 +void f(char[]) {} // defines \#1 +void f(const char*) {} // OK: another overload +void f(char *const) {} // error: redefines \#1 + +void g(char(*)[2]); // \#2 +void g(char[3][2]) {} // defines \#2 +void g(char[3][3]) {} // OK: another overload + +void h(int x(const int)); // \#3 +void h(int (*)(int)) {} // defines \#3 +\end{codeblock} +\end{example} \pnum A function type with a \grammarterm{cv-qualifier-seq} or a @@ -3431,10 +3592,10 @@ \pnum \indextext{overloading}% +\begin{note} A single name can be used for several different functions in a single scope; this is function overloading\iref{over}. -All declarations for a function shall have equivalent return types, -parameter-type-lists, and \grammarterm{requires-clause}{s}\iref{temp.over.link}. +\end{note} \pnum \indextext{function return type|see{return type}}% @@ -3471,9 +3632,6 @@ In particular, parameter names are also optional in function definitions and names used for a parameter in different declarations and the definition of a function need not be the same. -If a parameter name is present in a function declaration that is not a definition, -it cannot be used outside of -its function declarator because that is the extent of its potential scope\iref{basic.scope.param}. \end{note} \pnum @@ -3747,8 +3905,8 @@ \pnum For non-template functions, default arguments can be added in later declarations of a -function in the same scope. -Declarations in different +function that inhabit the same scope. +Declarations that inhabit different scopes have completely distinct sets of default arguments. That is, declarations in inner scopes do not acquire default @@ -3793,9 +3951,10 @@ For a given inline function defined in different translation units, the accumulated sets of default arguments at the end of the translation units shall be the same; no diagnostic is required. -If a friend declaration specifies a default argument expression, -that declaration shall be a definition and shall be the only -declaration of the function or function template in the translation unit. +If a friend declaration $D$ specifies a default argument expression, +that declaration shall be a definition and there shall be no other +declaration of the function or function template +which is reachable from $D$ or from which $D$ is reachable. \pnum \indextext{argument!type checking of default}% @@ -3806,11 +3965,10 @@ declaration of a variable of the parameter type, using the copy-initialization semantics\iref{dcl.init}. The names in the -default argument are bound, and the semantic constraints are checked, +default argument are looked up, and the semantic constraints are checked, at the point where the default argument appears. Name lookup and checking of semantic constraints for default -arguments in function templates and in member functions of -class templates are performed as described in~\ref{temp.inst}. +arguments of templated functions are performed as described in~\ref{temp.inst}. \begin{example} In the following code, \indextext{argument!example of default}% @@ -3833,9 +3991,7 @@ \end{codeblock} \end{example} \begin{note} -In member function declarations, -names in default arguments are looked up -as described in~\ref{basic.lookup.unqual}. +A default argument is a complete-class context\iref{class.mem}. Access checking applies to names in default arguments as described in \ref{class.access}. \end{note} @@ -3904,8 +4060,10 @@ A parameter shall not appear as a potentially-evaluated expression in a default argument. \indextext{argument and name hiding!default}% +\begin{note} Parameters of a function declared before a default argument are in scope and can hide namespace and class member names. +\end{note} \begin{example} \begin{codeblock} int a; @@ -3955,16 +4113,14 @@ int (*p2)() = &f; // error: type mismatch \end{codeblock} \end{example} -When a declaration of a function is introduced by way of a -\grammarterm{using-declaration}\iref{namespace.udecl}, -any default argument information associated -with the declaration is made known as well. -If the function is redeclared -thereafter in the namespace with additional default arguments, -the additional arguments are also known at any point following -the redeclaration where the -\grammarterm{using-declaration} -is in scope. +When an overload set contains a declaration of a function +that inhabits a scope $S$, +any default argument associated with any reachable declaration that inhabits $S$ +is available to the call. +\begin{note} +The candidate might have been found through a \grammarterm{using-declarator} +from which the declaration that provides the default argument is not reachable. +\end{note} \pnum \indextext{argument and virtual function!default}% @@ -4091,8 +4247,8 @@ \end{note} \pnum -A declaration of a block-scope variable with external or internal -linkage that has an \grammarterm{initializer} is ill-formed. +A declaration of a block variable with linkage +that has an \grammarterm{initializer} is ill-formed. \pnum \indextext{initialization!default}% @@ -4252,23 +4408,6 @@ \pnum If no initializer is specified for an object, the object is default-initialized. -\pnum -\indextext{initialization!class member}% -An initializer for a static member is in the scope of the member's class. -\begin{example} -\begin{codeblock} -int a; - -struct X { - static int a; - static int b; -}; - -int X::a = 1; -int X::b = a; // \tcode{X::b = X::a} -\end{codeblock} -\end{example} - \pnum If the entity being initialized does not have class type, the \grammarterm{expression-list} in a @@ -4544,7 +4683,7 @@ but the initializing declaration of a non-inline static data member\iref{class.static.data} might be the declaration within the class definition -and not the definition at namespace scope. +and not the definition (if any) outside it. \end{note} \rSec2[dcl.init.aggr]{Aggregates}% @@ -4613,12 +4752,12 @@ For each explicitly initialized element: \begin{itemize} \item -If the element is an anonymous union object and +If the element is an anonymous union member and the initializer list is a \grammarterm{designated-initializer-list}, -the anonymous union object is initialized by the +the anonymous union member is initialized by the \grammarterm{designated-initializer-list} \tcode{\{ }\placeholder{D}\tcode{ \}}, where \placeholder{D} is the \grammarterm{designated-initializer-clause} -naming a member of the anonymous union object. +naming a member of the anonymous union member. There shall be only one such \grammarterm{designated-initializer-clause}. \begin{example} \begin{codeblock} @@ -5915,9 +6054,8 @@ \end{note} \pnum -In the \grammarterm{function-body}, a -\defnadj{function-local predefined}{variable} denotes a block-scope object of static -storage duration that is implicitly defined (see~\ref{basic.scope.block}). +A \defnadj{function-local predefined}{variable} is a variable with static +storage duration that is implicitly defined in a function parameter scope. \pnum \indextext{__func__@\mname{func}}% @@ -6088,8 +6226,8 @@ This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not -potentially-evaluated. If a function is overloaded, it is referenced only if the -function is selected by overload resolution. The implicit +potentially-evaluated. For an overload set, only the +function selected by overload resolution is referenced. The implicit odr-use\iref{basic.def.odr} of a virtual function does not, by itself, constitute a reference. \end{note} @@ -6270,11 +6408,11 @@ \end{itemize} \pnum -The \grammarterm{unqualified-id}{s} \tcode{return_void} -and \tcode{return_value} are looked up in the scope of the promise type. -If both are found, the program is ill-formed. +If searches for the names \tcode{return_void} and \tcode{return_value} +in the scope of the promise type each find any declarations, +the program is ill-formed. \begin{note} -If the \grammarterm{unqualified-id} \tcode{return_void} is found, flowing off +If \tcode{return_void} is found, flowing off the end of a coroutine is equivalent to a \tcode{co_return} with no operand. Otherwise, flowing off the end of a coroutine results in undefined behavior\iref{stmt.return.coroutine}. @@ -6303,24 +6441,26 @@ An implementation may need to allocate additional storage for a coroutine. This storage is known as the \defn{coroutine state} and is obtained by calling a non-array allocation function\iref{basic.stc.dynamic.allocation}. -The allocation function's name is looked up in the scope of the promise type. -If this lookup fails, the allocation function's name is looked up in the -global scope. -If the lookup finds an allocation function in the scope of the promise type, +The allocation function's name is looked up by searching for it in the scope of the promise type. +\begin{itemize} +\item +If any declarations are found, overload resolution is performed on a function call created by assembling an argument list. The first argument is the amount of space requested, and has type \tcode{std::size_t}. The lvalues $\tcode{p}_1 \dotsc \tcode{p}_n$ are the succeeding arguments. +\item +Otherwise, a search is performed in the global scope. +\end{itemize} If no viable function is found\iref{over.match.viable}, overload resolution is performed again on a function call created by passing just the amount of space required as an argument of type \tcode{std::size_t}. \pnum -The \grammarterm{unqualified-id} \tcode{get_return_object_on_allocation_failure} -is looked up in the scope of the promise type by class member access -lookup\iref{basic.lookup.qual}. -If any declarations are found, then the result +If a search for the name \tcode{get_return_object_on_allocation_failure} +in the scope of the promise type\iref{class.member.lookup} finds +any declarations, then the result of a call to an allocation function used to obtain storage for the coroutine state is assumed to return \tcode{nullptr} if it fails to obtain storage, and if a global allocation function is selected, @@ -6378,19 +6518,20 @@ of a coroutine handle\iref{coroutine.handle} that refers to the coroutine is invoked. -In the latter case objects with automatic storage duration that -are in scope at the suspend point are destroyed in the reverse order of the -construction. The storage for the coroutine state is released by calling a +In the latter case, +control in the coroutine is considered +to be transferred out of the function\iref{stmt.dcl}. +The storage for the coroutine state is released by calling a non-array deallocation function\iref{basic.stc.dynamic.deallocation}. If \tcode{destroy} is called for a coroutine that is not suspended, the program has undefined behavior. \pnum -The deallocation function's name is looked up in the scope of the promise type. -If this lookup fails, the deallocation function's name is looked up in the -global scope. If deallocation function lookup finds both a usual deallocation +The deallocation function's name is looked up by searching for it in the scope of the promise type. +If nothing is found, a search is performed in the +global scope. If both a usual deallocation function with only a pointer parameter and a usual deallocation function with -both a pointer parameter and a size parameter, then the selected deallocation +both a pointer parameter and a size parameter are found, then the selected deallocation function shall be the one with two parameters. Otherwise, the selected deallocation function shall be the function with one parameter. If no usual deallocation function is found, the program is ill-formed. @@ -6508,14 +6649,14 @@ expression. Let \tcode{i} be an index prvalue of type \tcode{std::size_t} corresponding to $\tcode{v}_\tcode{i}$. -The \grammarterm{unqualified-id} \tcode{get} is looked up -in the scope of \tcode{E} by class member access lookup\iref{basic.lookup.qual}, -and if that finds at least one declaration +If a search for the name \tcode{get} +in the scope of \tcode{E}\iref{class.member.lookup} +finds at least one declaration that is a function template whose first template parameter is a non-type parameter, the initializer is \tcode{\exposid{e}.get()}. Otherwise, the initializer is \tcode{get(\exposid{e})}, -where \tcode{get} is looked up in the associated namespaces\iref{basic.lookup.argdep}. +where \tcode{get} undergoes argument-dependent lookup\iref{basic.lookup.argdep}. In either case, \tcode{get} is interpreted as a \grammarterm{template-id}. \begin{note} Ordinary unqualified lookup\iref{basic.lookup.unqual} is not performed. @@ -6654,6 +6795,9 @@ \end{example} \end{note} +The \grammarterm{identifier} in an \grammarterm{enum-head-name} +is not looked up and is introduced by +the \grammarterm{enum-specifier} or \grammarterm{opaque-enum-declaration}. If the \grammarterm{enum-head-name} of an \grammarterm{opaque-enum-declaration} contains a \grammarterm{nested-name-specifier}, the declaration shall be an explicit specialization\iref{temp.expl.spec}. @@ -6713,17 +6857,14 @@ \pnum If an \grammarterm{enum-head-name} contains a \grammarterm{nested-name-specifier}, -it shall not begin with a \grammarterm{decltype-specifier} and the enclosing \grammarterm{enum-specifier} -or \grammarterm{opaque-enum-declaration} shall -refer to an enumeration that was previously declared directly in the class or -namespace to which the \grammarterm{nested-name-specifier} refers, -or in an element of the inline namespace -set\iref{namespace.def} of that namespace (i.e., neither -inherited nor introduced by a \grammarterm{using-declaration}), and the -\grammarterm{enum-specifier} or \grammarterm{opaque-enum-declaration} -shall appear in a namespace enclosing the previous -declaration. +or \grammarterm{opaque-enum-declaration} $D$ +shall not inhabit a class scope and +shall correspond to one or more declarations nominable +in the class, class template, or namespace +to which the \grammarterm{nested-name-specifier} refers\iref{basic.scope.scope}. +All those declarations shall have the same target scope; +the target scope of $D$ is that scope. \pnum \indextext{\idxcode{enum}!type of}% @@ -6767,11 +6908,11 @@ \end{itemize} \pnum -An enumeration whose underlying type is fixed is an incomplete type from its -point of declaration\iref{basic.scope.pdecl} to immediately after its +An enumeration whose underlying type is fixed is an incomplete type +until immediately after its \grammarterm{enum-base} (if any), at which point it becomes a complete type. -An enumeration whose underlying type is not fixed is an incomplete type from -its point of declaration to immediately after the closing \tcode{\}} of its +An enumeration whose underlying type is not fixed is an incomplete type +until the closing \tcode{\}} of its \grammarterm{enum-specifier}, at which point it becomes a complete type. \pnum @@ -6846,10 +6987,8 @@ \pnum \indextext{class!scope of enumerator}% -Each \grammarterm{enum-name} and each unscoped \grammarterm{enumerator} is -declared in the scope that immediately contains the \grammarterm{enum-specifier}. -Each scoped \grammarterm{enumerator} is declared in the scope of the -enumeration. +The name of each unscoped enumerator is also bound +in the scope that immediately contains the \grammarterm{enum-specifier}. An unnamed enumeration that does not have a typedef name for linkage purposes\iref{dcl.typedef} and that has a first enumerator @@ -6857,8 +6996,6 @@ by its underlying type and its first enumerator; such an enumeration is said to have an enumerator as a name for linkage purposes. -These names obey the scope rules defined for all names -in~\ref{basic.scope} and~\ref{basic.lookup}. \begin{note} Each unnamed enumeration with no enumerators is a distinct type. \end{note} @@ -6881,30 +7018,6 @@ } \end{codeblock} \end{example} -\indextext{member!enumerator}% -\begin{note} -An enumerator declared in class scope can be referred to using the class -member access operators \tcode{.} (dot) and \tcode{->} -(arrow)\iref{expr.ref}, -or with the scope resolution operator \tcode{::}\iref{class.qual}. -\begin{example} -\begin{codeblock} -struct X { - enum direction { left='l', right='r' }; - int f(int i) { return i==left ? 0 : i==right ? 1 : 2; } -}; - -void g(X* p) { - direction d; // error: \tcode{direction} not in scope - int i; - i = p->f(left); // error: \tcode{left} not in scope - i = p->f(X::right); // OK - i = p->f(p->left); // OK - // ... -} -\end{codeblock} -\end{example} -\end{note} \rSec2[enum.udecl]{The \tcode{using enum} declaration}% \indextext{enumeration!using declaration}% @@ -6921,14 +7034,12 @@ \pnum A \grammarterm{using-enum-declaration} -introduces the enumerator names of the named enumeration -as if by a \grammarterm{using-declaration} for each enumerator. +is equivalent to a \grammarterm{using-declaration} for each enumerator. \pnum \begin{note} A \grammarterm{using-enum-declaration} in class scope -adds the enumerators of the named enumeration as members to the scope. -This means they are accessible for member lookup. +makes the enumerators of the named enumeration available via member lookup. \begin{example} \begin{codeblock} enum class fruit { orange, apple }; @@ -6966,7 +7077,9 @@ \indextext{namespaces|(} \pnum -A namespace is an optionally-named declarative region. The name of a +A namespace is an optionally-named entity +whose scope can contain declarations of any kind of entity. +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 From a17f78711d768fc721b3ceae36c6c9c51d08bb74 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 20 Nov 2020 23:39:17 +0100 Subject: [PATCH 29/60] dcl.dcl remainder --- source/classes.tex | 3 +- source/concepts.tex | 2 +- source/declarations.tex | 705 ++++++++++++---------------------------- source/templates.tex | 4 +- source/xrefdelta.tex | 1 + 5 files changed, 207 insertions(+), 508 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index bb5fc221b3..c3dce52e63 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -4966,8 +4966,7 @@ \pnum \indextext{friend function!linkage of}% A function first declared in a friend declaration -has the linkage of the namespace of which it is a member~(\ref{basic.link}, -\ref{namespace.memdef}). +has the linkage of the namespace of which it is a member\iref{basic.link}. Otherwise, the function retains its previous linkage\iref{dcl.stc}. \pnum diff --git a/source/concepts.tex b/source/concepts.tex index 9950a81649..74e341d991 100644 --- a/source/concepts.tex +++ b/source/concepts.tex @@ -943,7 +943,7 @@ \item at least one disqualifying parameter is a key parameter; or \item the declaration contains no key parameters; or \item the declaration declares a function template that -is not visible in its namespace\iref{namespace.memdef}. +is not visible in its namespace. \end{itemize} \end{itemize} diff --git a/source/declarations.tex b/source/declarations.tex index adc4f335f9..745a090c0d 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -7080,20 +7080,19 @@ A namespace is an optionally-named entity whose scope can contain declarations of any kind of entity. 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, +namespace can be used to access entities that belong to that namespace; +that is, the \defnx{members}{member!namespace} of the namespace. +Unlike other entities, the definition of a namespace can be split over several parts of one or -more translation units. +more translation units and modules. \pnum \begin{note} -A namespace name with external linkage is exported -if any of its \grammarterm{namespace-definition}{s} is exported, -or if it contains any +A \grammarterm{namespace-definition} is exported +if it contains any \grammarterm{export-declaration}{s}\iref{module.interface}. -A namespace is never attached to a module, -and never has module linkage -even if it is not exported. +A namespace is never attached to a named module +and never has a name with module linkage. \end{note} \begin{example} \begin{codeblock} @@ -7105,8 +7104,13 @@ \end{example} \pnum -The outermost declarative region of a translation unit is a namespace; +There is a \defnadj{global}{namespace} with no declaration see~\ref{basic.scope.namespace}. +The global namespace belongs to the global scope; +it is not an unnamed namespace\iref{namespace.unnamed}. +\begin{note} +Lacking a declaration, it cannot be found by name lookup. +\end{note} \rSec2[namespace.def]{Namespace definition}% @@ -7154,22 +7158,21 @@ \end{bnf} \pnum -Every \grammarterm{namespace-definition} shall appear at namespace scope\iref{basic.scope.namespace}. +Every \grammarterm{namespace-definition} shall inhabit a namespace scope\iref{basic.scope.namespace}. \pnum -In a \grammarterm{named-namespace-definition}, +In a \grammarterm{named-namespace-definition} $D$, the \grammarterm{identifier} is the name of the namespace. -If the \grammarterm{identifier}, when looked up\iref{basic.lookup.unqual}, -refers to a \grammarterm{namespace-name} (but not a \grammarterm{namespace-alias}) -that was introduced in the namespace -in which the \grammarterm{named-namespace-definition} appears -or that was introduced in a member of the inline namespace set of that namespace, -the \grammarterm{namespace-definition} -\indextext{extend|see{namespace, extend}} -\defnx{extends}{namespace!extend} the previously-declared namespace. -Otherwise, the \grammarterm{identifier} is introduced -as a \grammarterm{namespace-name} into the declarative region -in which the \grammarterm{named-namespace-definition} appears. +If the \grammarterm{identifier} is looked up +by searching for it in the scopes of the namespace $A$ +in which $D$ appears +and of every element of the inline namespace set of $A$. +If the lookup finds a \grammarterm{namespace-definition} for a namespace $N$, +\indextext{extend|see{namespace, extend}}% +$D$ \defnx{extends}{namespace!extend} $N$, +and the target scope of $D$ is the scope to which $N$ belongs. +If the lookup finds nothing, the \grammarterm{identifier} is introduced +as a \grammarterm{namespace-name} into $A$. \pnum Because a \grammarterm{namespace-definition} contains @@ -7189,29 +7192,6 @@ \end{codeblock} \end{example} -\pnum -The \defnx{enclosing namespaces}{namespace!enclosing} of a declaration are those -namespaces in which the declaration lexically appears, except for a -redeclaration of a namespace member outside its original namespace -(e.g., a definition as specified in~\ref{namespace.memdef}). Such a -redeclaration has the same enclosing namespaces as the original -declaration. -\begin{example} -\begin{codeblock} -namespace Q { - namespace V { - void f(); // enclosing namespaces are the global namespace, \tcode{Q}, and \tcode{Q::V} - class C { void m(); }; - } - void V::f() { // enclosing namespaces are the global namespace, \tcode{Q}, and \tcode{Q::V} - extern void h(); // ... so this declares \tcode{Q::V::h} - } - void V::C::m() { // enclosing namespaces are the global namespace, \tcode{Q}, and \tcode{Q::V} - } -} -\end{codeblock} -\end{example} - \pnum If the optional initial \tcode{inline} keyword appears in a \grammarterm{namespace-definition} for a particular namespace, that namespace is @@ -7238,7 +7218,7 @@ instantiated\iref{temp.explicit}, or explicitly specialized\iref{temp.expl.spec} as though it were a member of the enclosing namespace. Finally, looking up a name in the enclosing namespace via explicit qualification\iref{namespace.qual} will include -members of the inline namespace brought in by the \grammarterm{using-directive} even if +members of the inline namespace even if there are declarations of that name in the enclosing namespace. \pnum @@ -7247,9 +7227,6 @@ \tcode{O} can be used as though they were members of \tcode{M} or \tcode{N}. The \defn{inline namespace set} of \tcode{N} is the transitive closure of all inline namespaces in \tcode{N}. -The \defn{enclosing namespace set} of \tcode{O} is the set of namespaces -consisting of the innermost non-inline namespace enclosing -an inline namespace \tcode{O}, together with any intervening inline namespaces. \pnum A \grammarterm{nested-namespace-definition} with an @@ -7322,130 +7299,6 @@ \end{codeblock} \end{example} -\rSec3[namespace.memdef]{Namespace member definitions}% -\indextext{namespace!member definition} - -\pnum -A declaration in a namespace \tcode{N} (excluding declarations in nested scopes) -whose \grammarterm{declarator-id} is an \grammarterm{unqualified-id}\iref{dcl.meaning}, -whose \grammarterm{class-head-name}\iref{class.pre} or -\grammarterm{enum-head-name}\iref{dcl.enum} is an \grammarterm{identifier}, or -whose \grammarterm{elaborated-type-specifier} is of the form \grammarterm{class-key} -\opt{\grammarterm{attribute-specifier-seq}} \grammarterm{identifier}\iref{dcl.type.elab}, or -that is an \grammarterm{opaque-enum-declaration}, -declares (or redeclares) its \grammarterm{unqualified-id} or -\grammarterm{identifier} as a member of \tcode{N}. -\begin{note} -An explicit instantiation\iref{temp.explicit} or -explicit specialization\iref{temp.expl.spec} of a template -does not introduce a name and thus can be declared using an -\grammarterm{unqualified-id} in a member of the enclosing namespace set, -if the primary template is declared in an inline namespace. -\end{note} -\begin{example} -\begin{codeblock} -namespace X { - void f() { @\commentellip@ } // OK: introduces \tcode{X::f()} - - namespace M { - void g(); // OK: introduces \tcode{X::M::g()} - } - using M::g; - void g(); // error: conflicts with \tcode{X::M::g()} -} -\end{codeblock} -\end{example} - -\pnum -Members of a named namespace can also be -defined outside that namespace by explicit -qualification\iref{namespace.qual} of the name being defined, provided -that the entity being defined was already declared in the namespace and -the definition appears after the point of declaration in a namespace -that encloses the declaration's namespace. -\begin{example} -\begin{codeblock} -namespace Q { - namespace V { - void f(); - } - void V::f() { @\commentellip@ } // OK - void V::g() { @\commentellip@ } // error: \tcode{g()} is not yet a member of \tcode{V} - namespace V { - void g(); - } -} - -namespace R { - void Q::V::g() { @\commentellip@ } // error: \tcode{R} doesn't enclose \tcode{Q} -} -\end{codeblock} -\end{example} - -\pnum -If a friend declaration in a non-local class first declares a -class, function, class template or function template -\begin{footnote} -this implies that the name of the class or function is unqualified. -\end{footnote} -the friend is a member of the innermost enclosing -namespace. The friend declaration does not by itself make the name -visible to unqualified lookup\iref{basic.lookup.unqual} or qualified -lookup\iref{basic.lookup.qual}. -\begin{note} -The name of the friend will be -visible in its namespace if a matching declaration is provided at namespace -scope (either before or after the class definition granting friendship). -\end{note} -If a friend -function or function template is called, its name may be found by the -name lookup that considers functions from namespaces and classes -associated with the types of the function -arguments\iref{basic.lookup.argdep}. If the -name in a friend declaration is neither qualified nor a -\grammarterm{template-id} and the declaration is a function or an -\grammarterm{elaborated-type-specifier}, the lookup to determine whether -the entity has been previously declared shall not consider any scopes -outside the innermost enclosing namespace. -\begin{note} -The other forms of -friend declarations cannot declare a new member of the innermost -enclosing namespace and thus follow the usual lookup rules. -\end{note} -\begin{example} -\begin{codeblock} -// Assume \tcode{f} and \tcode{g} have not yet been declared. -void h(int); -template void f2(T); -namespace A { - class X { - friend void f(X); // \tcode{A::f(X)} is a friend - class Y { - friend void g(); // \tcode{A::g} is a friend - friend void h(int); // \tcode{A::h} is a friend - // \tcode{::h} not considered - friend void f2<>(int); // \tcode{::f2<>(int)} is a friend - }; - }; - - // \tcode{A::f}, \tcode{A::g} and \tcode{A::h} are not visible here - X x; - void g() { f(x); } // definition of \tcode{A::g} - void f(X) { @\commentellip@ } // definition of \tcode{A::f} - void h(int) { @\commentellip@ } // definition of \tcode{A::h} - // \tcode{A::f}, \tcode{A::g} and \tcode{A::h} are visible here and known to be friends -} - -using A::x; - -void h() { - A::f(x); - A::X::f(x); // error: \tcode{f} is not a member of \tcode{A::X} - A::X::Y::g(); // error: \tcode{g} is not a member of \tcode{A::X::Y} -} -\end{codeblock} -\end{example} - \rSec2[namespace.alias]{Namespace alias}% \indextext{namespace!alias}% \indextext{alias!namespace}% @@ -7471,32 +7324,15 @@ \end{bnf} \pnum -The \grammarterm{identifier} in a \grammarterm{namespace-alias-definition} is -a synonym for the name of the namespace denoted by the -\grammarterm{qualified-namespace-specifier} and becomes a -\grammarterm{namespace-alias}. +The \grammarterm{identifier} in a \grammarterm{namespace-alias-definition} +becomes a \grammarterm{namespace-alias} and denotes the namespace denoted by the +\grammarterm{qualified-namespace-specifier}. \begin{note} When looking up a \grammarterm{namespace-name} in a \grammarterm{namespace-alias-definition}, only namespace names are considered, see~\ref{basic.lookup.udir}. \end{note} -\pnum -In a declarative region, a \grammarterm{namespace-alias-definition} can be -used to redefine a \grammarterm{namespace-alias} declared in that -declarative region to refer only to the namespace to which it already -refers. -\begin{example} -The following declarations are well-formed: - -\begin{codeblock} -namespace Company_with_very_long_name { @\commentellip@ } -namespace CWVLN = Company_with_very_long_name; -namespace CWVLN = Company_with_very_long_name; // OK: duplicate -namespace CWVLN = CWVLN; -\end{codeblock} -\end{example} - \rSec2[namespace.udir]{Using namespace directive}% \indextext{using-directive|(} @@ -7516,20 +7352,21 @@ The optional \grammarterm{attribute-specifier-seq} appertains to the \grammarterm{using-directive}. \pnum -A \grammarterm{using-directive} specifies that the names in the nominated -namespace can be used in the scope in which the -\grammarterm{using-directive} appears after the \grammarterm{using-directive}. -During unqualified name lookup\iref{basic.lookup.unqual}, the names +\begin{note} +A \grammarterm{using-directive} makes the names in the nominated +namespace usable in the scope in which the +\grammarterm{using-directive} appears after the \grammarterm{using-directive} +(\ref{basic.lookup.unqual}, \ref{namespace.qual}). +During unqualified name lookup, the names appear as if they were declared in the nearest enclosing namespace which contains both the \grammarterm{using-directive} and the nominated namespace. -\begin{note} -In this context, ``contains'' means ``contains directly or indirectly''. \end{note} \pnum -A \grammarterm{using-directive} does not add any members to the declarative -region in which it appears. +\begin{note} +A \grammarterm{using-directive} does not introduce any names. +\end{note} \begin{example} \begin{codeblock} namespace A { @@ -7561,14 +7398,11 @@ \end{example} \pnum -For unqualified lookup\iref{basic.lookup.unqual}, the -\grammarterm{using-directive} is transitive: if a scope contains a -\grammarterm{using-directive} that nominates a second namespace that itself -contains \grammarterm{using-directive}{s}, the effect is as if the -\grammarterm{using-directive}{s} from the second namespace also appeared in -the first. \begin{note} -For qualified lookup, see~\ref{namespace.qual}. +A \grammarterm{using-directive} is transitive: if a scope contains a +\grammarterm{using-directive} that nominates a namespace that itself +contains \grammarterm{using-directive}{s}, the namespaces nominated by those +\grammarterm{using-directive}{s} are also eligible to be considered. \end{note} \begin{example} \begin{codeblock} @@ -7614,12 +7448,11 @@ \pnum -If a namespace is extended\iref{namespace.def} after a -\grammarterm{using-directive} for that namespace is given, the additional -members of the extended namespace and the members of namespaces -nominated by \grammarterm{using-directive}{s} in the -extending \grammarterm{namespace-definition} can be used after the -extending \grammarterm{namespace-definition}. +\begin{note} +Declarations in a namespace +that appear after a \grammarterm{using-directive} for that namespace +can be found through that \grammarterm{using-directive} after they appear. +\end{note} \pnum \begin{note} @@ -7654,16 +7487,11 @@ \pnum \indextext{overloading!using directive and}% -During overload resolution, all functions from the transitive search are -considered for argument matching. The set of declarations found by the -transitive search is unordered. \begin{note} -In particular, the order in which namespaces were considered and the +The order in which namespaces are considered and the relationships among the namespaces implied by the -\grammarterm{using-directive}{s} do not cause preference to be given to any -of the declarations found by the search. -\end{note} -An ambiguity exists if the best match finds two functions with the same +\grammarterm{using-directive}{s} do not affect overload resolution. +Neither is any function excluded because another has the same signature, even if one is in a namespace reachable through \grammarterm{using-directive}{s} in the namespace of the other. \begin{footnote} @@ -7674,6 +7502,7 @@ considering the set of names found as a result of following \grammarterm{using-directive}{s}. \end{footnote} +\end{note} \begin{example} \begin{codeblock} namespace D { @@ -7729,6 +7558,9 @@ \end{bnf} \pnum +\indextext{component name}% +The component names of a \grammarterm{using-declarator} are those +of its \grammarterm{nested-name-specifier} and \grammarterm{unqualified-id}. Each \grammarterm{using-declarator} in a \grammarterm{using-declaration} \begin{footnote} A \grammarterm{using-declaration} with more than one @@ -7736,46 +7568,39 @@ of \grammarterm{using-declaration}{s} with one \grammarterm{using-declarator} each. \end{footnote} -introduces a set of declarations into the declarative region in -which the \grammarterm{using-declaration} appears. -The set of declarations introduced by the \grammarterm{using-declarator} is found by -performing qualified name lookup~(\ref{basic.lookup.qual}, \ref{class.member.lookup}) -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 introduced by the \grammarterm{using-declarator}. -\begin{note} -Only the specified name is so declared; -specifying an enumeration name in a \grammarterm{using-declaration} -does not declare its enumerators -in the \grammarterm{using-declaration}{'s} declarative region. -\end{note} -\indextext{inheritance!\idxgram{using-declaration} and}% -If the \grammarterm{using-declarator} names a constructor, -it declares that the class \defnx{inherits}{constructor!inherited} the set of constructor declarations -introduced by the \grammarterm{using-declarator} from the nominated base class. +names the set of declarations found by lookup\iref{basic.lookup.qual} +for the \grammarterm{using-declarator}, +except that class and enumeration declarations that would be discarded +are merely ignored when checking for ambiguity\iref{basic.lookup}, +conversion function templates with a dependent return type are ignored, and +certain functions are hidden as described below. +If the terminal name of the \grammarterm{using-declarator} +is dependent\iref{temp.dep.type}, +the \grammarterm{using-declarator} is considered to name a constructor +if and only if the \grammarterm{nested-name-specifier} has a terminal name +that is the same as the \grammarterm{unqualified-id}. +If the lookup in any instantiation finds +that a \grammarterm{using-declarator} +that is not considered to name a constructor does do so, or +that a \grammarterm{using-declarator} +that is considered to name a constructor does not, +the program is ill-formed. \pnum -Every \grammarterm{using-declaration} is a \grammarterm{declaration} and a -\grammarterm{member-declaration} and can therefore be used in a class definition. -\begin{example} -\begin{codeblock} -struct B { - void f(char); - void g(char); - enum E { e }; - union { int x; }; -}; - -struct D : B { - using B::f; - void f(int) { f('c'); } // calls \tcode{B::f(char)} - void g(int) { g('c'); } // recursively calls \tcode{D::g(int)} -}; -\end{codeblock} -\end{example} +\indextext{inheritance!\idxgram{using-declaration} and}% +If the \grammarterm{using-declarator} names a constructor, +it declares that the class \defnx{inherits}{constructor!inherited} the named set of constructor declarations +from the nominated base class. +\begin{note} +Otherwise, +the \grammarterm{unqualified-id} in the \grammarterm{using-declarator} +is bound to the \grammarterm{using-declarator}, +which is replaced during name lookup +with the declarations it names\iref{basic.lookup}. +If such a declaration is of an enumeration, +the names of its enumerators are not bound. +For the keyword \keyword{typename}, see \ref{temp.res}. +\end{note} \pnum In a \grammarterm{using-declaration} used as a @@ -7783,7 +7608,7 @@ each \grammarterm{using-declarator} shall either name an enumerator or have a \grammarterm{nested-name-specifier} -naming a base class of the class being defined. +naming a base class of the current class. \begin{example} \begin{codeblock} enum class button { up, down }; @@ -7794,31 +7619,37 @@ \end{codeblock} \end{example} If a -\grammarterm{using-declarator} names a constructor, its -\grammarterm{nested-name-specifier} shall name a direct base class of the class -being defined. +\grammarterm{using-declarator} names a constructor, +its \grammarterm{nested-name-specifier} shall name +a direct base class of the current class. +If the immediate (class) scope is associated with a class template, +it shall derive from the specified base class or +have at least one dependent base class. \begin{example} \begin{codeblock} -template -struct X : bases... { - using bases::g...; +struct B { + void f(char); + enum E { e }; + union { int x; }; }; -X x; // OK: \tcode{B::g} and \tcode{D::g} introduced -\end{codeblock} -\end{example} -\begin{example} -\begin{codeblock} -class C { - int g(); +struct C { + int f(); }; -class D2 : public B { - using B::f; // OK: \tcode{B} is a base of \tcode{D2} +struct D : B { + using B::f; // OK: \tcode{B} is a base of \tcode{D} using B::e; // OK: \tcode{e} is an enumerator of base \tcode{B} using B::x; // OK: \tcode{x} is a union member of base \tcode{B} - using C::g; // error: \tcode{C} isn't a base of \tcode{D2} + using C::f; // error: \tcode{C} isn't a base of \tcode{D} + void f(int) { f('c'); } // calls \tcode{B::f(char)} + void g(int) { g('c'); } // recursively calls \tcode{D::g(int)} }; +template +struct X : bases... { + using bases::f...; +}; +X x; // OK: \tcode{B::f} and \tcode{C::f} named \end{codeblock} \end{example} @@ -7826,10 +7657,7 @@ \begin{note} Since destructors do not have names, a \grammarterm{using-declaration} cannot refer to a -destructor for a base class. Since specializations of member templates -for conversion functions are not found by name lookup, they are not -considered when a \grammarterm{using-declaration} specifies a conversion -function\iref{temp.mem}. +destructor for a base class. \end{note} If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator @@ -7878,61 +7706,14 @@ \end{example} \pnum -Members declared by a \grammarterm{using-declaration} can be referred to by -explicit qualification just like other member -names\iref{namespace.qual}. -\begin{example} -\begin{codeblock} -void f(); - -namespace A { - void g(); -} - -namespace X { - using ::f; // global \tcode{f} - using A::g; // \tcode{A}'s \tcode{g} -} - -void h() -{ - X::f(); // calls \tcode{::f} - X::g(); // calls \tcode{A::g} -} -\end{codeblock} -\end{example} - -\pnum -A \grammarterm{using-declaration} is a \grammarterm{declaration} and can -therefore be used repeatedly where (and only where) multiple -declarations are allowed. -\begin{example} -\begin{codeblock} -namespace A { - int i; -} - -namespace A1 { - using A::i, A::i; // OK: double declaration -} - -struct B { - int i; -}; - -struct X : B { - using B::i, B::i; // error: double member declaration -}; -\end{codeblock} -\end{example} +If a declaration is named by two \grammarterm{using-declarator}s +that inhabit the same class scope, the program is ill-formed. \pnum \begin{note} -For a \grammarterm{using-declaration} -whose \grammarterm{nested-name-specifier} names a namespace, -members added to the namespace after the \grammarterm{using-declaration} -are not in the set of introduced declarations, so they are not -considered when a use of the name is made. Thus, additional +A \grammarterm{using-declarator} +whose \grammarterm{nested-name-specifier} names a namespace +does not name declarations added to the namespace after it. Thus, additional overloads added after the \grammarterm{using-declaration} are ignored, but default function arguments\iref{dcl.fct.default}, default template arguments\iref{temp.param}, and template specializations~(\ref{temp.class.spec}, @@ -7961,23 +7742,26 @@ \end{example} \pnum +If a declaration named by a \grammarterm{using-declaration} +that inhabits the target scope of another declaration +potentially conflicts with it\iref{basic.scope.scope} and +either is reachable from the other, the program is ill-formed. +If two declarations named by \grammarterm{using-declaration}s +that inhabit the same scope potentially conflict, +either is reachable from the other, and +they do not both declare functions or function templates, +the program is ill-formed. \begin{note} -Partial specializations of class templates are found by looking up the -primary class template and then considering all partial specializations -of that template. If a \grammarterm{using-declaration} names a class -template, partial specializations introduced after the -\grammarterm{using-declaration} are effectively visible because the primary -template is visible\iref{temp.class.spec}. +Overload resolution possibly cannot distinguish +between conflicting function declarations. \end{note} - -\pnum -Since a \grammarterm{using-declaration} is a declaration, the restrictions -on declarations of the same name in the same declarative -region\iref{basic.scope} also apply to \grammarterm{using-declaration}{s}. \begin{example} \begin{codeblock} namespace A { int x; + int f(int); + int g; + void h(); } namespace B { @@ -7986,84 +7770,39 @@ struct x { }; void f(int); void f(double); - void g(char); // OK: hides \tcode{struct g} + void g(char); // OK: hides \tcode{struct g} } void func() { int i; - using B::i; // error: \tcode{i} declared twice + using B::i; // error: conflicts void f(char); - using B::f; // OK: each \tcode{f} is a function - f(3.5); // calls \tcode{B::f(double)} + using B::f; // OK: each \tcode{f} is a function + using A::f; // OK, but interferes with \tcode{B::f(int)} + f(1); // error: ambiguous + static_cast(f)(1); // OK: calls \tcode{A::f} + f(3.5); // calls \tcode{B::f(double)} using B::g; - g('a'); // calls \tcode{B::g(char)} - struct g g1; // \tcode{g1} has class type \tcode{B::g} + g('a'); // calls \tcode{B::g(char)} + struct g g1; // \tcode{g1} has class type \tcode{B::g} + using A::g; // error: conflicts with \tcode{B::g} + void h(); + using A::h; // error: conflicts using B::x; - using A::x; // OK: hides \tcode{struct B::x} - x = 99; // assigns to \tcode{A::x} - struct x x1; // \tcode{x1} has class type \tcode{B::x} + using A::x; // OK: hides \tcode{struct B::x} + x = 99; // assigns to \tcode{A::x} + struct x x1; // \tcode{x1} has class type \tcode{B::x} } \end{codeblock} \end{example} -\pnum -If a function declaration in namespace scope or block scope has the same -name and the same parameter-type-list\iref{dcl.fct} as -a function introduced by a \grammarterm{using-declaration}, and the -declarations do not declare the same function, the program is -ill-formed. If a function template declaration in namespace scope has -the same -name, -parameter-type-list, -trailing \grammarterm{requires-clause} (if any), -return type, and -\grammarterm{template-head}, -as a function template introduced by a -\grammarterm{using-declaration}, the program is ill-formed. -\begin{note} -Two \grammarterm{using-declaration}{s} can introduce functions with the same -name and the same parameter-type-list. If, for a call to an unqualified -function name, function overload resolution selects the functions -introduced by such \grammarterm{using-declaration}{s}, the function call is -ill-formed. -\begin{example} -\begin{codeblock} -namespace B { - void f(int); - void f(double); -} -namespace C { - void f(int); - void f(double); - void f(char); -} - -void h() { - using B::f; // \tcode{B::f(int)} and \tcode{B::f(double)} - using C::f; // \tcode{C::f(int)}, \tcode{C::f(double)}, and \tcode{C::f(char)} - f('h'); // calls \tcode{C::f(char)} - f(1); // error: ambiguous: \tcode{B::f(int)} or \tcode{C::f(int)}? - void f(int); // error: \tcode{f(int)} conflicts with \tcode{C::f(int)} and \tcode{B::f(int)} -} -\end{codeblock} -\end{example} -\end{note} - \pnum \indextext{name hiding!using-declaration and}% -When a \grammarterm{using-declarator} brings declarations from a base class into -a derived class, member functions and member function templates in -the derived class override and/or hide member functions and member -function templates with the same -name, -parameter-type-list\iref{dcl.fct}, -trailing \grammarterm{requires-clause} (if any), -cv-qualification, and -\grammarterm{ref-qualifier} (if any), -in a base -class (rather than conflicting). -Such hidden or overridden declarations are excluded from the set of -declarations introduced by the \grammarterm{using-declarator}. +The set of declarations named by a \grammarterm{using-declarator} +hat inhabits a class \tcode{C} does not include +member functions and member function templates of a base class +that correspond to (and thus would conflict with) +a declaration of a function or function template in \tcode{C}. \begin{example} \begin{codeblock} struct B { @@ -8119,17 +7858,17 @@ \indextext{overloading!using-declaration and}% \begin{note} For the purpose of forming a set of candidates during overload resolution, -the functions that are -introduced by a \grammarterm{using-declaration} into a derived class -are treated as though they were members of the derived class\iref{class.member.lookup}. In +the functions +named by a \grammarterm{using-declaration} in a derived class +are treated as though they were direct members of the derived class. In particular, the implicit object parameter is treated as if it were a reference to the derived class rather than to the base class\iref{over.match.funcs}. This has no effect on the type of the function, and in all other -respects the function remains a member of the base class. +respects the function remains part of the base class. \end{note} \pnum -Constructors that are introduced by a \grammarterm{using-declaration} +Constructors that are named by a \grammarterm{using-declaration} are treated as though they were constructors of the derived class when looking up the constructors of the derived class\iref{class.qual} or forming a set of overload candidates~(\ref{over.match.ctor}, \ref{over.match.copy}, \ref{over.match.list}). @@ -8145,16 +7884,9 @@ \pnum \indextext{access control!using-declaration and}% In a \grammarterm{using-declarator} that does not name a constructor, -all members of the set of introduced declarations shall be accessible. +every declaration named shall be accessible. In a \grammarterm{using-declarator} that names a constructor, no access check is performed. -In particular, if a derived class uses a -\grammarterm{using-declarator} to access a member of a base class, the -member name shall be accessible. If the name is that of an overloaded -member function, then all functions named shall be accessible. The base -class members mentioned by a \grammarterm{using-declarator} shall be -visible in the scope of at least one of the direct base classes of the -class where the \grammarterm{using-declarator} is specified. \pnum \begin{note} @@ -8183,13 +7915,12 @@ \end{note} \pnum -A synonym created by a \grammarterm{using-declaration} has the usual +A \grammarterm{using-declaration} has the usual accessibility for a \grammarterm{member-declaration}. -A \grammarterm{using-declarator} that names a constructor does not -create a synonym; instead, the additional constructors +Base-class constructors considered because of a \grammarterm{using-declarator} are accessible if they would be accessible -when used to construct an object of the corresponding base class, -and the accessibility of the \grammarterm{using-declaration} is ignored. +when used to construct an object of the base class; +the accessibility of the \grammarterm{using-declaration} is ignored. \begin{example} \begin{codeblock} class A { @@ -8209,13 +7940,6 @@ \end{codeblock} \end{example} -\pnum -If a \grammarterm{using-declarator} uses the keyword \tcode{typename} and -specifies a dependent name\iref{temp.dep}, the name introduced by the -\grammarterm{using-declaration} is treated as a -\grammarterm{typedef-name}\iref{dcl.typedef}.% -\indextext{using-declaration|)} - \rSec1[dcl.asm]{The \tcode{asm} declaration}% \indextext{declaration!\idxcode{asm}}% \indextext{assembler}% @@ -8241,8 +7965,9 @@ \indextext{specification!linkage|(} \pnum -All function types, function names with external linkage, and variable -names with external linkage have a \defn{language linkage}. +All functions and variables whose names have external linkage +and all function types +have a \defn{language linkage}. \begin{note} Some of the properties associated with an entity with language linkage are specific to each implementation and are not described here. For @@ -8250,8 +7975,8 @@ particular form of representing names of objects and functions with external linkage, or with a particular calling convention, etc. \end{note} -The default language linkage of all function types, function names, and -variable names is \Cpp{} language linkage. Two function types with +The default language linkage of all function types, functions, and +variables is \Cpp{} language linkage. Two function types with different language linkages are distinct types even if they are otherwise identical. @@ -8286,10 +8011,9 @@ \pnum \indextext{specification!linkage!implementation-defined}% -Every implementation shall provide for linkage to functions written in -the C programming language, +Every implementation shall provide for linkage to the C programming language, \indextext{C!linkage to}% -\tcode{"C"}, and linkage to \Cpp{} functions, \tcode{"C++"}. +\tcode{"C"}, and \Cpp{}, \tcode{"C++"}. \begin{example} \begin{codeblock} complex sqrt(complex); // \Cpp{} linkage by default @@ -8312,30 +8036,32 @@ \pnum \indextext{specification!linkage!nesting}% Linkage specifications nest. When linkage specifications nest, the -innermost one determines the language linkage. A linkage specification -does not establish a scope. A \grammarterm{linkage-specification} shall -occur only in namespace scope\iref{basic.scope}. In a -\grammarterm{linkage-specification}, the specified language linkage applies -to the function types of all function declarators, function names with -external linkage, and variable names with external linkage declared -within the \grammarterm{linkage-specification}. +innermost one determines the language linkage. +\begin{note} +A linkage specification does not establish a scope. +\end{note} +A \grammarterm{linkage-specification} shall inhabit a namespace scope. +In a \grammarterm{linkage-specification}, +the specified language linkage applies +to the function types of all function declarators and +to all functions and variables. \begin{example} \begin{codeblock} -extern "C" // the name \tcode{f1} and its function type have C language linkage; +extern "C" // \tcode{f1} and its function type have C language linkage; void f1(void(*pf)(int)); // \tcode{pf} is a pointer to a C function extern "C" typedef void FUNC(); -FUNC f2; // the name \tcode{f2} has \Cpp{} language linkage and the - // function's type has C language linkage +FUNC f2; // \tcode{f2} has \Cpp{} language linkage and + // its type has C language linkage -extern "C" FUNC f3; // the name of function \tcode{f3} and the function's type have C language linkage +extern "C" FUNC f3; // \tcode{f3} and its type have C language linkage -void (*pf2)(FUNC*); // the name of the variable \tcode{pf2} has \Cpp{} linkage and the type - // of \tcode{pf2} is ``pointer to \Cpp{} function that takes one parameter of type +void (*pf2)(FUNC*); // the variable \tcode{pf2} has \Cpp{} linkage; its type + // is ``pointer to \Cpp{} function that takes one parameter of type // pointer to C function'' extern "C" { - static void f4(); // the name of the function \tcode{f4} has internal linkage (not C language linkage) - // and the function's type has C language linkage. + static void f4(); // the name of the function \tcode{f4} has internal linkage, + // so \tcode{f4} has no language linkage; its type has C language linkage } extern "C" void f5() { @@ -8355,28 +8081,26 @@ \indextext{class!linkage specification}% A C language linkage is ignored in determining the language linkage of -the names of class members and the +class members and the function type of class member functions. \begin{example} \begin{codeblock} extern "C" typedef void FUNC_c(); class C { - void mf1(FUNC_c*); // the name of the function \tcode{mf1} and the member function's type have - // \Cpp{} language linkage; the parameter has type ``pointer to C function'' + void mf1(FUNC_c*); // the function \tcode{mf1} and its type have \Cpp{} language linkage; + // the parameter has type ``pointer to C function'' - FUNC_c mf2; // the name of the function \tcode{mf2} and the member function's type have - // \Cpp{} language linkage + FUNC_c mf2; // the function \tcode{mf2} and its type have \Cpp{} language linkage - static FUNC_c* q; // the name of the data member \tcode{q} has \Cpp{} language linkage and - // the data member's type is ``pointer to C function'' + static FUNC_c* q; // the data member \tcode{q} has \Cpp{} language linkage; + // its type is ``pointer to C function'' }; extern "C" { class X { - void mf(); // the name of the function \tcode{mf} and the member function's type have - // \Cpp{} language linkage - void mf2(void(*)()); // the name of the function \tcode{mf2} has \Cpp{} language linkage; + void mf(); // the function \tcode{mf} and its type have \Cpp{} language linkage + void mf2(void(*)()); // the function \tcode{mf2} has \Cpp{} language linkage; // the parameter has type ``pointer to C function'' }; } @@ -8384,45 +8108,20 @@ \end{example} \pnum -If two declarations declare functions with the same name and -parameter-type-list\iref{dcl.fct} to be members of the same -namespace or declare objects with the same name to be members of the same -namespace and the declarations give the names different language linkages, the -program is ill-formed; no diagnostic is required if the declarations appear in -different translation units. +If two declarations of an entity give it different language linkages, the +program is ill-formed; no diagnostic is required if neither declaration +is reachable from the other. \indextext{consistency!linkage specification}% -Except for functions with \Cpp{} linkage, a function declaration without a -linkage specification shall not precede the first linkage specification -for that function. A function can be declared without a linkage -specification after an explicit linkage specification has been seen; the -linkage explicitly specified in the earlier declaration is not affected -by such a function declaration. +A redeclaration of an entity without a linkage specification +inherits the language linkage of the entity and (if applicable) its type. \pnum \indextext{function!linkage specification overloaded}% -At most one function with a particular name can have C language linkage. -Two declarations for a function with C language linkage with the same -function name (ignoring the namespace names that qualify it) that appear -in different namespace scopes refer to the same function. Two -declarations for a variable with C language linkage with the same name -(ignoring the namespace names that qualify it) that appear in different -namespace scopes refer to the same variable. -An entity with C language linkage shall not be declared with the same name -as a variable in global scope, unless both declarations denote the same entity; -no diagnostic is required if the declarations appear in different translation units. -A variable with C language linkage shall not be declared with the same name as a -function with C language linkage (ignoring the namespace names that qualify the -respective names); no diagnostic is required if the declarations appear in -different translation units. -\begin{note} -Only -one definition for an entity with a given name -with C language linkage can appear in the -program (see~\ref{basic.def.odr}); -this implies that such an entity -must not be defined in more -than one namespace scope. -\end{note} +Two declarations declare the same entity +if they (re)introduce the same name, +one declares a function or variable with C language linkage, +and the other declares such an entity or a variable +that belongs to the global scope- \begin{example} \begin{codeblock} int x; @@ -8879,7 +8578,7 @@ a template specialization. \pnum -A name or entity declared without the \tcode{deprecated} attribute can later be redeclared +An entity declared without the \tcode{deprecated} attribute can later be redeclared with the attribute and vice-versa. \begin{note} Thus, an entity initially declared without the diff --git a/source/templates.tex b/source/templates.tex index 45efc303f5..ba0259f131 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -3281,7 +3281,7 @@ \pnum A class template partial specialization may be declared in any scope in which the corresponding primary template -may be defined~(\ref{namespace.memdef}, \ref{class.mem}, \ref{temp.mem}). +may be defined~(\ref{dcl.meaning}, \ref{class.mem}, \ref{temp.mem}). \begin{example} \begin{codeblock} template struct A { @@ -6894,7 +6894,7 @@ \pnum An explicit specialization may be declared in any scope in which the corresponding primary template -may be defined~(\ref{namespace.memdef}, \ref{class.mem}, \ref{temp.mem}). +may be defined~(\ref{dcl.meaning}, \ref{class.mem}, \ref{temp.mem}). \pnum A declaration of a function template, class template, or variable template being explicitly diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 8e0c3e60c9..538af245bd 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -28,6 +28,7 @@ \movedxref{basic.funscope}{stmt.label} \movedxref{basic.scope.hiding}{basic.lookup} \movedxref{basic.lookup.classref}{basic.lookup.qual} +\movedxref{namespace.memdef}{namespace.def} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From 298c2efc19b2a8f7bdac5e5d9d896e8e08908ef0 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 21 Nov 2020 00:32:29 +0100 Subject: [PATCH 30/60] [dcl.link] Clarify sentence structure --- source/declarations.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index 745a090c0d..a703ca841a 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -8120,8 +8120,8 @@ Two declarations declare the same entity if they (re)introduce the same name, one declares a function or variable with C language linkage, -and the other declares such an entity or a variable -that belongs to the global scope- +and the other declares such an entity or declares a variable +that belongs to the global scope. \begin{example} \begin{codeblock} int x; From c8b2b4923804ea849858fd3346a4a4aa50446b5b Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 21 Nov 2020 19:35:08 +0100 Subject: [PATCH 31/60] module --- source/modules.tex | 119 +++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 69 deletions(-) diff --git a/source/modules.tex b/source/modules.tex index 55e84dc25f..180cf6596e 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -138,7 +138,15 @@ A \defn{module} is either a named module or the global module. A declaration is \defnx{attached}{attached!declaration} to a module as follows: \begin{itemize} -\item If the declaration +\item +If the declaration is a non-dependent friend declaration +that nominates a function with a \grammarterm{declarator-id} +that is a \grammarterm{qualified-id} or \grammarterm{template-id} or +that nominates a class +other than with an \grammarterm{elaborated-type-specifier} with neither +a \grammarterm{nested-name-specifier} nor a \grammarterm{simple-template-id}, +it is attached to the module to which the friend is attached\iref{basic.link}. +\item Otherwise, if the declaration \begin{itemize} \item is a replaceable global allocation or deallocation function (\ref{new.delete.single}, \ref{new.delete.array}), or @@ -196,8 +204,8 @@ \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 inhabit +a namespace scope and appear 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}. @@ -206,17 +214,19 @@ \grammarterm{declaration}, \grammarterm{declaration-seq} (if any), or \grammarterm{module-import-declaration}. -An \grammarterm{export-declaration} does not -establish a scope and its \grammarterm{declaration} -or \grammarterm{declaration-seq} +The \grammarterm{declaration} or \grammarterm{declaration-seq} of +an \grammarterm{export-declaration} shall not contain an \grammarterm{export-declaration} or \grammarterm{module-import-declaration}. +\begin{note} +An \grammarterm{export-declaration} does not establish a scope. +\end{note} \pnum A declaration is \defnx{exported}{declaration!exported} if it is +declared within an \grammarterm{export-declaration} and +inhabits a namespace scope or it is \begin{itemize} -\item a namespace-scope declaration declared within an - \grammarterm{export-declaration}, or \item a \grammarterm{namespace-definition} that contains an exported declaration, or \item a declaration within a header unit\iref{module.import} @@ -305,10 +315,10 @@ \end{note} \pnum -A redeclaration of an exported declaration of an entity -is implicitly exported. -An exported redeclaration of a non-exported declaration -of an entity is ill-formed. +A redeclaration of an entity or \grammarterm{typedef-name} $X$ +is implicitly exported +if $X$ was introduced by an exported declaration; +otherwise it shall not be exported. \begin{example} \begin{codeblock} export module M; @@ -320,14 +330,12 @@ \end{example} \pnum -A name is \defnx{exported}{name!exported} by a module -if it is introduced or redeclared -by an exported declaration in the purview of that module. \begin{note} -Exported names have either external linkage or no linkage; see \ref{basic.link}. -Namespace-scope names exported by a module are visible to name lookup -in any translation unit importing that module; see \ref{basic.scope.namespace}. -Class and enumeration member names are visible to name lookup in any +Names introduced by exported declarations +have either external linkage or no linkage; see \ref{basic.link}. +Namespace-scope declarations exported by a module can be found by name lookup +in any translation unit importing that module\ref{basic.lookup}. +Class and enumeration member names can be found by name lookup in any context in which a definition of the type is reachable. \end{note} \begin{example} @@ -372,27 +380,6 @@ \end{codeblocktu} \end{example} -\pnum -\begin{note} -Redeclaring a name in an \grammarterm{export-declaration} -cannot change the linkage of the name\iref{basic.link}. -\begin{example} -\begin{codeblocktu}{Interface unit of \tcode{M}} -export module M; -static int f(); // \#1 -export int f(); // error: \#1 gives internal linkage -struct S; // \#2 -export struct S; // error: \#2 gives module linkage -namespace { - namespace N { - extern int x; // \#3 - } -} -export int N::x; // error: \#3 gives internal linkage -\end{codeblocktu} -\end{example} -\end{note} - \pnum \begin{note} Declarations in an exported \grammarterm{namespace-definition} @@ -420,11 +407,11 @@ \pnum A \grammarterm{module-import-declaration} -shall only appear at global namespace scope. +shall inhabit the global namespace scope. In a module unit, all \grammarterm{module-import-declaration}{s} and \grammarterm{export-declaration}{s} exporting \grammarterm{module-import-declaration}{s} -shall precede all other \grammarterm{declaration}{s} in +shall appear before all other \grammarterm{declaration}{s} in the \grammarterm{declaration-seq} of the \grammarterm{translation-unit} and of the \grammarterm{private-module-fragment} (if any). @@ -435,8 +422,8 @@ A \grammarterm{module-import-declaration} \defnx{imports}{import} a set of translation units determined as described below. \begin{note} -Namespace-scope names exported by the imported translation units -become visible\iref{basic.scope.namespace} +Namespace-scope declarations exported by the imported translation units +can be found by name lookup\iref{basic.lookup} in the importing translation unit and declarations within the imported translation units become reachable\iref{module.reach} @@ -527,7 +514,7 @@ in the module unit purview of $U$. \begin{footnote} This is consistent -with the rules for visibility of imported names\iref{basic.scope.namespace}. +with the lookup rules for imported names\iref{basic.lookup}. \end{footnote} These rules can in turn lead to the importation of yet more translation units. @@ -620,14 +607,8 @@ appearing in $S$, or \item -$S$ contains an expression \tcode{E} of the form - -\begin{ncsimplebnf} -postfix-expression \terminal{(} \opt{expression-list} \terminal{)} -\end{ncsimplebnf} -whose \grammarterm{postfix-expression} denotes a dependent name, -or for an operator expression whose operator denotes a dependent name, -and $D$ is found by name lookup for the corresponding name +$S$ contains a dependent call \tcode{E}\iref{temp.dep} +and $D$ is found by name lookup for the dependent name in an expression synthesized from \tcode{E} by replacing each type-dependent argument or operand with a value of a placeholder type @@ -635,8 +616,8 @@ \item $S$ contains an expression that -takes the address of an overloaded function\iref{over.over} -whose set of overloads contains $D$ and +takes the address of an overload set\iref{over.over} +that contains $D$ and for which the target type is dependent, or \item @@ -648,8 +629,8 @@ \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 +and $D$ neither is a friend declaration +nor inhabits a block scope, or \item $D$ declares a namespace $N$ and $M$ is a member of $N$, or \item @@ -870,9 +851,9 @@ \pnum The \defn{instantiation context} is a set of points within the program -that determines which names are visible -to argument-dependent name lookup\iref{basic.lookup.argdep} -and which declarations are reachable\iref{module.reach} +that determines which declarations are found by +argument-dependent name lookup\iref{basic.lookup.argdep} +and which are reachable\iref{module.reach} in the context of a particular declaration or template instantiation. \pnum @@ -983,8 +964,8 @@ \begin{note} While module interface units are reachable even when they are only transitively imported via a non-exported import declaration, -namespace-scope names from such module interface units are not visible -to name lookup\iref{basic.scope.namespace}. +namespace-scope names from such module interface units are not found by +name lookup\iref{basic.lookup}. \end{note} \pnum @@ -1006,9 +987,7 @@ \pnum A declaration $D$ is -\defnx{reachable}{reachable!declaration} if, -for any point $P$ in the -instantiation context\iref{module.context}, +\defnx{reachable from}{reachable from!declaration} a point $P$ if \begin{itemize} \item $D$ appears prior to $P$ in the same translation unit, or \item $D$ is not discarded\iref{module.global.frag}, @@ -1017,6 +996,9 @@ and does not appear within a \grammarterm{private-module-fragment}. \end{itemize} +A declaration is \defnx{reachable}{reachable!declaration} +if it is reachable from +any point in the instantiation context\iref{module.context}. \begin{note} Whether a declaration is exported has no bearing on whether it is reachable. \end{note} @@ -1029,8 +1011,7 @@ 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. +names bound, 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. @@ -1072,8 +1053,8 @@ \pnum \begin{note} -An entity can have reachable declarations -even if it is not visible to name lookup. +Declarations of an entity can be reachable +even where they cannot be found by name lookup. \end{note} \begin{example} \begin{codeblocktu}{Translation unit \#1} From 841248a2dad651ce13e50feba3070e81485b3232 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 21 Nov 2020 20:13:13 +0100 Subject: [PATCH 32/60] class first part --- source/classes.tex | 173 +++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 110 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index c3dce52e63..2e6f0f259e 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -68,11 +68,12 @@ An unnamed class thus can't be \tcode{final}. \end{note} +Otherwise, the \grammarterm{class-name} is an \grammarterm{identifier}; +it is not looked up, and the \grammarterm{class-specifier} introduces it. \pnum -A \grammarterm{class-name} is inserted into the scope in which it is -declared immediately after the \grammarterm{class-name} is seen. The -\grammarterm{class-name} is also inserted into the scope of the class +The +\grammarterm{class-name} is also bound in the scope of the class (template) itself; this is known as the \defn{injected-class-name}. For purposes of access checking, the injected-class-name is treated as if it were a public member name. @@ -87,17 +88,27 @@ \pnum If a \grammarterm{class-head-name} contains a \grammarterm{nested-name-specifier}, -the \grammarterm{class-specifier} shall refer to a class that was -previously declared directly in the class or namespace to which the -\grammarterm{nested-name-specifier} refers, -or in an element of the inline namespace set\iref{namespace.def} of that namespace -(i.e., not merely inherited or -introduced by a \grammarterm{using-declaration}), and the -\grammarterm{class-specifier} shall appear in a namespace enclosing the -previous declaration. -In such cases, the \grammarterm{nested-name-specifier} of the -\grammarterm{class-head-name} of the -definition shall not begin with a \grammarterm{decltype-specifier}. +the \grammarterm{class-specifier} shall not inhabit a class scope. +If its \grammarterm{class-name} is an \grammarterm{identifier}, +the\grammarterm{ class-specifier} shall correspond to +one or more declarations nominable in +the class, class template, or namespace to which the +\grammarterm{nested-name-specifier} refers; +they shall all have the same target scope, and the target scope of the +\grammarterm{class-specifier} is that scope. +\begin{example} +\begin{codeblock} +namespace N { + template + struct A { + struct B; + }; +} +using N::A; +template struct A::B {}; // OK +template<> struct A {}; // error: \tcode{A} not nominable in \tcode{::} +\end{codeblock} +\end{example} \pnum \begin{note} @@ -323,8 +334,8 @@ int f(Y); \end{codeblock} \indextext{overloading}% -declare an overloaded\iref{over} function \tcode{f()} and not -simply a single function \tcode{f()} twice. For the same reason, +declare overloads\iref{over} named \tcode{f} and not +simply a single function \tcode{f} twice. For the same reason, \begin{codeblock} struct S { int a; }; struct S { int a; }; // error: double definition @@ -334,16 +345,11 @@ \pnum \indextext{definition!scope of class}% -\indextext{class name!scope of}% -A class declaration introduces the class name into the scope where -\indextext{name hiding!class definition}% -it is declared and hides any -class, variable, function, or other declaration of that name in an -enclosing scope\iref{basic.scope}. If a class name is declared in a -scope where a variable, function, or enumerator of the same name is also -declared, then when both declarations are in scope, the class can be -referred to only using an -\grammarterm{elaborated-type-specifier}\iref{basic.lookup.elab}. +\begin{note} +It can be necessary to use an \grammarterm{elaborated-type-specifier} +to refer to a class +that belongs to a scope in which its name is also bound to +a variable, function, or enumerator\iref{basic.lookup.elab}. \begin{example} \begin{codeblock} struct stat { @@ -352,20 +358,18 @@ stat gstat; // use plain \tcode{stat} to define variable -int stat(struct stat*); // redeclare \tcode{stat} as function +int stat(struct stat*); // \tcode{stat} now also names a function void f() { struct stat* ps; // \tcode{struct} prefix needed to name \tcode{struct stat} - stat(ps); // call \tcode{stat()} + stat(ps); // call \tcode{stat} function } \end{codeblock} \end{example} \indextext{class name!elaborated}% \indextext{declaration!forward class}% -A \grammarterm{declaration} consisting solely of \grammarterm{class-key} -\grammarterm{identifier}\tcode{;} is either a redeclaration of the name in the current scope -or a forward declaration of the identifier as a class name. It -introduces the class name into the current scope. +An \grammarterm{elaborated-type-specifier} can also be used to declare +an \grammarterm{identifier} as a \grammarterm{class-name}. \begin{example} \begin{codeblock} struct s { int a; }; @@ -378,7 +382,6 @@ } \end{codeblock} \end{example} -\begin{note} Such declarations allow definition of classes that refer to each other. \begin{example} \begin{codeblock} @@ -405,8 +408,8 @@ \begin{note} An \grammarterm{elaborated-type-specifier}\iref{dcl.type.elab} can also be used as a \grammarterm{type-specifier} as part of a declaration. It -differs from a class declaration in that if a class of the elaborated -name is in scope the elaborated name will refer to it. +differs from a class declaration in that it can refer to +an existing class of the given name. \end{note} \begin{example} \begin{codeblock} @@ -503,7 +506,7 @@ full set of members of the class; no member can be added elsewhere. A \defnadj{direct}{member} of a class \tcode{X} is a member of \tcode{X} that was first declared within the \grammarterm{member-specification} of \tcode{X}, -including anonymous union objects\iref{class.union.anon} and direct members thereof. +including anonymous union members\iref{class.union.anon} and direct members thereof. Members of a class are data members, member functions\iref{class.mfct}, nested types, enumerators, and member templates\iref{temp.mem} and specializations thereof. @@ -574,16 +577,24 @@ are sufficiently different\iref{over.load}. \end{note} +\pnum +A redeclaration of a class member outside its class definition shall be +a definition, +an explicit specialization, or +an explicit instantiation (\ref{temp.expl.spec}, \ref{temp.explicit}). +The member shall not be a non-static data member. + \pnum \indextext{completely defined}% -A \defn{complete-class context} of a class is a +A \defn{complete-class context} of a class (template) is a \begin{itemize} \item function body\iref{dcl.fct.def.general}, \item default argument\iref{dcl.fct.default}, +\item default template argument\iref{temp.param}, \item \grammarterm{noexcept-specifier}\iref{except.spec}, or \item default member initializer \end{itemize} -within the \grammarterm{member-specification} of the class. +within the \grammarterm{member-specification} of the class or class template. \begin{note} A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested class is defined within @@ -852,47 +863,15 @@ \pnum \indextext{member function!inline}% \indextext{definition!member function}% -A member function may be defined\iref{dcl.fct.def} in its class definition, -in which case it is an inline\iref{dcl.inline} member function -if it is attached to the global module, or -it may be defined outside of its class -definition if it has already been declared but not defined in its class -definition. +If a member function is attached to the global module and is defined\iref{dcl.fct.def} in its class definition, +it is inline\iref{dcl.inline}. \begin{note} A member function is also inline if it is declared \tcode{inline}, \tcode{constexpr}, or \tcode{consteval}. \end{note} -\pnum -A member function definition that appears outside of the -class definition shall appear in a namespace scope enclosing the class -definition. Except for member function definitions that appear outside -of a class definition, and except for explicit specializations of member -functions of class templates and member function -templates\iref{temp.spec} appearing outside of the class definition, a -member function shall not be redeclared. -\begin{note} -There can be at most one definition of a non-inline member function in -a program. There can be more than one -inline member function definition in a program. -See~\ref{basic.def.odr} and~\ref{dcl.inline}. -\end{note} -\begin{note} -Member functions of a class have the linkage of the name of the class. -See~\ref{basic.link}. -\end{note} - \pnum \indextext{operator!scope resolution}% -If the definition of a member function is lexically outside its class -definition, the member function name shall be qualified by its class -name using the \tcode{::} operator. -\begin{note} -A name used in a member function definition (that is, in the -\grammarterm{parameter-declaration-clause} including the default -arguments\iref{dcl.fct.default} or in the member function body) is looked up -as described in~\ref{basic.lookup}. -\end{note} \begin{example} \begin{codeblock} struct X { @@ -903,8 +882,8 @@ void X::f(T t = count) { } \end{codeblock} -The member function \tcode{f} of class \tcode{X} is defined in global -scope; the notation \tcode{X::f} specifies that the function \tcode{f} +The definition of the member function \tcode{f} of class \tcode{X} inhabits the global +scope; the notation \tcode{X::f} indicates that the function \tcode{f} is a member of class \tcode{X} and in the scope of class \tcode{X}. In the function definition, the parameter type \tcode{T} refers to the typedef member \tcode{T} declared in class \tcode{X} and the default @@ -912,15 +891,6 @@ declared in class \tcode{X}. \end{example} -\pnum -\begin{note} -A \tcode{static} local variable or local type in a member function always refers to -the same entity, whether or not the member function is inline. -\end{note} - -\pnum -Previously declared member functions may be mentioned in friend declarations. - \pnum \indextext{local class!member function in}% Member functions of a local class shall be defined inline in their class @@ -973,9 +943,8 @@ \pnum When an \grammarterm{id-expression}\iref{expr.prim.id} that is not part of a class member access syntax\iref{expr.ref} and not used to form a -pointer to member\iref{expr.unary.op} is used in -a member of class \tcode{X} in a context where \tcode{this} can be -used\iref{expr.prim.this}, +pointer to member\iref{expr.unary.op} is used +where the current class is \tcode{X}\iref{expr.prim.this}, if name lookup\iref{basic.lookup} resolves the name in the \grammarterm{id-expression} to a non-static non-type member of some class @@ -984,7 +953,7 @@ \tcode{C} is \tcode{X} or a base class of \tcode{X}, the \grammarterm{id-expression} is transformed into a class member access expression\iref{expr.ref} using -\tcode{(*this)}\iref{class.this} as the \grammarterm{postfix-expression} +\tcode{(*this)} as the \grammarterm{postfix-expression} to the left of the \tcode{.} operator. \begin{note} If \tcode{C} is not \tcode{X} or a base class of \tcode{X}, the class @@ -1034,29 +1003,13 @@ \indextext{member function!const}% \indextext{member function!volatile}% \indextext{member function!const volatile}% -A non-static member function may be declared \tcode{const}, -\tcode{volatile}, or \tcode{const} \tcode{volatile}. These -\grammarterm{cv-qualifier}{s} affect the type of the \tcode{this} -pointer\iref{class.this}. They also affect the function -type\iref{dcl.fct} of the member function; a member function declared -\tcode{const} is a \defn{const member function}, a member function -declared \tcode{volatile} is a \defn{volatile member function} and a -member function declared \tcode{const} \tcode{volatile} is a -\defn{const volatile member function}. -\begin{example} -\begin{codeblock} -struct X { - void g() const; - void h() const volatile; -}; -\end{codeblock} - -\tcode{X::g} is a const member function and \tcode{X::h} is a -const volatile member function. -\end{example} - -\pnum -A non-static member function may be declared with a \grammarterm{ref-qualifier}\iref{dcl.fct}; see~\ref{over.match.funcs}. +\begin{note} +A non-static member function can be declared with +\grammarterm{cv-qualifier}{s}, which affect the type of the \tcode{this} +pointer\iref{expr.prim.this}, +and/or a \grammarterm{ref-qualifier}\iref{dcl.fct}; +both affect overload resolution\iref{over.match.funcs} +\end{note} \pnum A non-static member function may be declared From 421097c0469ae5500b499b1e079dbdfe864eac11 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 21 Nov 2020 21:17:01 +0100 Subject: [PATCH 33/60] class.this --- source/classes.tex | 80 +----------------------------------------- source/intro.tex | 2 +- source/overloading.tex | 2 +- source/xrefdelta.tex | 1 + 4 files changed, 4 insertions(+), 81 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 2e6f0f259e..722505c96d 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -1015,84 +1015,6 @@ A non-static member function may be declared virtual\iref{class.virtual} or pure virtual\iref{class.abstract}. -\rSec3[class.this]{The \tcode{this} pointer}% -\indextext{\idxcode{this}} -\indextext{member function!\idxcode{this}} - -\pnum -\indextext{this pointer@\tcode{this} pointer|see{\tcode{this}}}% -In the body of a non-static\iref{class.mfct} member function, the -keyword \tcode{this} is a prvalue whose value is -a pointer to the object for which the function is called. -\indextext{\idxcode{this}!type of}% -The type of \tcode{this} in a member function -whose type has a \grammarterm{cv-qualifier-seq} \cv{} and -whose class is \tcode{X} -is ``pointer to \cv{} \tcode{X}''. -\begin{note} -Thus in a const member function, the object for which the function is -called is accessed through a const access path. -\end{note} -\begin{example} -\begin{codeblock} -struct s { - int a; - int f() const; - int g() { return a++; } - int h() const { return a++; } // error -}; - -int s::f() const { return a; } -\end{codeblock} - -The \tcode{a++} in the body of \tcode{s::h} is ill-formed because it -tries to modify (a part of) the object for which \tcode{s::h()} is -called. This is not allowed in a const member function because -\tcode{this} is a pointer to \tcode{const}; that is, \tcode{*this} has -\tcode{const} type. -\end{example} - -\pnum -\begin{note} -Similarly, \tcode{volatile} semantics\iref{dcl.type.cv} apply in -volatile member functions when accessing the object and its -non-static data members. -\end{note} - -\pnum -A member function whose type has a \grammarterm{cv-qualifier-seq} \cvqual{cv1} -can be called on an -object expression\iref{expr.ref} of type \cvqual{cv2} \tcode{T} only -if \cvqual{cv1} is the same as or more cv-qualified than \cvqual{cv2}\iref{basic.type.qualifier}. -\begin{example} -\begin{codeblock} -void k(s& x, const s& y) { - x.f(); - x.g(); - y.f(); - y.g(); // error -} -\end{codeblock} - -The call \tcode{y.g()} is ill-formed because \tcode{y} is \tcode{const} -and \tcode{s::g()} is a non-const member function, that is, -\tcode{s::g()} is less-qualified than the object expression \tcode{y}. -\end{example} - -\pnum -\indextext{\idxcode{const}!constructor and}% -\indextext{\idxcode{const}!destructor and}% -\indextext{\idxcode{volatile}!constructor and}% -\indextext{\idxcode{volatile}!destructor and}% -\begin{note} -Constructors and destructors -cannot be declared \tcode{const}, \tcode{volatile}, or \tcode{const} -\tcode{volatile}. -However, these functions can be invoked -to create and destroy objects with cv-qualified types; -see~\ref{class.ctor} and~\ref{class.dtor}. -\end{note} - \rSec2[special]{Special member functions} \indextext{~@\tcode{\~}|see{destructor}}% @@ -2774,7 +2696,7 @@ \pnum \begin{note} A static member function does not have a \tcode{this} -pointer\iref{class.this}. +pointer\iref{expr.prim.this}. A static member function cannot be declared \tcode{virtual}\iref{dcl.fct.spec}. There cannot be a static and a non-static member function with the same name, parameter-type-list, and trailing \grammarterm{requires-clause}\iref{over.load}. diff --git a/source/intro.tex b/source/intro.tex index fbc90fb5fc..ae03349682 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -434,7 +434,7 @@ \begin{defnote} Observer functions are specified as \tcode{const} -member functions\iref{class.this}. +member functions. \end{defnote} \indexdefn{parameter}% diff --git a/source/overloading.tex b/source/overloading.tex index 3bcbb3444e..7ad38582dd 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -833,7 +833,7 @@ in the call augmented by the addition of an implied object argument as in a qualified function call. If the keyword -\tcode{this}\iref{class.this} is in scope and refers to +\tcode{this}\iref{expr.prim.this} is in scope and refers to class \tcode{T}, or a derived class of diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 538af245bd..d18431eb23 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -29,6 +29,7 @@ \movedxref{basic.scope.hiding}{basic.lookup} \movedxref{basic.lookup.classref}{basic.lookup.qual} \movedxref{namespace.memdef}{namespace.def} +\movedxref{class.this}{expr.prim.this} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From 3ba0e2610c555faba292fa2c2af179ed9430f051 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 21 Nov 2020 22:23:56 +0100 Subject: [PATCH 34/60] class next part --- source/classes.tex | 204 +++++++++++++++++-------------------------- source/xrefdelta.tex | 1 + 2 files changed, 83 insertions(+), 122 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 722505c96d..349b46db9e 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -921,7 +921,6 @@ \rSec2[class.mfct.non-static]{Non-static member functions}% -\rSec3[class.mfct.non-static.general]{General}% \indextext{member function!non-static} \pnum @@ -1115,8 +1114,7 @@ \indextext{special member function|see{constructor}}% \pnum -A \defn{constructor} is introduced by a declaration -whose \grammarterm{declarator} is a +A \grammarterm{declarator} declares a \defn{constructor} if it is a function declarator\iref{dcl.fct} of the form \begin{ncbnf} ptr-declarator \terminal{(} parameter-declaration-clause \terminal{)} \opt{noexcept-specifier} \opt{attribute-specifier-seq} @@ -1127,16 +1125,20 @@ one of the following forms: \begin{itemize} \item -in a \grammarterm{member-declaration} that belongs to the -\grammarterm{member-specification} of a class or class template -but is not a friend -declaration\iref{class.friend}, the \grammarterm{id-expression} is the -injected-class-name\iref{class.pre} of the immediately-enclosing entity or +in a friend declaration\iref{class.friend}, +the \grammarterm{id-expression} is a \grammarterm{qualified-id} +that names a constructor\iref{class.qual}; +\item +otherwise, in a \grammarterm{member-declaration} that belongs to the +\grammarterm{member-specification} of a class or class template, +the \grammarterm{id-expression} is the +injected-class-name\iref{class.pre} of the immediately-enclosing entity; \item -in a declaration at namespace scope or in a friend declaration, the -\grammarterm{id-expression} is a \grammarterm{qualified-id} that names a -constructor\iref{class.qual}. +otherwise, the +\grammarterm{id-expression} is a \grammarterm{qualified-id} +whose \grammarterm{unqualified-id} is +the injected-class-name of its lookup context. \end{itemize} Constructors do not have names. In a constructor declaration, each \grammarterm{decl-specifier} in the optional @@ -1155,11 +1157,11 @@ \pnum \indextext{constructor!explicit call}% A constructor is used to initialize objects of its class type. +\begin{note} Because constructors do not have names, they are never found during name lookup; however an explicit type conversion using the functional notation\iref{expr.type.conv} will cause a constructor to be called to initialize an object. -\begin{note} The syntax looks like an explicit call of the constructor. \end{note} \begin{example} @@ -1871,17 +1873,13 @@ if not declared by the user, a base class copy/move assignment operator is always hidden by the corresponding assignment operator of a derived class\iref{over.ass}. -A -\grammarterm{using-declaration}\iref{namespace.udecl} that brings in from a base class an assignment operator +\begin{note} +A \grammarterm{using-declaration} that names an assignment operator with a parameter type that could be that of a -copy/move assignment operator for the -derived class is not considered an explicit declaration of such an -operator and does not suppress the implicit declaration of the derived class -operator; -the operator introduced by the -\grammarterm{using-declaration} -is hidden by the implicitly-declared operator in the derived -class. +copy/move assignment operator for a +derived class does not suppress the implicit declaration of the derived class +operator\iref{namespace.udecl}. +\end{note} \pnum \indextext{assignment operator!copy!trivial}% @@ -2006,11 +2004,12 @@ \rSec2[class.dtor]{Destructors}% \indextext{destructor}% \indextext{special member function|see{destructor}}% - +\defnadj{prospective}{destructor} is introduced by a \pnum -A \defnadj{prospective}{destructor} is introduced by a declaration -whose \grammarterm{declarator} is a -function declarator\iref{dcl.fct} of the form +A declaration whose \grammarterm{declarator-id} +has an \grammarterm{unqualified-id} that begins with a \tcode{\~} +declares a \defnadj{prospective}{destructor}; +its declarator shall be a function declarator\iref{dcl.fct} of the form \begin{ncbnf} ptr-declarator \terminal{(} parameter-declaration-clause \terminal{)} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \end{ncbnf} @@ -2028,10 +2027,11 @@ injected-class-name\iref{class.pre} of the immediately-enclosing entity or \item -in a declaration at namespace scope or in a friend declaration, the +otherwise, the \grammarterm{id-expression} is \grammarterm{nested-name-specifier} -\tcode{\~}\grammarterm{class-name} and the \grammarterm{class-name} names the -same class as the \grammarterm{nested-name-specifier}. +\tcode{\~}\grammarterm{class-name} and the \grammarterm{class-name} +is the injected-class-name of the +class nominated by the \grammarterm{nested-name-specifier}. \end{itemize} A prospective destructor shall take no arguments\iref{dcl.fct}. @@ -2158,8 +2158,6 @@ If the destructor of a class is virtual and any objects of that class or any derived class are created in the program, the destructor shall be defined. -If a class has a base class with a virtual destructor, its destructor -(whether user- or implicitly-declared) is virtual. \pnum \begin{note} @@ -2400,30 +2398,6 @@ \end{codeblock} \end{example} -\pnum -User-defined conversions are used implicitly only if they are unambiguous. -\indextext{name hiding!user-defined conversion and}% -A conversion function in a derived class does not hide a conversion function -in a base class unless the two functions convert to the same type. -Function overload resolution\iref{over.match.best} selects the best -conversion function to perform the conversion. -\begin{example} -\begin{codeblock} -struct X { - operator int(); -}; - -struct Y : X { - operator char(); -}; - -void f(Y& a) { - if (a) { // error: ambiguous between \tcode{X::operator int()} and \tcode{Y::operator char()} - } -} -\end{codeblock} -\end{example} - \rSec3[class.conv.ctor]{Conversion by constructor}% \indextext{conversion!user-defined}% @@ -2498,7 +2472,7 @@ \indextext{conversion!user-defined}% \pnum -A member function of a class \tcode{X} having no parameters with a name of the form +A member function of a class \tcode{X} with a name of the form \begin{bnf} \nontermdef{conversion-function-id}\br \keyword{operator} conversion-type-id @@ -2513,10 +2487,10 @@ \nontermdef{conversion-declarator}\br ptr-operator \opt{conversion-declarator} \end{bnf} -specifies a conversion from -\tcode{X} -to the type specified by the -\grammarterm{conversion-type-id}. +shall have no parameters and +specifies a conversion from \tcode{X} to +the type specified by the \grammarterm{conversion-type-id}, +interpreted as a \grammarterm{type-id}\iref{dcl.name}. Such functions are called \defnx{conversion functions}{conversion function}. A \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} of a conversion function (if any) shall be neither @@ -2608,7 +2582,32 @@ \pnum \indextext{conversion!inheritance of user-defined}% -Conversion functions are inherited. +\begin{note} +A conversion function in a derived class hides only +conversion functions in base classes that convert to the same type. +A conversion function template with a dependent return type hides only +templates in base classes that correspond to it\iref{class.member.lookup}; +otherwise, it hides and is hidden as a non-template function. +Function overload resolution\iref{over.match.best} selects +the best conversion function to perform the conversion. +\begin{example} +\begin{codeblock} +struct X { + operator int(); +}; + +struct Y : X { + operator char(); +}; + +void f(Y& a) { + if (a) { // error: ambiguous between \tcode{X::operator int()} and \ +code{Y::operator char()} + } +} +\end{codeblock} +\end{example} +\end{note} \pnum \indextext{conversion!virtual user-defined}% @@ -2654,26 +2653,6 @@ \end{codeblock} \end{example} -\pnum -A static member may be referred to directly in the scope of its -class or in the scope of a class derived\iref{class.derived} -from its class; in this case, the static member is referred to -as if a \grammarterm{qualified-id} expression was used, with the -\grammarterm{nested-name-specifier} of the \grammarterm{qualified-id} naming -the class scope from which the static member is referenced. -\begin{example} -\begin{codeblock} -int g(); -struct X { - static int g(); -}; -struct Y : X { - static int i; -}; -int Y::i = g(); // equivalent to \tcode{Y::g();} -\end{codeblock} -\end{example} - \pnum Static members obey the usual class member access rules\iref{class.access}. When used in the declaration of a class @@ -2697,11 +2676,8 @@ \begin{note} A static member function does not have a \tcode{this} pointer\iref{expr.prim.this}. -A static member function cannot be declared \tcode{virtual}\iref{dcl.fct.spec}. -There cannot be a static and a non-static member function with -the same name, parameter-type-list, and trailing \grammarterm{requires-clause}\iref{over.load}. -A static member function cannot not be declared \tcode{const}, -\tcode{volatile}, or \tcode{const volatile}\iref{dcl.fct}. +A static member function cannot be qualified with \tcode{const}, +\tcode{volatile}, or \tcode{virtual}\iref{dcl.fct}. \end{note} \rSec3[class.static.data]{Static data members} @@ -2726,16 +2702,13 @@ The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than -\cv{}~\tcode{void}. The definition for a static data -member that is not defined inline in the class definition -shall appear in a namespace scope enclosing the member's class -definition. +\cv{}~\tcode{void}. \indextext{operator use!scope resolution}% -In the definition at namespace scope, the name of the static -data member shall be qualified by its class name using the \tcode{::} -operator. The \grammarterm{initializer} expression in the definition of a +\begin{note} +The \grammarterm{initializer} in the definition of a static data member is in the scope of its class\iref{basic.scope.class}. +\end{note} \begin{example} \begin{codeblock} class process { @@ -2747,8 +2720,8 @@ process* process::run_chain = running; \end{codeblock} -The static data member \tcode{run_chain} of class -\tcode{process} is defined in global scope; the notation +The definition of the static data member \tcode{run_chain} of class +\tcode{process} inhabits the global scope; the notation \tcode{process::run_chain} specifies that the member \tcode{run_chain} is a member of class \tcode{process} and in the scope of class \tcode{process}. In the static data member definition, the @@ -2763,6 +2736,8 @@ In the example above, \tcode{run_chain} and \tcode{running} exist even if no objects of class \tcode{process} are created by the program. \end{example} +The initialization and destruction of static data members are described in +\ref{basic.start.static}, \ref{basic.start.dynamic}, and \ref{basic.start.term}. \end{note} \pnum @@ -2775,8 +2750,8 @@ The member shall still be defined in a namespace scope if it is odr-used\iref{basic.def.odr} in the program and the namespace scope definition shall not contain an \grammarterm{initializer}. -An inline static data member may be defined in the class definition -and may specify a \grammarterm{brace-or-equal-initializer}. If the +The declaration of an inline static data member (which is a definition) +may specify a \grammarterm{brace-or-equal-initializer}. If the member is declared with the \tcode{constexpr} specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see \ref{depr.static.constexpr}). Declarations of other @@ -2793,11 +2768,6 @@ Static data members of a class in namespace scope have the linkage of the name of the class\iref{basic.link}. \end{note} -\pnum -Static data members are initialized and destroyed exactly like -non-local variables~(\ref{basic.start.static}, \ref{basic.start.dynamic}, -\ref{basic.start.term}). - \rSec2[class.bit]{Bit-fields}% \indextext{bit-field} @@ -2900,10 +2870,7 @@ \pnum A class can be declared within another class. A class declared within -another is called a \defnadj{nested}{class}. The name of a nested class -is local to its enclosing class. -\indextext{nested class!scope of}% -The nested class is in the scope of its enclosing class. +another is called a \defnadj{nested}{class}. \begin{note} See~\ref{expr.prim.id} for restrictions on the use of non-static data members and non-static member functions. @@ -2932,13 +2899,16 @@ }; }; -inner* p = 0; // error: \tcode{inner} not in scope +inner* p = 0; // error: \tcode{inner} not found \end{codeblock} \end{example} \pnum -Member functions and static data members of a nested class can be -defined in a namespace scope enclosing the definition of their class. +\begin{note} +Nested classes can be defined +either in the enclosing class or in an enclosing namespace; +member functions and static data members of a nested class can be +defined either in the nested class or in an enclosing namespace scope. \begin{example} \begin{codeblock} struct enclose { @@ -2951,16 +2921,7 @@ int enclose::inner::x = 1; void enclose::inner::f(int i) { @\commentellip@ } -\end{codeblock} -\end{example} -\pnum -If class \tcode{X} is defined in a namespace scope, a nested class -\tcode{Y} may be declared in class \tcode{X} and later defined in the -definition of class \tcode{X} or be later defined in a namespace scope -enclosing the definition of class \tcode{X}. -\begin{example} -\begin{codeblock} class E { class I1; // forward declaration of nested class class I2; @@ -2969,13 +2930,12 @@ class E::I2 { }; // definition of nested class \end{codeblock} \end{example} +\end{note} \pnum \indextext{friend function!nested class}% -Like a member function, a friend function\iref{class.friend} defined -within a nested class is in the lexical scope of that class; it obeys -the same rules for name binding as a static member function of that -class\iref{class.static}, but it has no special access rights to +A friend function\iref{class.friend} defined +within a nested class has no special access rights to members of an enclosing class. \rSec2[class.nested.type]{Nested type names} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index d18431eb23..5214e8df94 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -30,6 +30,7 @@ \movedxref{basic.lookup.classref}{basic.lookup.qual} \movedxref{namespace.memdef}{namespace.def} \movedxref{class.this}{expr.prim.this} +\movedxref{class.mfct.non-static.general}{class.mfct.non-static} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From 01cb09adf3301c25bac6a5185d04c7af54641a19 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 21 Nov 2020 22:26:55 +0100 Subject: [PATCH 35/60] class.nested.type removed --- source/classes.tex | 24 ------------------------ source/compatibility.tex | 2 +- source/xrefdelta.tex | 1 + 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 349b46db9e..f21f691626 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2938,30 +2938,6 @@ within a nested class has no special access rights to members of an enclosing class. -\rSec2[class.nested.type]{Nested type names} -\indextext{type name!nested}% -\indextext{type name!nested!scope of}% - -\pnum -Type names obey exactly the same scope rules as other names. In -particular, type names defined within a class definition cannot be used -outside their class without qualification. -\begin{example} -\begin{codeblock} -struct X { - typedef int I; - class Y { @\commentellip@ }; - I a; -}; - -I b; // error -Y c; // error -X::Y d; // OK -X::I e; // OK -\end{codeblock} -\end{example} -\indextext{class|)} - \rSec1[class.union]{Unions}% \rSec2[class.union.general]{General}% diff --git a/source/compatibility.tex b/source/compatibility.tex index 4fd3a14948..7e8ca80d18 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -2603,7 +2603,7 @@ \howwide Seldom. -\diffref{class.nested.type} +\diffref{class.member.lookup} \change In \Cpp{}, a typedef name may not be redeclared in a class definition after being used in that definition. diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 5214e8df94..ef22529cba 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -31,6 +31,7 @@ \movedxref{namespace.memdef}{namespace.def} \movedxref{class.this}{expr.prim.this} \movedxref{class.mfct.non-static.general}{class.mfct.non-static} +\movedxref{class.nested.type}{diff.basic} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From 244f9f37d420b3c0085ae9c658664e706ac6daf6 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 22 Nov 2020 20:40:42 +0100 Subject: [PATCH 36/60] classes (rest) --- source/classes.tex | 346 +++++++++++++++++++-------------------------- 1 file changed, 149 insertions(+), 197 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index f21f691626..9208eb516d 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -3115,19 +3115,18 @@ \keyword{union} \terminal{\{} member-specification \terminal{\}} \terminal{;} \end{ncsimplebnf} is called an \defn{anonymous union}; it defines an unnamed type and -an unnamed object of that type called an \defn{anonymous union object}. +an unnamed object of that type called +an \defn{anonymous union member} if it is a non-static data member or +an \defn{anonymous union variable} otherwise. \indextext{access control!anonymous \tcode{union}}% \indextext{restriction!anonymous \tcode{union}}% Each \grammarterm{member-declaration} in the \grammarterm{member-specification} -of an anonymous union shall either define a public non-static data member or +of an anonymous union shall either define one or more public non-static data members or be a \grammarterm{static_assert-declaration}. Nested types, anonymous unions, and functions shall not be declared within an anonymous union. -The names of the members of an anonymous union shall be distinct from -the names of any other entity in the scope in which the anonymous union -is declared. For the purpose of name lookup, after the anonymous union -definition, the members of the anonymous union are considered to have -been defined in the scope in which the anonymous union is declared. +The names of the members of an anonymous union +are bound in the scope inhabited by the union declaration. \begin{example} \begin{codeblock} void f() { @@ -3144,10 +3143,10 @@ \pnum \indextext{\idxcode{union}!global anonymous}% \indextext{scope!anonymous \tcode{union} at namespace}% -Anonymous unions declared in a named namespace or in the global -namespace shall be declared \tcode{static}. Anonymous unions declared at +Anonymous unions declared in the scope of a namespace with external linkage +shall be declared \tcode{static}. Anonymous unions declared at block scope shall be declared with any storage class allowed for a -block-scope variable, or with no storage class. A storage class is not +block variable, or with no storage class. A storage class is not allowed in a declaration of an anonymous union in a class scope. \pnum @@ -3202,11 +3201,7 @@ \pnum A class can be declared within a function definition; such a class is -called a \defnadj{local}{class}. The name of a local class is local to -its enclosing scope. -\indextext{local class!scope of}% -The local class is in the scope of the enclosing scope, and has the same -access to names outside the function as does the enclosing function. +called a \defnadj{local}{class}. \begin{note} A declaration in a local class cannot odr-use\iref{basic.def.odr} @@ -3236,7 +3231,7 @@ }; } -local* p = 0; // error: \tcode{local} not in scope +local* p = 0; // error: \tcode{local} not found \end{codeblock} \end{example} @@ -3317,6 +3312,11 @@ The optional \grammarterm{attribute-specifier-seq} appertains to the \grammarterm{base-specifier}. \pnum +\indextext{component name}% +The component names of a \grammarterm{class-or-decltype} are those of its +\grammarterm{nested-name-specifier}, +\grammarterm{type-name}, and/or +\grammarterm{simple-template-id}. \indextext{type!incomplete}% A \grammarterm{class-or-decltype} shall denote a (possibly cv-qualified) class type that is not @@ -3328,8 +3328,9 @@ for the class being defined. \indextext{base class}% \indextext{derivation|see{inheritance}}% -During the lookup for a base class name, non-type names are -ignored\iref{basic.lookup}. +The lookup for the component name of +the \grammarterm{type-name} or \grammarterm{simple-template-id} +is type-only\iref{basic.lookup}. A class \tcode{B} is a base class of a class \tcode{D} if it is a direct base class of \tcode{D} or a direct base class of one of \tcode{D}'s base classes. @@ -3342,21 +3343,17 @@ \grammarterm{access-specifier}. \end{note} \indextext{access control!base class member}% -Unless redeclared in the derived class, members of a base class are also -considered to be members of the derived class. -Members of a base class other than constructors are said to be -\defnx{inherited}{inheritance} -by the derived class. Constructors of a base class -can also be inherited as described in~\ref{namespace.udecl}. -Inherited members can be referred to in +Members of a base class are also members of the derived class. +\begin{note} +Constructors of a base class can be explicitly inherited\iref{namespace.udecl}. +Base class members can be referred to in expressions in the same manner as other members of the derived class, unless their names are hidden or ambiguous\iref{class.member.lookup}. \indextext{operator!scope resolution}% -\begin{note} The scope resolution operator \tcode{::}\iref{expr.prim.id.qual} can be used -to refer to a direct or indirect base member explicitly. This allows -access to a name that has been redeclared in the derived class. A -derived class can itself serve as a base class subject to access +to refer to a direct or indirect base member explicitly, +even if it is hidden in the derived class. +A derived class can itself serve as a base class subject to access control; see~\ref{class.access.base}. A pointer to a derived class can be implicitly converted to a pointer to an accessible unambiguous base class\iref{conv.ptr}. An lvalue of a derived class type can be bound @@ -3468,9 +3465,10 @@ \begin{note} A class can be an indirect base class more than once and can be a direct and an indirect base class. There are limited things that can be done -with such a class. The non-static data members and member functions of -the direct base class cannot be referred to in the scope of the derived -class. However, the static members, enumerations and types can be +with such a class; +lookup that finds its non-static data members and member functions +in the scope of the derived class will be ambiguous. +However, the static members, enumerations and types can be unambiguously referred to. \end{note} \begin{example} @@ -3598,8 +3596,7 @@ Virtual functions support dynamic binding and object-oriented programming. \end{note} -A class that declares or inherits a virtual function is -called a \defnadj{polymorphic}{class}. +A class with a virtual member function is called a \defnadj{polymorphic}{class}. \begin{footnote} If all virtual functions are immediate functions, @@ -3609,12 +3606,12 @@ \end{footnote} \pnum -If a virtual member function \tcode{vf} is declared in a class -\tcode{Base} and in a class \tcode{Derived}, derived directly or -indirectly from \tcode{Base}, a member function \tcode{vf} with the same -name, parameter-type-list\iref{dcl.fct}, cv-qualification, and ref-qualifier -(or absence of same) as \tcode{Base::vf} is declared, -then \tcode{Derived::vf} \term{overrides} +If a virtual member function $F$ is declared in a class $B$ and +in a class $D$ derived (directly or indirectly) from $B$ +a declaration of a member function $G$ +that corresponds\iref{basic.scope.scope} to a declaration of $F$, +ignoring \grammarterm{trailing requires-clause}s, +then $G$ \term{overrides} \begin{footnote} A function with the same name but a different parameter list\iref{over} @@ -3622,13 +3619,13 @@ does not override. Access control\iref{class.access} is not considered in determining overriding. \end{footnote} -\tcode{Base::vf}. For convenience we say that any virtual function -overrides itself. +$F$. +For convenience we say that any virtual function overrides itself. \indextext{overrider!final}% -A virtual member function \tcode{C::vf} of a class object \tcode{S} is a \defn{final -overrider} unless the most derived class\iref{intro.object} of which \tcode{S} is a -base class subobject (if any) declares or inherits another member function that overrides -\tcode{vf}. In a derived class, if a virtual member function of a base class subobject +A virtual member function $V$ of a class object $S$ is a \defn{final +overrider} unless the most derived class\iref{intro.object} of which $S$ is a +base class subobject (if any) has another member function that overrides $V$. +In a derived class, if a virtual member function of a base class subobject has more than one final overrider the program is ill-formed. \begin{example} \begin{codeblock} @@ -3727,11 +3724,6 @@ \end{codeblock} \end{example} -\pnum -Even though destructors are not inherited, a destructor in a derived -class overrides a base class destructor declared virtual; -see~\ref{class.dtor} and~\ref{class.free}. - \pnum The return type of an overriding function shall be either identical to the return type of the overridden function or \defnx{covariant}{return type!covariant} with @@ -3760,7 +3752,7 @@ \pnum If the class type in the covariant return type of \tcode{D::f} differs from that of \tcode{B::f}, the class type in the return type of \tcode{D::f} shall be -complete at the point of declaration of \tcode{D::f} or shall be the +complete at the locus of the overriding declaration or shall be the class type \tcode{D}. When the overriding function is called as the final overrider of the overridden function, its result is converted to the type returned by the (statically chosen) overridden @@ -4024,7 +4016,7 @@ \pnum \indextext{function!virtual!pure}% -A class is abstract if it contains or inherits at least one pure virtual +A class is abstract if it has at least one pure virtual function for which the final overrider is pure virtual. \begin{example} \begin{codeblock} @@ -4084,24 +4076,28 @@ \item \indextext{access control!\idxcode{private}}% private; -that is, its name can be used only by members and friends +that is, it can be named only by members and friends of the class in which it is declared. \item \indextext{access control!\idxcode{protected}}% protected; -that is, its name can be used only by members and friends +that is, it can be named only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see~\ref{class.protected}). \item \indextext{access control!\idxcode{public}}% public; -that is, its name can be used anywhere without access restriction. +that is, it can be named anywhere without access restriction. \end{itemize} +\begin{note} +A constructor or destructor can be named by an expression\iref{basic.def.odr} +even though it has no name. +\end{note} \pnum -A member of a class can also access all the names to which the class has access. +A member of a class can also access all the members to which the class has access. A local class of a member function may access -the same names that the member function itself may access. +the same members that the member function itself may access. \begin{footnote} Access permissions are thus transitive and cumulative to nested @@ -4133,17 +4129,18 @@ \end{example} \pnum -Access control is applied uniformly to all names, whether the names are -referred to from declarations or expressions. +Access control is applied uniformly to declarations and expressions. \begin{note} -Access control applies to names nominated by +Access control applies to members nominated by friend declarations\iref{class.friend} and \grammarterm{using-declaration}{s}\iref{namespace.udecl}. \end{note} -In the case of overloaded function names, access control is applied to +When a \grammarterm{using-declarator} is named, +access control is applied to it, not to the declarations that replace it. +For an overload set, access control is applied only to the function selected by overload resolution. \begin{note} -Because access control applies to names, if access control is applied to a +Because access control applies to the declarations named, if access control is applied to a typedef name, only the accessibility of the typedef name itself is considered. The accessibility of the entity referred to by the typedef is not considered. For example, @@ -4164,21 +4161,18 @@ \pnum \begin{note} -Access to members and base classes is controlled, not their -visibility\iref{basic.lookup}. -Names of members are still visible, and implicit conversions to base -classes are still considered, when those members and base classes are -inaccessible. +Access control does not prevent members from being found by name lookup or +implicit conversions to base classes from being considered. \end{note} The interpretation of a given construct is established without regard to access control. If the interpretation -established makes use of inaccessible member names or base classes, +established makes use of inaccessible members or base classes, the construct is ill-formed. \pnum -All access controls in \ref{class.access} affect the ability to access a class member -name from the declaration of a particular +All access controls in \ref{class.access} affect the ability to name a class member +from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's \grammarterm{member-specification}{.} @@ -4237,16 +4231,16 @@ \pnum \indextext{argument!access checking and default}% \indextext{access control!default argument}% -The names in a default argument\iref{dcl.fct.default} are -bound at the point of declaration, and access is checked at that -point rather than at any points of use of the default argument. +Access is checked for a default argument\iref{dcl.fct.default} +at the point of declaration, +rather than at any points of use of the default argument. Access checking for default arguments in function templates and in member functions of class templates is performed as described in~\ref{temp.inst}. \pnum -The names in a default \grammarterm{template-argument}\iref{temp.param} -have their access checked in the context in which they appear rather than at any -points of use of the default \grammarterm{template-argument}. +Access for a default \grammarterm{template-argument}\iref{temp.param} +is checked in the context in which it appears rather than at any +points of use of it. \begin{example} \begin{codeblock} class B { }; @@ -4427,8 +4421,8 @@ \pnum \begin{note} -A member of a private base class might be inaccessible as an inherited -member name, but accessible directly. +A member of a private base class might be inaccessible as inherited, +but accessible directly. Because of the rules on pointer conversions\iref{conv.ptr} and explicit casts~(\ref{expr.type.conv}, \ref{expr.static.cast}, \ref{expr.cast}), a conversion from a pointer to a derived class to a pointer @@ -4548,8 +4542,8 @@ \end{note} The access to a member is affected by the class in which the member is named. -This naming class is the class in which the member name was looked -up and found. +This naming class is +the class in whose scope name lookup performed a search that found the member. \begin{note} This class can be explicit, e.g., when a \grammarterm{qualified-id} @@ -4656,7 +4650,7 @@ \pnum A friend of a class is a function or class that is -given permission to use the private and protected member names from the class. +given permission to name the private and protected members of the class. A class specifies its friends, if any, by way of friend declarations. Such declarations give special access rights to the friends, but they do not make the nominated friends members of the befriending class. @@ -4686,8 +4680,8 @@ \pnum \indextext{friend!class access and}% -Declaring a class to be a friend implies that the names of private and -protected members from the class granting friendship can be accessed in the +Declaring a class to be a friend implies that private and +protected members of the class granting friendship can be named in the \grammarterm{base-specifier}{s} and member declarations of the befriended class. \begin{example} @@ -4722,15 +4716,6 @@ \end{codeblock} \end{example} -A class shall not be defined in a friend declaration. -\begin{example} -\begin{codeblock} -class A { - friend class B { }; // error: cannot define class in friend declaration -}; -\end{codeblock} -\end{example} - \pnum A friend declaration that does not declare a function shall have one of the following forms: @@ -4761,7 +4746,7 @@ class X2 { friend Ct; // OK: \tcode{class C} is a friend - friend D; // error: no type-name \tcode{D} in scope + friend D; // error: \tcode{D} not found friend class D; // OK: elaborated-type-specifier declares new class }; @@ -4782,9 +4767,8 @@ \pnum \indextext{declaration!overloaded name and \tcode{friend}}% -When a friend -declaration refers to an overloaded name or operator, only the function specified -by the parameter types becomes a friend. +\begin{note} +A friend declaration refers to an entity, not (all overloads) of a name. A member function of a class \tcode{X} can be a friend of @@ -4800,12 +4784,12 @@ }; \end{codeblock} \end{example} +\end{note} \pnum \indextext{friend function!inline}% -A function can be defined in a friend declaration of a class if and only if the -class is a non-local class\iref{class.local}, the function name is unqualified, -and the function has namespace scope. +A function may be defined in a friend declaration of a class if and only if the +class is a non-local class\iref{class.local} and the function name is unqualified. \begin{example} \begin{codeblock} class M { @@ -4818,9 +4802,10 @@ \pnum Such a function is implicitly an inline\iref{dcl.inline} function if it is attached to the global module. -A friend -function defined in a class is in the (lexical) scope of the class in which it is defined. -A friend function defined outside the class is not\iref{basic.lookup.unqual}. +\begin{note} +If a friend function is defined outside a class, +it is not in the scope of the class. +\end{note} \pnum No @@ -4831,7 +4816,7 @@ \pnum \indextext{friend!access specifier and}% -A name nominated by a friend declaration shall be accessible in the scope of the +A member nominated by a friend declaration shall be accessible in the class containing the friend declaration. The meaning of the friend declaration is the same whether the friend declaration appears in the private, protected, or public\iref{class.mem} @@ -4869,18 +4854,43 @@ \pnum \indextext{local class!friend}% \indextext{friend!local class and}% -If a friend declaration appears in a local class\iref{class.local} and the -name specified is an unqualified name, a prior declaration is looked -up without considering scopes that are outside the innermost enclosing -non-class scope. -For a friend function declaration, if there is no -prior declaration, the program is ill-formed. -For a friend class -declaration, if there is no prior declaration, the class that is -specified belongs to the innermost enclosing non-class scope, but if it is -subsequently referenced, its name is not found by name lookup -until a matching declaration is provided in the innermost enclosing -non-class scope. +\begin{note} +A friend declaration never binds any names +(\ref{dcl.meaning}, \ref{dcl.type.elab}). +\end{note} +\begin{example} +\begin{codeblock} +// Assume \tcode{f} and \tcode{g} have not yet been declared. +void h(int); +template void f2(T); +namespace A { + class X { + friend void f(X); // \tcode{A::f(X)} is a friend + class Y { + friend void g(); // \tcode{A::g} is a friend + friend void h(int); // \tcode{A::h} is a friend + // \tcode{::h} not considered + friend void f2<>(int); // \tcode{::f2<>(int)} is a friend + }; + }; + + // \tcode{A::f}, \tcode{A::g} and \tcode{A::h} are not visible here + X x; + void g() { f(x); } // definition of \tcode{A::g} + void f(X) { @\commentellip@ } // definition of \tcode{A::f} + void h(int) { @\commentellip@ } // definition of \tcode{A::h} + // \tcode{A::f}, \tcode{A::g} and \tcode{A::h} are visible here and known to be friends +} + +using A::x; + +void h() { + A::f(x); + A::X::f(x); // error: \tcode{f} is not a member of \tcode{A::X} + A::X::Y::g(); // error: \tcode{g} is not a member of \tcode{A::X::Y} +} +\end{codeblock} +\end{example} \begin{example} \begin{codeblock} class X; @@ -5009,7 +5019,7 @@ \indextext{access control!multiple access} \pnum -If a name can be reached by several paths through a multiple inheritance +If a declaration can be reached by several paths through a multiple inheritance graph, the access is that of the path that gives most access. \begin{example} \begin{codeblock} @@ -5240,10 +5250,8 @@ \end{bnf} \pnum -In a \grammarterm{mem-initializer-id} an initial unqualified -\grammarterm{identifier} is looked up in the scope of the constructor's class -and, if not found in that scope, it is looked up in the scope containing the -constructor's definition. +Lookup for an unqualified name in a \grammarterm{mem-initializer-id} +ignores the constructor's function parameter scope. \begin{note} If the constructor's class contains a member with the same name as a direct or virtual base class of the class, a @@ -5281,7 +5289,7 @@ If a \grammarterm{mem-initializer-id} is ambiguous because it designates both a direct non-virtual base class and -an inherited virtual base class, the +an indirect virtual base class, the \grammarterm{mem-initializer} is ill-formed. \begin{example} @@ -5569,14 +5577,12 @@ \pnum \indextext{initializer!scope of member}% -Names in the -\grammarterm{expression-list} -or \grammarterm{braced-init-list} -of a -\grammarterm{mem-initializer} -are evaluated in the scope of the constructor for which the -\grammarterm{mem-initializer} -is specified. +\begin{note} +The \grammarterm{expression-list} or \grammarterm{braced-init-list} +of a \grammarterm{mem-initializer} +is in the function parameter scope of the constructor +and can use \keyword{this} to refer to the object being initialized. +\end{note} \begin{example} \begin{codeblock} class X { @@ -5610,17 +5616,6 @@ \tcode{X} is created. \end{example} -\begin{note} -Because the -\grammarterm{mem-initializer} -are evaluated in the scope of the constructor, the -\tcode{this} -pointer can be used in the -\grammarterm{expression-list} -of a -\grammarterm{mem-initializer} -to refer to the object being initialized. -\end{note} \pnum \indextext{initialization!member function call during}% @@ -6103,8 +6098,9 @@ \item in a \grammarterm{throw-expression}\iref{expr.throw}, when the operand is the name of a non-volatile object with automatic storage duration (other than a function or catch-clause parameter) -whose scope does not extend beyond the end of the innermost enclosing -\grammarterm{try-block} (if there is one), +that belongs to a scope that does not contain +the innermost enclosing \grammarterm{compound-statement} +associated with a \grammarterm{try-block} (if there is one), the copy/move operation can be omitted by constructing the object directly into the exception object @@ -6173,9 +6169,9 @@ Here the criteria for elision can eliminate the copying of the object \tcode{t} with automatic storage duration into the result object for the function call \tcode{f()}, -which is the global object \tcode{t2}. -Effectively, the construction of the local object \tcode{t} -can be viewed as directly initializing the global object \tcode{t2}, +which is the non-local object \tcode{t2}. +Effectively, the construction of \tcode{t} +can be viewed as directly initializing \tcode{t2}, and that object's destruction will occur at program exit. Adding a move constructor to \tcode{Thing} has the same effect, but it is the move construction from the object with automatic storage duration to \tcode{t2} that is elided. @@ -6199,11 +6195,11 @@ \item if the operand of a \grammarterm{throw-expression}\iref{expr.throw} is a (possibly parenthesized) \grammarterm{id-expression} that names an implicitly movable entity -whose scope does not extend beyond the \grammarterm{compound-statement} +that belongs to a scope that does not contain the \grammarterm{compound-statement} of the innermost \grammarterm{try-block} or \grammarterm{function-try-block} (if any) whose \grammarterm{compound-statement} or \grammarterm{ctor-initializer} -encloses the \grammarterm{throw-expression}, +contains the \grammarterm{throw-expression}, \end{itemize} overload resolution to select the constructor for the copy or the \tcode{return_value} overload to call @@ -6659,46 +6655,6 @@ \end{codeblock} \end{example} -\pnum -\indextext{\idxcode{delete}}% -When an object is deleted with a -\grammarterm{delete-expression}\iref{expr.delete}, -a deallocation function -\indextext{function!deallocation}% -(\tcode{operator delete()} -\indextext{\idxcode{operator delete}}% -for non-array objects or -\tcode{operator delete[]()} -\indextext{\idxcode{operator delete}}% -for arrays) is (implicitly) called to reclaim the storage occupied by -the object\iref{basic.stc.dynamic.deallocation}. - -\pnum -Class-specific deallocation function lookup is a part of general deallocation -function lookup\iref{expr.delete} and occurs as follows. -If the \grammarterm{delete-expression} -is used to deallocate a class object whose static type has a virtual -destructor, the deallocation function is the one selected at the point -of definition of the dynamic type's virtual -destructor\iref{class.dtor}. -\begin{footnote} -A similar provision is not needed for -the array version of \tcode{operator} \tcode{delete} because~\ref{expr.delete} -requires that in this situation, the static type of the object to be deleted be -the same as its dynamic type. -\end{footnote} -Otherwise, if the -\grammarterm{delete-expression} -is used to deallocate an object of class -\tcode{T} -or array thereof, -the deallocation function's name is looked up in the scope of -\tcode{T}. -If this lookup fails to find the name, general deallocation function -lookup\iref{expr.delete} continues. -If the result of the lookup is ambiguous or inaccessible, or if the lookup -selects a placement deallocation function, the program is ill-formed. - \pnum \indextext{\idxcode{delete}!type of}% Any deallocation function for a class @@ -6728,10 +6684,9 @@ \grammarterm{cast-expression} of a \grammarterm{delete-expression} -refers to an object of class type, -because the deallocation function actually called is looked up in the scope of -the class that is the dynamic type of the object -if the destructor is virtual, the effect is the same in that case. +refers to an object of class type with a virtual destructor, +because the deallocation function is chosen by the destructor +of the dynamic type of the object, the effect is the same in that case. For example, \begin{codeblock} struct B { @@ -6797,11 +6752,8 @@ \end{note} \pnum -Access to the deallocation function is checked statically. -\begin{note} -Hence, even though a different one might actually be executed, -the statically visible deallocation function is required to be accessible. -\end{note} +Access to the deallocation function is checked statically, +even though a different one might actually be executed. \begin{example} For the call on line ``// 1'' above, if From 64a1348f98b16e7c521a500aa1c41d40ad642be0 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 22 Nov 2020 21:21:40 +0100 Subject: [PATCH 37/60] over first part --- source/overloading.tex | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/source/overloading.tex b/source/overloading.tex index 7ad38582dd..74e445ce7d 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -9,22 +9,18 @@ \pnum \indextext{overloaded function|see{overloading}}% \indextext{function!overloaded|see{overloading}}% -When two or more different declarations are specified for a single name -in the same scope, that name is said to be -\defnx{overloaded}{overloading}, -and the declarations -are called -\defnx{overloaded declarations}{declaration!overloaded}. -Only function and function template -declarations can be overloaded; variable and type declarations -cannot be overloaded. +\begin{note} +Each of two or more entities with the same name in the same scope, +which must be functions or function templates, +is commonly called an “overload”. +\end{note} \pnum -When a function name is used in a call, which function +When a function is named in a call, which function declaration is being referenced and the validity of the call are determined by comparing the types of the arguments at the point of use with the types of the parameters -in the declarations that are visible at the point of use. +in the declarations in the overload set. This function selection process is called \defn{overload resolution} and is defined in~\ref{over.match}. \begin{example} From e1fa190e615441afaeb31049e7a09ed5d09a9e69 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 22 Nov 2020 21:24:41 +0100 Subject: [PATCH 38/60] over.load, over.dcl removal --- source/classes.tex | 2 +- source/overloading.tex | 377 ----------------------------------------- source/xrefdelta.tex | 2 + 3 files changed, 3 insertions(+), 378 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 9208eb516d..220d0c99a3 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -574,7 +574,7 @@ \end{itemize} \begin{note} A single name can denote several member functions provided their types -are sufficiently different\iref{over.load}. +are sufficiently different\iref{basic.scope.scope}. \end{note} \pnum diff --git a/source/overloading.tex b/source/overloading.tex index 74e445ce7d..2b9904fcd5 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -34,383 +34,6 @@ \end{codeblock} \end{example} -\rSec1[over.load]{Overloadable declarations} -\indextext{overloading!declarations}% - -\pnum -\indextext{overloading!prohibited}% -Not all function declarations can be overloaded. -Those that cannot be -overloaded are specified here. -A program is ill-formed if it contains -two such non-overloadable declarations in the same scope. -\begin{note} -This restriction applies to explicit declarations in a scope, and between -such declarations and -declarations made through a -\grammarterm{using-declaration}\iref{namespace.udecl}. -It does not apply to sets of functions fabricated as a result of -name lookup (e.g., because of -\grammarterm{using-directive}{s}) -or overload resolution -(e.g., for operator functions). -\end{note} - -\pnum -Certain function declarations cannot be overloaded: - -\begin{itemize} -\item -\indextext{return type!overloading and}% -Function declarations that differ only in the return type, -the exception specification\iref{except.spec}, or both -cannot be overloaded. -\item -\indextext{\idxcode{static}!overloading and}% -Member function declarations with -the same name, -the same parameter-type-list\iref{dcl.fct}, and -the same trailing \grammarterm{requires-clause} (if any) -cannot be overloaded if any of them is a -\tcode{static} -member function declaration\iref{class.static}. -Likewise, member function template declarations with -the same name, -the same parameter-type-list, -the same trailing \grammarterm{requires-clause} (if any), and -the same \grammarterm{template-head} -cannot be -overloaded if any of them is a -\tcode{static} -member function template declaration. -The types of the implicit object parameters constructed for the member -functions for the purpose of overload resolution\iref{over.match.funcs} -are not considered when comparing parameter-type-lists for enforcement of -this rule. -In contrast, if there is no -\tcode{static} -member function declaration among a set of member function -declarations with -the same name, -the same parameter-type-list, and -the same trailing \grammarterm{requires-clause} (if any), -then -these member function declarations can be overloaded if they differ in -the type of their implicit object parameter. -\begin{example} -The following illustrates this distinction: - -\begin{codeblock} -class X { - static void f(); - void f(); // error - void f() const; // error - void f() const volatile; // error - void g(); - void g() const; // OK: no static \tcode{g} - void g() const volatile; // OK: no static \tcode{g} -}; -\end{codeblock} -\end{example} - -\item Member function declarations with -the same name, -the same parameter-type-list\iref{dcl.fct}, and -the same trailing \grammarterm{requires-clause} (if any), -as well as member function template -declarations with -the same name, -the same parameter-type-list, -the same trailing \grammarterm{requires-clause} (if any), and -the same \grammarterm{template-head}, -cannot be overloaded if any of them, but not -all, have a \grammarterm{ref-qualifier}\iref{dcl.fct}. -\begin{example} -\begin{codeblock} -class Y { - void h() &; - void h() const &; // OK - void h() &&; // OK, all declarations have a ref-qualifier - void i() &; - void i() const; // error: prior declaration of \tcode{i} has a ref-qualifier -}; -\end{codeblock} -\end{example} - -\end{itemize} - -\pnum -\indextext{equivalent parameter declarations}% -\indextext{equivalent parameter declarations!overloading and}% -\begin{note} -As specified in~\ref{dcl.fct}, -function declarations that have equivalent parameter declarations -and \grammarterm{requires-clause}{s}, if any\iref{temp.constr.decl}, -declare -the same function and therefore cannot -be overloaded: - -\begin{itemize} -\item -\indextext{\idxcode{typedef}!overloading and}% -Parameter declarations that differ only in the use of equivalent typedef -``types'' are equivalent. -A -\tcode{typedef} -is not a separate type, but only a synonym for another type\iref{dcl.typedef}. -\begin{example} -\begin{codeblock} -typedef int Int; - -void f(int i); -void f(Int i); // OK: redeclaration of \tcode{f(int)} -void f(int i) { @\commentellip@ } -void f(Int i) { @\commentellip@ } // error: redefinition of \tcode{f(int)} -\end{codeblock} -\end{example} - -\indextext{\idxcode{enum}!overloading and}% -Enumerations, on the other hand, are distinct types and can be used to -distinguish -overloaded function declarations. -\begin{example} -\begin{codeblock} -enum E { a }; - -void f(int i) { @\commentellip@ } -void f(E i) { @\commentellip@ } -\end{codeblock} -\end{example} - -\item -\indextext{overloading!array versus pointer}% -\indextext{array!overloading and pointer versus}% -Parameter declarations that differ only in a pointer -\tcode{*} -versus an array -\tcode{[]} -are equivalent. -That is, the array declaration is adjusted to become a pointer -declaration\iref{dcl.fct}. -Only the second and subsequent array dimensions are significant in -parameter types\iref{dcl.array}. -\begin{example} -\begin{codeblock} -int f(char*); -int f(char[]); // same as \tcode{f(char*);} -int f(char[7]); // same as \tcode{f(char*);} -int f(char[9]); // same as \tcode{f(char*);} - -int g(char(*)[10]); -int g(char[5][10]); // same as \tcode{g(char(*)[10]);} -int g(char[7][10]); // same as \tcode{g(char(*)[10]);} -int g(char(*)[20]); // different from \tcode{g(char(*)[10]);} -\end{codeblock} -\end{example} - -\item -\indextext{overloading!function versus pointer}% -\indextext{function!overloading and pointer versus}% -Parameter declarations that differ only in that one is a function type -and the other is a pointer to the same function type are equivalent. -That is, the function type is adjusted to become a pointer to function type\iref{dcl.fct}. -\begin{example} -\begin{codeblock} -void h(int()); -void h(int (*)()); // redeclaration of \tcode{h(int())} -void h(int x()) { } // definition of \tcode{h(int())} -void h(int (*x)()) { } // error: redefinition of \tcode{h(int())} -\end{codeblock} -\end{example} - -\item -\indextext{\idxcode{const}!overloading and}% -\indextext{\idxcode{volatile}!overloading and}% -Parameter declarations that differ only in the presence or absence of -\tcode{const} -and/or -\tcode{volatile} -are equivalent. -That is, the -\tcode{const} -and -\tcode{volatile} -type-specifiers for -each parameter type are ignored when determining which function is being -declared, -defined, or called. -\begin{example} -\begin{codeblock} -typedef const int cInt; - -int f (int); -int f (const int); // redeclaration of \tcode{f(int)} -int f (int) { @\commentellip@ } // definition of \tcode{f(int)} -int f (cInt) { @\commentellip@ } // error: redefinition of \tcode{f(int)} -\end{codeblock} -\end{example} - -Only the -\tcode{const} -and -\tcode{volatile} -type-specifiers at the outermost level of the -parameter type specification are ignored in this fashion; -\tcode{const} -and -\tcode{volatile} -type-specifiers buried within a parameter type specification are significant -and can be used to distinguish overloaded function -declarations. -\begin{footnote} -When a parameter type includes a function type, -such as in the case of a parameter type that is a pointer to function, the -\tcode{const} -and -\tcode{volatile} -type-specifiers at the outermost level of the parameter type -specifications for the inner function type are also ignored. -\end{footnote} -In particular, for any type -\tcode{T}, -``pointer to -\tcode{T}'', -``pointer to -\tcode{const} -\tcode{T}'', -and -``pointer to -\tcode{volatile} -\tcode{T}'' -are considered distinct parameter types, as are -``reference to -\tcode{T}'', -``reference to -\tcode{const} -\tcode{T}'', -and -``reference to -\tcode{volatile} -\tcode{T}''. -\item -\indextext{default initializers!overloading and}% -Two parameter declarations that differ only in their default arguments -are equivalent. -\begin{example} -Consider the following: - -\begin{codeblock} -void f (int i, int j); -void f (int i, int j = 99); // OK: redeclaration of \tcode{f(int, int)} -void f (int i = 88, int j); // OK: redeclaration of \tcode{f(int, int)} -void f (); // OK: overloaded declaration of \tcode{f} - -void prog () { - f (1, 2); // OK: call \tcode{f(int, int)} - f (1); // OK: call \tcode{f(int, int)} - f (); // error: \tcode{f(int, int)} or \tcode{f()}? -} -\end{codeblock} -\end{example} -\end{itemize} -\end{note} - -\rSec1[over.dcl]{Declaration matching}% -\indextext{overloading!declaration matching}% -\indextext{scope!overloading and}% -\indextext{base class!overloading and} - -\pnum -Two function declarations of the same name refer to the same function if they -are in the same scope and have equivalent parameter declarations\iref{over.load} -and equivalent\iref{temp.over.link} trailing \grammarterm{requires-clause}{s}, if any\iref{dcl.decl}. -\begin{note} -Since a \grammarterm{constraint-expression} is an unevaluated operand, -equivalence compares the expressions without evaluating them. -\begin{example} -\begin{codeblock} -template concept C = true; -template struct A { - void f() requires C<42>; // \#1 - void f() requires true; // OK, different functions -}; -\end{codeblock} -\end{example} -\end{note} -A function member of a derived class is -\textit{not} -in the same scope as a function member of the same name in a base class. -\begin{example} -\begin{codeblock} -struct B { - int f(int); -}; - -struct D : B { - int f(const char*); -}; -\end{codeblock} - -\indextext{name hiding!function}% -\indextext{name hiding!overloading versus}% -Here -\tcode{D::f(const char*)} -hides -\tcode{B::f(int)} -rather than overloading it. - -\indextext{Ben}% -\begin{codeblock} -void h(D* pd) { - pd->f(1); // error: - // \tcode{D::f(const char*)} hides \tcode{B::f(int)} - pd->B::f(1); // OK - pd->f("Ben"); // OK, calls \tcode{D::f} -} -\end{codeblock} -\end{example} - -\pnum -A locally declared function is not in the same scope as a function in -a containing scope. -\begin{example} -\begin{codeblock} -void f(const char*); -void g() { - extern void f(int); - f("asdf"); // error: \tcode{f(int)} hides \tcode{f(const char*)} - // so there is no \tcode{f(const char*)} in this scope -} - -void caller () { - extern void callee(int, int); - { - extern void callee(int); // hides \tcode{callee(int, int)} - callee(88, 99); // error: only \tcode{callee(int)} in scope - } -} -\end{codeblock} -\end{example} - -\pnum -\indextext{access control!overloading and}% -\indextext{overloading!access control and}% -Different versions of an overloaded member function can be given different -access rules. -\begin{example} -\begin{codeblock} -class buffer { -private: - char* p; - int size; -protected: - buffer(int s, char* store) { size = s; p = store; } -public: - buffer(int s) { p = new char[size = s]; } -}; -\end{codeblock} -\end{example} - \rSec1[over.match]{Overload resolution}% \rSec2[over.match.general]{General}% diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index ef22529cba..69f8fcb6d0 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -32,6 +32,8 @@ \movedxref{class.this}{expr.prim.this} \movedxref{class.mfct.non-static.general}{class.mfct.non-static} \movedxref{class.nested.type}{diff.basic} +\movedxref{over.load}{basic.scope.scope} +\movedxref{over.dcl}{basic.link} % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From 359af02e790d66dac40cb2b25e9931560608d34c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 22 Nov 2020 22:06:25 +0100 Subject: [PATCH 39/60] over (remainder) --- source/overloading.tex | 314 ++++++++++++++++------------------------- 1 file changed, 123 insertions(+), 191 deletions(-) diff --git a/source/overloading.tex b/source/overloading.tex index 2b9904fcd5..1a2b2e42d7 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -12,7 +12,7 @@ \begin{note} Each of two or more entities with the same name in the same scope, which must be functions or function templates, -is commonly called an “overload”. +is commonly called an ``overload''. \end{note} \pnum @@ -201,9 +201,8 @@ class of the implied object argument for the purpose of defining the type of the implicit object parameter. For non-conversion functions -introduced by a -\grammarterm{using-declaration} -into a derived class, the function is +nominated by a \grammarterm{using-declaration} +in a derived class, the function is considered to be a member of the derived class for the purpose of defining the type of the implicit object parameter. For static member functions, the implicit object parameter is considered @@ -256,6 +255,28 @@ \end{codeblock} \end{example} +\pnum +In each case where conversion functions of a class \tcode{S} are considered +for initializing an object or reference of type \tcode{T}, +the candidate functions include the result of a search +for the \grammarterm{conversion-function-id} \tcode{\keyword{operator} T} +in \tcode{S}. +\begin{note} +This search can find a specialization of +a conversion function template\iref{basic.lookup}. +\end{note} +Each such case also defines sets of \defnadj{permissible}{types} +for explicit and non-explicit conversion functions; +each (non-template) conversion function +that is a non-hidden member of \tcode{S}, +yields a permissible type, and, +for the former set, is non-explicit is also a candidate function. +If initializing an object, for any permissible type \cv{} \tcode{U}, any +\cvqual{cv2} \tcode{U}, \cvqual{cv2} \tcode{U\&}, or \cvqual{cv2} \tcode{U\&\&} +is also a permissible type. +If the set of permissible types for explicit conversion functions is empty, +any candidates that are explicit are discarded. + \pnum In each case where a candidate is a function template, candidate function template specializations @@ -265,8 +286,8 @@ has an \grammarterm{explicit-specifier} whose \grammarterm{constant-expression} is value-dependent\iref{temp.dep}, template argument deduction is performed first and then, -if the context requires a candidate that -is not explicit and the generated specialization is explicit\iref{dcl.fct.spec}, +if the context admits only candidates that +are not explicit and the generated specialization is explicit\iref{dcl.fct.spec}, it will be removed from the candidate set. Those candidates are then handled as candidate functions in the usual way. @@ -284,8 +305,8 @@ and non-template functions\iref{dcl.fct} are treated equivalently for the remainder of overload resolution. \end{footnote} -A given name can refer to one or more function templates and also -to a set of non-template functions. +A given name can refer to, or a conversion can consider, +one or more function templates as well as a set of non-template functions. In such a case, the candidate functions generated from each function template are combined with the set of non-template candidate functions. @@ -354,9 +375,8 @@ \pnum Of interest in~\ref{over.call.func} are only those function calls in -which the -\grammarterm{postfix-expression} -ultimately contains a name that +which the \grammarterm{postfix-expression} +ultimately contains an \grammarterm{id-expression} that denotes one or more functions. Such a \grammarterm{postfix-expression}, @@ -374,13 +394,9 @@ qualified function calls and unqualified function calls. \pnum -In qualified function calls, the name to be resolved is an -\grammarterm{id-expression} -and is preceded by an -\tcode{->} -or -\tcode{.} -operator. +In qualified function calls, +the function is named by an \grammarterm{id-expression} +preceded by an \tcode{->} or \tcode{.} operator. Since the construct \tcode{A->B} @@ -408,16 +424,8 @@ resolution for both glvalue and class prvalue objects. \end{footnote} -Under this -assumption, the -\grammarterm{id-expression} -in the call is looked up as a -member function of -\tcode{T} -following the rules for looking up names in -classes\iref{class.member.lookup}. -The function declarations found by that lookup constitute the set of -candidate functions. +The function declarations found by name lookup\iref{class.member.lookup} +constitute the set of candidate functions. The argument list is the \grammarterm{expression-list} in the call augmented by the addition of the left operand of @@ -427,16 +435,9 @@ implied object argument\iref{over.match.funcs}. \pnum -In unqualified function calls, the name is not qualified by an -\tcode{->} -or -\tcode{.} -operator and has the more general form of a +In unqualified function calls, the function is named by a \grammarterm{primary-expression}. -The name is looked up in the context of the function -call following the normal rules for name lookup -in expressions\iref{basic.lookup}. -The function declarations found by that lookup constitute the +The function declarations found by name lookup\iref{basic.lookup} constitute the set of candidate functions. Because of the rules for name lookup, the set of candidate functions consists (1) entirely of non-member functions or (2) entirely of @@ -451,18 +452,10 @@ \grammarterm{expression-list} in the call augmented by the addition of an implied object argument as in a qualified function call. -If the keyword -\tcode{this}\iref{expr.prim.this} is in scope and refers to -class -\tcode{T}, -or a derived class of -\tcode{T}, -then the implied object argument is -\tcode{(*this)}. -If the keyword -\tcode{this} -is not in -scope or refers to another class, then +If the current class is, or is derived, from \tcode{T} and the keyword +\tcode{this}\iref{expr.prim.this} refers to it, +then the implied object argument is \tcode{(*this)}. +Otherwise, a contrived object of type \tcode{T} becomes the implied object @@ -479,10 +472,8 @@ object parameter, the contrived object will not be the cause to select or reject a function. -\end{footnote} -If the argument list is augmented by a contrived object and overload -resolution selects one of the non-static member functions of -\tcode{T}, +\end{footnote}; +if overload resolution selects a non-static member function, the call is ill-formed. \rSec4[over.call.object]{Call to object of class type} @@ -494,8 +485,8 @@ then the set of candidate functions includes at least the function call operators of \tcode{T}. The function call operators of \tcode{T} -are obtained by ordinary lookup of the name \tcode{\keyword{operator}()} -in the context of \tcode{(E).\keyword{operator}()}. +are the results of a search for the name \tcode{\keyword{operator}()} +in the scope of \tcode{T}. \pnum In addition, for each non-explicit conversion function declared in \tcode{T} of the @@ -660,18 +651,18 @@ are constructed as follows: \begin{itemize} \item -If \tcode{T1} -is a complete class type or a class currently being defined, the set of member candidates is the -result of the qualified lookup of -\tcode{T1::\keyword{operator}@}\iref{over.call.func}; otherwise, the set of member -candidates is empty. +If \tcode{T1} is a complete class type or a class currently being defined, +the set of member candidates is the result of a search for +\tcode{\keyword{operator}@} in the scope of \tcode{T1}; +otherwise, the set of member candidates is empty. \item -The set of non-member candidates is the result of the unqualified lookup of +For the operators \tcode{=}, \tcode{[]}, or \tcode{->}, +the set of non-member candidates is empty; +otherwise, it includes the result of unqualified lookup for \tcode{\keyword{operator}@} -in the context of -the expression according to the usual rules for name -lookup in unqualified function calls\iref{basic.lookup.argdep} except -that all member functions are ignored. +in the rewritten function call +(\ref{basic.lookup.unqual}, \ref{basic.lookup.argdep}), +ignoring all member functions. However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of type \tcode{T1} @@ -967,27 +958,18 @@ \item When the type of the initializer expression is a class type ``\cv{}~\tcode{S}'', -the non-explicit conversion functions of -\tcode{S} -and its base classes are considered. +conversion functions are considered. +The permissible types for non-explicit conversion functions are +\tcode{T} and any class derived from \tcode{T}. When initializing a temporary object\iref{class.mem} to be bound to the first parameter of a constructor where the parameter is of type ``reference to \cvqual{cv2} \tcode{T}'' and the constructor is called with a single argument in the context of -direct-initialization of an object of type ``\cvqual{cv3} \tcode{T}'', explicit -conversion functions are also considered. -Those that are not hidden within -\tcode{S} -and yield a type whose cv-unqualified version is the same type as -\tcode{T} -or is a derived class thereof -are candidate functions. -A call to a conversion function returning ``reference to \tcode{X}'' -is a glvalue of type \tcode{X}, and such a conversion function is -therefore considered to yield \tcode{X} for this process of selecting -candidate functions. +direct-initialization of an object of type ``\cvqual{cv3} \tcode{T}'', +the permissible types for explicit conversion functions are the same; +otherwise there are none. \end{itemize} \pnum @@ -1010,38 +992,20 @@ being initialized. Overload resolution is used to select the conversion function to be invoked. -Assuming that ``\cvqual{cv1} \tcode{T}'' is the -type of the object being initialized, and ``\cv{}~\tcode{S}'' is the type -of the initializer expression, with -\tcode{S} -a class type, +Assuming that ``\cv{} \tcode{T}'' is the +type of the object being initialized, the candidate functions are selected as follows: \begin{itemize} \item -The conversion functions of -\tcode{S} -and its base classes are considered. -Those non-explicit conversion functions that are not hidden -within -\tcode{S} -and yield type -\tcode{T} -or a type that can be converted to type -\tcode{T} -via a standard conversion sequence\iref{over.ics.scs} -are candidate functions. -For direct-initialization, those explicit conversion functions that are not -hidden within \tcode{S} and yield type \tcode{T} or a type that can be converted -to type \tcode{T} with a qualification conversion\iref{conv.qual} are also -candidate functions. -Conversion functions that return a cv-qualified type -are considered to yield the cv-unqualified version of that type -for this process of selecting candidate functions. -A call to a conversion function returning ``reference to \tcode{X}'' -is a glvalue of type \tcode{X}, and such a conversion function is -therefore considered to yield \tcode{X} for this process of selecting -candidate functions. +The permissible types for non-explicit conversion functions are +those that can be converted to type \tcode{T} +via a standard conversion sequence\iref{over.ics.scs}. +For direct-initialization, +the permissible types for explicit conversion functions are +those that be converted to type \tcode{T} +with a (possibly trivial) qualification conversion\iref{conv.qual}; +otherwise there are none. \end{itemize} \pnum @@ -1061,36 +1025,25 @@ Overload resolution is used to select the conversion function to be invoked. Assuming that ``reference to \cvqual{cv1} \tcode{T}'' is the -type of the reference being initialized, and -``\cv{}~\tcode{S}'' is the type -of the initializer expression, with -\tcode{S} -a class type, +type of the reference being initialized, the candidate functions are selected as follows: \begin{itemize} \item -The conversion functions of -\tcode{S} -and its base classes are considered. -Those non-explicit conversion functions that are not hidden within -\tcode{S} -and yield type ``lvalue reference to \cvqual{cv2} \tcode{T2}'' -(when initializing an lvalue reference or an rvalue reference to function) or +Let $R$ be a set of types including ``lvalue reference to \cvqual{cv2} \tcode{T2}'' +(when initializing an lvalue reference or an rvalue reference to function) and ``\cvqual{cv2} \tcode{T2}'' or ``rvalue reference to \cvqual{cv2} \tcode{T2}'' (when initializing an -rvalue reference or an lvalue reference to function), +rvalue reference or an lvalue reference to function) +for any \tcode{T2}. +The permissible types for non-explicit conversion functions are +the members of $R$ where ``\cvqual{cv1} \tcode{T}'' is reference-compatible\iref{dcl.init.ref} -with ``\cvqual{cv2} \tcode{T2}'', -are candidate functions. For direct-initialization, those explicit -conversion functions that are not hidden within \tcode{S} and yield -type ``lvalue reference to \cvqual{cv2} \tcode{T2}'' -(when initializing an lvalue reference or an rvalue reference to function) -or ``rvalue reference to \cvqual{cv2} \tcode{T2}'' -(when initializing an rvalue reference or an lvalue reference to function), -where \tcode{T2} is the same type as \tcode{T} or can be -converted to type \tcode{T} with a qualification -conversion\iref{conv.qual}, are also candidate functions. - +with ``\cvqual{cv2} \tcode{T2}''. +For direct-initialization, the permissible types for explicit +conversion functions are the members of $R$ +where \tcode{T2} can be converted to type \tcode{T} +with a (possibly trivial) qualification conversion\iref{conv.qual}; +otherwise there are none. \end{itemize} \pnum @@ -1849,13 +1802,11 @@ \end{example} \pnum -If the best viable function resolves to a function for -which multiple declarations were found, and if at least -two of these declarations --- or the declarations they -refer to in the case of -\grammarterm{using-declaration}{s} ---- specify a default argument that made the function -viable, the program is ill-formed. +If the best viable function resolves to a function +for which multiple declarations were found, and +if any two of these declarations inhabit different scopes and +specify a default argument that made the function viable, +the program is ill-formed. \begin{example} \begin{codeblock} namespace A { @@ -2840,15 +2791,20 @@ \indextext{overloading!resolution!implicit conversions and|)}% \indextext{overloading!resolution|)} -\rSec1[over.over]{Address of overloaded function}% +\rSec1[over.over]{Address of an overload set}% \indextext{overloading!address of overloaded function}% \indextext{overloaded function!address of} \pnum -A use of a function name without arguments is resolved to -a function, a pointer to function, or a pointer to member function +An \grammarterm{id-expression} +whose terminal name refers to an overload set $S$ and +that appears without arguments +is resolved to +a function, +a pointer to function, or +a pointer to member function for a specific function -that is chosen from a set of selected functions +that is chosen from a set of functions selected from $S$ determined based on the target type required in the context (if any), as described below. The target can be @@ -2871,7 +2827,7 @@ a non-type \grammarterm{template-parameter}\iref{temp.arg.nontype}. \end{itemize} -The function name can be preceded by the \tcode{\&} operator. +The \grammarterm{id-expression} can be preceded by the \tcode{\&} operator. \begin{note} Any redundant set of parentheses surrounding the function name is ignored\iref{expr.prim.paren}. @@ -2890,26 +2846,10 @@ \end{note} \pnum -For each function template designated by the name, -template argument deduction is done\iref{temp.deduct.funcaddr}, and -if the argument deduction succeeds, -the -resulting template argument list is -used to generate a single -function template specialization, -which is added to the set of selected functions -considered. -\begin{note} -As described in~\ref{temp.arg.explicit}, if deduction fails and the -function template name is followed by an explicit template argument list, -the -\grammarterm{template-id} -is then examined to see whether it identifies a single function template -specialization. If it does, the -\grammarterm{template-id} -is considered to be an lvalue for that function template specialization. -The target type is not used in that determination. -\end{note} +The specialization, if any, generated by template argument deduction +(\ref{temp.over}, \ref{temp.deduct.funcaddr}, \ref{temp.arg.explicit}) +for each function template named +is added to the set of selected functions considered. \pnum Non-member functions and static member functions @@ -2917,10 +2857,11 @@ reference to function type. Non-static member functions match targets of pointer-to-member-function type. +\begin{note} %% FIXME: Should this only apply after the eliminations in the next paragraph? -If a non-static member function is selected, the reference to the overloaded -function name is required to have the form of a pointer to member as -described in~\ref{expr.unary.op}. +If a non-static member function is chosen, +the result can be used only to form a pointer to member\iref{expr.unary.op}. +\end{note} \pnum All functions with @@ -2995,16 +2936,9 @@ \pnum \begin{note} -If -\tcode{f()} -and -\tcode{g()} -are both overloaded functions, the -Cartesian product of possibilities is considered -to resolve -\tcode{f(\&g)}, -or the equivalent expression -\tcode{f(g)}. +If \tcode{f} and \tcode{g} are both overload sets, +the Cartesian product of possibilities is considered +to resolve \tcode{f(\&g)}, or the equivalent expression \tcode{f(g)}. \end{note} \pnum @@ -3030,14 +2964,14 @@ \pnum \indextext{operator!overloaded}% -A function declaration having one of the following -\grammarterm{operator-function-id}{s} -as its name declares an -\defnx{operator function}{function!operator}. -A function template declaration having one of the -following \grammarterm{operator-function-id}{s} as its name -declares an \defnx{operator function template}{function!operator!template}. A specialization -of an operator function template is also an operator function. +A declaration +whose \grammarterm{declarator-id} is an \grammarterm{operator-function-id} +shall declare a function or function template or +an explicit instantiation or specialization of a function template. +A function so declared is an \defnadj{operator}{function}. +A function template so declared is +an \defnx{operator function template}{function!operator!template}. +A specialization of an operator function template is also an operator function. An operator function is said to \defnx{implement}{operator!implementation} the operator named in its @@ -3207,9 +3141,8 @@ \end{note} \pnum -The unary and binary forms of the same operator are considered to have -the same name. \begin{note} +The unary and binary forms of the same operator have the same name. Consequently, a unary operator can hide a binary operator from an enclosing scope, and vice versa. \end{note} @@ -3849,10 +3782,9 @@ \pnum A declaration whose \grammarterm{declarator-id} is a -\grammarterm{literal-operator-id} shall be a declaration of a namespace-scope -function or function template (it could be a friend -function\iref{class.friend}), an explicit instantiation or specialization of a -function template, or a \grammarterm{using-declaration}\iref{namespace.udecl}. +\grammarterm{literal-operator-id} shall declare a function or function template +that belongs to a namespace (it could be a friend function\iref{class.friend}) or +an explicit instantiation or specialization of a function template. A function declared with a \grammarterm{literal-operator-id} is a \defnx{literal operator}{literal!operator}. A function template declared with a \grammarterm{literal-operator-id} is a \defnx{literal operator template}{literal!operator!template}. From 45b9fa85991f0f3268ff9badbff09676c1ab4424 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 23 Nov 2020 17:00:57 +0100 Subject: [PATCH 40/60] template (first part) --- source/templates.tex | 177 +++++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 91 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index ba0259f131..32e94f7e98 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -107,20 +107,16 @@ \end{example} \pnum -A -\grammarterm{template-declaration} +\begin{note} +A \grammarterm{template-declaration} can appear only as a namespace scope or class scope declaration. +\end{note} Its \grammarterm{declaration} shall not be an \grammarterm{export-declaration}. -In a function template declaration, the last component of the -\grammarterm{declarator-id} -shall not be a -\grammarterm{template-id}. +In a function template declaration, the \grammarterm{unqualified-id} of the +\grammarterm{declarator-id} shall be a name. \begin{note} -That last component can be an \grammarterm{identifier}, an \grammarterm{operator-function-id}, -a \grammarterm{conversion-function-id}, or a \grammarterm{literal-operator-id}. In -a class template declaration, if the -class name +In a class template declaration, if the \grammarterm{class-name} is a \grammarterm{simple-template-id}, the declaration declares a class template partial specialization\iref{temp.class.spec}. @@ -137,32 +133,27 @@ \pnum \indextext{template name!linkage of}% -A template name has linkage\iref{basic.link}. -Specializations (explicit or implicit) of -a template that has internal linkage are -distinct from all specializations in other translation -units. +A specialization (explicit or implicit) of one template is +distinct from all specializations of any other template. A template, a template explicit specialization\iref{temp.expl.spec}, and a class -template partial specialization shall not have C linkage. Use of a linkage specification -other than \tcode{"C"} or \tcode{"C++"} with any of these constructs is -conditionally-supported, with -\impldef{semantics of linkage specification on templates} semantics. -Template definitions shall obey the one-definition rule\iref{basic.def.odr}. +template partial specialization shall not have C linkage. \begin{note} Default arguments for function templates and for member functions of class templates are considered definitions for the purpose of template -instantiation\iref{temp.decls} and must also obey the one-definition rule. +instantiation\iref{temp.decls} and must obey the one-definition rule\iref{basic.def.odr}. \end{note} \pnum -A class template shall not have the same name as any other -template, class, function, variable, enumeration, enumerator, namespace, or -type in the same scope\iref{basic.scope}, except as specified in~\ref{temp.class.spec}. -Except that a function template can be overloaded either by non-template -functions\iref{dcl.fct} with the same name or by other function templates -with the same name\iref{temp.over}, -a template name declared in namespace scope or in class scope shall be unique -in that scope. +\begin{note} +A class shall cannot have the same name as any other +name bound in the same scope\iref{basic.scope.scope}, except +that a function template can share a name with non-template +functions\iref{dcl.fct} and/or function templates\iref{temp.over}. +Specializations, including partial specializations\iref{temp.class.spec}, +do not reintroduce or bind names. +Their target scope is the target scope of the primary template, +so all specializations of a template belong to the same scope as it does. +\end{note} \pnum \indextext{entity!templated}% @@ -179,7 +170,7 @@ \end{itemize} \begin{note} -A local class, a local variable, or a friend function defined in a +A local class, a local or block variable, or a friend function defined in a templated entity is a templated entity. \end{note} @@ -254,6 +245,10 @@ \opt{nested-name-specifier} concept-name \terminal{<} \opt{template-argument-list} \terminal{>} \end{bnf} +\indextext{component name}% +The component names of a \grammarterm{type-constraint} are +its \grammarterm{concept-name} and +those of its \grammarterm{nested-name-specifier} (if any). \begin{note} The \tcode{>} token following the \grammarterm{template-parameter-list} of a @@ -313,9 +308,9 @@ declaration. \pnum -A -\grammarterm{type-parameter} -whose identifier does not follow an ellipsis +The \grammarterm{identifier} in a \grammarterm{type-parameter} is not looked up. +A \grammarterm{type-parameter} +whose \grammarterm{identifier} does not follow an ellipsis defines its \grammarterm{identifier} to be a @@ -508,11 +503,11 @@ A default \grammarterm{template-argument} shall not be specified in a friend class template declaration. -If a friend function template declaration -specifies a default -\grammarterm{template-argument}, -that declaration shall be a definition and shall be the only declaration of -the function template in the translation unit. +If a friend function template declaration $D$ +specifies a default \grammarterm{template-argument}, +that declaration shall be a definition and +there shall be no other declaration of the function template +which is reachable from $D$ or from which $D$ is reachable. \pnum The set of default @@ -566,10 +561,9 @@ \end{example} \pnum -A -\grammarterm{template-parameter} -shall -not be given default arguments by two different declarations in the same scope. +A \grammarterm{template-parameter} +shall not be given default arguments by two different declarations +if one is reachable from the other. \begin{example} \begin{codeblock} template class X; @@ -697,27 +691,59 @@ \end{bnf} \pnum -An \grammarterm{identifier} is a \grammarterm{template-name} -if it is associated by name lookup with -a template or an overload set that contains a function template, or -the \grammarterm{identifier} is followed by \tcode{<}, -the \grammarterm{template-id} would form an \grammarterm{unqualified-id}, and -name lookup either finds one or more functions or finds nothing. +\indextext{component name}% +The component name of a +\grammarterm{simple-template-id}, +\grammarterm{template-id}, or +\grammarterm{template-name} +is the first name in it. + +\pnum +A \tcode{<} is interpreted as the delimiter of +a \grammarterm{template-argument-list} +if it follows a name that is not a \grammarterm{conversion-function-id} and +\begin{itemize} +\item +that follows the keyword \keyword{template} or a \tcode{\~} +after a \grammarterm{nested-name-specifier} or +in a class member access expression, or +\item +for which name lookup finds the injected-class-name of a class template or +finds any declaration of a template, or +\item +that is an unqualified name +for which name lookup either finds one or more functions or finds nothing, or +\item +that is a terminal name +in a \grammarterm{using-declarator}\iref{namespace.udecl}, +a \grammarterm{declarator-id}\iref{dcl.meaning}, or +a type-only context +other than a \grammarterm{nested-name-specifier}\iref{temp.res}. +\end{itemize} \begin{note} -Whether a name actually refers to a template -cannot be known in some cases -until after argument dependent lookup is done\iref{basic.lookup.argdep}. +If the name is an \grammarterm{identifier}, +it is then interpreted as a \grammarterm{template-name}. +The keyword \keyword{template} is used to indicate +that a dependent qualified name\iref{temp.dep.type} denotes a template +where an expression might appear. \end{note} +\begin{example} +\begin{codeblock} +struct X { + template X* alloc(); + template static X* adjust(); +}; +template void f(T* p) { + T* p1 = p->alloc<200>(); // error: \tcode{<} means less than + T* p2 = p->template alloc<200>(); // OK: \tcode{<} starts template argument list + T::adjust<100>(); // error: \tcode{<} means less than + T::template adjust<100>(); // OK: \tcode{<} starts template argument list +} +\end{codeblock} +\end{example} \pnum \indextext{\idxcode{<}!template and}% -When a name is considered to be a -\grammarterm{template-name}, -and it is followed by a \tcode{<}, -the \tcode{<} -is always taken as the delimiter of a -\grammarterm{template-argument-list} -and never as the less-than operator. When parsing a \grammarterm{template-argument-list}, the first non-nested \tcode{>} @@ -755,39 +781,8 @@ \end{example} \pnum -The keyword \keyword{template} is said to appear at the top level in -a \grammarterm{qualified-id} -if it appears outside of a \grammarterm{template-argument-list} or -\grammarterm{decltype-specifier}. -In a \grammarterm{qualified-id} of a \grammarterm{declarator-id} or -in a \grammarterm{qualified-id} formed by a \grammarterm{class-head-name}\iref{class.pre} or -\grammarterm{enum-head-name}\iref{dcl.enum}, -the keyword \keyword{template} shall not appear at the top level. -In a \grammarterm{qualified-id} used as the name in a -\grammarterm{typename-specifier}\iref{temp.res}, -\grammarterm{elaborated-type-specifier}\iref{dcl.type.elab}, -\grammarterm{using-declaration}\iref{namespace.udecl}, or -\grammarterm{class-or-decltype}\iref{class.derived}, -an optional keyword \keyword{template} appearing at the top level is ignored. -In these contexts, a \tcode{<} token is always assumed to introduce a -\grammarterm{template-argument-list}. -In all other contexts, when naming a template specialization of -a member of an unknown specialization\iref{temp.dep.type}, -the member template name shall be prefixed by the keyword \keyword{template}. -\begin{example} -\begin{codeblock} -struct X { - template X* alloc(); - template static X* adjust(); -}; -template void f(T* p) { - T* p1 = p->alloc<200>(); // error: \tcode{<} means less than - T* p2 = p->template alloc<200>(); // OK: \tcode{<} starts template argument list - T::adjust<100>(); // error: \tcode{<} means less than - T::template adjust<100>(); // OK: \tcode{<} starts template argument list -} -\end{codeblock} -\end{example} +The keyword \keyword{template} shall not appear immediately after +a declarative \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. \pnum A name prefixed by the keyword From 5e6efc91004fcbff6b95a3f95bce2bb7555fb9da Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 23 Nov 2020 23:19:56 +0100 Subject: [PATCH 41/60] template (second part) --- source/templates.tex | 464 +++++++++++++++++-------------------------- 1 file changed, 182 insertions(+), 282 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index 32e94f7e98..5f56b90dbd 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -787,8 +787,11 @@ \pnum A name prefixed by the keyword \keyword{template} -shall be a \grammarterm{template-id} or -the name shall refer to a class template or an alias template. +shall be followed by a template argument list or +refer to a class template or an alias template. +The latter case is deprecated\iref{depr.template.template}. +The keyword \keyword{template} shall not appear immediately +before a \tcode{\~} token (as to name a destructor). \begin{note} The keyword \keyword{template} @@ -799,16 +802,8 @@ \tcode{typename} prefix, the \keyword{template} -prefix is allowed in cases where it is not strictly -necessary; i.e., when the \grammarterm{nested-name-specifier} or -the expression on the left of -the -\tcode{->} -or -\tcode{.} -is not dependent on a -\grammarterm{template-parameter}, or the use does not appear in the -scope of a template. +prefix is allowed +even when lookup for the name would already find a template. \end{note} \begin{example} \begin{codeblock} @@ -827,7 +822,7 @@ template struct C { }; }; -// OK: \tcode{T::template C} names a class template: +// deprecated: \tcode{T::C} is assumed to name a class template: template class TT = T::template C> struct D { }; D > db; \end{codeblock} @@ -878,9 +873,6 @@ names a constrained non-function template or a constrained template \grammarterm{template-parameter}, -%%% FIXME: Do we need to say this? -but not a member template -that is a member of an unknown specialization\iref{temp.res}, and all \grammarterm{template-argument}{s} in the \grammarterm{simple-template-id} @@ -987,6 +979,16 @@ \end{codeblock} \end{example} +\pnum +The template argument list of a \grammarterm{template-head} is +a template argument list in which the $n^\text{th}$ template argument +has the value of +the $n^\text{th}$ template parameter of the \grammarterm{template-head}. +If the $n^\text{th}$ template parameter is +a template parameter pack\iref{temp.variadic}, +the $n^\text{th}$ template argument is a pack expansion +whose pattern is the name of the template parameter pack. + \pnum In a \grammarterm{template-argument}, @@ -1016,19 +1018,11 @@ \end{example} \pnum -The name of a -\grammarterm{template-argument} -shall be accessible at the point where it is used as a -\grammarterm{template-argument}. \begin{note} -If the name of the -\grammarterm{template-argument} -is accessible at the point where it is used as a -\grammarterm{template-argument}, -there is no further access restriction in the resulting instantiation where the -corresponding -\grammarterm{template-parameter} -name is used. +Names used in a \grammarterm{template-argument} +are subject to access control where they appear. +Because a \grammarterm{template-parameter} is not a class member, +no access control applies. \end{note} \begin{example} \begin{codeblock} @@ -1111,7 +1105,7 @@ template specialization, the program is ill-formed. \pnum -When name lookup for the name in a +When name lookup for the component name of a \grammarterm{template-id} finds an overload set, both non-template functions in the overload set and function templates in the overload set for @@ -1120,9 +1114,11 @@ do not match the \grammarterm{template-parameter}{s} are ignored. +\begin{note} If none of the function templates have matching \grammarterm{template-parameter}{s}, the program is ill-formed. +\end{note} \pnum When a \grammarterm{simple-template-id} does not name a function, @@ -1322,8 +1318,8 @@ specialization based on the template \grammarterm{template-parameter} is instantiated. -If a specialization is not visible at the point of instantiation, -and it would have been selected had it been visible, the program is ill-formed, +If a specialization is not reachable from the point of instantiation, +and it would have been selected had it been reachable, the program is ill-formed, no diagnostic required. \begin{example} \begin{codeblock} @@ -2158,22 +2154,15 @@ \rSec2[temp.decls.general]{General} \pnum -A -\grammarterm{template-id}, -that is, the -\grammarterm{template-name} -followed by a -\grammarterm{template-argument-list} -shall not be specified in the declaration of a primary template declaration. -\begin{example} -\begin{codeblock} -template class A { }; // error -template void sort(T1 data[I]); // error -\end{codeblock} -\end{example} -\begin{note} -However, this syntax is allowed in class template partial specializations\iref{temp.class.spec}. -\end{note} +A \defnadj{primary}{template} declaration is one +in which the name of the template is not followed by +a \grammarterm{template-argument-list}. +The template argument list of a primary template is +the template argument list of its \grammarterm{template-head}\iref{temp.arg}. +A template declaration in which the name of the template is followed by +a \grammarterm{template-argument-list} is +a partial specialization of +the template named in the declaration\iref{temp.class.spec}. \pnum For purposes of name lookup and instantiation, @@ -2251,20 +2240,17 @@ \end{example} \pnum -When a member function, a member class, a member enumeration, a static data member or -a member template of a class +\begin{note} +When a member of a class template is defined outside of the class template definition, -the member definition is defined as a template definition in which the -\grammarterm{template-head} is equivalent to that -of the class template\iref{temp.over.link}. -The names of the template parameters used in the definition of the member may -be different from the template parameter names used in the class +the member definition is defined as a template definition with the +\grammarterm{template-head} equivalent to that +of the class template. +The names of the template parameters used in the definition of the member +can differ from the template parameter names used in the class template definition. -The template argument list following the class template name in the member -definition shall name the parameters in the same order as the one used in -the template parameter list of the member. Each template -parameter pack shall be expanded with an ellipsis in the template -argument list. +The class template name in the member definition is followed by +the template argument list of the \grammarterm{template-head}\iref{temp.arg}. \begin{example} \begin{codeblock} template struct A { @@ -2307,13 +2293,13 @@ struct S::Inner { }; // OK \end{codeblock} \end{example} +\end{note} \pnum -In a redeclaration, partial -specialization, -explicit specialization or explicit -instantiation of a class template, the -\grammarterm{class-key} +In a partial specialization, +explicit specialization or +explicit instantiation of a class template, +the \grammarterm{class-key} shall agree in kind with the original class template declaration\iref{dcl.type.elab}. \rSec3[temp.mem.func]{Member functions of class templates} @@ -2398,7 +2384,7 @@ for a deduced class type\iref{dcl.type.class.deduct}. Deduction guides are not found by name lookup. Instead, when performing class template argument deduction\iref{over.match.class.deduct}, -any deduction guides declared for the class template are considered. +all reachable deduction guides declared for the class template are considered. \begin{bnf} \nontermdef{deduction-guide}\br @@ -2435,14 +2421,13 @@ as the \grammarterm{template-name} of the \grammarterm{simple-template-id}. A \grammarterm{deduction-guide} -shall be declared -in the same scope -as the corresponding class template -and, for a member class template, with the same access. +shall inhabit the scope +to which the corresponding class template belongs +and, for a member class template, have the same access. Two deduction guide declarations -in the same translation unit for the same class template -shall not have equivalent \grammarterm{parameter-declaration-clause}{s}. +shall not have equivalent \grammarterm{parameter-declaration-clause}{s} +if either is reachable from the other. \rSec3[temp.mem.class]{Member classes of class templates} @@ -2617,11 +2602,12 @@ \end{example} \pnum +\begin{note} A specialization of a conversion function template is referenced in the same way as a non-template conversion function that converts to -the same type. +the same type\iref{class.conv.fct}. \begin{example} \begin{codeblock} struct A { @@ -2638,39 +2624,11 @@ } \end{codeblock} \end{example} -\begin{note} There is no syntax to form a \grammarterm{template-id}\iref{temp.names} by providing an explicit template argument list\iref{temp.arg.explicit} -for a conversion function template\iref{class.conv.fct}. +for a conversion function template. \end{note} -\pnum -A specialization of a -conversion function template -is not found by name -lookup. -Instead, any -conversion function templates -visible in the -context of the use are considered. -For each such operator, if argument -deduction succeeds\iref{temp.deduct.conv}, the resulting specialization is -used as if found by name lookup. - -\pnum -A \grammarterm{using-declaration} in a derived class cannot refer to a specialization -of a -conversion function template -in a base class. - -\pnum -Overload resolution\iref{over.ics.rank} and partial -ordering\iref{temp.func.order} are used to select the best conversion function -among multiple -specializations of conversion function templates -and/or non-template -conversion functions. - \rSec2[temp.variadic]{Variadic templates} \pnum @@ -2978,27 +2936,6 @@ A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or a non-template function or class. -For a friend function declaration that is not a template declaration: -\begin{itemize} -\item -if the name of the friend is a qualified or unqualified \grammarterm{template-id}, -the friend declaration refers to a specialization of a function -template, otherwise, -\item -if the name of the friend is a \grammarterm{qualified-id} and a matching non-template -function is found in the specified class or namespace, the friend -declaration refers to that function, otherwise, -\item -if the name of the friend is a \grammarterm{qualified-id} and a matching -function template -is found in the specified class -or namespace, the friend declaration refers to -the deduced specialization of that function template\iref{temp.deduct.decl}, otherwise, -\item -the name shall be an \grammarterm{unqualified-id} that declares (or redeclares) a -non-template function. -\end{itemize} - \begin{example} \begin{codeblock} template class task; @@ -3056,6 +2993,20 @@ as friends. \end{example} +\pnum +Friend classes, class templates, functions, or function templates +can be declared within a class template. +When a template is instantiated, +its friend declarations are found by name lookup +as if the specialization had been explicitly declared at +its point of instantiation. +\begin{note} +They may introduce entities +that belong to an enclosing namespace scope\iref{dcl.meaning}, +in which case they are attached to +the same module as the class template\iref{module.unit}. +\end{note} + \pnum A friend template may be declared within a class or class template. A friend function template may be defined within a class or class @@ -3105,8 +3056,8 @@ if deduction of the template parameters of \placeholder{C} from \placeholder{S} succeeds, and substituting the deduced template arguments into the friend declaration -produces a declaration that would be a valid redeclaration -of the member of the specialization. +produces a declaration that corresponds to +the member of the specialization. \begin{example} \begin{codeblock} template struct A { @@ -3143,11 +3094,6 @@ \end{codeblock} \end{example} -\pnum -\begin{note} -A friend declaration can first declare a member of an enclosing namespace scope\iref{temp.inject}. -\end{note} - \pnum A friend template shall not be declared in a local class. @@ -3185,29 +3131,20 @@ \pnum \indextext{specialization!class template partial}% -\indextext{primary class template|see{template, primary}}% -A -\defnx{primary class template}{template!primary} -declaration is one in which the class template name is an -identifier. -A template declaration in which the class template name is a -\grammarterm{simple-template-id} -is a -\defnx{partial specialization}{specialization!class template partial} -of the class template named in the -\grammarterm{simple-template-id}. A partial specialization of a class template provides an alternative definition of the template that is used instead of the primary definition when the arguments in a specialization match those given in the partial specialization\iref{temp.class.spec.match}. -The primary template shall be declared before any specializations of +A declaration of the primary template shall precede any specialization of that template. -A partial specialization shall be declared before the first use of a class template +A partial specialization shall be reachable from any use of a class template specialization that would make use of the partial specialization as the result of -an implicit or explicit instantiation in every translation unit in which such a use -occurs; no diagnostic is required. +an implicit or explicit instantiation; no diagnostic is required. \pnum +Two partial specialization declarations declare the same entity +if they are partial specializations of the same template and have equivalent +\grammarterm{template-head}s and template argument lists\iref{temp.over.link}. Each class template partial specialization is a distinct template and definitions shall be provided for the members of a template partial specialization\iref{temp.class.spec.mfunc}. @@ -3247,31 +3184,9 @@ \pnum The template parameters are specified in the angle bracket enclosed list -that immediately follows the keyword -\keyword{template}. -For partial specializations, the template argument list is explicitly -written immediately following the class template name. -For primary templates, this list is implicitly described by the -template parameter list. -Specifically, the order of the template arguments is the sequence in -which they appear in the template parameter list. -\begin{example} -The template argument list for the primary template in the example -above is -\tcode{}. -\end{example} -\begin{note} -The template argument list cannot be specified in the primary template -declaration. -For example, - -\begin{codeblock} -template -class A { }; // error -\end{codeblock} -\end{note} +that immediately follows the keyword \keyword{template}. +The template argument list of a partial specialization is +the \grammarterm{template-argument-list} of the \grammarterm{ class-name}. \pnum A class template partial specialization may be declared in any @@ -3295,8 +3210,8 @@ \end{example} \pnum -Partial specialization declarations themselves are not found by name lookup. -Rather, when the primary template name is used, any previously-declared partial +Partial specialization declarations do not introduce a name. +Instead, when the primary template name is used, any reachable partial specializations of the primary template are also considered. One consequence is that a @@ -3539,12 +3454,6 @@ \rSec3[temp.class.spec.mfunc]{Members of class template specializations} \pnum -The template parameter list of a member of a class template partial -specialization shall match the template parameter list of the class template -partial specialization. -The template argument list of a member of a class template partial -specialization shall match the template argument list of the class template -partial specialization. A class template partial specialization is a distinct template. The members of the class template partial specialization are unrelated to the members of the primary template. @@ -3636,8 +3545,10 @@ \end{example} \pnum -A function template can be overloaded with other function templates -and with non-template functions\iref{dcl.fct}. +\begin{note} +A function template can have the same name as other function templates +and non-template functions\iref{dcl.fct} in the same scope. +\end{note} A non-template function is not related to a function template (i.e., it is never considered to be a specialization), @@ -3757,11 +3668,13 @@ The intent is to avoid \grammarterm{lambda-expression}{s} appearing in the signature of a function template with external linkage. \end{note} -For determining whether two dependent names\iref{temp.dep} are -equivalent, only the name itself is considered, not the result of name -lookup in the context of the template. If multiple declarations of the -same function template differ in the result of this name lookup, the -result for the first declaration is used. +For determining whether two dependent names\iref{temp.dep} are equivalent, +only the name itself is considered, not the result of name lookup. +\begin{note} +If such a dependent name is unqualified, +it is looked up from +the first declaration of the function template\iref{temp.dep.candidate}. +\end{note} \begin{example} \begin{codeblock} template void f(A); // \#1 @@ -3772,7 +3685,7 @@ template decltype(g(T())) h() // redeclaration of \tcode{h()} uses the earlier lookup\ldots { return g(T()); } // \ldots{} although the lookup here does find \tcode{g(int)} int i = h(); // template argument substitution fails; \tcode{g(int)} - // was not in scope at the first declaration of \tcode{h()} + // not considered at the first declaration of \tcode{h()} // ill-formed, no diagnostic required: the two expressions are functionally equivalent but not equivalent template void foo(const char (*s)[([]{}, N)]); @@ -3795,6 +3708,15 @@ \begin{note} For instance, one could have redundant parentheses. \end{note} +\begin{example} +\begin{codeblock} +template concept C = true; +template struct A { + void f() requires C<42>; // \#1 + void f() requires true; // OK, different functions +}; +\end{codeblock} +\end{example} \pnum Two \grammarterm{template-head}{s} are @@ -3829,32 +3751,6 @@ the same set of template argument lists. \pnum -\indextext{template!function!equivalent|see{equivalent, function templates}}% -Two function templates are -\defnx{equivalent}{equivalent!function templates} -if they -are declared in the same scope, -have the same name, -have equivalent \grammarterm{template-head}{s}, -and -have return types, parameter lists, -and trailing \grammarterm{requires-clause}{s} (if any) -that are equivalent using the rules described above to compare -expressions involving -template parameters. -\indextext{equivalent!functionally|see{functionally equivalent}}% -\indextext{template!function!functionally equivalent|see{functionally equivalent, function templates}}% -Two function templates are -\defnx{functionally equivalent}{functionally equivalent!function templates} -if they -are declared in the same scope, -have the same name, -accept and are satisfied by the same set of template argument lists, -and -have return types and parameter lists that -are functionally equivalent using the rules described above to -compare expressions involving -template parameters. If the validity or meaning of the program depends on whether two constructs are equivalent, and they are functionally equivalent but not equivalent, the program is ill-formed, @@ -3889,10 +3785,10 @@ \pnum \indextext{overloading!resolution!template}% \indextext{ordering!function template partial|see{template, function, partial ordering}}% -If a function template is overloaded, -the use of a function template specialization can be ambiguous because -template argument deduction\iref{temp.deduct} may associate the function -template specialization with more than one function template declaration. +If multiple function templates share a name, +the use of that name can be ambiguous because +template argument deduction\iref{temp.deduct} may identify +a specialization for more than one function template. \defnx{Partial ordering}{template!function!partial ordering} of overloaded function template declarations is used in the following contexts to select the function template to which a function template specialization @@ -4273,7 +4169,7 @@ \pnum A \grammarterm{concept-definition} -shall appear at namespace scope\iref{basic.scope.namespace}. +shall inhabit a namespace scope\iref{basic.scope.namespace}. \pnum A concept shall not have associated constraints\iref{temp.constr.decl}. @@ -4305,55 +4201,86 @@ \rSec2[temp.res.general]{General} \pnum -\indextext{overloading!resolution!template name}% -\indextext{lookup!template name}% -Three kinds of names can be used within a template definition: +A name that appears in a declaration $D$ of a template $T$ is looked up +from where it appears +in an unspecified declaration of $T$ that is or is reachable from $D$ and +from which no other declaration of $T$ +that contains the usage of the name is reachable. +If the name is dependent (as specified in \ref{temp.dep}, +it is looked up for each specialization (after substitution) +because the lookup depends on a template parameter. +\begin{note} +Some dependent names are also looked up during parsing to determine +that they are dependent or to interpret following \tcode{<} tokens. +Uses of other names might be type-dependent or value-dependent +(\ref{temp.dep.expr}, \ref{temp.dep.constexpr}. +A \grammarterm{using-declarator} is never dependent in a specialization and +is therefore replaced during lookup for that specialization\iref{basic.lookup}. +\end{note} +\begin{example} +\begin{codeblock} +struct A { operator int(); }; +template +struct D : B { + T get() { return operator T(); } // \grammarterm{conversion-function-id} is dependent +}; +int f(D d) { return d.get(); } // OK: lookup finds A::operator int +\end{codeblock} +\end{example} +\begin{example} +\begin{codeblock} +void f(char); -\begin{itemize} -\item -The name of the template itself, -and names declared within the template itself. -\item -Names dependent on a -\grammarterm{template-parameter}\iref{temp.dep}. -\item -Names from scopes which are visible within the template definition. -\end{itemize} +template void g(T t) { + f(1); // \tcode{f(char)} + f(T(1)); // dependent + f(t); // dependent + dd++; // not dependent; error: declaration for \tcode{dd} not found +} -\pnum -A name used in a template declaration or definition and that is -dependent on a -\grammarterm{template-parameter} -is assumed not to name a type unless -the applicable name lookup finds a type name or the name -is qualified by the keyword -\tcode{typename}. +enum E { e }; +void f(E); + +double dd; +void h() { + g(e); // will cause one call of \tcode{f(char)} followed by two calls of \tcode{f(E)} + g('a'); // will cause three calls of \tcode{f(char)} +} +\end{codeblock} +\end{example} \begin{example} \begin{codeblock} -// no \tcode{B} declared here - -class X; +struct A { + struct B { @\commentellip@ }; + int a; + int Y; +}; -template class Y { - class Z; // forward declaration of member class +int a; - void f() { - X* a1; // declare pointer to \tcode{X} - T* a2; // declare pointer to \tcode{T} - Y* a3; // declare pointer to \tcode{Y} - Z* a4; // declare pointer to \tcode{Z} - typedef typename T::A TA; - TA* a5; // declare pointer to \tcode{T}'s \tcode{A} - typename T::A* a6; // declare pointer to \tcode{T}'s \tcode{A} - T::A* a7; // error: no visible declaration of \tcode{a7} - // \tcode{T::A} is not a type name; multiplication of \tcode{T::A} by \tcode{a7} - B* a8; // error: no visible declarations of \tcode{B} and \tcode{a8} - // \tcode{B} is not a type name; multiplication of \tcode{B} by \tcode{a8} - } +template struct Y : T { + struct B { @\commentellip@ }; + B b; // The \tcode{B} defined in \tcode{Y} + void f(int i) { a = i; } // \tcode{::a} + Y* p; // \tcode{Y} }; + +Y ya; \end{codeblock} + +The members \tcode{A::B}, \tcode{A::a}, and \tcode{A::Y} +of the template argument \tcode{A} +do not affect the binding of names in \tcode{Y}. \end{example} +\pnum +If the validity or meaning of the program would be changed by +considering a default argument or default template argument +introduced in a declaration that is reachable from +the point of instantiation of a specialization\iref{temp.point} +but is not found by lookup for the specialization, +the program is ill-formed, no diagnostic required. + \begin{bnf} \nontermdef{typename-specifier}\br \keyword{typename} nested-name-specifier identifier\br @@ -4675,27 +4602,6 @@ definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation. -\begin{example} -\begin{codeblock} -void f(char); - -template void g(T t) { - f(1); // \tcode{f(char)} - f(T(1)); // dependent - f(t); // dependent - dd++; // not dependent; error: declaration for \tcode{dd} not found -} - -enum E { e }; -void f(E); - -double dd; -void h() { - g(e); // will cause one call of \tcode{f(char)} followed by two calls of \tcode{f(E)} - g('a'); // will cause three calls of \tcode{f(char)} -} -\end{codeblock} -\end{example} \pnum \begin{note} @@ -5930,12 +5836,6 @@ \rSec2[temp.inject]{Friend names declared within a class template} -\pnum -Friend classes or functions can be declared within a class template. -When a template is instantiated, the names of its friends are treated -as if the specialization had been explicitly declared at its point of -instantiation. - \pnum As with non-template classes, the names of namespace-scope friend functions of a class template specialization are not visible during From ffed22489b4dcffbd84f33cbc6c83c048fdbf707 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 24 Nov 2020 10:00:59 +0100 Subject: [PATCH 42/60] template (third part) --- source/templates.tex | 460 +++++++++++-------------------------------- 1 file changed, 112 insertions(+), 348 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index 5f56b90dbd..47678d08da 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -145,7 +145,7 @@ \pnum \begin{note} -A class shall cannot have the same name as any other +A class cannot have the same name as any other name bound in the same scope\iref{basic.scope.scope}, except that a function template can share a name with non-template functions\iref{dcl.fct} and/or function templates\iref{temp.over}. @@ -248,7 +248,7 @@ \indextext{component name}% The component names of a \grammarterm{type-constraint} are its \grammarterm{concept-name} and -those of its \grammarterm{nested-name-specifier} (if any). +those of its \grammarterm{nested-name-specifier} (if any). \begin{note} The \tcode{>} token following the \grammarterm{template-parameter-list} of a @@ -3001,7 +3001,7 @@ as if the specialization had been explicitly declared at its point of instantiation. \begin{note} -They may introduce entities +They can introduce entities that belong to an enclosing namespace scope\iref{dcl.meaning}, in which case they are attached to the same module as the class template\iref{module.unit}. @@ -3185,7 +3185,7 @@ \pnum The template parameters are specified in the angle bracket enclosed list that immediately follows the keyword \keyword{template}. -The template argument list of a partial specialization is +The template argument list of a partial specialization is the \grammarterm{template-argument-list} of the \grammarterm{ class-name}. \pnum @@ -4288,14 +4288,19 @@ \end{bnf} \pnum +\indextext{component name}% +The component names of a \grammarterm{typename-specifier} are +its \grammarterm{identifier} (if any) and +those of its \grammarterm{nested-name-specifier} and +\grammarterm{simple-template-id} (if any). A \grammarterm{typename-specifier} denotes the type or class template denoted by the \grammarterm{simple-type-specifier}\iref{dcl.type.simple} formed by omitting the keyword \tcode{typename}. -The usual qualified name lookup\iref{basic.lookup.qual} is used to find the -\grammarterm{qualified-id} -even in the presence of -\tcode{typename}. +\begin{note} +The usual qualified name lookup\iref{basic.lookup.qual} applies +even in the presence of \tcode{typename}. +\end{note} \begin{example} \begin{codeblock} struct A { @@ -4318,28 +4323,27 @@ \end{example} \pnum -A qualified name used as the name in a -\grammarterm{class-or-decltype}\iref{class.derived} -or an -\grammarterm{elaborated-type-specifier} -is implicitly assumed to name a type, without the use of the -\tcode{typename} -keyword. -In a \grammarterm{nested-name-specifier} that immediately contains a \grammarterm{nested-name-specifier} -that depends on a template parameter, the \grammarterm{identifier} or \grammarterm{simple-template-id} -is implicitly assumed to name a type, without the use of the \tcode{typename} keyword. -\begin{note} -The -\tcode{typename} -keyword is not permitted by the syntax of these constructs. -\end{note} - -\pnum -A \grammarterm{qualified-id} -is assumed to name a type if +A qualified or unqualified name is said to be in a type-only context +if it is the terminal name of \begin{itemize} -\item it is a qualified name in a type-id-only context (see below), or -\item it is a \grammarterm{decl-specifier} of the \grammarterm{decl-specifier-seq} of a +\item a +\grammarterm{typename-specifier}, +\grammarterm{nested-name-specifier}, +\grammarterm{elaborated-type-specifier}, +\grammarterm{class-or-decltype}, or +\item +a \grammarterm{type-specifier} of a +\grammarterm{new-type-id}, +\grammarterm{defining-type-id}, +\grammarterm{conversion-type-id}, +\grammarterm{trailing-return-type}, +default argument of a \grammarterm{type-parameter}, or +\grammarterm{type-id} of a +\keyword{static_cast}, +\keyword{const_cast}, +\keyword{reinterpret_cast}, or +\keyword{dynamic_cast}, or +\item a \grammarterm{decl-specifier} of the \grammarterm{decl-specifier-seq} of a \begin{itemize} \item \grammarterm{simple-declaration} or a \grammarterm{function-definition} in namespace scope, \item \grammarterm{member-declaration}, @@ -4360,25 +4364,6 @@ \item \grammarterm{parameter-declaration} of a (non-type) \grammarterm{template-parameter}. \end{itemize} \end{itemize} -A qualified name is said to be in a \defn{type-id-only context} -if it appears in a -\grammarterm{type-id}, -\grammarterm{new-type-id}, or -\grammarterm{defining-type-id} -and the smallest enclosing -\grammarterm{type-id}, -\grammarterm{new-type-id}, or -\grammarterm{defining-type-id} -is a -\grammarterm{new-type-id}, -\grammarterm{defining-type-id}, -\grammarterm{trailing-return-type}, -default argument of a \grammarterm{type-parameter} of a template, or -\grammarterm{type-id} of a -\tcode{static_cast}, -\tcode{const_cast}, -\tcode{reinterpret_cast}, or -\tcode{dynamic_cast}. \begin{example} \begin{codeblock} template T::R f(); // OK, return type of a function declaration at global scope @@ -4400,10 +4385,13 @@ \end{example} \pnum -A \grammarterm{qualified-id} that refers to a member of an unknown specialization, -that is not prefixed by \tcode{typename}, -and that is not otherwise assumed to name a type (see above) -denotes a non-type. +A \grammarterm{qualified-id} +whose terminal name is dependent and that is in a type-only context +is considered to denote a type. +A name +that refers to a \grammarterm{using-declarator} whose terminal name is dependent +is interpreted as a \grammarterm{typedef-name} +if the \grammarterm{using-declarator} uses the keyword \keyword{typename}. \begin{example} \begin{codeblock} template void f(int i) { @@ -4425,21 +4413,6 @@ \end{codeblock} \end{example} -\pnum -Within the definition of a class template or within the definition of a -member of a class template following the \grammarterm{declarator-id}, the keyword -\tcode{typename} -is not required when referring to -a member of the current instantiation\iref{temp.dep.type}. -\begin{example} -\begin{codeblock} -template struct A { - typedef int B; - B b; // OK, no \tcode{typename} required -}; -\end{codeblock} -\end{example} - \pnum \indextext{checking!syntax}% \indextext{checking!point of error}% @@ -4521,6 +4494,8 @@ t = i; // diagnosed if \tcode{X::f} is instantiated, and the assignment to \tcode{t} is an error p = i; // may be diagnosed even if \tcode{X::f} is not instantiated p = j; // may be diagnosed even if \tcode{X::f} is not instantiated + X::g(t); // OK + X::h(); // may be diagnosed even if \tcode{X::f} is not instantiated } void g(T t) { +; // may be diagnosed even if \tcode{X::g} is not instantiated @@ -4535,74 +4510,6 @@ \end{codeblock} \end{example} -\pnum -When looking for the declaration of a name used in a template definition, -the usual lookup rules~(\ref{basic.lookup.unqual}, \ref{basic.lookup.argdep}) -are used for non-dependent names. -The lookup of names dependent on the template parameters -is postponed until the actual template argument is known\iref{temp.dep}. -\begin{example} -\begin{codeblock} -#include -using namespace std; - -template class Set { - T* p; - int cnt; -public: - Set(); - Set(const Set&); - void printall() { - for (int i = 0; i}. \pnum -Within the scope of a class template specialization or -partial specialization, when the injected-class-name is -used as a \grammarterm{type-name}, +When the inject-class-name of a class template specialization or +partial specialization is used as a \grammarterm{type-name}, it is equivalent to the \grammarterm{template-name} followed by the \grammarterm{template-argument}{s} of the class template specialization or partial @@ -4659,7 +4565,7 @@ The injected-class-name of a class template or class template specialization can be used as either a \grammarterm{template-name} or a \grammarterm{type-name} -wherever it is in scope. +wherever it is named. \begin{example} \begin{codeblock} template struct Base { @@ -4670,7 +4576,7 @@ typename Derived::Base* p; // meaning \tcode{Derived::Base} }; -template class U = T::template Base> struct Third { }; +template class U = T::Base> struct Third { }; Third > t; // OK: default argument uses injected-class-name as a template \end{codeblock} \end{example} @@ -4714,95 +4620,55 @@ \end{example} \pnum -The name of a -\grammarterm{template-parameter} -shall not be redeclared within its scope (including nested scopes). -A -\grammarterm{template-parameter} -shall not have the same name as the template name. +The name of a \grammarterm{template-parameter} +shall not be bound to any following declaration contained by the scope +to which the template-parameter belongs. \begin{example} \begin{codeblock} template class Y { - int T; // error: template-parameter redeclared + int T; // error: \grammarterm{template-parameter} hidden void f() { - char T; // error: template-parameter redeclared + char T; // error: \grammarterm{template-parameter} hidden } + friend void T(); // OK: no name bound }; -template class X; // error: template-parameter redeclared -\end{codeblock} -\end{example} - -\pnum -In the definition of a member of -a class template that appears outside of the class template definition, -the name of a member of the class template hides the name of a -\grammarterm{template-parameter} -of any enclosing class templates (but not a \grammarterm{template-parameter} of the -member if the member is a class or function template). -\begin{example} -\begin{codeblock} -template struct A { - struct B { @\commentellip@ }; - typedef void C; - void f(); - template void g(U); -}; - -template void A::f() { - B b; // \tcode{A}'s \tcode{B}, not the template parameter -} - -template template void A::g(C) { - B b; // \tcode{A}'s \tcode{B}, not the template parameter - C c; // the template parameter \tcode{C}, not \tcode{A}'s \tcode{C} -} +template class X; // error: hidden by \grammarterm{template-parameter} \end{codeblock} \end{example} \pnum -In the definition of a member of a class template that appears outside of the -namespace containing the class template definition, -the name of a -\grammarterm{template-parameter} -hides the name of a member of this namespace. +Unqualified name lookup considers +the template parameter scope of a \grammarterm{template-declaration} +immediately after the outermost scope associated with the template declared +(even if its parent scope does not contain +the \grammarterm{template-parameter-list}). +\begin{note} +The scope of a class template, +including its non-dependent base classes +(\ref{temp.dep.type}, \ref{class.member.lookup}), +is searched before its template parameter scope. +\end{note} \begin{example} \begin{codeblock} +struct B { }; namespace N { - class C { }; - template class B { - void f(T); + typedef void V; + template struct A : B { + typedef void C; + void f(); + template void g(U); }; } -template void N::B::f(C) { - C b; // \tcode{C} is the template parameter, not \tcode{N::C} -} -\end{codeblock} -\end{example} -\pnum -In the definition of a class template or in the definition of a member of such -a template that appears outside of the template definition, -for each non-dependent base class\iref{temp.dep.type}, -if the name of the base class -or the name of a member of the -base class is the same as the name of a -\grammarterm{template-parameter}, -the base class name or member name hides the -\grammarterm{template-parameter} -name\iref{basic.lookup}. -\begin{example} -\begin{codeblock} -struct A { - struct B { @\commentellip@ }; - int a; - int Y; -}; +template void N::A::f() { // \tcode{N::V} not considered here + V v; // \tcode{V} is still the template parameter, not \tcode{N::V} +} -template struct X : A { - B b; // \tcode{A}'s \tcode{B} - a b; // error: \tcode{A}'s \tcode{a} isn't a type name -}; +template template void N::A::g(C) { + B b; // the base class, not the template parameter + C c; // the template parameter \tcode{C}, not \tcode{A}'s \tcode{C} +} \end{codeblock} \end{example} @@ -4831,19 +4697,14 @@ as described below. \pnum -In an expression of the form: +A \defnadj{dependent}{call} is an expression, +possibly formed as a non-member candidate for an operator\iref{over.match.oper}, +of the form: \begin{ncsimplebnf} postfix-expression \terminal{(} \opt{expression-list} \terminal{)} \end{ncsimplebnf} -where the -\grammarterm{postfix-expression} -is an -\grammarterm{unqualified-id}, -the -\grammarterm{unqualified-id} -denotes a -\defnx{dependent name}{name!dependent} -if +where the \grammarterm{postfix-expression} +is an \grammarterm{unqualified-id} and \begin{itemize} \item any of the expressions in the \grammarterm{expression-list} is a pack @@ -4859,13 +4720,22 @@ is a \grammarterm{template-id} in which any of the template arguments depends on a template parameter. \end{itemize} - -If an operand of an operator is a type-dependent expression, the operator -also denotes a dependent name. +The component name of an \grammarterm{unqualified-id} is dependent if +\begin{itemize} +\item +it is a \grammarterm{conversion-function-id} +whose \grammarterm{conversion-type-id} is dependent, or +\item +it is \tcode{\keyword{operator}=} and +the current class is a templated entity, or +\item +the \grammarterm{unqualified-id} is +the \grammarterm{postfix-expression} in a dependent call. +\end{itemize} \begin{note} -Such names are unbound and -are looked up at the point of the template instantiation\iref{temp.point} in -both the context of the template definition and the +Such names +are looked up only at the point of the template instantiation\iref{temp.point} +in both the context of the template definition and the context of the point of instantiation\iref{temp.dep.candidate}. \end{note} @@ -4893,68 +4763,10 @@ \grammarterm{template-parameter}. \end{example} -\pnum -In the definition of a class or class template, -the scope of a dependent base class\iref{temp.dep.type} -is not examined during unqualified -name lookup either at the point of definition of the -class template or member or during an instantiation of -the class template or member. -\begin{example} -\begin{codeblock} -typedef double A; -template class B { - typedef int A; -}; -template struct X : B { - A a; // \tcode{a} has type \tcode{double} -}; -\end{codeblock} - -The type name -\tcode{A} -in the definition of -\tcode{X} -binds to the typedef name defined in the global -namespace scope, not to the typedef name -defined in the base class -\tcode{B}. -\end{example} -\begin{example} -\begin{codeblock} -struct A { - struct B { @\commentellip@ }; - int a; - int Y; -}; - -int a; - -template struct Y : T { - struct B { @\commentellip@ }; - B b; // The \tcode{B} defined in \tcode{Y} - void f(int i) { a = i; } // \tcode{::a} - Y* p; // \tcode{Y} -}; - -Y ya; -\end{codeblock} - -The members -\tcode{A::B}, -\tcode{A::a}, -and -\tcode{A::Y} -of the template argument -\tcode{A} -do not affect the binding of names in -\tcode{Y}. -\end{example} - \rSec3[temp.dep.type]{Dependent types} \pnum -A name refers to the +A name or \grammarterm{template-id} refers to the \defn{current instantiation} if it is \begin{itemize} @@ -4965,8 +4777,8 @@ \item in the definition of a primary class template or a member of a primary class template, the name of the -class template followed by the template argument list of the -primary template (as described below) enclosed in +class template followed by the template argument list of +its \grammarterm{template-head}\iref{temp.arg} enclosed in \tcode{<>} (or an equivalent template alias specialization), \item in the definition of a nested class of a class template, @@ -4975,27 +4787,11 @@ \item in the definition of a partial specialization or a member of a partial specialization, the name of -the class template followed by the template argument list of -the partial specialization enclosed in -\tcode{<>} (or an equivalent template alias specialization). -If the $n^\text{th}$ template parameter is -a template parameter pack, the $n^\text{th}$ template argument is a pack -expansion\iref{temp.variadic} whose pattern is the name of -the template parameter pack. +the class template followed by the template argument list +equivalent to that of the partial specialization\iref{temp.class.spec} +enclosed in \tcode{<>} (or an equivalent template alias specialization). \end{itemize} -\pnum -The template argument list of a primary template is a -template argument list in which the -$n^\text{th}$ -template argument has the value of the -$n^\text{th}$ -template parameter of the class template. -If the $n^\text{th}$ template parameter is a template -parameter pack\iref{temp.variadic}, the $n^\text{th}$ template argument is a pack -expansion\iref{temp.variadic} whose pattern is the name of -the template parameter pack. - \pnum A template argument that is equivalent to a template parameter can be used in place of that @@ -5082,50 +4878,16 @@ \pnum \indextext{member of the current instantiation|see{current instantiation, member of the}}% -A name is a +A qualified\iref{basic.lookup.qual} or unqualified name is a \defnx{member of the current instantiation}{current instantiation!member of the} -if it is - +if \begin{itemize} \item -An unqualified name that, when looked up, refers to -at least one member of a class that is -the current instantiation or a non-dependent base class thereof. -\begin{note} -This can only occur when looking up a name in a scope enclosed by the -definition of a class template. -\end{note} +its lookup context, if it is a \grammarterm{qualified name}, +is the current instantiation, and \item -A -\grammarterm{qualified-id} -in which the -\grammarterm{nested-name-specifier} -refers to the current instantiation -and that, when looked up, refers to at least one member of a class that is -the current -instantiation or a non-dependent base class thereof. -\begin{note} -If no such -member is found, and the current instantiation has any dependent base classes, -then the \grammarterm{qualified-id} is a member of an unknown specialization; -see below. -\end{note} - -\item -An \grammarterm{id-expression} denoting the member in a class member access -expression\iref{expr.ref} for which the type of the object expression is the -current instantiation, and the \grammarterm{id-expression}, when looked -up\iref{basic.lookup.qual}, refers to at least one member of a class -that is the current -instantiation or a non-dependent base class thereof. -\begin{note} -If no such -member is found, and the current instantiation has any dependent base classes, -then the \grammarterm{id-expression} is a member of an unknown specialization; -see below. -\end{note} +lookup for it finds any member of a class that is the current instantiation \end{itemize} - \begin{example} \begin{codeblock} template class A { @@ -5143,9 +4905,11 @@ \end{example} \indextext{dependent member of the current instantiation|see{current instantiation, dependent member of the}}% -A name is a \defnx{dependent member of the current instantiation}{current instantiation!dependent member of the} if it is a +A qualified or unqualified name names a \defnx{dependent member of the current instantiation}{current instantiation!dependent member of the} if it is a member of the current instantiation that, when looked up, refers to at least -one member of a class that is the current instantiation. +one member declaration +(including a \grammarterm{using-declarator} whose terminal name is dependent) +of a class that is the current instantiation. \pnum A name is a From c020c4b4fe1f12656be15e5ab00f6a6be53cc795 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 24 Nov 2020 18:54:57 +0100 Subject: [PATCH 43/60] template (remainder) --- source/basic.tex | 4 +- source/templates.tex | 452 +++++++++++-------------------------------- source/xrefdelta.tex | 2 + 3 files changed, 116 insertions(+), 342 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index b6725a025f..b0e1a2d899 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -723,7 +723,7 @@ If \tcode{D} is a template and is defined in more than one translation unit, then the preceding requirements shall apply both to names from the template's enclosing scope used in the -template definition\iref{temp.nondep}, and also to dependent names at +template definition, and also to dependent names at the point of instantiation\iref{temp.dep}. These requirements also apply to corresponding entities defined within each definition of \tcode{D} @@ -2754,7 +2754,7 @@ that refers to a set of overloads that contains $E$. \begin{note} Non-dependent names in an instantiated declaration -do not refer to a set of overloads\iref{temp.nondep}. +do not refer to a set of overloads\iref{temp.res}. \end{note} \end{itemize} diff --git a/source/templates.tex b/source/templates.tex index 47678d08da..6dd6a2bd6a 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4908,70 +4908,49 @@ A qualified or unqualified name names a \defnx{dependent member of the current instantiation}{current instantiation!dependent member of the} if it is a member of the current instantiation that, when looked up, refers to at least one member declaration -(including a \grammarterm{using-declarator} whose terminal name is dependent) +(including a \grammarterm{using-declarator} whose terminal name is dependent) of a class that is the current instantiation. \pnum -A name is a -\defn{member of an unknown specialization} -if it is +A qualified name\iref{basic.lookup.qual} is dependent if \begin{itemize} \item -A -\grammarterm{qualified-id} -in which the -\grammarterm{nested-name-specifier} -names a dependent type that is not the current instantiation. - -\item A \grammarterm{qualified-id} in which the \grammarterm{nested-name-specifier} -refers to the current instantiation, the current instantiation has at least one -dependent base class, and name lookup of the \grammarterm{qualified-id} does not -find any member of a class that is the current instantiation or a non-dependent -base class thereof. - -\item An \grammarterm{id-expression} denoting the member in a class member access -expression\iref{expr.ref} in which either -\begin{itemize} -\item the type of the object expression is the current instantiation, the -current instantiation has at least one dependent base class, and name lookup -of the \grammarterm{id-expression} does not find a member of a class that is -the current instantiation or a non-dependent base class thereof; or - -\item the type of the object expression is not the current instantiation -and the object expression is type-dependent. -\end{itemize} +it is a \grammarterm{conversion-function-id} +whose \grammarterm{conversion-type-id} is dependent, or +\item +its lookup context is dependent and is not the current instantiation, or +\item +its lookup context is the current instantiation and +it is \tcode{\keyword{operator}=} +\begin{footnote} +Every instantiation of a class template declares +a different set of assignment operators. +\end{footnote}, or +\item +its lookup context is the current instantiation and +has at least one dependent base class, and +qualified name lookup for the name finds nothing\iref{basic.lookup.qual}. \end{itemize} - -\pnum -If a \grammarterm{qualified-id} in which the \grammarterm{nested-name-specifier} -refers to the current instantiation is not a member of the current instantiation -or a member of an unknown specialization, the program is ill-formed even if the -template containing the \grammarterm{qualified-id} is not instantiated; no -diagnostic required. Similarly, if the \grammarterm{id-expression} in a class -member access expression for which the type of the object expression is the -current instantiation does not refer to a member of the current instantiation -or a member of an unknown specialization, the program is ill-formed even if the -template containing the member access expression is not instantiated; no diagnostic -required. \begin{example} \begin{codeblock} -template class A { - typedef int type; - void f() { - A::type i; // OK: refers to a member of the current instantiation - typename A::other j; // error: neither a member of the current instantiation nor - // a member of an unknown specialization - } +struct A { + using B = int; + A f(); }; +struct C : A {}; +template +void g(T t) { + decltype(t.A::f())::B i; // error: \keyword{typename} needed to interpret \tcode{B} as a type +} +template void g(C); // \ldots even though \tcode{A} is \tcode{::A} here \end{codeblock} \end{example} \pnum If, for a given set of template arguments, a specialization of a template is instantiated that refers to a member of the current instantiation with a -\grammarterm{qualified-id} or class member access expression, the name in the -\grammarterm{qualified-id} or class member access expression is looked up in the +qualified name, the name in is looked up in the template instantiation context. If the result of this lookup differs from the result of name lookup in the template definition context, name lookup is ambiguous. @@ -5003,10 +4982,10 @@ \item a template parameter, \item -a member of an unknown specialization, +denoted by a dependent (qualified) name, \item -a nested class or enumeration that is a dependent member of the current -instantiation, +a nested class or enumeration that is a direct member of +a class that is the current instantiation, \item a cv-qualified type where the cv-unqualified type is dependent, \item @@ -5046,38 +5025,32 @@ \pnum \tcode{this} -is type-dependent if the class type of the enclosing member function is +is type-dependent if the current class\iref{expr.prim.this} is dependent\iref{temp.dep.type}. \pnum -An -\grammarterm{id-expression} -is type-dependent if it is not a concept-id and it contains +An \grammarterm{id-expression} is type-dependent +if it is a \grammarterm{template-id} that is not a concept-id and is dependent; +or if its terminal name is \begin{itemize} \item -an -\grammarterm{identifier} associated by name lookup with one or more declarations declared with a dependent type, \item -an -\grammarterm{identifier} associated by name lookup with a non-type \grammarterm{template-parameter} declared with a type that contains a placeholder type\iref{dcl.spec.auto}, \item -an -\grammarterm{identifier} associated by name lookup with a variable declared with a type that contains a placeholder type\iref{dcl.spec.auto} where the initializer is type-dependent, \item -an \grammarterm{identifier} associated by name lookup with one or more -declarations of member functions of the current instantiation declared -with a return type that contains a placeholder type, +associated by name lookup with one or more +declarations of member functions of a class that is the current instantiation +declared with a return type that contains a placeholder type, \item -an \grammarterm{identifier} associated by name lookup with +associated by name lookup with a structured binding declaration\iref{dcl.struct.bind} whose \grammarterm{brace-or-equal-initializer} is type-dependent, \item @@ -5086,19 +5059,9 @@ \mname{func}\iref{dcl.fct.def.general}, where any enclosing function is a template, a member of a class template, or a generic lambda, \item -a -\grammarterm{template-id} -that is dependent, -\item -a -\grammarterm{conversion-function-id} -that specifies a dependent type, or +a \grammarterm{conversion-function-id} that specifies a dependent type, or \item -a -\grammarterm{nested-name-specifier} -or a -\grammarterm{qualified-id} -that names a member of an unknown specialization; +dependent \end{itemize} or if it names a dependent member of the current instantiation that is a static data member of type @@ -5148,9 +5111,9 @@ \pnum A class member access expression\iref{expr.ref} is type-dependent if +the terminal name of its \grammarterm{id-expression}, if any, is dependent or the expression refers to a member of the current instantiation and -the type of the referenced member is dependent, or the class member access -expression refers to a member of an unknown specialization. +the type of the referenced member is dependent. \begin{note} In an expression of the form \tcode{x.y} @@ -5169,13 +5132,7 @@ refers to a dependent type that is not the current instantiation, the type of \tcode{y} -is always dependent. If -\tcode{x} -or \tcode{xp} -refers to a non-dependent type or refers to the current instantiation, the -type of -\tcode{y} -is the type of the class member access expression. +is always dependent. \end{note} \pnum @@ -5293,36 +5250,9 @@ a dependent type. \pnum -A template -\grammarterm{template-argument} -is dependent if it names a -\grammarterm{template-parameter} -or is a -\grammarterm{qualified-id} -that refers to a member of an unknown specialization. - -\rSec2[temp.nondep]{Non-dependent names} - -\pnum -Non-dependent names used in a template definition are found using the -usual name lookup and bound at the point they are used. -\begin{example} -\begin{codeblock} -void g(double); -void h(); - -template class Z { -public: - void f() { - g(1); // calls \tcode{g(double)} - h++; // ill-formed: cannot increment function; this could be diagnosed - // either here or at the point of instantiation - } -}; - -void g(int); // not in scope at the point of the template definition, not considered for the call \tcode{g(1)} -\end{codeblock} -\end{example} +A template \grammarterm{template-parameter} is dependent if +it names a \grammarterm{template-parameter} or +its terminal name is dependent. \rSec2[temp.dep.res]{Dependent name resolution} \rSec3[temp.point]{Point of instantiation} @@ -5421,22 +5351,13 @@ \pnum \indextext{functions!candidate}% -For a function call where the \grammarterm{postfix-expression} is a -dependent name, -the candidate functions are found using the usual lookup -rules from the template definition context -(\ref{basic.lookup.unqual}, \ref{basic.lookup.argdep}). -\begin{note} -For the part of the lookup using associated namespaces\iref{basic.lookup.argdep}, -function declarations found in the template instantiation context -are found by this lookup, as described in \ref{basic.lookup.argdep}. -\end{note} -If -the call would be ill-formed or would find a better match had the lookup -within the associated namespaces considered all the function declarations with -external linkage introduced in those namespaces in all translation units, +If a dependent call\iref{temp.dep} would be ill-formed or +would find a better match had the lookup for its dependent name +considered all the function declarations with external linkage +introduced in the associated 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. +template instantiation contexts\iref{basic.lookup.argdep}, +then the program is ill-formed, no diagnostic required. \pnum \begin{example} @@ -5598,35 +5519,6 @@ \end{codeblocktu} \end{example} -\rSec2[temp.inject]{Friend names declared within a class template} - -\pnum -As with non-template classes, the names of namespace-scope friend -functions of a class template specialization are not visible during -an ordinary lookup unless explicitly declared at namespace scope\iref{class.friend}. -Such names may be found under the rules for associated -classes\iref{basic.lookup.argdep}. -\begin{footnote} -Friend declarations do not -introduce new names into any scope, either -when the template is declared or when it is instantiated. -\end{footnote} -\begin{example} -\begin{codeblock} -template struct number { - number(int); - friend number gcd(number x, number y) { return 0; }; -}; - -void g() { - number a(3), b(4); - a = gcd(a,b); // finds \tcode{gcd} because \tcode{number} is an associated class, - // making \tcode{gcd} visible in its namespace (global scope) - b = gcd(3,4); // error: \tcode{gcd} is not visible -} -\end{codeblock} -\end{example} - \rSec1[temp.spec]{Template instantiation and specialization} \rSec2[temp.spec.general]{General} @@ -5663,13 +5555,13 @@ \tcode{\keyword{template}<>}. In an explicit specialization declaration for a variable template, a class template, -a member of a class template or a class member template, -the name of the variable or class that is explicitly specialized shall be a -\grammarterm{simple-template-id}. +a member of a class template, or a class member template, +the variable or class that is explicitly specialized +shall be specified with a \grammarterm{simple-template-id}. In the explicit specialization declaration for a function template or a member function template, -the name of the function or member function explicitly specialized may be a -\grammarterm{template-id}. +the function or member function explicitly specialized may be specified +using a \grammarterm{template-id}. \begin{example} \begin{codeblock} template struct A { @@ -5711,10 +5603,10 @@ \item both an explicit instantiation and a declaration of an explicit specialization shall not appear in a program unless -the explicit instantiation follows a declaration of the explicit -specialization. +the explicit specialization is reachable from the explicit instantiation. \end{itemize} -An implementation is not required to diagnose a violation of this rule. +An implementation is not required to diagnose a violation of this rule +if neither declaration is reachable from the other. \pnum The usual access checking rules do not apply to names @@ -5826,7 +5718,8 @@ } \end{codeblock} \end{example} -If a class template has been declared, but not defined, +If the template selected for the specialization\iref{temp.class.spec.match} +has been declared, but not defined, at the point of instantiation\iref{temp.point}, the instantiation yields an incomplete class type\iref{basic.types}. \begin{example} @@ -5914,8 +5807,7 @@ \end{example} \pnum -Unless a member of a class template or a member template -is a declared specialization, +Unless a member of a templated class is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist or @@ -6044,8 +5936,8 @@ \pnum An implementation shall not implicitly instantiate a function template, a variable template, -a member template, a non-virtual member function, a member class, a -static data member of a class template, or a substatement of a constexpr if +a member template, a non-virtual member function, or a member class or +static data member of a templated class, or a substatement of a constexpr if statement\iref{stmt.if}, unless such instantiation is required. \begin{note} The instantiation of a generic lambda @@ -6065,44 +5957,6 @@ function call causes specializations in the default argument to be implicitly instantiated. -\pnum -Implicitly instantiated class, function, and variable template specializations -are placed in the namespace where the template is defined. -Implicitly instantiated specializations for members of a class template are -placed in the namespace where the enclosing class template is defined. -Implicitly instantiated member templates are placed in the namespace where the -enclosing class or class template is defined. -\begin{example} -\begin{codeblock} -namespace N { - template class List { - public: - T* get(); - }; -} - -template class Map { -public: - N::List lt; - V get(K); -}; - -void g(Map& m) { - int i = m.get("Nicholas"); -} -\end{codeblock} - -A call of -\tcode{lt.get()} -from -\tcode{Map::get()} -would place -\tcode{List::get()} -in the namespace -\tcode{N} -rather than in the global namespace. -\end{example} - \pnum If a function template \tcode{f} @@ -6269,43 +6123,9 @@ shall be a \grammarterm{simple-declaration} whose \grammarterm{init-declarator-list} comprises a single \grammarterm{init-declarator} that does not have an \grammarterm{initializer}. -If the explicit instantiation is for -a function or member function, -the -\grammarterm{unqualified-id} -in the -\grammarterm{declarator} -shall be either a -\grammarterm{template-id} -or, where all template arguments can be deduced, a -\grammarterm{template-name} or \grammarterm{operator-function-id}. -\begin{note} -The declaration can declare a -\grammarterm{qualified-id}, -in which case the -\grammarterm{unqualified-id} -of the -\grammarterm{qualified-id} -must be a -\grammarterm{template-id}. -\end{note} -If the explicit instantiation is for a member function, a member class or -a static data member of a class template specialization, -the name of the class template specialization in the -\grammarterm{qualified-id} -for the member name shall be a \grammarterm{simple-template-id}. If the explicit instantiation is for a variable template specialization, the \grammarterm{unqualified-id} in the \grammarterm{declarator} shall be a \grammarterm{simple-template-id}. -An explicit instantiation shall appear in an enclosing namespace -of its template. If the name declared in the explicit -instantiation is an unqualified name, the explicit instantiation -shall appear in the namespace where its template is declared or, if that -namespace is inline\iref{namespace.def}, any namespace from its enclosing -namespace set. -\begin{note} -Regarding qualified names in declarators, see~\ref{dcl.meaning}. -\end{note} \begin{example} \begin{codeblock} template class Array { void mf(); }; @@ -6323,16 +6143,18 @@ \end{example} \pnum +An explicit instantiation does not introduce a name\iref{basic.scope.scope}. A declaration of a function template, a variable template, a member function or static data member of a class template, or a member function template of a class or class -template shall precede an explicit instantiation of that entity. A definition +template shall be reachable from any explicit instantiation of that entity. +A definition of a class template, a member class of a class template, or a member class -template of a class or class template shall precede an explicit instantiation -of that entity unless the explicit instantiation is preceded by an explicit -specialization of the entity with the same template arguments. -If the -\grammarterm{declaration} +template of a class or class template shall be reachable from any explicit instantiation +of that entity unless an explicit +specialization of the entity with the same template arguments +is reachable therefrom. +If the x\grammarterm{declaration} of the explicit instantiation names an implicitly-declared special member function\iref{special}, the program is ill-formed. @@ -6372,36 +6194,14 @@ data member of a class template shall be present in every translation unit in which it is explicitly instantiated. -\pnum -An explicit instantiation of a class, function template, or variable template -specialization is -placed in the namespace in which the template is defined. -An explicit instantiation for a member of a class template is placed in -the namespace where the enclosing class template is defined. -An explicit instantiation for a member template is placed in the namespace -where the enclosing class or class template is defined. -\begin{example} -\begin{codeblock} -namespace N { - template class Y { void mf() { } }; -} - -template class Y; // error: class template \tcode{Y} not visible in the global namespace - -using N::Y; -template class Y; // error: explicit instantiation outside of the namespace of the template - -template class N::Y; // OK: explicit instantiation in namespace \tcode{N} -template void N::Y::mf(); // OK: explicit instantiation in namespace \tcode{N} -\end{codeblock} -\end{example} - \pnum A trailing \grammarterm{template-argument} can be left unspecified in an explicit instantiation of a function template specialization or of a member function template specialization provided -it can be deduced from the type of a function parameter\iref{temp.deduct}. +it can be deduced\iref{temp.deduct.decl}. +If all template arguments can be deduced, +the empty template argument list \tcode{<>} may be omitted. \begin{example} \begin{codeblock} template class Array { @\commentellip@ }; @@ -6429,8 +6229,8 @@ An explicit instantiation that names a class template specialization is also an explicit instantiation of the same kind (declaration or definition) of each -of its members (not including members inherited from base classes and members -that are templates) that has not been previously explicitly specialized in +of its direct non-template members +that has not been previously explicitly specialized in the translation unit containing the explicit instantiation, provided that the associated constraints, if any, of that member are satisfied by the template arguments of the explicit @@ -6450,7 +6250,7 @@ \pnum An explicit instantiation of a prospective destructor\iref{class.dtor} -shall name the selected destructor of the class. +shall correspond to the selected destructor of the class. \pnum If an entity is the subject of both an explicit instantiation declaration @@ -6556,14 +6356,15 @@ may be defined~(\ref{dcl.meaning}, \ref{class.mem}, \ref{temp.mem}). \pnum +An explicit specialization does not introduce a name\iref{basic.scope.scope}. A declaration of a function template, class template, or variable template being explicitly -specialized shall precede the declaration of +specialized shall be reachable from the declaration of the explicit specialization. \begin{note} A declaration, but not a definition of the template is required. \end{note} -The definition of a class or class template shall precede the +The definition of a class or class template shall be reachable from the declaration of an explicit specialization for a member template of the class or class template. \begin{example} @@ -6584,7 +6385,7 @@ may be explicitly specialized for a class specialization that is implicitly instantiated; in this case, the definition of the class template shall -precede the explicit specialization for the member of the class +be reachable from the explicit specialization for the member of the class template. If such an explicit specialization for the member of a class template names an implicitly-declared special member function\iref{special}, @@ -6595,8 +6396,8 @@ instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required. -In this case, the definition of the class template explicit specialization -shall be in scope at the point at which the member is defined. +The definition of the class template explicit specialization +shall be reachable from the definition of any member of it. The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need @@ -6715,24 +6516,6 @@ When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation. -\pnum -A template explicit specialization is in the scope of the namespace in which -the template was defined. -\begin{example} -\begin{codeblock} -namespace N { - template class X { @\commentellip@ }; - template class Y { @\commentellip@ }; - - template<> class X { @\commentellip@ }; // OK: specialization in same namespace - template<> class Y; // forward-declare intent to specialize for \tcode{double} -} - -template<> class N::Y { @\commentellip@ }; // OK: specialization in enclosing namespace -template<> class N::Y { @\commentellip@ }; // OK: specialization in enclosing namespace -\end{codeblock} -\end{example} - \pnum A \grammarterm{simple-template-id} @@ -6755,7 +6538,7 @@ can be left unspecified in the \grammarterm{template-id} naming an explicit function template specialization -provided it can be deduced from the function argument type. +provided it can be deduced\iref{temp.deduct.decl}. \begin{example} \begin{codeblock} template class Array { @\commentellip@ }; @@ -7033,22 +6816,15 @@ \pnum Trailing template arguments that can be deduced\iref{temp.deduct} or -obtained from default -\grammarterm{template-argument}{s} -may be omitted from the list of explicit -\grammarterm{template-argument}{s}. +obtained from default \grammarterm{template-argument}{s} +may be omitted from the list of explicit \grammarterm{template-argument}{s}. +\begin{note} A trailing template parameter pack\iref{temp.variadic} not otherwise deduced will be deduced as an empty sequence of template arguments. +\end{note} If all of the template arguments can be deduced, they may all be omitted; -in this case, the empty template argument list -\tcode{<>} +in this case, the empty template argument list \tcode{<>} itself may also be omitted. -In contexts where deduction is done and fails, or in contexts where -deduction is not done, if a template argument list is specified and it, -along with any default template arguments, identifies a single function -template specialization, then the -\grammarterm{template-id} -is an lvalue for the function template specialization. \begin{example} \begin{codeblock} template X f(Y); @@ -7427,7 +7203,7 @@ template