It is completely possible to write C code which does attempt to write to string literals.

The same is trivially true for C++: https://godbolt.org/z/h5znfchf8

But that uses a cast.

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 was just editing my comment to add this point :)

No, it isn't. It will crash.

It might crash, or it might work as naively expected, or it might do something else.

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).

[1] https://godbolt.org/z/MboK3hTPx

That happens because the string is static. If you rewrite that so s is an argument to writable(), it will segfault.

Although, I am curious if that optimization could happen across compilation units via LTO...

I'm not sure what you mean. In `writable()`, there's no read-only data; `s` is a non-const char array (it has to be static because the function returns a pointer to it). The string literal is only there to tell the compiler how to initialize the array, `s` is not actually the string literal.

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`.

> 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

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.

Ah, I understand you now, you're right.

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...

It is possible. Some platforms have no concept of rodata. You can mremap a segment. Lots of valid ways to do it.

Well, at that point you deserve it :)

A good reason to define it as an invalid program then and fail at compile time?

Yes. I am literally arguing for doing that in this entire thread.