Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

Alejandro Colomar
2022-11-13T16:26:11Z

[-- Attachment #1.1: Type: text/plain, Size: 4129 bytes --]

Hi Martin,

On 11/13/22 16:32, Martin Uecker wrote:
> Am Sonntag, den 13.11.2022, 16:15 +0100 schrieb Alejandro Colomar:
>> Hi Martin,
>>
>> On 11/13/22 15:58, Martin Uecker wrote:
>>> Am Sonntag, den 13.11.2022, 15:02 +0100 schrieb Alejandro Colomar:
>>>> On 11/13/22 14:33, Alejandro Colomar wrote:
>>>>> On 11/13/22 14:19, Alejandro Colomar wrote:
>>>>>>> But there are not only syntactical problems, because
>>>>>>> also the type of the parameter might become relevant
>>>>>>> and then you can get circular dependencies:
>>>>>>>
>>>>>>> void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);
>>>>>>
>>>>>> This seems to be a difficult stone in the road.
>>>
>>> But note that GNU forward declarations solve this nicely.
>>
>> How would that above be solved with GNU fwd decl? I'm guessing that it can't.
>> How do you forward declare incomplete VMTs?.
>
> You can't express it. This was my point: it is impossible
> to create circular dependencies.
>
> ...
>
>>>>>> {
>>>>>> for (/* void */; dst <= end; dst++) {
>>>>>> *dst = *src++;
>>>>>> if (*dst == '\0')
>>>>>> return dst;
>>>>>> }
>>>>>> /* Truncation detected */
>>>>>> *end = '\0';
>>>>>>
>>>>>> #if !defined(NDEBUG)
>>>>>> /* Consume the rest of the input string. */
>>>>>> while (*src++) {};
>>>>>> #endif
>>>>>>
>>>>>> return end + 1;
>>>>>> }
>>>>> And I forgot to say it: Default promotions rank high (probably the highest) in
>>>>> my list of most hated features^Wbugs in C.
>>>
>>> If you replaced them with explicit conversion you then have
>>> to add by hand all the time, I am pretty sure most people
>>> would hate this more. (and it could also hide bugs)
>>
>> Yeah, casts are also in my top 3 list of things to avoid (although in this case
>> there's no bug); maybe a bit over default promotions :)
>>
>> I didn't mean that all promotions are bad. Just the gratuitous ones, like
>> promoting everything to int before even needing it. That makes uint16_t a
>> theoretical type, because whenever you try to use it, you end up with a signed
>> 32-bit type; fun heh? :P _BitInt() solves that for me.
>
> uint16_t is for storing data. My expectation is that people
> will find _BitInt() difficult and error-prone to use for
> small sizes. But maybe I am wrong...

I'm a bit concerned about the suffix to create literals. I'd have preferred a
suffix that allowed creating a specific size (instead of the minimum one. i.e.,
1u16 or something like that. But otherwise I think it can be better. I don't
have in mind a big issue I had a year ago with uint16_t, but it required 3 casts
in a line. With _BitInt() I think none (or maybe one, for giving 1 the
appropriate size) would have been needed. But we'll see how it works out.

>
>> But sure, in (1u + 1l), promotions are fine to get a common type.
>>
>>>>> I wouldn't convert it to size_t, but
>>>>> rather follow normal promotion rules.
>>>
>>> The point of making it size_t is that you then
>>> do need to know the type of the parameter to make
>>> sense of the expression. If the type matters, then you get
>>> mutual dependencies as in the example above.
>>
>> Except if you treat incomplete types as... incomplete types (for which sizeof()
>> is disallowed by the standard). And the issue we're having is that the types
>> are not yet complete at the time we're using them, aren't they?
>
> It is not an incomplete type. When doing parsing and do not have
> a declaration we know nothing about it (not just not the size).
> If we assume we know the type (by looking ahead) we get mutual
> dependencies.

Then I'd do the following: .identifier always has an incomplete type.

I'm preparing a complete description of what I think of the feature. I'll add that.

>
> Also the capability to parse, fold, and do type checking
> in one go is something worth preserving in my opinion.

Makes sense.

Thanks for all the help, both!

Cheers,

Alex