why a structured binding does not potentially conflict with a variable

Viewed 99

The newest standard has been modified to add the content of P1787. One rule about two declarations that potentially conflict is:

Two declarations potentially conflict if they correspond and cause their shared name to denote different entities ([basic.link]).

I don't know the meaning of wording "different entities" here. Does it mean these entities that has different kinds or mean that they are different entities determined by basic.link#8? The entities have these kinds:

An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.

Such for a example,

void fun();  //#1
extern int fun;  //#2
int main(){}

If the wording "different entities" means the former, then #1 denotes a function and #2 denotes a variable, they're different kind of entities. And such two declaration are in the same scope, Hence they are ill-formed per:

The program is ill-formed if, in any scope, a name is bound to two declarations that potentially conflict and one precedes the other

However, if the differenct entities should be determined by [basic.link#8] instead of determing it according to kind of entities. Then, it also makes sense. Because, per [basic.link#8]

Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names for linkage purposes, if any ([dcl.typedef], [dcl.enum]), they correspond ([basic.scope.scope]), have the same target scope that is not a function or template parameter scope, and either

  • they appear in the same translation unit, or
  • they both declare names with module linkage and are attached to the same module, or
  • they both declare names with external linkage.

Since they're corresponding and have the same target scope, and also bullet 1 or bullet 3 is satisfied. So, #1 and #2 are the same entity. However, they violate the following rule:

For any two declarations of an entity E:

  • If one declares E to be a variable or function, the other shall declare E as one of the same type.

So, Regardless of how to understand "different entities", the first example is always ill-formed. These compilers indeed give a right dignosis.

However, consider the second example

#include <iostream>
struct D{
   int m;
};
auto [x] = D{0};  //#1
void show(){
  std::cout<<&x<<"\n";
}
int main(){
  extern int x;  //#2
  std::cout<<&x<<"\n";
}

GCC prints the same address. Instead, Clang reports a link error.

Similarly, if "different entities" is the former opinion. Then #1 is a structured binding while #2 is a variable. According to this rule:

if the declaration inhabits a block scope S and declares a function ([dcl.fct]) or uses the extern specifier, the declaration shall not be attached to a named module ([module.unit]); its target scope is the innermost enclosing namespace scope, but the name is bound in S.

So, such two declarations has the same target scope. Hence, they should potentially conflict. If "different entities" is determined by [basic.link]. According to [basic.link#8], they are the same entity. However, it also violates

If one declares E to be a variable or function, the other shall declare E as one of the same type.

So, anyhow, the second example should be ill-formed. Why GCC gives the result that such two entity has the same address. Rather, Clang only gives a link error?

In addition, Is it necessary to add a precondition for [basic.link#8], that is, two entities should be first have the same kind?

0 Answers
Related