9 Declarations [dcl.dcl]

9.2 Specifiers [dcl.spec]

9.2.9 Type specifiers [dcl.type]

9.2.9.5 Elaborated type specifiers [dcl.type.elab]

The component names of an elaborated-type-specifier are its identifier (if any) and those of its nested-name-specifier and simple-template-id (if any).
If an elaborated-type-specifier is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit specialization ([temp.expl.spec]), a partial specialization ([temp.spec.partial]), an explicit instantiation ([temp.explicit]), or it has one of the following forms:
In the first case, the elaborated-type-specifier declares the identifier as a class-name.
The second case shall appear only in an explicit-specialization ([temp.expl.spec]) or in a template-declaration (where it declares a partial specialization).
The attribute-specifier-seq, if any, appertains to the class or template being declared.
Otherwise, an elaborated-type-specifier E shall not have an attribute-specifier-seq.
If E contains an identifier but no nested-name-specifier and (unqualified) lookup for the identifier finds nothing, E shall not be introduced by the enum keyword and declares the identifier as a class-name.
The target scope of E is the nearest enclosing namespace or block scope.
A friend-type-specifier that is an elaborated-type-specifier shall have one of the following forms: Any unqualified lookup for the identifier (in the first case) does not consider scopes that contain the nearest enclosing namespace or block scope; no name is bound.
[Note 1: 
A using-directive in the target scope is ignored if it refers to a namespace not contained by that scope.
— end note]
[Note 2: 
[basic.lookup.elab] describes how name lookup proceeds in an elaborated-type-specifier.
An elaborated-type-specifier can be used to refer to a previously declared class-name or enum-name even if the name has been hidden by a non-type declaration.
— end note]
If the identifier or simple-template-id in an elaborated-type-specifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name ([dcl.type.simple]).
[Note 3: 
This implies that, within a class template with a template type-parameter T, the declaration friend class T; is ill-formed.
However, the similar declaration friend T; is well-formed.
— end note]
The class-key or enum keyword present in an elaborated-type-specifier shall agree in kind with the declaration to which the name in the elaborated-type-specifier refers.
This rule also applies to the form of elaborated-type-specifier that declares a class-name or friend class since it can be construed as referring to the definition of the class.
Thus, in any elaborated-type-specifier, the enum keyword shall be used to refer to an enumeration ([dcl.enum]), the union class-key shall be used to refer to a union ([class.union]), and either the class or struct class-key shall be used to refer to a non-union class ([class.pre]).
[Example 1: enum class E { a, b }; enum E x = E::a; // OK struct S { } s; class S* p = &s; // OK — end example]