Date: Thu, 22 Jan 2026 22:40:30 -0800
On Thursday, 22 January 2026 22:17:50 Pacific Standard Time Jan Schultke wrote:
> But behavior needs to be implemented in some fashion, and specifying
> certain behavior constrains what implementations are possible, sometimes in
> surprising ways.
>
> If you receive a long double function parameter and your calling
> conventions are so that this is passed via floating-point stack, there are
> no padding bits in that object which could be cleared. Ergo, if you ran
> std::clear_padding, this would require spilling the object from the
> floating-point stack into memory so that the padding bits can be accessed
> later, with the guaranteed cleared value.
No, it does not. Again, all that matters is that logically those bits are
cleared. But if you never observe them, then the compiler can apply an as-if
transformation and eliminate the clearing in the first place.
This applies to any type with padding, not just long double.
If you do observe them, then the compiler must ensure you observe zeroes.
Whether it wrote those zeroes to memory or not is irrelevant.
uint32_t f(long double f)
{
std::clear_padding(f);
// some other code, irrelevant what
uint32_t r;
memcpy(&r, &f, sizeof(r));
return r;
}
the compiler can implement the return as:
return 0;
> To be fair, I don't think std::clear_padding creates this problem; you can
> already memcpy into an object to manipulate its padding bits, so the
> problem starts with padding bits being observable. However, use of
> clear_padding and memcpy idioms may pessimize code in practice, so perhaps
> that's not an idiom we want to promote.
>
> By comparison, std::bit_cast_clear_padding ignores the values of input
> padding bits, so the compiler would never be required to track their values.
Agreed.
But we may have a condition where bit-casting is not acceptable. Imagine one
wants to do a checksum of an array of a struct that contains padding bits. But
checksumming algorithms are not template-generic. They are type-erased and
operate on a memory region. Therefore, if this array is of arbitrary size, we
wouldn't want to bit-cast it to a byte array of equivalent size.
The only alternative is to apply std::clear_padding() on the actual objects.
By definition, that doesn't change the semantic value of the objects. But it
does allow calling the out-of-line, type-erased checksumming algorithm.
> But behavior needs to be implemented in some fashion, and specifying
> certain behavior constrains what implementations are possible, sometimes in
> surprising ways.
>
> If you receive a long double function parameter and your calling
> conventions are so that this is passed via floating-point stack, there are
> no padding bits in that object which could be cleared. Ergo, if you ran
> std::clear_padding, this would require spilling the object from the
> floating-point stack into memory so that the padding bits can be accessed
> later, with the guaranteed cleared value.
No, it does not. Again, all that matters is that logically those bits are
cleared. But if you never observe them, then the compiler can apply an as-if
transformation and eliminate the clearing in the first place.
This applies to any type with padding, not just long double.
If you do observe them, then the compiler must ensure you observe zeroes.
Whether it wrote those zeroes to memory or not is irrelevant.
uint32_t f(long double f)
{
std::clear_padding(f);
// some other code, irrelevant what
uint32_t r;
memcpy(&r, &f, sizeof(r));
return r;
}
the compiler can implement the return as:
return 0;
> To be fair, I don't think std::clear_padding creates this problem; you can
> already memcpy into an object to manipulate its padding bits, so the
> problem starts with padding bits being observable. However, use of
> clear_padding and memcpy idioms may pessimize code in practice, so perhaps
> that's not an idiom we want to promote.
>
> By comparison, std::bit_cast_clear_padding ignores the values of input
> padding bits, so the compiler would never be required to track their values.
Agreed.
But we may have a condition where bit-casting is not acceptable. Imagine one
wants to do a checksum of an array of a struct that contains padding bits. But
checksumming algorithms are not template-generic. They are type-erased and
operate on a memory region. Therefore, if this array is of arbitrary size, we
wouldn't want to bit-cast it to a byte array of equivalent size.
The only alternative is to apply std::clear_padding() on the actual objects.
By definition, that doesn't change the semantic value of the objects. But it
does allow calling the out-of-line, type-erased checksumming algorithm.
-- Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org Principal Engineer - Intel Data Center - Platform & Sys. Eng.
Received on 2026-01-23 06:40:34
