Yeah. It’s also problematic for some of the most important use cases like hand-rolled v-tables. V-table entries really want to use both address and constant diversity, but with the intrinsics that means passing a pretty complicated expression as the discriminator argument:
struct vtable my_vtable = {
ptrauth_sign_constant(&my_function_pointer,
ptrauth_key_function_pointer,
ptrauth_blend_discriminator(&my_vtable.current_field, 0x1234)),
...
};
So, first off, this muddies writing constant v-table initializers a lot, and you have to write it separately and correctly on every single v-table. __ptrauth allows you to just write the qualifier in the struct definition, and then writing initializers just works.
But it also complicates the compiler and implementation quite a bit, because what expressions are you actually going to allow as the constant discriminator? If it can be an arbitrary blend call, then the image format and loader have to support that, which is a lot of extra encoding and runtime complexity. __ptrauth allows you to just support the simple pattern of blending the storage address with a constant. To allow just that with the intrinsics, you’d need to recognize that the pointer passed to ptrauth_blend_discriminator was actually the address of the current field being initialized, which is a pretty weird rule (and probably doesn’t work well in the new age of C++ constant evaluation).