[...]
If we store a 'const' object in a section of memory that later gets
set read-only, we need to be sure that it is really a const object --
i.e. it can't contain mutable members.
So I've implemented "std::contains_mutable". Here's my compiler patch
for GNU g++:
https://github.com/healytpk/gcc-thomas-healy/commit/tag_contains_mutable
And here it is tested up on GodBolt:
https://godbolt.org/z/KosvqTETo
The stuff about flash isn't necessary or useful. If there is a rationale for adding something like `std::contains_mutable(_member)` to the Standard, it would be because compiler vendors "already have to do it anyway," i.e. the same rationale we saw for std::is_implicit_lifetime, std::is_scoped_enum, std::reference_converts_from_temporary, etc. These are properties that affect what the front-end and/or back-end allow you to do with a type, so, every compiler must have a way to check for them already. All the type-trait does is expose that way to the end-user.
The example is:
struct C {
int i_;
};
struct M {
mutable int i_;
};
void fc(std::initializer_list<C> il);
void fm(std::initializer_list<M> il);
void withC() {
static_assert(!__builtin_contains_mutable(C));
fc({{1},{2},{3}});
fc({{1},{2},{3}});
}
void withM() {
static_assert(__builtin_contains_mutable(M));
fm({{1},{2},{3}});
fm({{1},{2},{3}});
}
Notice the difference in codegen between withC() and withM(). `withC()` can store a single backing array in .rodata and hand to `fc` a view over that constant backing array. `withM()` needs to copy that backing array onto the stack, because `fm` is permitted to modify its partially-mutable elements through its argument `il`. (That is, `withM()` does not benefit from the optimization newly permitted by P2752.)
So, GCC clearly already has a notion of "contains mutable members." Your type-trait should just expose that notion to the end-user, and as such, it's a plausible candidate to propose for standardization, IMO.
However, I took a quick look at your GCC patch, and it looks to me as if you reinvented the wheel there. Why is your patch not (in spirit) a one-liner? Why are you manually iterating over members and bases? This is not the implementation I would expect to see, given the above rationale.
It is possible that GCC's existing "contains mutable" logic is not yet factored out into a simple function (because I bet it's used in only one place right now). In that case, instead of merely finding and calling that function, you'll need to factor out that function as part of your patch. I have no special knowledge or connections re GCC, but I'd imagine that a well-written such patch might actually be accepted upstream, if accompanied by a rationale such as I've given here.
Last I checked, Clang trunk doesn't do P2752's optimization at all. I'm fairly certain that, if you were to work up a well-written patch for checking this type-property in Clang and submit it, along with the explanation that this is a (compiler-internal) building block for the optimization permitted by P2752, it would be graciously accepted. Even more so if you simultaneously submit a second patch that uses this building block to implement P2752, bringing Clang into parity with GCC.
my $.02,
–Arthur