Core NB Comment Resolutions (original) (raw)

Document number: P2103R0
Date: 2020-02-14
Project: Programming Language C++
Reference: ISO/IEC IS 14882:2017
Reply to: William M. Miller
Edison Design Group, Inc.
wmm@edg.com

Core Language Changes for NB Comments at the February, 2020 (Prague) meeting

References in this document reflect the section and paragraph numbering of documentWG21 N4849.


US028. Define grammar for "punctuator"

  1. Change 5.4 [lex.pptoken] paragraph 1 as follows:

Each preprocessing token that is converted to a token (5.6 [lex.token]) shall have the lexical form of a keyword, an identifier, a literal, or an operator, or a or punctuator.

  1. Change the grammar in 5.6 [lex.token] as follows: token: identifier
    keyword
    literal
    operator
    punctuator
    operator-or-punctuator
  2. Change 5.11 [lex.key] paragraph 2 as follows:

Furthermore, the alternative representations shown in Table 6 for certain operators and punctuators (5.5 [lex.digraph]) are reserved and shall not be used otherwise:.

  1. Change 5.12 [lex.operators] paragraph 1 as follows:

The lexical representation of C++ programs includes a number of preprocessing tokens which that are used in the syntax of the preprocessor or are converted into tokens for operators and punctuators:

preprocessing-operator: one of

## %: %:%:

preprocessing-op-or-punc operator-or-punctuator: one of

{ } [ ] # ## ( ) <: :> <% %> %: %:%: ; : ... new delete ? :: . .* -> ->* ~ ! + - * / % ^ & | = += -= *= /= %= ^= &= |= == != < > <= >= <=> && || << >> <<= >>= ++ -- , and or xor not bitand bitor compl and_eq or_eq xor_eq not_eq

preprocessing-op-or-punc: preprocessing-operator
operator-or-punctuator

Each preprocessing-op-or-punc operator-or-punctuator is converted to a single token in translation phase 7 (5.2 [lex.phases]).


  1. Change the grammar in 6.6 [basic.link] paragraph 1 as follows: translation-unit top-level-declaration-seqopt
    global-module-fragmentopt module-declaration top-level-declaration-seqopt private-module-fragmentopt

top-level-declaration-seq: top-level-declaration
top-level-declaration-seq top-level-declaration

top-level-declaration: module-import-declaration
declaration 2. Change 6.6 [basic.link] paragraph 2 as follows:

A token sequence beginning with export_opt_ moduleand not immediately followed by :: is never interpreted as the declaration ofa top-level-declaration.

[Note: P1857R3 deletes this paragraph, which supersedes this change. It is to be applied only if P1857R3 is not adopted.]

  1. Change the grammar and paragraph 1 of 10.4 [module.global] as follows:

global-module-fragment: module ; top-level-declaration-seqopt

[Note: Prior to phase 4 of translation, only preprocessing directives can appear in the top-level-declaration-seq(15.5 [cpp.glob.frag]). —_end note_]

  1. Change 10.4 [module.global] paragraph 4 as follows:

