[dcl.stc]

# 9 Declarations [[dcl]](./#dcl)

## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.stc)

### 9.2.2 Storage class specifiers [dcl.stc]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L518)

The storage class specifiers are

[storage-class-specifier:](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")  
static  
thread_local  
extern  
mutable

At most one [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") shall appear in a given[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), except that thread_local may appear with static orextern[.](#1.sentence-2)

If thread_local appears in any declaration of
a variable it shall be present in all declarations of that entity[.](#1.sentence-3)

If a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") appears in a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), there can be notypedef specifier in the same [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and
the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [class.mem.general]") of the declaration shall not be
empty (except for an anonymous union declared in a namespace scope ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")))[.](#1.sentence-4)

The[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") applies to the name declared by each[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]") in the list and not to any names declared by
other specifiers[.](#1.sentence-5)

[*Note [1](#note-1)*:

See [[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization") and [[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation") for restrictions
in explicit specializations and explicit instantiations, respectively[.](#1.sentence-6)

â *end note*]

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L546)

[*Note [2](#note-2)*:

A variable declared without a [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") at block scope or declared as a function parameter
has [automatic storage duration](basic.stc.auto#def:storage_duration,automatic "6.8.6.4 Automatic storage duration [basic.stc.auto]") by default[.](#2.sentence-1)

â *end note*]

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L553)

The thread_local specifier
indicates that the named entity has thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"))[.](#3.sentence-1)

It
shall be applied only
to the declaration of a variable of namespace or block scope,
to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")), or
to the declaration of a static data member[.](#3.sentence-2)

When thread_local is applied to a variable of block scope the[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") static is implied if no other[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") appears in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")[.](#3.sentence-3)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L565)

The static specifier shall be applied only
to the declaration of a variable or function,
to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")), or
to the declaration of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions"))[.](#4.sentence-1)

There can be nostatic function declarations within a block, nor anystatic function parameters[.](#4.sentence-2)

A static specifier used in
the declaration of a variable declares the variable to have static storage
duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")), unless accompanied by thethread_local specifier, which declares the variable to have thread
storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"))[.](#4.sentence-3)

A static specifier can be
used in declarations of class members; [[class.static]](class.static "11.4.9 Static members") describes its
effect[.](#4.sentence-4)

For the linkage of a name declared with a static specifier,
see [[basic.link]](basic.link "6.7 Program and linkage")[.](#4.sentence-5)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L584)

The extern specifier shall be applied only to the declaration of a variable
or function[.](#5.sentence-1)

The extern specifier shall not be used in the
declaration of a class member or function parameter[.](#5.sentence-2)

For the linkage of a name declared with an extern specifier,
see [[basic.link]](basic.link "6.7 Program and linkage")[.](#5.sentence-3)

[*Note [3](#note-3)*:

The extern keyword can also be used in[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]")*s* and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")*s*, but it is not a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") in such contexts[.](#5.sentence-4)

â *end note*]

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L600)

All declarations for a given entity shall give its name the same linkage[.](#6.sentence-1)

[*Note [4](#note-4)*:

The linkage given by some declarations is affected by previous declarations[.](#6.sentence-2)

Overloads are distinct entities[.](#6.sentence-3)

â *end note*]

[*Example [1](#example-1)*: static char* f(); // f() has internal linkagechar* f() // f() still has internal linkage{ /* ... */ }char* g(); // g() has external linkagestatic char* g() // error: inconsistent linkage{ /* ... */ }void h();inline void h(); // external linkageinline void l();void l(); // external linkageinline void m();extern void m(); // external linkagestatic void n();inline void n(); // internal linkagestatic int a; // a has internal linkageint a; // error: two definitionsstatic int b; // b has internal linkageextern int b; // b still has internal linkageint c; // c has external linkagestatic int c; // error: inconsistent linkageextern int d; // d has external linkagestatic int d; // error: inconsistent linkage â *end example*]

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L642)

The name of a declared but undefined class can be used in anextern declaration[.](#7.sentence-1)

Such a declaration can only be used in ways
that do not require a complete class type[.](#7.sentence-2)

[*Example [2](#example-2)*: struct S;extern S a;extern S f();extern void g(S);

void h() { g(a); // error: S is incomplete f(); // error: S is incomplete} â *end example*]

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L661)

The mutable specifier shall appear only in the declaration of
a non-static data member ([[class.mem]](class.mem "11.4 Class members"))
whose type is neither const-qualified nor a reference type[.](#8.sentence-1)

[*Example [3](#example-3)*: class X {mutable const int* p; // OKmutable int* const q; // error}; â *end example*]

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L674)

[*Note [5](#note-5)*:

The mutable specifier on a class data member nullifies aconst specifier applied to the containing class object and
permits modification of the mutable class member even though the rest of
the object is const ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers"), [[dcl.type.cv]](dcl.type.cv "9.2.9.2 The cv-qualifiers"))[.](#9.sentence-1)

â *end note*]
