cplusplus / draft

C++ standards drafts
http://www.open-std.org/jtc1/sc22/wg21/
5.68k stars 749 forks source link

[basic.scope.scope] The meaning of "denote different entities" is vague #4787

Open xmh0511 opened 3 years ago

xmh0511 commented 3 years ago

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

Since [basic.link] follows "different entities", it hints that the meaning of "different entities" is given in [basic.link#8]. Consider this example

void fun();
extern int fun;

According to [basic.scope.scope#3], such two declarations correspond, and according to [basic.link#8], they declare the same entity. According to [basic#pre-5]

An entity E is denoted by the name (if any) that is introduced by a declaration of E or by a typedef-name introduced by a declaration specifying E.

Since these two declarations declare the same entity, does it mean the names fun in the two declarations denote the same entity? However, according to [basic#pre-3]

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

How can a function and a variable be the same entity? It seems result in this issue. That is, what's the exact meaning of "denote different entities"? Merely determined by [basic.link#8] or should base it on by adding some other restrictions?

cpplearner commented 3 years ago

Yes, they declare the same entity. They are invalid because [basic.link]/11:

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.
xmh0511 commented 3 years ago

IMO, although they violate [basic.link]/11, but it doesn't mean violate [basic.link]/11 can be considered they don't denote the same entity, right? This issue tries to claim the exact meaning of "denote different entities". Two different kinds of entities categorized by [basic#pre-3] should be different entities even if they satisfy [basic.link#8].

Conflating [basic.link#8] and [basic.link]/11 to clarify which two declarations declare the same entity is what I'm intending to propose.

Two declarations 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

  • [...]

and

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

they declare the same entity

cpplearner commented 3 years ago

IMO, although they violate [basic.link]/11, but it doesn't mean violate [basic.link]/11 can be considered they don't denote the same entity, right?

Right. They do declare the same entity. And [basic.link]/11 makes it clear that an entity cannot be redeclared to have a different category, otherwise it's an error.

xmh0511 commented 3 years ago

Well, consider this example

namespace A {}
namespace B = A; //#1
namespace B {}  //#2

#1 and #2 correspond and they declare the same entity according to [basic.link#8], it still does not violate [basic.link]/11

For any two declarations of an entity E:

  • If one declares E to be a namespace, the other shall do so.

#1 declares E to be a namespace, #2 also declares E to be a namespace. I mean [basic.link]/11 does not require that they must be the same namespace. Hence, it also obeys [basic.scope#scope-4]. So, Is it well-formed? I don't think so, it's the example in [basic.scope#scope-4]. Isn't it a defect?

jensmaurer commented 3 years ago

http://lists.isocpp.org/core/2021/08/11348.php

jensmaurer commented 3 years ago

Regarding the namespace example: [basic.link] p8 is not applicable, because #1 does not declare an entity at all (a namespace-alias is not an entity; similar to the fact that a typedef-name is not entity).

Thus, [basic.scope.scope] p4 kicks in, because the two declarations denote different entities (#1 denotes the entity "namespace A", but #2 denotes the entity "namespace B").

xmh0511 commented 3 years ago

Since that's the case, I think we should still improve [basic.scope.scope] p4, change it to

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

Specifically, [basic.pre] refers [basic.pre] p5

An entity E is denoted by the name (if any) that is introduced by a declaration of E or by a typedef-name introduced by a declaration specifying E.

Although, [basic.pre] p5 seems to have omitted a case that is namespace-alias, IMO, [basic.pre] p5 should be that

An entity E is denoted by the name (if any) that is introduced by a declaration of E or by a typedef-name introduced by a declaration specifying E or by a namespace-alias introduced by a namespace-alias-definition specifying E.

The modification to [basic.scope.scope] p4 make the meaning more clear, the rule requires whether the name introduced by the declarations denote different entities or not; Instead, not merely whether two declarations declare the same entity. The link [basic.link] could result in that misleading. The latter case still can be determined as per [basic.link] if two declarations do declare entities.

In addition, we should phrase the similar wording for [namespace.alias] as did in [dcl.typedef]

Add a rule in [namespace.alias] p2

The identifier in a namespace-alias-definition becomes a namespace-alias and denotes the namespace denoted by the qualified-namespace-specifier. namespace-alias does not introduce a new namespace the way a namespace-definition does.

It stresses that namespace-alias-definition is a declaration that does not introduce an entity. @jensmaurer Please have a look.

jensmaurer commented 3 years ago

I'm sympathetic to augmenting [basic.pre] p5 to mention the namespace alias, and I think a clarifying note in [basic.link] p8 that some declarations don't declare entities might be helpful to highlight "declarations of entities".