Skip to content

[basic.scope.scope] Remove incorrect namespace redeclaration example CWG3214 - #9241

Open
yehudamber wants to merge 1 commit into
cplusplus:mainfrom
yehudamber:patch-1
Open

[basic.scope.scope] Remove incorrect namespace redeclaration example CWG3214#9241
yehudamber wants to merge 1 commit into
cplusplus:mainfrom
yehudamber:patch-1

Conversation

@yehudamber

Copy link
Copy Markdown

Since the adoption of P2996 "Reflection for C++26", and the changes it made to [namespace.alias], namespace aliases are no longer alternative names for namespaces but entities of their own kind. Therefore, redeclaring a namespace as a namespace alias, even denoting the original namespace, violates [basic.link]/11.3, since one declaration declares the entity as a namespace and the other does not.

Since the adoption of P2996 "Reflection for C++26", and the changes it made to [namespace.alias], namespace aliases are no longer alternative names for namespaces but entities of their own kind. Therefore, redeclaring a namespace as a namespace alias, even denoting the original namespace, violates [basic.link]/11.3, since one declaration declares the entity as a namespace and the other does not.
@eisenwave eisenwave added the P2-Bug Presentational errors and omissions label Aug 4, 2026
@timsong-cpp

timsong-cpp commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

If they are different entities, then [basic.link]/11.3 does not apply at all. That paragraph only applies to two declarations of the same entity.

Ah, [basic.link]/8 says that two declarations declare the same entity if they correspond (and various other things not relevant here), which they do since they introduce the same name. But that reasoning would seem to apply equally to typedef struct T T; and if so, that's definitely a defect.

@yehudamber

Copy link
Copy Markdown
Author

But that reasoning would seem to apply equally to typedef struct T T; and if so, that's definitely a defect.

Good point. I thought [basic.scope.scope]/4.2 covers such cases, but I see now it does not apply when the other declaration declares a type alias.
So maybe the rule at [basic.link]/8 is what needs to be fixed?

@katzdm

katzdm commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

I agree [basic.link]/8 is problematic. Maybe something like this?

Two declarations D1 and D2 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]),

  • D1 and D2 correspond ([basic.scope.scope]),
  • D1 and D2 have the same target scope that is not a function or template parameter scope,
  • neither D1 nor D2 is a name-independent declaration,
  • if either D1 or D2 declares a type alias or a namespace alias, the underlying entities declared by D1 and D2 are either both types or both namespaces, and
  • one of the following holds:
    • D1 and D2 appear in the same translation unit,
    • D1 and D2 both declare type aliases or namespace aliases that have the same underlying entity, or
    • D1 and D2 both declare names with module or external linkage and are attached to the same module.

?

@jensmaurer

Copy link
Copy Markdown
Member

@katzdm We already have "D1 and D2 both declare type aliases or namespace aliases that have the same underlying entity, or" in the next bullet, so something feels redundant here.

Also, I get confused whether type aliases are meant to have namespaces as underlying entities with this phrasing. Maybe make that two bullets?

Also, I'm not seeing how this fixes the problem that

struct T;
typedef struct T T;

should NOT declare the same entity twice.

@timsong-cpp

Copy link
Copy Markdown
Contributor

"either D1 and D2 both declare type aliases or neither declares a type alias" and the same for namespace aliases?

@katzdm

katzdm commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

@jensmaurer It's two different cases - I'm fine with two different bullets, but we should keep the existing bullet separate. So, this for instance would be fine (and equivalent) to me:

Two declarations D1 and D2 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]),

  • D1 and D2 correspond ([basic.scope.scope]),
  • D1 and D2 have the same target scope that is not a function or template parameter scope,
  • neither D1 nor D2 is a name-independent declaration,
  • if either D1 or D2 declares a type alias, both D1 and D2 declare type aliases,
  • if either D1 or D2 declares a namespace alias, both D1 and D2 declare namespace aliases, and
  • one of the following holds:
    • D1 and D2 appear in the same translation unit,
    • D1 and D2 both declare type aliases or namespace aliases that have the same underlying entity, or
    • D1 and D2 both declare names with module or external linkage and are attached to the same module.

Something along the lines of what @timsong-cpp said would be fine as well. No strong preference on the phrasing.

@jensmaurer

jensmaurer commented Aug 9, 2026

Copy link
Copy Markdown
Member

This is not an editorial issue, and removing the example does not fix anything. CWG3214

@jensmaurer jensmaurer added cwg Issue must be reviewed by CWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking. labels Aug 9, 2026
@jensmaurer jensmaurer changed the title [basic.scope.scope] Remove incorrect namespace redeclaration example [basic.scope.scope] Remove incorrect namespace redeclaration example CWG3214 Aug 9, 2026
@yehudamber

Copy link
Copy Markdown
Author

@jensmaurer Seems good, thank you!
The proposed wording does affect more cases (e.g. corresponding type alias declaration and namespace alias declaration) that currently declare the same entity, but since aliases have no linkage, and declarations that both declare a type alias or a namespace alias are not affected, those case are only when both declarations appear in the same TU, and since alias declarations always bind their name in their target scope (I believe), those cases will just become name collisions between entities instead of conflicting declarations of the same entity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cwg Issue must be reviewed by CWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking. P2-Bug Presentational errors and omissions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants