On 2/21/23 19:38, Eric Blake wrote:
On Tue, Feb 21, 2023 at 01:24:17PM +0000, Richard W.M. Jones wrote:
>>>> +++ b/generator/states-connect-socket-activation.c
>>>> @@ -51,7 +51,7 @@ prepare_socket_activation_environment (string_vector
*env)
>>>> char *p;
>>>> size_t i;
>>>>
>>>> - assert (env->len == 0);
>>>> + *env = (string_vector)empty_vector;
>>>
>>> Do you actually need to cast this?
>>
>> This is not a cast, but a C99 compound literal. And yes, it is
>> necessary, as empty_vector is just:
>>
>> #define empty_vector { .ptr = NULL, .len = 0, .cap = 0 }
>>
>> So this is *not* initialization, but assignment. We have a string_vector
>> object (a structure) on the LHS, so we ned a structure on the RHS as
>> well. The compound literal provides that (unnamed, automatic storage
>> duration) structure. It looks like a cast (quite intentionally, I'd
>> hazard), but it's not a cast.
>
> OK it's not a cast, but struct assignment is well defined so is the
> change necessary?
Struct assignment requires a source struct. Either a named one (which
we do not have here without declaring one), or via a compound literal
(which resembles a cast).
It sounds like it would be nice to have a type-specific macro, as in
'empty_string_vector', 'empty_int_vector', and so on, per each use of
DEFINE_VECTOR_TYPE() - but while our one macro can easily declare
other type-specific functions, you can't really use the preprocessor
to define further type-specific macros. So having to tell the user to
supply their own type name when reusing the type-agnostic initializer
portion of a compound literal is not too bad in the long run, although
it might be worth documenting the practice in vector.h.
... another follow-up item :)