From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id B92983858D28; Wed, 17 Nov 2021 17:23:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B92983858D28 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r12-5343] libstdc++: Set active member of union in std::string [PR103295] X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/master X-Git-Oldrev: 054bf99841aad3869c70643b2ba2d9f85770c980 X-Git-Newrev: 6afa1083c6ee7b31629fb0c16299b952cb17868c Message-Id: <20211117172302.B92983858D28@sourceware.org> Date: Wed, 17 Nov 2021 17:23:02 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Nov 2021 17:23:02 -0000 https://gcc.gnu.org/g:6afa1083c6ee7b31629fb0c16299b952cb17868c commit r12-5343-g6afa1083c6ee7b31629fb0c16299b952cb17868c Author: Jonathan Wakely Date: Wed Nov 17 10:23:14 2021 +0000 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. Diff: --- libstdc++-v3/include/bits/basic_string.h | 15 ++++++++++++++- libstdc++-v3/include/bits/basic_string.tcc | 10 ++++++++-- 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 0b7d6c0a981..9d281f5daf2 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 5743770b42a..5a51f7e21b5 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()); }