SmallString: Replace manual itoa implementation with std::to_chars

GCC 12 was producing a huge warning log about this, thinking we were
overflowing the buffer. I don't see how.

In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/12/bits/stl_algobase.h:182:11,
    inlined from ‘void std::__reverse(_RandomAccessIterator, _RandomAccessIterator, random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/12/bits/stl_algo.h:1107:18,
    inlined from ‘void std::reverse(_BIter, _BIter) [with _BIter = char*]’ at /usr/include/c++/12/bits/stl_algo.h:1134:21,
    inlined from ‘static std::size_t Utils::BasicSmallString<Size>::itoa(long long int, char*, uint) [with unsigned int Size = 31]’ at smallstring.h:956:21,
[... many more frames ...]
move.h:205:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
smallstring.h:615:14: note: at offset 46 into destination object ‘buffer’ of size 22
  615 |         char buffer[22];
      |              ^~~~~~
smallstring.h:615:14: note: at offset [14, 22] into destination object ‘buffer’ of size 22
smallstring.h:615:14: note: at offset 46 into destination object ‘buffer’ of size 22

Change-Id: Iba16e8ea451b444ab213fffd16f491e608ee713a
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Thiago Macieira
2022-06-01 11:16:20 -07:00
committed by Marco Bubke
parent d7ba5a84b0
commit aa5d2eaf13

View File

@@ -39,6 +39,7 @@
#endif
#include <algorithm>
#include <charconv>
#include <cmath>
#include <cstdlib>
#include <climits>
@@ -603,19 +604,31 @@ public:
static
BasicSmallString number(int number)
{
char buffer[12];
std::size_t size = itoa(number, buffer, 10);
return BasicSmallString(buffer, size);
#ifdef __cpp_lib_to_chars
// +1 for the sign, +1 for the extra digit
char buffer[std::numeric_limits<int>::digits10 + 2];
auto result = std::to_chars(buffer, buffer + sizeof(buffer), number, 10);
Q_ASSERT(result.ec == std::errc{});
auto endOfConversionString = result.ptr;
return BasicSmallString(buffer, endOfConversionString);
#else
return std::to_string(number);
#endif
}
static
BasicSmallString number(long long int number)
{
char buffer[22];
std::size_t size = itoa(number, buffer, 10);
return BasicSmallString(buffer, size);
#ifdef __cpp_lib_to_chars
// +1 for the sign, +1 for the extra digit
char buffer[std::numeric_limits<long long int>::digits10 + 2];
auto result = std::to_chars(buffer, buffer + sizeof(buffer), number, 10);
Q_ASSERT(result.ec == std::errc{});
auto endOfConversionString = result.ptr;
return BasicSmallString(buffer, endOfConversionString);
#else
return std::to_string(number);
#endif
}
static
@@ -913,51 +926,6 @@ private:
m_data.allocated.data.size = size;
}
static
std::size_t itoa(long long int number, char* string, uint base)
{
using llint = long long int;
using lluint = long long unsigned int;
std::size_t size = 0;
bool isNegative = false;
lluint unsignedNumber = 0;
if (number == 0)
{
string[size] = '0';
string[++size] = '\0';
return size;
}
if (number < 0 && base == 10)
{
isNegative = true;
if (number == std::numeric_limits<llint>::min())
unsignedNumber = lluint(std::numeric_limits<llint>::max()) + 1;
else
unsignedNumber = lluint(-number);
} else {
unsignedNumber = lluint(number);
}
while (unsignedNumber != 0)
{
int remainder = int(unsignedNumber % base);
string[size++] = (remainder > 9) ? char((remainder - 10) + 'a') : char(remainder + '0');
unsignedNumber /= base;
}
if (isNegative)
string[size++] = '-';
string[size] = '\0';
std::reverse(string, string+size);
return size;
}
private:
Internal::StringDataLayout<Size> m_data;
};