Title
Unnamed types in entities with linkage
Status
cd1
Section
6.6 [basic.link]
Submitter
Daveed Vandevoorde

Created on 2002-10-31.00:00:00 last changed 189 months ago

Messages

Date: 2004-10-15.00:00:00

[Voted into WP at October 2004 meeting.]

Date: 2004-10-15.00:00:00

[Voted into WP at October 2004 meeting.]

Date: 2003-04-15.00:00:00

Notes from April 2003 meeting:

There was agreement that this check is not needed for variables and functions with extern "C" linkage, and a change there is desirable to allow use of legacy C headers. The check is also not needed for entities with internal linkage, but there was no strong sentiment for changing that case.

We also considered relaxing this requirement for extern "C++" variables but decided that we did not want to change that case.

We noted that if extern "C" functions are allowed an additional check is needed when such functions are used as arguments in calls of function templates. Deduction will put the type of the extern "C" function into the type of the template instance, i.e., there would be a need to mangle the name of an unnamed type. To plug that hole we need an additional requirement on the template created in such a case.

Proposed resolution (April 2003, revised slightly October 2003 and March 2004):

In 6.6 [basic.link] paragraph 8, change

A name with no linkage (notably, the name of a class or enumeration declared in a local scope (6.4.3 [basic.scope.block])) shall not be used to declare an entity with linkage. If a declaration uses a typedef name, it is the linkage of the type name to which the typedef refers that is considered.

to

A type is said to have linkage if and only if
  • it is a class or enumeration type that is named (or has a name for linkage purposes (9.2.4 [dcl.typedef])) and the name has linkage; or
  • it is a specialization of a class template (Clause 13 [temp]) [Footnote: a class template always has external linkage, and the requirements of 13.4.2 [temp.arg.type] and 13.4.3 [temp.arg.nontype] ensure that the template arguments will also have appropriate linkage]; or
  • it is a fundamental type (6.8.2 [basic.fundamental]); or
  • it is a compound type (6.8.4 [basic.compound]) other than a class or enumeration, compounded exclusively from types that have linkage; or
  • it is a cv-qualified (6.8.5 [basic.type.qualifier]) version of a type that has linkage.
A type without linkage shall not be used as the type of a variable or function with linkage, unless the variable or function has extern "C" linkage (9.11 [dcl.link]). [Note: in other words, a type without linkage contains a class or enumeration that cannot be named outside of its translation unit. An entity with external linkage declared using such a type could not correspond to any other entity in another translation unit of the program and is thus not permitted. Also note that classes with linkage may contain members whose types do not have linkage, and that typedef names are ignored in the determination of whether a type has linkage.]

Change 13.4.2 [temp.arg.type] paragraph 2 from (note: this is the wording as updated by issue 62)

The following types shall not be used as a template-argument for a template type-parameter:
  • a type whose name has no linkage
  • an unnamed class or enumeration type that has no name for linkage purposes (9.2.4 [dcl.typedef])
  • a cv-qualified version of one of the types in this list
  • a type created by application of declarator operators to one of the types in this list
  • a function type that uses one of the types in this list

to

A type without linkage (6.6 [basic.link]) shall not be used as a template-argument for a template type-parameter.

Once this issue is ready, issue 319 should be moved back to ready as well.

Date: 2013-01-14.00:00:00

6.6 [basic.link] paragraph 8 says (among other things):

A name with no linkage (notably, the name of a class or enumeration declared in a local scope (6.4.3 [basic.scope.block])) shall not be used to declare an entity with linkage. If a declaration uses a typedef name, it is the linkage of the type name to which the typedef refers that is considered.

I would expect this to catch situations such as the following:

  // File 1:
  typedef struct {} *UP;
  void f(UP) {}

  // File 2:
  typedef struct {} *UP; // Or: typedef struct {} U, *UP;
  void f(UP);

The problem here is that most implementations must generate the same mangled name for "f" in two translation units. The quote from the standard above isn't quite clear, unfortunately: There is no type name to which the typedef refers.

A related situation is the following:

  enum { no, yes } answer;
The variable "answer" is declared as having external linkage, but it is declared with an unnamed type. Section 6.6 [basic.link] talks about the linkage of names, however, and does therefore not prohibit this. There is no implementation issue for most compilers because they do not ordinarily mangle variable names, but I believe the intent was to allow that implementation technique.

Finally, these problems are much less relevant when declaring names with internal linkage. For example, I would expect there to be few problems with:

  typedef struct {} *UP;
  static void g(UP);

I recently tried to interpret 6.6 [basic.link] paragraph 8 with the assumption that types with no names have no linkage. Surprisingly, this resulted in many diagnostics on variable declarations (mostly like "answer" above).

I'm pretty sure the standard needs clarifying words in this matter, but which way should it go?

See also issue 319.

History
Date User Action Args
2008-10-05 00:00:00adminsetstatus: wp -> cd1
2005-05-01 00:00:00adminsetstatus: dr -> wp
2004-11-07 00:00:00adminsetstatus: ready -> dr
2004-04-09 00:00:00adminsetstatus: review -> ready
2004-02-13 00:00:00adminsetmessages: + msg951
2004-02-13 00:00:00adminsetstatus: ready -> review
2003-11-15 00:00:00adminsetstatus: review -> ready
2003-04-25 00:00:00adminsetmessages: + msg815
2003-04-25 00:00:00adminsetmessages: + msg814
2003-04-25 00:00:00adminsetstatus: open -> review
2002-10-31 00:00:00admincreate