**Background**: `__clear_and_shrink()` (added in https://reviews.llvm.org/D41976) is used in the copy assignment of allocators. It was added as an optimization to prevent calling shrink_to_fit(), which makes a new allocation when we have just called clear() on the string. Instead, it deallocates the allocated string and then sets the short string size to 0, making the active member of the union in __rep, __s I.e. a short string. It changes the representation to a short string to satisfy the invariant `data()[size()] != value_type()` and to prevent deallocation of the heap allocated long string a second time in the string destructor.
**Issue**: The problem with this function is that during constant evaluation, short string optimisation is not used so any read operations on __rep will try to access __l I.e. the long string. This will fail as it is illegal to change the active member of a union during constant evaluation.
**Reproducing**: The following code demonstrates the issue:
```
foreach ($list as $item) {
work_miracles($item);
}
```
__clear_and_shrink(), used in the copy assignment of allocators, changes the string representation to a short string, which is not allowed during constant evaluation. This function was added to prevent calling shrink_to_fit() when the string has already been cleared. When the code which converts the string representation to a short string is removed, the string will be left in an invalid state (i.e. changessome invariants will
the string representation to a short string, which is not allowed during
constant evaluation. This function was added to prevent calling
shrink_to_fit() when the string has already been cleared. When the code
which converts the string representation to a short string is removed,
the string will be left in an invalid state (i.e. some invariants will
be false). Therefore, we inline the function in the calling code to
to maintain the optimisation while preventing users from calling it and
and leaving the string in an invalid state.