On 4/19/23 15:19, Eric Blake wrote:
> On Wed, Apr 19, 2023 at 11:53:44AM +0100, Richard W.M. Jones wrote:
>> On Tue, Apr 18, 2023 at 07:26:21PM +0200, Laszlo Ersek wrote:
>>> (The changes in this patch are simple, but likely more controversial than
>>> the rest.)
>>>
>>> The following four components don't play nice together:
>>>
>>> - Needlessly spelling out "extern" for function declarations in header
>>>   files. (C99 6.2.2p5: "If the declaration of an identifier for a function
>>>   has no storage-class specifier, its linkage is determined exactly as if
>>>   it were declared with the storage-class specifier extern [...]".)
>>
>> Well I didn't know that ...
> 
> https://stackoverflow.com/questions/18171373/why-are-some-functions-declared-extern-and-header-file-not-included-in-source-in/18173554#18173554
> 
> gives some more interesting details (including what happens if you
> declare a function more than once, using different specifiers across
> the declarations).

In 2009, I constructed the following table, and I've been using it since:

-----------------
Name space: ordinary identifiers

Declaration             | Scope | Linkage                                       
                     | Storage duration       | Definition
------------------------+-------+--------------------------------------------------------------------+------------------------+--------------------------
       int obj_1;       | file  | external ((6.1.2.2 p5)                        
                     | static (6.1.2.4 p2)    | tentative (6.7.2 p2)
extern int obj_2;       | file  | same as any visible file scope declaration / 
external (6.1.2.2 p4) | static (6.1.2.4 p2)*   | none (6.7.2)
static int obj_3;       | file  | internal (6.1.2.2 p3)                         
                     | static (6.1.2.4 p2)    | tentative (6.7.2 p2)
       int obj_4 = 1;   | file  | external ((6.1.2.2 p5)                        
                     | static (6.1.2.4 p2)    | external (6.7.2 p1)
extern int obj_5 = 1;   | file  | same as any visible file scope declaration / 
external (6.1.2.2 p4) | static (6.1.2.4 p2)*   | external (6.7.2 p1)
static int obj_6 = 1;   | file  | internal (6.1.2.2 p3)                         
                     | static (6.1.2.4 p2)    | external (6.7.2 p1)
       int fun_1(void); | file  | same as any visible file scope declaration / 
external (6.1.2.2 p5) | n/a (6.1.2.4)          | none (6.5 p4 fn56, 6.7.1)
extern int fun_2(void); | file  | same as any visible file scope declaration / 
external (6.1.2.2 p4) | n/a (6.1.2.4)          | none (6.5 p4 fn56, 6.7.1)
static int fun_3(void); | file  | internal (6.1.2.2 p3)                         
                     | n/a (6.1.2.4)          | none (6.5 p4 fn56, 6.7.1)
------------------------+-------+--------------------------------------------------------------------+------------------------+--------------------------
       int obj_7;       | block | none (6.1.2.2 p6)                             
                     | automatic (6.1.2.4 p3) | yes (6.1.2.4 p3, 6.5 p4)
extern int obj_8;       | block | same as any visible file scope declaration / 
external (6.1.2.2 p4) | static (6.1.2.4 p2)*   | none (6.7.2)
static int obj_9;       | block | none (6.1.2.2 p6)                             
                     | static (6.1.2.4 p2)    | yes (6.1.2.4 p2, 6.5 p4)
       int obj_10 = 1;  | block | none (6.1.2.2 p6)                             
                     | automatic (6.1.2.4 p3) | yes (6.1.2.4 p3, 6.5 p4)
extern int obj_11 = 1;  | block | INVALID (6.5.7 p4)**                          
                     | INVALID                | INVALID
static int obj_12 = 1;  | block | none (6.1.2.2 p6)                             
                     | static (6.1.2.4 p2)    | yes (6.1.2.4 p2, 6.5 p4)
       int fun_4(void); | block | same as any visible file scope declaration / 
external (6.1.2.2 p5) | n/a (6.1.2.4)          | none (6.5 p4 fn56, 6.7.1)
extern int fun_5(void); | block | same as any visible file scope declaration / 
external (6.1.2.2 p4) | n/a (6.1.2.4)          | none (6.5 p4 fn56, 6.7.1)
static int fun_6(void); | block | INVALID (6.1.2.2 p3 fn13, 6.5.1 p4)           
                     | INVALID                | INVALID

* any visible file scope declaration can only specify either external or 
internal linkage

** such a declaration would specify "same as any visible file scope declaration 
/ external (6.1.2.2 p4)" linkage, that is, external or internal (see *)
-----------------

All the references are to C89, unfortunately. I've never gotten around updating 
them to C99. :/

> 
> I'm okay with dropping extern on functions if you want, but that can
> be a separate patch; leaving them doesn't hurt either (other than the
> line length issues where your line splitting techniques are fine).

Removing the "extern"s is too much churn :) We use them very consistently, and 
they are not "wrong" by any means. They're a bit uncomfortable in this case, 
but if the current patch is tolerable, I'd prefer it over a global 
de-extern-ing.

> 
>>> +++ b/lib/internal.h
>>> @@ -407,7 +407,9 @@ extern int nbd_internal_wait_until_connected (struct 
>>> nbd_handle *h)
>>>    LIBNBD_ATTRIBUTE_NONNULL (1);
>>>  
>>>  /* crypto.c */
>>> -extern struct socket *nbd_internal_crypto_create_session (struct 
>>> nbd_handle *, struct socket *oldsock)
>>> +extern struct socket *
>>> +  nbd_internal_crypto_create_session (struct nbd_handle *,
>>> +                                      struct socket *oldsock)
>>>    LIBNBD_ATTRIBUTE_NONNULL (1, 2);
> 
> Looks reasonable to me.  emacs may have a bit of a difficulty in
> auto-indenting this back to the same place, but it is infrequent
> enough that manual override is still viable.
> 

Thanks! I'll stick with this, then.
Laszlo
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to