The C17 draft states the following (6.9.2, ¶2):
A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier
static, constitutes a tentative definition. [...]
There are 5 storage class specifiers: extern, static, _Thread_local, register, auto. Of these, only the former 3 can occur at file scope. Outside of all functions, _Thread_local can – but needn't be – combined with extern or static. Hence, for tentative definitions, there are the following possibilities in terms of storage class specifiers:
int i1; // tentative definition, external linkage
extern int i2; // non-definition declaration, external linkage
static int i3; // tentative definition, internal linkage
_Thread_local int i4; // ?, external linkage
_Thread_local extern int i5; // ?, external linkage
_Thread_local static int i6; // ?, internal linkage
(Note here that the keyword _Thread_local doesn't influence linkage.)
The declarations of i1 and i3 are tentative definitions. But what about i4, i5, i6 – are their declarations tentative definitions? Why or why not?
I am guessing that the answer for i5 is 'no', because neither of the two conditions
- has no storage class specifier
- has the storage class specifier
static
applies. But I'm unsure about i4 and i6.
without a storage-class specifierwith the storage-class specifier staticwithout a storage-class specifierwith the storage-class specifier staticwithout a storage-class specifierwith the storage-class specifier staticSure.