From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 105864 invoked by alias); 23 Apr 2017 17:55:09 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 105795 invoked by uid 89); 23 Apr 2017 17:55:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.6 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.2 spammy=farm, recommendations, 29639, 2126 X-HELO: mail-wm0-f51.google.com Received: from mail-wm0-f51.google.com (HELO mail-wm0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 23 Apr 2017 17:54:58 +0000 Received: by mail-wm0-f51.google.com with SMTP id u65so7896311wmu.1 for ; Sun, 23 Apr 2017 10:54:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding; bh=vj8JnCZmV+JEuVywf9z1kED3jfDukSzzU0L2dji7Jz0=; b=ucgvDlhAOC+zB2XcHl7ffvK0O1vO2mcbTX3zBVGyxlrWswRuOnY3Nxfhz2No8PVnp0 iJOPlH8yW8Nweoay3od5XS7McavPp8iWGRifDPVggm4g07FEMf3fE55Nh9fPXWV+2hsI huHO83oHMOTM56shJNo3B415sESqBDN/eSBySi03hwJK54j5CQkgh9TUT/rDBpGAFBjJ xW/bODGIIqEQsKv41LsjH3EuhUwrAayu7p9TILU1j8KWaxN5sRhy5Bp1XzuWn+mgWQEo 6Gu5TnwZZoCNW0RgOZUBYl+jW0mA6zcChKQcwfNuQ1LYD8XNZyUppvpwg4075TRNSzQb CkTw== X-Gm-Message-State: AN3rC/7b1uDWiJkhpQoYBOQmIkEIAkqZcbs26ThEy8V/8VRXkM6OZ82R XaKSFrUD5E70B7UzqUBL3w== X-Received: by 10.28.94.194 with SMTP id s185mr6567739wmb.103.1492970097700; Sun, 23 Apr 2017 10:54:57 -0700 (PDT) Received: from [192.168.0.102] ([37.189.166.198]) by smtp.gmail.com with ESMTPSA id 75sm10936989wmp.2.2017.04.23.10.54.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 23 Apr 2017 10:54:56 -0700 (PDT) To: Jonathan Wakely , libstdc++@gcc.gnu.org, "gcc-patches@gcc.gnu.org" From: Pedro Alves Subject: [PATCH] Finish implementing P0426R1 "Constexpr for std::char_traits" for C++17 Message-ID: <0867f2ad-1381-fdda-2f03-2fdbd450faed@redhat.com> Date: Sun, 23 Apr 2017 18:54:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-SW-Source: 2017-04/txt/msg00985.txt.bz2 Hi! As I had suggested in PR c++/80265, here's a patch that uses __builtin_constant_p to tell whether we can defer to a constexpr algorithm, which avoids having to wait for compiler support. Unfortunately I ran out of cycles today to run a full bootstrap/regtest cycle, but constexpr_functions_c++17.cc passes cleanly on x86_64 GNU/Linux at least. If this looks like a reasonable approach, I can maybe try running full tests on the gcc compile farm next week. WDYT? Thanks, Pedro Alves >From 91606ca1f51309121e292559bcb6b2cfc126737b Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Sun, 23 Apr 2017 14:16:09 +0100 Subject: [PATCH] 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-04-23 Pedro Alves * 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, std::char_traits): Add _GLIBCXX17_CONSTEXPR on compare, length, find and assign 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, test_length, test_find, test_compare, test_length and test_find static_assert tests. --- libstdc++-v3/doc/xml/manual/status_cxx2017.xml | 4 +- libstdc++-v3/include/bits/char_traits.h | 120 ++++++++++++++++++--- .../requirements/constexpr_functions_c++17.cc | 16 +-- 3 files changed, 116 insertions(+), 24 deletions(-) diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml index 0e35f75..fed91f9 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml @@ -489,8 +489,8 @@ Feature-testing recommendations for C++. P0426R1 - 7 (partial) - ??? + 7 + __cpp_lib_constexpr_char_traits >= 201611 diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 75db5b8..cc636a9 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -40,6 +40,10 @@ #include // For streampos #include // 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 _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 + 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 + 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(__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::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::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::find(__s, __n, __a); +#endif if (__n == 0) return 0; return static_cast(__builtin_memchr(__s, __a, __n)); @@ -292,9 +350,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return static_cast(__builtin_memcpy(__s1, __s2, __n)); } - static char_type* + static _GLIBCXX17_CONSTEXPR char_type* assign(char_type* __s, size_t __n, char_type __a) { +#if __cplusplus > 201402 + if (__constant_string_p(__s) + && __builtin_constant_p(__n) + && __builtin_constant_p(__a)) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif if (__n == 0) return __s; return static_cast(__builtin_memset(__s, __a, __n)); @@ -347,24 +411,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::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::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::find(__s, __n, __a); +#endif if (__n == 0) return 0; - return wmemchr(__s, __a, __n); + else + return wmemchr(__s, __a, __n); } static char_type* @@ -383,12 +468,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return wmemcpy(__s1, __s2, __n); } - static char_type* + static _GLIBCXX17_CONSTEXPR char_type* assign(char_type* __s, size_t __n, char_type __a) { +#if __cplusplus > 201402 + if (__constant_string_p(__s) + && __builtin_constant_p(__n) + && __builtin_constant_p(__a)) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif if (__n == 0) return __s; - return wmemset(__s, __a, __n); + else + return wmemset(__s, __a, __n); } static _GLIBCXX_CONSTEXPR char_type 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 index 014caa0..efd280f 100644 --- 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 @@ -74,20 +74,20 @@ template } #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>() ); -// static_assert( test_compare>() ); -// static_assert( test_length>() ); -// static_assert( test_find>() ); +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>() ); +static_assert( test_compare>() ); +static_assert( test_length>() ); +static_assert( test_find>() ); #endif static_assert( test_assign>() ); static_assert( test_compare>() ); -- 2.5.5