aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-11-17 10:23:14 +0000
committerJonathan Wakely <jwakely@redhat.com>2021-11-17 17:21:25 +0000
commit6afa1083c6ee7b31629fb0c16299b952cb17868c (patch)
tree80ca1827605ce99fa1690f650cb3f707e857a363
parent054bf99841aad3869c70643b2ba2d9f85770c980 (diff)
downloadgcc-6afa1083c6ee7b31629fb0c16299b952cb17868c.zip
gcc-6afa1083c6ee7b31629fb0c16299b952cb17868c.tar.gz
gcc-6afa1083c6ee7b31629fb0c16299b952cb17868c.tar.bz2
libstdc++: Set active member of union in std::string [PR103295]
Clang diagnoses that the new constexpr std::string constructors are not usable in constant expressions, because they start to write to members of the union without setting an active member. This adds a new helper function which returns the address of the local buffer after making it the active member. This doesn't fix all problems with Clang, because it still refuses to write to memory returned by the allocator. libstdc++-v3/ChangeLog: PR libstdc++/103295 * include/bits/basic_string.h (_M_use_local_data()): New member function to make local buffer the active member. (assign(const basic_string&)): Use it. * include/bits/basic_string.tcc (_M_construct, reserve()): Likewise.
-rw-r--r--libstdc++-v3/include/bits/basic_string.h15
-rw-r--r--libstdc++-v3/include/bits/basic_string.tcc10
2 files changed, 22 insertions, 3 deletions
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 0b7d6c0..9d281f5 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -325,6 +325,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_M_get_allocator() const
{ return _M_dataplus; }
+ // Ensure that _M_local_buf is the active member of the union.
+ __attribute__((__always_inline__))
+ _GLIBCXX14_CONSTEXPR
+ pointer
+ _M_use_local_data() _GLIBCXX_NOEXCEPT
+ {
+#if __cpp_lib_is_constant_evaluated
+ if (__builtin_is_constant_evaluated())
+ _M_local_buf[0] = _CharT();
+#endif
+ return _M_local_data();
+ }
+
private:
#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
@@ -1487,7 +1500,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
if (__str.size() <= _S_local_capacity)
{
_M_destroy(_M_allocated_capacity);
- _M_data(_M_local_data());
+ _M_data(_M_use_local_data());
_M_set_length(0);
}
else
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 5743770..5a51f7e 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -170,9 +170,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
size_type __len = 0;
size_type __capacity = size_type(_S_local_capacity);
+ pointer __p = _M_use_local_data();
+
while (__beg != __end && __len < __capacity)
{
- _M_data()[__len++] = *__beg;
+ __p[__len++] = *__beg;
++__beg;
}
@@ -223,6 +225,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_data(_M_create(__dnew, size_type(0)));
_M_capacity(__dnew);
}
+ else
+ _M_use_local_data();
// Check for out_of_range and length_error exceptions.
__try
@@ -247,6 +251,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_data(_M_create(__n, size_type(0)));
_M_capacity(__n);
}
+ else
+ _M_use_local_data();
if (__n)
this->_S_assign(_M_data(), __n, __c);
@@ -355,7 +361,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__length <= size_type(_S_local_capacity))
{
- this->_S_copy(_M_local_data(), _M_data(), __length + 1);
+ this->_S_copy(_M_use_local_data(), _M_data(), __length + 1);
_M_destroy(__capacity);
_M_data(_M_local_data());
}