Finish implementing P0426R1 "Constexpr for std::char_traits" for C++17
As discussed in PR c++/80265 ("__builtin_{memcmp,memchr,strlen} are not usable in constexpr functions"), use __builtin_constant_p to tell whether we can defer to a constexpr algorithm. I used __always_inline__ just to be thorough. It isn't really really necessary as far as I could determine. Changes like these: if (__n == 0) return 0; - return wmemcmp(__s1, __s2, __n); + else + return wmemcmp(__s1, __s2, __n); are necessary otherwise G++ complains that we're calling a non-constexpr function, which looks like a a manifestation of PR67026 to me. libstdc++-v3: 2017-06-12 Pedro Alves <palves@redhat.com> * doc/xml/manual/status_cxx2017.xml: Update C++17 constexpr char_traits status. * doc/html/*: Regenerate. * include/bits/char_traits.h (_GLIBCXX_ALWAYS_INLINE): Define if not already defined. (__cpp_lib_constexpr_char_traits): Uncomment. (__constant_string_p, __constant_char_array_p): New. (std::char_traits<char>, std::char_traits<wchar_t>): Add _GLIBCXX17_CONSTEXPR on compare, length and find and use __constant_string_p, __constant_char_array_p and __builtin_constant_p to defer to __gnu_cxx::char_traits at compile time. * testsuite/21_strings/char_traits/requirements/ constexpr_functions_c++17.cc: Uncomment __cpp_lib_constexpr_char_traits tests. Uncomment test_compare<char>, test_length<char>, test_find<char>, test_compare<wchar_t>, test_length<wchar_t> and test_find<wchar_t> static_assert tests. From-SVN: r252030
This commit is contained in:
parent
a13244e8fe
commit
54316fafea
|
@ -1,3 +1,29 @@
|
|||
2017-09-12 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
Backport from mainline
|
||||
2017-06-12 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* doc/xml/manual/status_cxx2017.xml: Update C++17 constexpr
|
||||
char_traits status.
|
||||
* doc/html/*: Regenerate.
|
||||
|
||||
* include/bits/char_traits.h (_GLIBCXX_ALWAYS_INLINE): Define if
|
||||
not already defined.
|
||||
(__cpp_lib_constexpr_char_traits): Uncomment.
|
||||
(__constant_string_p, __constant_char_array_p): New.
|
||||
(std::char_traits<char>, std::char_traits<wchar_t>): Add
|
||||
_GLIBCXX17_CONSTEXPR on compare, length and find and use
|
||||
__constant_string_p, __constant_char_array_p and
|
||||
__builtin_constant_p to defer to __gnu_cxx::char_traits at compile
|
||||
time.
|
||||
|
||||
* testsuite/21_strings/char_traits/requirements/
|
||||
constexpr_functions_c++17.cc: Uncomment
|
||||
__cpp_lib_constexpr_char_traits tests. Uncomment
|
||||
test_compare<char>, test_length<char>, test_find<char>,
|
||||
test_compare<wchar_t>, test_length<wchar_t> and test_find<wchar_t>
|
||||
static_assert tests.
|
||||
|
||||
2017-09-04 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
Backport from mainline
|
||||
|
|
|
@ -684,11 +684,11 @@ Feature-testing recommendations for C++</a>.
|
|||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0505r0.html" target="_top">
|
||||
P0505R0
|
||||
</a>
|
||||
</td><td align="center"> 7 </td><td align="left"><code class="code"> ??? </code></td></tr><tr bgcolor="#B0B0B0"><td align="left"> Constexpr for <code class="code">std::char_traits</code> </td><td align="left">
|
||||
</td><td align="center"> 7 </td><td align="left"><code class="code"> ??? </code></td></tr><tr><td align="left"> Constexpr for <code class="code">std::char_traits</code> </td><td align="left">
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0426r1.html" target="_top">
|
||||
P0426R1
|
||||
</a>
|
||||
</td><td align="center"> 7 (partial) </td><td align="left"><code class="code"> ??? </code></td></tr><tr><td align="left"> Integrating <code class="code">std::string_view</code> and <code class="code">std::string</code> </td><td align="left">
|
||||
</td><td align="center"> 7.3 </td><td align="left"><code class="code"> __cpp_lib_constexpr_char_traits >= 201611 </code></td></tr><tr><td align="left"> Integrating <code class="code">std::string_view</code> and <code class="code">std::string</code> </td><td align="left">
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0254r2.pdf" target="_top">
|
||||
P0254R2
|
||||
</a>
|
||||
|
@ -961,4 +961,4 @@ particular release.
|
|||
</td></tr></tbody></table></div></div><br class="table-break" /></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="intro.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="intro.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="license.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part I.
|
||||
Introduction
|
||||
|
||||
</td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> License</td></tr></table></div></body></html>
|
||||
</td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> License</td></tr></table></div></body></html>
|
||||
|
|
|
@ -482,15 +482,14 @@ Feature-testing recommendations for C++</link>.
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||||
<entry> Constexpr for <code>std::char_traits</code> </entry>
|
||||
<entry>
|
||||
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0426r1.html">
|
||||
P0426R1
|
||||
</link>
|
||||
</entry>
|
||||
<entry align="center"> 7 (partial) </entry>
|
||||
<entry><code> ??? </code></entry>
|
||||
<entry align="center"> 7.3 </entry>
|
||||
<entry><code> __cpp_lib_constexpr_char_traits >= 201611 </code></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
#include <bits/postypes.h> // For streampos
|
||||
#include <cwchar> // For WEOF, wmemmove, wmemset, etc.
|
||||
|
||||
#ifndef _GLIBCXX_ALWAYS_INLINE
|
||||
#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
|
||||
#endif
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
@ -139,7 +143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); }
|
||||
};
|
||||
|
||||
// #define __cpp_lib_constexpr_char_traits 201611
|
||||
#define __cpp_lib_constexpr_char_traits 201611
|
||||
|
||||
template<typename _CharT>
|
||||
_GLIBCXX14_CONSTEXPR int
|
||||
|
@ -212,6 +216,42 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
|||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#if __cplusplus > 201402
|
||||
/**
|
||||
* @brief Determine whether the characters of a NULL-terminated
|
||||
* string are known at compile time.
|
||||
* @param __s The string.
|
||||
*
|
||||
* Assumes that _CharT is a built-in character type.
|
||||
*/
|
||||
template<typename _CharT>
|
||||
static _GLIBCXX_ALWAYS_INLINE constexpr bool
|
||||
__constant_string_p(const _CharT* __s)
|
||||
{
|
||||
while (__builtin_constant_p(*__s) && *__s)
|
||||
__s++;
|
||||
return __builtin_constant_p(*__s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine whether the characters of a character array are
|
||||
* known at compile time.
|
||||
* @param __a The character array.
|
||||
* @param __n Number of characters.
|
||||
*
|
||||
* Assumes that _CharT is a built-in character type.
|
||||
*/
|
||||
template<typename _CharT>
|
||||
static _GLIBCXX_ALWAYS_INLINE constexpr bool
|
||||
__constant_char_array_p(const _CharT* __a, size_t __n)
|
||||
{
|
||||
size_t __i = 0;
|
||||
while (__builtin_constant_p(__a[__i]) && __i < __n)
|
||||
__i++;
|
||||
return __i == __n;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 21.1
|
||||
/**
|
||||
* @brief Basis for explicit traits specializations.
|
||||
|
@ -256,21 +296,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
< static_cast<unsigned char>(__c2));
|
||||
}
|
||||
|
||||
static /* _GLIBCXX17_CONSTEXPR */ int
|
||||
static _GLIBCXX17_CONSTEXPR int
|
||||
compare(const char_type* __s1, const char_type* __s2, size_t __n)
|
||||
{
|
||||
#if __cplusplus > 201402
|
||||
if (__builtin_constant_p(__n)
|
||||
&& __constant_char_array_p(__s1, __n)
|
||||
&& __constant_char_array_p(__s2, __n))
|
||||
return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
|
||||
#endif
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
return __builtin_memcmp(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
static /* _GLIBCXX17_CONSTEXPR */ size_t
|
||||
static _GLIBCXX17_CONSTEXPR size_t
|
||||
length(const char_type* __s)
|
||||
{ return __builtin_strlen(__s); }
|
||||
{
|
||||
#if __cplusplus > 201402
|
||||
if (__constant_string_p(__s))
|
||||
return __gnu_cxx::char_traits<char_type>::length(__s);
|
||||
#endif
|
||||
return __builtin_strlen(__s);
|
||||
}
|
||||
|
||||
static /* _GLIBCXX17_CONSTEXPR */ const char_type*
|
||||
static _GLIBCXX17_CONSTEXPR const char_type*
|
||||
find(const char_type* __s, size_t __n, const char_type& __a)
|
||||
{
|
||||
#if __cplusplus > 201402
|
||||
if (__builtin_constant_p(__n)
|
||||
&& __builtin_constant_p(__a)
|
||||
&& __constant_char_array_p(__s, __n))
|
||||
return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
|
||||
#endif
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
|
||||
|
@ -347,24 +405,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
|
||||
{ return __c1 < __c2; }
|
||||
|
||||
static /* _GLIBCXX17_CONSTEXPR */ int
|
||||
static _GLIBCXX17_CONSTEXPR int
|
||||
compare(const char_type* __s1, const char_type* __s2, size_t __n)
|
||||
{
|
||||
#if __cplusplus > 201402
|
||||
if (__builtin_constant_p(__n)
|
||||
&& __constant_char_array_p(__s1, __n)
|
||||
&& __constant_char_array_p(__s2, __n))
|
||||
return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
|
||||
#endif
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
return wmemcmp(__s1, __s2, __n);
|
||||
else
|
||||
return wmemcmp(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
static /* _GLIBCXX17_CONSTEXPR */ size_t
|
||||
static _GLIBCXX17_CONSTEXPR size_t
|
||||
length(const char_type* __s)
|
||||
{ return wcslen(__s); }
|
||||
{
|
||||
#if __cplusplus > 201402
|
||||
if (__constant_string_p(__s))
|
||||
return __gnu_cxx::char_traits<char_type>::length(__s);
|
||||
else
|
||||
#endif
|
||||
return wcslen(__s);
|
||||
}
|
||||
|
||||
static /* _GLIBCXX17_CONSTEXPR */ const char_type*
|
||||
static _GLIBCXX17_CONSTEXPR const char_type*
|
||||
find(const char_type* __s, size_t __n, const char_type& __a)
|
||||
{
|
||||
#if __cplusplus > 201402
|
||||
if (__builtin_constant_p(__n)
|
||||
&& __builtin_constant_p(__a)
|
||||
&& __constant_char_array_p(__s, __n))
|
||||
return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
|
||||
#endif
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
return wmemchr(__s, __a, __n);
|
||||
else
|
||||
return wmemchr(__s, __a, __n);
|
||||
}
|
||||
|
||||
static char_type*
|
||||
|
|
|
@ -74,20 +74,20 @@ template<typename CT>
|
|||
}
|
||||
|
||||
#ifndef __cpp_lib_constexpr_char_traits
|
||||
// #error Feature-test macro for constexpr char_traits is missing
|
||||
# error Feature-test macro for constexpr char_traits is missing
|
||||
#elif __cpp_lib_constexpr_char_traits != 201611
|
||||
// #error Feature-test macro for constexpr char_traits has the wrong value
|
||||
# error Feature-test macro for constexpr char_traits has the wrong value
|
||||
#endif
|
||||
|
||||
static_assert( test_assign<std::char_traits<char>>() );
|
||||
// static_assert( test_compare<std::char_traits<char>>() );
|
||||
// static_assert( test_length<std::char_traits<char>>() );
|
||||
// static_assert( test_find<std::char_traits<char>>() );
|
||||
static_assert( test_compare<std::char_traits<char>>() );
|
||||
static_assert( test_length<std::char_traits<char>>() );
|
||||
static_assert( test_find<std::char_traits<char>>() );
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
static_assert( test_assign<std::char_traits<wchar_t>>() );
|
||||
// static_assert( test_compare<std::char_traits<wchar_t>>() );
|
||||
// static_assert( test_length<std::char_traits<wchar_t>>() );
|
||||
// static_assert( test_find<std::char_traits<wchar_t>>() );
|
||||
static_assert( test_compare<std::char_traits<wchar_t>>() );
|
||||
static_assert( test_length<std::char_traits<wchar_t>>() );
|
||||
static_assert( test_find<std::char_traits<wchar_t>>() );
|
||||
#endif
|
||||
static_assert( test_assign<std::char_traits<char16_t>>() );
|
||||
static_assert( test_compare<std::char_traits<char16_t>>() );
|
||||
|
|
Loading…
Reference in New Issue