Consider the following code:
class A {};
class B {
using A = A;
};
With Clang and ICC this compiles fine, while GCC fails with the following message:
error: declaration of ‘using A = class A’ changes meaning of ‘A’ [-fpermissive]
4 | using A = A;
| ^
Question: Which compiler is correct and why?
Clang and ICC have it right.
[basic.scope.pdecl]
3 ... The point of declaration of an alias or alias template immediately follows the defining-type-id to which the alias refers.
Where the grammar for an alias declaration is
[dcl.pre]
1 ...
alias-declaration: using identifier attribute-specifier-seqopt = defining-type-id ;
So the "new" meaning of A
isn't officially declared until after the part of the declaration that still refers to the "old" A
.
Now, that's not to say there is no potential for problems here. For we also have
[basic.scope.class]
2 A name
N
used in a classS
shall refer to the same declaration in its context and when re-evaluated in the completed scope ofS
. No diagnostic is required for a violation of this rule.
Had you written:
class A {};
class B {
A a;
using A = A;
};
We now have A
referring to different declarations between its first use, and the complete class scope. Sure, it's the same type being named, but via different declatation. That's enough to make the code ill-formed NDR. And GCC likely has a heuristic to protect code from this. Which is being tripped by your benign example.