A declaration Din a global module fragment of a module unit is discarded if Dis not decl-reachable fromany top-level-declaration inthe top-level-declaration-seq of the translation unit translation-unit. [Note: A discarded declaration...

  1. Change the grammar in 10.5 [module.context] as follows: private-module-fragment: module : private ; top-level-declaration-seqopt
  2. Change 10.6 [module.reach] paragraph 3 as follows:

During the implicit instantiation of a template whose point of instantiation is specified as that of an enclosing specialization (13.8.4.1 [temp.point]), the instantiation context is the union of the instantiation context of the enclosing specialization and, if the template is defined in a module interface unit of a module _M_and the point of instantiation is not in a module interface unit of M, the point at the end of the top-level-declaration-seq of the primary module interface unit of M (prior to the private-module-fragment, if any).

  1. Change 13.8.4.1 [temp.point] paragraph 7 as follows:

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above,

  1. Change the grammar in 9.1 [dcl.pre] paragraph 1 as follows: declaration: block-declaration
    nodeclspec-function-declaration
    function-definition
    template-declaration
    deduction-guide
    explicit-instantiation
    explicit-specialization
    export-declaration
    linkage-specification
    namespace-definition
    empty-declaration
    attribute-declaration
    module-import-declaration
  2. Change 10.3 [module.import] paragraph 1 as follows:

A module-import-declaration shall only appear at global namespace scope. In a module unit, all _module-import-declaration_s shall precede all other _top-level-declaration_s in the top-level-declaration-seq of the translation-unit and of the private-module-fragment (if any). The optional attribute-specifier-seq appertains to the module-import-declaration.

  1. Add the following as a new paragraph after 9.11 [dcl.link] paragraph 3:

Every implementation shall provide for linkage to functions written in the C programming language, "C", and linkage to C++ functions, "C++". [Example:... —_end example_]

A module-import-declaration shall not be directly contained in a linkage-specification. A _module-import-declaration_appearing in a linkage specification with other than C++ language linkage is conditionally-supported with implementation-defined semantics.


US041. Enforce correspondence of containing objects for pointer values / aliasing

Change 6.7.3 [basic.life] paragraph 8 as follows:

If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if: the original object is transparently replaceable (see below) by the new object.

An original object is _transparently replaceable_by a new object if:

[Example:...


CA104. Clarify declaration matching and partial ordering requiring substitution into constraints

  1. Add the following as a new paragraph at the end of 13.5.2 [temp.constr.decl]:

When determining whether a given introduced constraint-expression C1 of a declaration in an instantiated specialization of a templated class is equivalent (13.7.6.1 [temp.over.link]) to the corresponding constraint-expression C2 of a declaration outside the class body, C1 is instantiated. If the instantiation results in an invalid expression, the _constraint-expression_s are not equivalent. [Note: This can happen when determining which member template is specialized by an explicit specialization declaration. —_end note_] [Example:

template concept C = true; template struct A { template U f(U) requires C; // #1 template U f(U) requires C; // #2 };

template <> template U A::f(U u) requires C { return u; } // OK, specializes #2

Substituting int for T inC produces an invalid expression, so the specialization does not match #1. Substituting int for Tin C produces C, which is equivalent to the constraint-expression for the specialization, so it does match #2. —_end example_]

  1. Change 13.9.1 [temp.inst] paragraph 17 as follows:

The _type-constraint_s and requires-clause of a template specialization or member function are not instantiated along with the specialization or function itself, even for a member function of a local class; substitution into the atomic constraints formed from them is instead performed as specified in 13.5.2 [temp.constr.decl] and 13.5.1.2 [temp.constr.atomic] when determining whether the constraints are satisfied or as specified in 13.5.2 [temp.constr.decl] when comparing declarations. [Note: The satisfaction of constraints


CA107. Parameter mapping for non-dependent entities

US117. Comparing types and type-constraints

  1. Change 13.5.1.2 [temp.constr.atomic] paragraph 1 as follows:

An atomic constraint is formed from an expression E and a mapping from the template parameters that appear within E to template arguments involving that are formed via substitution during constraint normalization in the declaration of a constrained entity (and, therefore, can involve the unsubstituted template parameters of the constrained entity), called the parameter mapping(13.5.2 [temp.constr.decl]). [Note: Atomic constraints are formed by constraint normalization (13.5.3 [temp.constr.normal]). E is never a logical AND expression (7.6.14 [expr.log.and]) nor a logical OR expression (7.6.15 [expr.log.or]). —_end note_]

  1. Change 13.5.1.2 [temp.constr.atomic] paragraph 2 as follows:

Two atomic constraints, e1 and e2,are identical if they are formed from the same_expression_ and if, given a hypothetical template A whose _template-parameter-list_consists of _template-parameter_s corresponding and equivalent (13.7.6.1 [temp.over.link]) to those mapped by the parameter mappings of the expression, a template-id naming Awhose _template-argument_s are the targets of the parameter mappings are equivalent according to the rules for expressions described in 13.7.6.1 [temp.over.link]. mapping of e1 is the same (13.6 [temp.type]) as a _template-id_naming A whose _template-argument_s are the targets of the parameter mapping of e2. [_Note:_The comparison of parameter mappings of atomic constraints operates in a manner similar to that of declaration matching with alias template substitution (13.7.7 [temp.alias]). [Example:

template constexpr bool Atomic = true; template concept C = Atomic; template concept Add1 = C<N + 1>; template concept AddOne = C<N + 1>; template void f() requires Add1<2 * M>; template int f() requires AddOne<2 * M> && true;

int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic // with mapping similar to N ↦ 2 * M + 1

template struct WrapN; template using Add1Ty = WrapN<N + 1>; template using AddOneTy = WrapN<N + 1>; template void g(Add1Ty<2 * M> *); template void g(AddOneTy<2 * M> *);

void h() { g<0>(nullptr); // OK, there is only one g }

—_end example_]

This similarity includes the situation where a program is ill-formed, no diagnostic required, when the meaning of the program depends on whether two constructs are equivalent, and they are functionally equivalent but not equivalent. [Example:

template void f2() requires Add1<2 * N>; template int f2() requires Add1<N * 2> && true; void h2() { f2<0>(); // ill-formed, no diagnostic required: // required determination of subsumption between atomic constraints that are // functionally equivalent but not equivalent }

—_end example_] —_end note_]


US115. Hidden non-template friends need a requires-clause

  1. Add the following after 3.20 [defns.signature]:
3.21 [defns.signature.friend]

signature
‹non-template friend function with trailing_requires-clause_› name, parameter-type-list (9.3.3.5 [dcl.fct]), enclosing class, and trailing requires-clause (9.3 [dcl.decl])

  1. Add the following after 3.21 [defns.signature.templ]:
3.23 [defns.signature.templ.friend]

signature
‹friend function template with constraint involving enclosing template parameters› name, parameter-type-list (9.3.3.5 [dcl.fct]), return type, enclosing class,template-head, and trailing requires-clause

  1. Change 13.7.4 [temp.friend] paragraph 9 as follows:

A non-template friend declaration shall not have with a requires-clause shall be a definition. A friend function template with a constraint that depends on a template parameter from an enclosing template shall be a definition. Such a constrained friend function or function template declaration does not declare the same function or function template as a declaration in any other scope.