Title
Incorrect matching rules for block-scope extern declarations
Status
cd5
Section
6.6 [basic.link]
Submitter
Chen Fuxingi

Created on 2017-12-17.00:00:00 last changed 47 months ago

Messages

Date: 2018-11-15.00:00:00

Proposed resolution (November, 2018):

Change 6.6 [basic.link] paragraph 6 as follows:

The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage. If there is a visible declaration of an entity with linkage having the same name and type, 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 declarative region, 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. [Example:

  static void f();
  extern "C" void h();
  static int i = 0;      // #1
  void g() {
    extern void f();     // internal linkage
    extern void h();     // C language linkage

    int i;               // #2: i has no linkage
    {
      extern void f();   // internal linkage
      extern int i;      // #3: external linkage, ill-formed
    }
  }

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]

Date: 2018-10-15.00:00:00

Notes from the October, 2018 teleconference:

CWG agreed with the direction and noted that a similar situation occurs with extern "C" functions.

Date: 2019-02-15.00:00:00

[Accepted as a DR at the February, 2019 meeting.]

According to 6.6 [basic.link] paragraph 6,

The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage. If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, the block scope declaration declares that same entity and receives the linkage of the previous declaration. 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.

The requirement that the entities have the same type does not cover all cases that it should. Consider an example like:

  static int a[3];
  void g() {
    printf("%p\n", (void*)a);
    extern int a[];
    printf("%p\n", (void*)a);
  }

According to the cited wording, the block-scope declaration of a does not match the namespace scope declaration because int[] and int[3] are different types, thus the first reference to a refers to the static variable while the second one refers to a variable a defined in some other translation unit. This is clearly not intended, and current implementations treat both references as referring to the static variable.

History
Date User Action Args
2020-12-15 00:00:00adminsetmessages: + msg6358
2020-12-15 00:00:00adminsetmessages: + msg6357
2017-12-17 00:00:00admincreate