Date: Thu, 30 Mar 2023 12:58:17 +0200
czw., 30 mar 2023 o 12:36 Alejandro Colomar
<alx.mailinglists_at_[hidden]> napisał(a):
>
>
>
> On Thu, Mar 30, 2023, 12:27 Marcin Jaczewski via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> czw., 30 mar 2023 o 11:26 Alejandro Colomar via Std-Proposals
>> <std-proposals_at_[hidden]> napisał(a):
>> >
>> >
>> >
>> > On 3/30/23 10:58, David Brown via Std-Proposals wrote:
>> > > On 29/03/2023 17:18, Arthur O'Dwyer via Std-Proposals wrote:
>> > >
>> > >> A new `uintmax_extended_t` (or whatever) can communicate properly from
>> > >> the get-go: "Hey! This type will change in the future! Don't build it
>> > >> into your APIs!"
>> > >> But then, if you aren't using this type in APIs, then where /*are*/ you
>> > >> using it, and why does it need to exist in the standard library at all?
>> > >>
>> > > That, I think, is the key point - /why/ would you want a "maximum size
>> > > integer type" ?
>> >
>> > For example to printf(3) an off_t variable.
>> > Or to write a [[gnu::always_inline]] function that accepts any integer.
>> > Or to write a type-generic macro that handles any integer.
>> >
>> > The addition of functions that handle [u]intmax_t was the design mistake.
>> > If they had been added as macros, we wouldn't be discussing ABI issues,
>> > because macros don't have ABI. Of course, the problem is that _Generic(3)
>> > was only added in C11, but intmax_t was added in C99, so they had to do it
>> > as functions. History sucks.
>> >
>>
>> No, this would change nothing, if it was macro, you still could put it
>> on some API and then worry about ABI break.
>> Usage of this causes risk of ABI break, not how it was defined.
>
>
> I already mentioned this on this thread (but maybe I sent the mail from an incorrect account and didn't reach the list): In the Linux man-pages page for _Generic(3), I wrote a proof of concept of how to implement imaxabs(3) and similar calls as macros, so that no traces of
> intmax_t are left in any ABI:
>
> <https://manpages.debian.org/testing/manpages-dev/_Generic.3.en.html>
>
> The actual calls will be made to functions of fundamental types.
>
> That would require modifying the standard to allow these calls to be implemented as macros only, with no real function of that name, but I think that shouldn't be a big deal. Implementations could keep a compat symbol for previous programs that called the function.
>
But ABI break can happen in user code too. If you have a lot of code
compiled by the old version, it could depend on `INTMAX_C`.
When you try to link the same code but compiled with a new compiler
you could have different behavior.
Like:
```
//shared definitions
void write_long(void* v)
{
*((long*)v) = 1;
}
void write_long_long(void* v)
{
*((long long*)v) = 1;
}
void write_long_long_long(void* v)
{
*((long long long*)v) = 1;
}
#define write _Generic(INTMAX_C(0), \
long: write_long, \
long long: write_long_long \
long long long: write_long_long_long \
)
//new code in one object file
void foo(void* v)
{
write(v);
}
//old code in another object file
void bar()
{
char p[sizeof(INTMAX_C(0))];
foo(p); //UB! buffer overrun
}
```
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
<alx.mailinglists_at_[hidden]> napisał(a):
>
>
>
> On Thu, Mar 30, 2023, 12:27 Marcin Jaczewski via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> czw., 30 mar 2023 o 11:26 Alejandro Colomar via Std-Proposals
>> <std-proposals_at_[hidden]> napisał(a):
>> >
>> >
>> >
>> > On 3/30/23 10:58, David Brown via Std-Proposals wrote:
>> > > On 29/03/2023 17:18, Arthur O'Dwyer via Std-Proposals wrote:
>> > >
>> > >> A new `uintmax_extended_t` (or whatever) can communicate properly from
>> > >> the get-go: "Hey! This type will change in the future! Don't build it
>> > >> into your APIs!"
>> > >> But then, if you aren't using this type in APIs, then where /*are*/ you
>> > >> using it, and why does it need to exist in the standard library at all?
>> > >>
>> > > That, I think, is the key point - /why/ would you want a "maximum size
>> > > integer type" ?
>> >
>> > For example to printf(3) an off_t variable.
>> > Or to write a [[gnu::always_inline]] function that accepts any integer.
>> > Or to write a type-generic macro that handles any integer.
>> >
>> > The addition of functions that handle [u]intmax_t was the design mistake.
>> > If they had been added as macros, we wouldn't be discussing ABI issues,
>> > because macros don't have ABI. Of course, the problem is that _Generic(3)
>> > was only added in C11, but intmax_t was added in C99, so they had to do it
>> > as functions. History sucks.
>> >
>>
>> No, this would change nothing, if it was macro, you still could put it
>> on some API and then worry about ABI break.
>> Usage of this causes risk of ABI break, not how it was defined.
>
>
> I already mentioned this on this thread (but maybe I sent the mail from an incorrect account and didn't reach the list): In the Linux man-pages page for _Generic(3), I wrote a proof of concept of how to implement imaxabs(3) and similar calls as macros, so that no traces of
> intmax_t are left in any ABI:
>
> <https://manpages.debian.org/testing/manpages-dev/_Generic.3.en.html>
>
> The actual calls will be made to functions of fundamental types.
>
> That would require modifying the standard to allow these calls to be implemented as macros only, with no real function of that name, but I think that shouldn't be a big deal. Implementations could keep a compat symbol for previous programs that called the function.
>
But ABI break can happen in user code too. If you have a lot of code
compiled by the old version, it could depend on `INTMAX_C`.
When you try to link the same code but compiled with a new compiler
you could have different behavior.
Like:
```
//shared definitions
void write_long(void* v)
{
*((long*)v) = 1;
}
void write_long_long(void* v)
{
*((long long*)v) = 1;
}
void write_long_long_long(void* v)
{
*((long long long*)v) = 1;
}
#define write _Generic(INTMAX_C(0), \
long: write_long, \
long long: write_long_long \
long long long: write_long_long_long \
)
//new code in one object file
void foo(void* v)
{
write(v);
}
//old code in another object file
void bar()
{
char p[sizeof(INTMAX_C(0))];
foo(p); //UB! buffer overrun
}
```
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2023-03-30 10:58:30