Title
friend declarations and module linkage
Status
tentatively ready
Section
11.8.4 [class.friend]
Submitter
Nathan Sidwell

Created on 2022-05-26.00:00:00 last changed 1 month ago

Messages

Date: 2024-03-20.01:22:41

Proposed resolution (approved by CWG 2024-03-20):

  1. Change in 6.6 [basic.link] paragraph 4 as follows:

    ... 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
    • a variable; or
    • a function; or
    • a named class (11.1 [class.pre]), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (9.2.4 [dcl.typedef]); or
    • a named enumeration (9.7.1 [dcl.enum]), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (9.2.4 [dcl.typedef]); or
    • an unnamed enumeration that has an enumerator as a name for linkage purposes (9.7.1 [dcl.enum]); or
    • a template
    has its linkage determined as follows:
    • if the entity is a function or function template first declared in a friend declaration and that declaration is a definition and the enclosing class is defined within an export-declaration, the name has the same linkage, if any, as the name of the enclosing class (11.8.4 [class.friend]);
    • otherwise, if the entity is a function or function template declared in a friend declaration and a corresponding non-friend declaration is reachable, the name has the linkage determined from that prior declaration,
    • otherwise, if the enclosing namespace has internal linkage, the name has internal linkage;
    • otherwise, if the declaration of the name is attached to a named module (10.1 [module.unit]) and is not exported (10.2 [module.interface]), the name has module linkage;
    • otherwise, the name has external linkage.
  2. Remove 11.8.4 [class.friend] paragraph 4:

    A function first declared in a friend declaration has the linkage of the namespace of which it is a member (6.6 [basic.link]). Otherwise, the function retains its previous linkage (9.2.2 [dcl.stc]).
Date: 2022-06-15.00:00:00

Proposed resolution (June, 2022) (approved by CWG 2023-01-27) [SUPERSEDED]:

  1. Change in 6.6 [basic.link] paragraph 4 as follows:

    ... 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
    • a variable; or
    • a function; or
    • a named class (11.1 [class.pre]), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (9.2.4 [dcl.typedef]); or
    • a named enumeration (9.7.1 [dcl.enum]), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (9.2.4 [dcl.typedef]); or
    • an unnamed enumeration that has an enumerator as a name for linkage purposes (9.7.1 [dcl.enum]); or
    • a template
    has its linkage determined as follows:
    • if the entity is a function or function template first declared in a friend declaration and that declaration is a definition, the name has the same linkage, if any, as the name of the enclosing class (11.8.4 [class.friend]);
    • otherwise, if the entity is a function or function template declared in a friend declaration and a corresponding non-friend declaration is reachable, the name has the linkage determined from that prior declaration,
    • otherwise, if the enclosing namespace has internal linkage, the name has internal linkage;
    • otherwise, if the declaration of the name is attached to a named module (10.1 [module.unit]) and is not exported (10.2 [module.interface]), the name has module linkage;
    • otherwise, the name has external linkage.
  2. Remove 11.8.4 [class.friend] paragraph 4:

    A function first declared in a friend declaration has the linkage of the namespace of which it is a member (6.6 [basic.link]). Otherwise, the function retains its previous linkage (9.2.2 [dcl.stc]).

EWG electronic poll 2022-06

Consensus for "A friend's linkage should be affected by the presence/absence of export on the containing class definition itself, but ONLY if the friend is a definition (option #2, modified by Jason's suggestion). This resolves CWG2588." See vote.

Date: 2022-05-15.00:00:00

Additional note (May, 2022):

Forwarded to EWG with paper issue 1253, by decision of the CWG chair.

EWG telecon 2022-06-09

Consensus: "A friend's linkage should be affected by the presence/absence of export on the containing class definition itself, but ONLY if the friend is a definition", pending confirmation by electronic polling.

Date: 2022-07-01.16:50:42

Consider:

  export module Foo;
  class X {
    friend void f(X); // #1 linkage?
  };

Subclause 11.8.4 [class.friend] paragraph 4 gives #1 external linkage:

A function first declared in a friend declaration has the linkage of the namespace of which it is a member (6.6 [basic.link]).

(There is no similar provision for friend classes first declared in a class.)

However, 6.6 [basic.link] bullet 4.8 gives it module linkage:

... otherwise, if the declaration of the name is attached to a named module (10.1 [module.unit]) and is not exported (10.2 [module.interface]), the name has module linkage;

Subclause 10.2 [module.interface] paragraph 2 does not apply:

A declaration is exported if it is declared within an export-declaration and inhabits a namespace scope or it is
  • a namespace-definition that contains an exported declaration, or
  • a declaration within a header unit (10.3 [module.import]) that introduces at least one name.

Also consider this related example:

  export module Foo;
  export class Y;
  // maybe many lines later, or even a different partition of Foo
  class Y {
    friend void f(Y); // #2 linkage?
  };
  • Should the friend's linkage be affected by the linkage of the befriending class? In this example, #2 would therefore have external linkage, as Y is exported.
  • Or should the friend's linkage be affected by the presence or absence of export on the class definition itself? In this example, #2 would thus have module linkage.
  • Or should the friend's linkage be determined ignoring any enclosing export and ignoring whether the enclosing class is exported, per 11.8.4 [class.friend] paragraph 4 (alone)?
  • Or should the friend's linkage be as-if the declaration inhabited its nearest enclosing namespace scope, without the friend?

See issue 2607 for a similar question about enumerators.

History
Date User Action Args
2024-03-20 14:10:31adminsetstatus: ready -> tentatively ready
2024-03-20 01:27:19adminsetstatus: tentatively ready -> ready
2024-03-20 01:00:27adminsetmessages: + msg7644
2024-02-13 08:15:14adminsetstatus: drafting -> tentatively ready
2022-07-10 07:32:02adminsetstatus: open -> drafting
2022-06-24 20:01:00adminsetmessages: + msg6868
2022-05-26 19:41:34adminsetmessages: + msg6834
2022-05-26 00:00:00admincreate