For example, clang started simply omitting writes to data it knows to be read-only (which is allowed because these writes are undefined behavior, so anything goes). See this example[1]: `writable()` will return "*ello", but `readonly()` will just return "hello" and not crash (note its assembly doesn't include a write).
Although, I am curious if that optimization could happen across compilation units via LTO...
If you change `writable()` to receive a `const char *` (and then cast it to `char *` to write), then clang will be forced to compile it with a store (even though it sees you storing to a `const char *`) because it doesn't know if the function will be called with a pointer to actual read-only data or just a pointer to writable data that was gratuitously converted to `const`.
That's exactly my point yeah, the optimization you described is only possible because you gave the compiler extra knowledge about the argument to that function (because it was static in the same compilation unit). It's artificial, typically that won't be the case.
I remember there was a lot of confusion when llvm started removing stores to read-only memory[1], some people got angry because it broke some kernel code (that only worked because being in a kernel the memory page wasn't actually marked as read-only) and thought it would break any code that cast away a `const`, which is very common and valid as long as it was gratuitously `const`, as you say.
[1] https://releases.llvm.org/9.0.0/docs/ReleaseNotes.html#notew...
Moreover, an old style cast. GNU c++ has an opt-in warning for those, -Wold-style-cast. You then need const_cast to get around that.
Then we can grep the program for that new style cast (unless it token-pasted the const_cast together in the preprocessor haha).
In C we can make such a program which contains no devices that defeat the type system, and which otherwise requires no diagnostic.
I'm not denying that there are codebases where trying this would result in an Armageddon of refactoring, but I would venture that's the exception rather than the rule.
Most C programmers use "const char*" for string literals, and have for a long time.