Mail Archives: djgpp/2020/12/10/16:33:51
Am 10.12.2020 um 20:45 schrieb Eli Zaretskii (eliz AT gnu DOT org) [via
djgpp AT delorie DOT com]:
>> From: "J.W. Jagersma (jwjagersma AT gmail DOT com) [via djgpp AT delorie DOT com]" <djgpp AT delorie DOT com>
>> Date: Thu, 10 Dec 2020 19:55:11 +0100
>>
>>>> -void (*__stdio_cleanup_hook)(void);
>>>> +extern void (*__stdio_cleanup_hook)(void); /* stdio/stdiohk.c */
>>>
>>> This part I don't understand: are you saying that it is no longer the
>>> default that a function not explicitly declared 'static' has the
>>> external linkage? Why do we need an explicit 'extern' qualifier?
>>>
>>> Thanks.
>>
>> This only applies to global variables (and __stdio_cleanup_hook here is a
>> function *pointer*), functions themselves still have implicit external linkage.
>
> And global variables don't?
Kind-a. In strict standard C, they do, but Unix C compilers have all
had a common extension since the dawn of time_t: they expand the concept
of "tentative definitions" (C99 6.9.2p2) from translation units to the
entire program, i.e. a non-initialized definition effectively remains in
"tentative" state until link-time. This extension was so wide-spread
that it's actually listed in the C standard informative annex J.5.11.
Or, to put it in terms of GCC options: -fcommon is againnst the C
standard, but it has always been the Unix standard. The reason is
hinted at by the name of the option: COMMON is a FORTRAN concept which
Unix linkers had to support from the get-go, and it's technically
equivalent to joining tentative definitions across translation units.
(A FORTRAN named COMMON translates to a global, un-initialized struct
variable. Individual translation units define it, then the linker puts
them all in the same place.)
So GCC 10 switched this default to the C standard-conforming value,
-fno-common, and that will break code which relied on -fcommon without
ever knowing it did.
And BTW the correct solution of this issue is _not_ to just put "extern"
in front of existing definitions, but rather to remove all but a single
one of those entirely, and replace them by #includes of the header that
does hold the corresponding extern declaration.
Rules of thumb: never write "extern" in a *.c file, and never write
"static" in a *.h file. You'll know when you're hitting an exception to
this rule.
- Raw text -