Description
PR #66576 allows std::string to use SSO representation during constant-evaluation time.
This means, however, that for "short enough" strings, you can make a constexpr global, but longer strings will produce an error (due to the pointer to a dynamic memory allocation, which cannot be transported from constant-evaluation-time to runtime). Unfortunately, the exact cutoff differs between implementations, and, in libc++, differs between 32-bit and 64-bit platforms.
E.g., constinit std::string g_str = "01234567890";
doesn't work on 32-bit libc++ platforms, and constinit std::string g_str = "0123456789012345678901";
doesn't work on libstdc++ or msvc, but does work on 64-bit libc++.
This is a portability trap. It would be nice to have a warning to tells users not to do that.
Initially, I suggested we'd want to diagnose if any string object was written out to the object file, but that's wrong: we shouldn't warn for std::string x = "hello";
; even if it is constant initialized, it'll also work on an implementation where it isn't. So @frederick-vs-ja suggested:
I think the warning should be triggered only if
- a constexpr or constinit object is a basic_string or contains a basic_string subobject, or
- the definition of a constexpr or constinit variable extends the lifetime of a temporary object that meets the previous condition.
One could either hardcode the type std::basic_string
for this diagnostic, or potentially add a new type attribute to trigger this diagnostic, if we think there might be other similar types which don't intend constant-initialization to be part of their supported API, but where it may sometimes be possible, in implementation-specific conditions.