Files
clang-p2996/libcxx/test/std/utilities/template.bitset/bitset.members/to_string.pass.cpp
James Y Knight b964419ec2 [libcxx] Allow string to use SSO in constant evaluation. (#66576)
Previously, libcxx forced all strings created during constant evaluation
to point to allocated memory. That was done due to implementation
difficultites, but it turns out not to be necessary. This patch permits
the use of SSO strings during constant evaluation, and also simplifies
the implementation.

This does have a downside in terms of enabling users to accidentally
write non-portable code, however, which I've documented in
UsingLibcxx.rst.

In particular, whether `constinit std::string x = "...";` will
successfully compile now depends on whether the string is smaller than
the SSO capacity -- in libc++, up to 22 bytes on 64-bit platforms, and
up to 10 bytes on 32-bit platforms. By comparison, libstdc++ and MSVC
have an SSO capacity of 15 bytes, except that in libstdc++,
constant-initialized strings cannot be used as function-locals because
the object contains a pointer to itself.

Closes #68434
2023-10-10 11:31:47 -07:00

159 lines
5.1 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// test:
// template <class charT, class traits, class Allocator>
// basic_string<charT, traits, Allocator>
// to_string(charT zero = charT('0'), charT one = charT('1')) const; // constexpr since C++23
//
// template <class charT, class traits>
// basic_string<charT, traits, allocator<charT> > to_string() const; // constexpr since C++23
//
// template <class charT>
// basic_string<charT, char_traits<charT>, allocator<charT> > to_string() const; // constexpr since C++23
//
// basic_string<char, char_traits<char>, allocator<char> > to_string() const; // constexpr since C++23
#include <bitset>
#include <cassert>
#include <cstddef>
#include <memory> // for std::allocator
#include <string>
#include <vector>
#include "../bitset_test_cases.h"
#include "test_macros.h"
template <class CharT, std::size_t N>
TEST_CONSTEXPR_CXX23 void check_equal(std::basic_string<CharT> const& s, std::bitset<N> const& b, CharT zero, CharT one) {
assert(s.size() == b.size());
for (std::size_t i = 0; i < b.size(); ++i) {
if (b[i]) {
assert(s[b.size() - 1 - i] == one);
} else {
assert(s[b.size() - 1 - i] == zero);
}
}
}
template <std::size_t N>
TEST_CONSTEXPR_CXX23 bool test_to_string() {
std::vector<std::bitset<N> > const cases = get_test_cases<N>();
for (std::size_t c = 0; c != cases.size(); ++c) {
std::bitset<N> const v = cases[c];
{
std::string s = v.template to_string<char>();
check_equal(s, v, '0', '1');
}
{
std::string s = v.to_string();
check_equal(s, v, '0', '1');
}
{
std::string s = v.template to_string<char>('0');
check_equal(s, v, '0', '1');
}
{
std::string s = v.to_string('0');
check_equal(s, v, '0', '1');
}
{
std::string s = v.template to_string<char>('0', '1');
check_equal(s, v, '0', '1');
}
{
std::string s = v.to_string('0', '1');
check_equal(s, v, '0', '1');
}
{
std::string s = v.to_string('x', 'y');
check_equal(s, v, 'x', 'y');
}
}
return true;
}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
template <std::size_t N>
TEST_CONSTEXPR_CXX23 bool test_to_string_wchar() {
std::vector<std::bitset<N> > const cases = get_test_cases<N>();
for (std::size_t c = 0; c != cases.size(); ++c) {
std::bitset<N> const v = cases[c];
{
std::wstring s = v.template to_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >();
check_equal(s, v, L'0', L'1');
}
{
std::wstring s = v.template to_string<wchar_t, std::char_traits<wchar_t> >();
check_equal(s, v, L'0', L'1');
}
{
std::wstring s = v.template to_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >('0');
check_equal(s, v, L'0', L'1');
}
{
std::wstring s = v.template to_string<wchar_t, std::char_traits<wchar_t> >('0');
check_equal(s, v, L'0', L'1');
}
{
std::wstring s = v.template to_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >('0', '1');
check_equal(s, v, L'0', L'1');
}
{
std::wstring s = v.template to_string<wchar_t, std::char_traits<wchar_t> >('0', '1');
check_equal(s, v, L'0', L'1');
}
}
return true;
}
#endif
int main(int, char**) {
test_to_string<0>();
test_to_string<1>();
test_to_string<31>();
test_to_string<32>();
test_to_string<33>();
test_to_string<63>();
test_to_string<64>();
test_to_string<65>();
test_to_string<1000>(); // not in constexpr because of constexpr evaluation step limits
#if TEST_STD_VER > 20
static_assert(test_to_string<0>());
static_assert(test_to_string<1>());
static_assert(test_to_string<31>());
static_assert(test_to_string<32>());
static_assert(test_to_string<33>());
static_assert(test_to_string<63>());
static_assert(test_to_string<64>());
static_assert(test_to_string<65>());
#endif
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test_to_string_wchar<0>();
test_to_string_wchar<1>();
test_to_string_wchar<31>();
test_to_string_wchar<32>();
test_to_string_wchar<33>();
test_to_string_wchar<63>();
test_to_string_wchar<64>();
test_to_string_wchar<65>();
test_to_string_wchar<1000>(); // not in constexpr because of constexpr evaluation step limits
#if TEST_STD_VER > 20
static_assert(test_to_string_wchar<0>());
static_assert(test_to_string_wchar<1>());
static_assert(test_to_string_wchar<31>());
static_assert(test_to_string_wchar<32>());
static_assert(test_to_string_wchar<33>());
static_assert(test_to_string_wchar<63>());
#endif
#endif
return 0;
}