From 8c3b5c719f4c837122402f8707cb89b677ee3869 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 3 Apr 2017 18:15:53 +0100 Subject: [PATCH] Implement P0426R1 "Constexpr for std::char_traits" for C++17 (partial) * include/bits/char_traits.h (__gnu_cxx::char_traits): Add _GLIBCXX14_CONSTEXPR on assign, compare, find, and length. (std::char_traits, std::char_traits): Add _GLIBCXX17_CONSTEXPR on assign. (std::char_traits, std::char_traits): Add _GLIBCXX17_CONSTEXPR on assign, compare, find, and length. * testsuite/21_strings/char_traits/requirements/ constexpr_functions_c++17.cc: New test. From-SVN: r246655 --- libstdc++-v3/ChangeLog | 11 ++ libstdc++-v3/include/bits/char_traits.h | 48 ++++---- .../requirements/constexpr_functions_c++17.cc | 107 ++++++++++++++++++ 3 files changed, 143 insertions(+), 23 deletions(-) create mode 100644 libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4073a82e2a3..caad393416e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2017-04-03 Jonathan Wakely + + * include/bits/char_traits.h (__gnu_cxx::char_traits): Add + _GLIBCXX14_CONSTEXPR on assign, compare, find, and length. + (std::char_traits, std::char_traits): Add + _GLIBCXX17_CONSTEXPR on assign. + (std::char_traits, std::char_traits): Add + _GLIBCXX17_CONSTEXPR on assign, compare, find, and length. + * testsuite/21_strings/char_traits/requirements/ + constexpr_functions_c++17.cc: New test. + 2017-04-03 Ville Voutilainen PR libstdc++/79141 diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index bcfc23a93b8..75db5b89321 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -88,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename _Char_types<_CharT>::off_type off_type; typedef typename _Char_types<_CharT>::state_type state_type; - static void + static _GLIBCXX14_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) { __c1 = __c2; } @@ -100,13 +100,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) { return __c1 < __c2; } - static int + static _GLIBCXX14_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, std::size_t __n); - static std::size_t + static _GLIBCXX14_CONSTEXPR std::size_t length(const char_type* __s); - static const char_type* + static _GLIBCXX14_CONSTEXPR const char_type* find(const char_type* __s, std::size_t __n, const char_type& __a); static char_type* @@ -139,8 +139,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } }; +// #define __cpp_lib_constexpr_char_traits 201611 + template - int + _GLIBCXX14_CONSTEXPR int char_traits<_CharT>:: compare(const char_type* __s1, const char_type* __s2, std::size_t __n) { @@ -153,7 +155,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - std::size_t + _GLIBCXX14_CONSTEXPR std::size_t char_traits<_CharT>:: length(const char_type* __p) { @@ -164,7 +166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - const typename char_traits<_CharT>::char_type* + _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* char_traits<_CharT>:: find(const char_type* __s, std::size_t __n, const char_type& __a) { @@ -238,7 +240,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef streamoff off_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT { __c1 = __c2; } @@ -254,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION < static_cast(__c2)); } - static int + static /* _GLIBCXX17_CONSTEXPR */ int compare(const char_type* __s1, const char_type* __s2, size_t __n) { if (__n == 0) @@ -262,11 +264,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __builtin_memcmp(__s1, __s2, __n); } - static size_t + static /* _GLIBCXX17_CONSTEXPR */ size_t length(const char_type* __s) { return __builtin_strlen(__s); } - static const char_type* + static /* _GLIBCXX17_CONSTEXPR */ const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { if (__n == 0) @@ -333,7 +335,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef wstreampos pos_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT { __c1 = __c2; } @@ -345,7 +347,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT { return __c1 < __c2; } - static int + static /* _GLIBCXX17_CONSTEXPR */ int compare(const char_type* __s1, const char_type* __s2, size_t __n) { if (__n == 0) @@ -353,11 +355,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return wmemcmp(__s1, __s2, __n); } - static size_t + static /* _GLIBCXX17_CONSTEXPR */ size_t length(const char_type* __s) { return wcslen(__s); } - static const char_type* + static /* _GLIBCXX17_CONSTEXPR */ const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { if (__n == 0) @@ -432,7 +434,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef u16streampos pos_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) noexcept { __c1 = __c2; } @@ -444,7 +446,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) noexcept { return __c1 < __c2; } - static int + static _GLIBCXX17_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, size_t __n) { for (size_t __i = 0; __i < __n; ++__i) @@ -455,7 +457,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return 0; } - static size_t + static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) { size_t __i = 0; @@ -464,7 +466,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __i; } - static const char_type* + static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { for (size_t __i = 0; __i < __n; ++__i) @@ -529,7 +531,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef u32streampos pos_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) noexcept { __c1 = __c2; } @@ -541,7 +543,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) noexcept { return __c1 < __c2; } - static int + static _GLIBCXX17_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, size_t __n) { for (size_t __i = 0; __i < __n; ++__i) @@ -552,7 +554,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return 0; } - static size_t + static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) { size_t __i = 0; @@ -561,7 +563,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __i; } - static const char_type* + static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { for (size_t __i = 0; __i < __n; ++__i) diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc new file mode 100644 index 00000000000..014caa02313 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc @@ -0,0 +1,107 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++1z } } + +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +template + constexpr bool + test_assign() + { + using char_type = typename CT::char_type; + char_type s1[2] = {}; + const char_type s2[2] = {1, 0}; + CT::assign(s1[0], s2[0]); + return s1[0] == char_type{1}; + } + +template + constexpr bool + test_compare() + { + using char_type = typename CT::char_type; + const char_type s1[3] = {1, 2, 3}; + const char_type s2[3] = {1, 2, 3}; + if (CT::compare(s1, s2, 3) != 0) + return false; + if (CT::compare(s2, s1, 3) != 0) + return false; + if (CT::compare(s1+1, s2, 2) <= 0) + return false; + return true; + } + +template + constexpr bool + test_length() + { + using char_type = typename CT::char_type; + const char_type s1[4] = {1, 2, 3, 0}; + if (CT::length(s1) != 3) + return false; + if (CT::length(s1+1) != 2) + return false; + return true; + } + +template + constexpr bool + test_find() + { + using char_type = typename CT::char_type; + const char_type s1[3] = {1, 2, 3}; + if (CT::find(s1, 3, char_type{2}) != s1+1) + return false; + if (CT::find(s1, 3, char_type{4}) != nullptr) + return false; + return true; + } + +#ifndef __cpp_lib_constexpr_char_traits +// #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 +#endif + +static_assert( test_assign>() ); +// static_assert( test_compare>() ); +// static_assert( test_length>() ); +// static_assert( test_find>() ); +#ifdef _GLIBCXX_USE_WCHAR_T +static_assert( test_assign>() ); +// static_assert( test_compare>() ); +// static_assert( test_length>() ); +// static_assert( test_find>() ); +#endif +static_assert( test_assign>() ); +static_assert( test_compare>() ); +static_assert( test_length>() ); +static_assert( test_find>() ); +static_assert( test_assign>() ); +static_assert( test_compare>() ); +static_assert( test_length>() ); +static_assert( test_find>() ); + +struct C { unsigned char c; }; +constexpr bool operator==(const C& c1, const C& c2) { return c1.c == c2.c; } +constexpr bool operator<(const C& c1, const C& c2) { return c1.c < c2.c; } +static_assert( test_assign>() ); +static_assert( test_compare>() ); +static_assert( test_length>() ); +static_assert( test_find>() ); -- 2.30.2