9 Declarations [dcl.dcl]

9.2 Specifiers [dcl.spec]

9.2.1 General [dcl.spec.general]

The specifiers that can be used in a declaration are
The optional attribute-specifier-seq in a decl-specifier-seq appertains to the type determined by the preceding decl-specifiers ([dcl.meaning]).
The attribute-specifier-seq affects the type only for the declaration it appears in, not other declarations involving the same type.
Each decl-specifier shall appear at most once in a complete decl-specifier-seq, except that long may appear twice.
At most one of the constexpr, consteval, and constinit keywords shall appear in a decl-specifier-seq.
If a type-name is encountered while parsing a decl-specifier-seq, it is interpreted as part of the decl-specifier-seq if and only if there is no previous defining-type-specifier other than a cv-qualifier in the decl-specifier-seq.
The sequence shall be self-consistent as described below.
[Example 1: typedef char* Pc; static Pc; // error: name missing
Here, the declaration static Pc is ill-formed because no name was specified for the static variable of type Pc.
To get a variable called Pc, a type-specifier (other than const or volatile) has to be present to indicate that the typedef-name Pc is the name being (re)declared, rather than being part of the decl-specifier sequence.
For another example, void f(const Pc); // void f(char* const) (not const char*) void g(const int Pc); // void g(const int)
— end example]
[Note 1:
Since signed, unsigned, long, and short by default imply int, a type-name appearing after one of those specifiers is treated as the name being (re)declared.
[Example 2: void h(unsigned Pc); // void h(unsigned int) void k(unsigned int Pc); // void k(unsigned int) — end example]
— end note]