Graf Zahl wrote: ↑Fri Dec 15, 2023 10:14 am
What I want for safety is a C++ compile mode that can be set to error out on unsafe constructs (like const ->non-const casts) so I can gradually update it.
The only way I can see that working without an all-new syntax is adding something like a
strict { ... } section for new/updated functions that enforces appropriate guidelines (and/or the compiler be more strict by default and have a
relaxed { ... } section to relax enforcement for old existing functions). Otherwise, it would be a pain, if not impossible, to enable interoperability and gradually update an existing codebase.
Graf Zahl wrote: ↑Fri Dec 15, 2023 10:14 am
Ultimately it does not matter if you assign a 64 bit integer to a 32 bit destination with ot without cast. The value gets truncated either way, but in the former case the truncation will even happen if the destination gets extended to 64 bit later and the cast is overlooked because it's virtually impossible to find. So ultimately 'my code compiles without warnings' most of the time just means that considerable effort was invested to hide the problems from the compiler, not to fix them.
A cast expresses intent. If I come across something like
uint64_t a; uint32_t b; ... b = a;, I'm going to have no idea if there's a bug there or not (was
b supposed to be 64 bit? was
a supposed to be 32 bit? did the coder realize the high bits were being lost? is there not supposed to be any high bits to lose at that point?), but if I see
b = static_cast<uint32_t>(a);, that let's me know whoever did this knows
a isn't 32-bit and
b is, and it's meant to convert losing whatever high bits there may be. A cast does matter in that sense, even if the generated bytecode ends up being identical. If
b is later changed to a 64-bit type, the existing behavior doesn't change with the cast, while the cast stands out as something to re-check (why cast to a different type than is being assigned to? perhaps change to a
a&0xffffffff style mask instead if it's meant to truncate the top bits, but it's the same thing either way). If the destination gets extended to 64 bits, that doesn't necessarily mean the value shouldn't still be truncated. This is basically the kind of bug I ran into that I mentioned before (except it was a "safe" implicit type promotion, rather than a silent truncation); some code was relying on a implicit conversion, some stuff changed that removed the conversion and the behavior silently changed, causing a non-obvious break in the code. If I had an explicit cast where I intended to convert, if I more clearly expressed my intent, it wouldn't have broken.
Graf Zahl wrote: ↑Fri Dec 15, 2023 12:48 pm
dpJudas wrote: ↑Fri Dec 15, 2023 10:55 am
while C++ developers have to start mumbling about how if you run linters and stuff then you
probably will find the safety critical bugs.
And even then it
probably will only find some inane things while glancing over the real problems.
You get the same result if the compiler errors with "don't use const_cast" than if a separate linter errors and stops the build with "don't use const_cast". I'm not saying existing linters are that great, that it wouldn't be better for the compiler itself to handle it, or that we shouldn't push for that, but at least what I've tried this seems decently granular to allow gradual adoption/use to get benefit out of.