From patchwork Mon Aug 20 20:26:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Fran=C3=A7ois_Dumont?= X-Patchwork-Id: 959954 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-484012-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="g+ZWHM8W"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="TWaT102u"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41vQMC2wRGz9s47 for ; Tue, 21 Aug 2018 06:26:42 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=bW7DP6Ac6y2EWv5i/OH8AGUJkN00GfL+m8hU+0gx4J4YKOLdsEe0g i/hxsRi+xXVHhrkcyPOmm27t6jPLxJkpoZEfFylUyKlF2u4c1L1j+/Fb0uUYtWl1 XkxATyTIZYYWMcdT0l3kBO9/aMiM8QaR3SP1AKVafVdWy48Aa39KqQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=S4J+pYMUPmXySOmz2yMxRHtSplU=; b=g+ZWHM8WRZiqpB+PxDax 5mEIKJ8v3lCLUcnOYJuTsJ2D0L4DNwy7WkTNlwemKB++MSK2RjqjSW3JM+AdSp3a fW+99qDQCzlwt3na0PKfVqGimOVpR8gvLEv1zbmCJKyeWlysa2QA5q5x968EzGUk 1eb1c88+SYYWYsBKyKkbjpk= Received: (qmail 77830 invoked by alias); 20 Aug 2018 20:26:34 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 77772 invoked by uid 89); 20 Aug 2018 20:26:33 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=algorithms X-HELO: mail-wr1-f45.google.com Received: from mail-wr1-f45.google.com (HELO mail-wr1-f45.google.com) (209.85.221.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 20 Aug 2018 20:26:31 +0000 Received: by mail-wr1-f45.google.com with SMTP id e7-v6so13996498wrs.9; Mon, 20 Aug 2018 13:26:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:subject:to:message-id:date:user-agent:mime-version :content-language; bh=1gQmKlXDHSPZrGCfp5YpEGyBkODWee6svjJrihmJ+pQ=; b=TWaT102uVouhGK1/bCAwLebS2/Lw6VCsi45IaSOTRoETurJQHrwc1wYKvU/anRCnqM tQ1MakzAinDnXpZh5/BOHWJpKiOHCKYHEvIOSXDedxV+PCy6oxrR8CMqLQWmJWwyo6vG LQ2GMeM4YpZY7DwGqmsPVqPsMjFT63+Fnnx/qc6hpVYYMZ85A9ape9K2KFSXEv8QnQjp S+4WmRKW4huwdAfspll9WsYMjmQMHaWPdjqpn8l3CWaCsOFj+lWwa1DRRqEbt1mtduw1 vVbDiRcV7BJ8ECIX94GtZzNwXo6hzgfPoPjVslnBqvLA2YQ3nzv3LKLXDw3pJXUxhir+ ky2A== Received: from [192.168.0.23] (arf62-1-82-237-250-248.fbx.proxad.net. [82.237.250.248]) by smtp.googlemail.com with ESMTPSA id h7-v6sm1163049wrs.3.2018.08.20.13.26.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Aug 2018 13:26:28 -0700 (PDT) From: =?utf-8?q?Fran=C3=A7ois_Dumont?= Subject: P0646R1 for Debug mode To: "libstdc++@gcc.gnu.org" , gcc-patches Message-ID: <70fc4895-52c8-9f0e-6922-920babb27f83@gmail.com> Date: Mon, 20 Aug 2018 22:26:27 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 This patch implements P0646R1 for Debug mode containers. It fixes tests: 23_containers/forward_list/operations/remove_cxx20_return.cc 23_containers/forward_list/operations/unique_cxx20_return.cc 23_containers/list/operations/remove_cxx20_return.cc 23_containers/list/operations/unique_cxx20_return.cc Note that it also adopt the Lib Defects 526 which had been implemented only for the normal mode. I'll commit this tomorrow if not told otherwise.     P0646R1 Improving the Return Value of Erase-Like Algorithms I     * include/debug/forward_list (forward_list::__remove_return_type):     Define typedef as size_type or void, according to __cplusplus value.     (_GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG): Define macro as abi-tag or     empty, according to __cplusplus value.     (_GLIBCXX20_ONLY): Define macro.     (forward_list::remove, forward_list::unique): Use typedef and macro     to change return type and add abi-tag for C++2a. Return number of     removed elements for C++2a.     (forward_list::remove_if, forward_list::unique): Use     typedef to change return type for C++2a. Return number of removed     elements for C++2a.     * include/debug/list (list::__remove_return_type): Define typedef as     size_type or void, according to __cplusplus value.     (_GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG): Define macro as abi-tag or     empty, according to __cplusplus value.     (_GLIBCXX20_ONLY): Define macro.     (list::remove, list::unique): Use typedef and macro to change return     type and add abi-tag for C++2a. Return number of removed elements for     C++2a.     (list::remove_if, list::unique): Use typedef     to change return type for C++2a. Return number of removed elements for     C++2a. François diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list index e5ac09e8..2340962 100644 --- a/libstdc++-v3/include/debug/forward_list +++ b/libstdc++-v3/include/debug/forward_list @@ -656,70 +656,114 @@ namespace __debug const_iterator __before, const_iterator __last) { splice_after(__pos, std::move(__list), __before, __last); } - void + private: +#if __cplusplus > 201703L +# define __cpp_lib_list_remove_return_type 201806L + using __remove_return_type = size_type; +# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG \ + __attribute__((__abi_tag__("__cxx20"))) +# define _GLIBCXX20_ONLY(__expr) __expr +#else + using __remove_return_type = void; +# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG +# define _GLIBCXX20_ONLY(__expr) +#endif + + public: + _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type remove(const _Tp& __val) { + if (!this->_M_iterators && !this->_M_const_iterators) + return _Base::remove(__val); + + size_type __removed __attribute__((__unused__)) = 0; _Base_iterator __x = _Base::before_begin(); _Base_iterator __old = __x++; + _Base_iterator __extra = _Base::end(); while (__x != _Base::end()) { if (*__x == __val) - __x = _M_erase_after(__old); - else - __old = __x++; + { + if (std::__addressof(*__x) != std::__addressof(__val)) + { + __x = _M_erase_after(__old); + _GLIBCXX20_ONLY( __removed++ ); + continue; + } + else + __extra = __old; + } + __old = __x++; } + + if (__extra != _Base::end()) + { + this->_M_erase_after(__extra); + _GLIBCXX20_ONLY( __removed++ ); + } + + return _GLIBCXX20_ONLY( __removed ); } template - void + __remove_return_type remove_if(_Pred __pred) { + if (!this->_M_iterators && !this->_M_const_iterators) + return _Base::remove_if(__pred); + + size_type __removed __attribute__((__unused__)) = 0; _Base_iterator __x = _Base::before_begin(); _Base_iterator __old = __x++; while (__x != _Base::end()) - { - if (__pred(*__x)) + if (__pred(*__x)) + { __x = _M_erase_after(__old); - else - __old = __x++; - } + _GLIBCXX20_ONLY( __removed++ ); + } + else + __old = __x++; + + return _GLIBCXX20_ONLY( __removed ); } - void + _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type unique() - { - _Base_iterator __first = _Base::begin(); - _Base_iterator __last = _Base::end(); - if (__first == __last) - return; - _Base_iterator __next = std::next(__first); - while (__next != __last) - { - if (*__first == *__next) - __next = _M_erase_after(__first); - else - __first = __next++; - } - } + { return unique(std::equal_to<_Tp>()); } template - void + __remove_return_type unique(_BinPred __binary_pred) { + if (!this->_M_iterators && !this->_M_const_iterators) + return _Base::unique(__binary_pred); + _Base_iterator __first = _Base::begin(); _Base_iterator __last = _Base::end(); if (__first == __last) - return; + return _GLIBCXX20_ONLY(0); + + size_type __removed __attribute__((__unused__)) = 0; _Base_iterator __next = std::next(__first); while (__next != __last) { if (__binary_pred(*__first, *__next)) - __next = _M_erase_after(__first); + { + __next = _M_erase_after(__first); + _GLIBCXX20_ONLY( __removed++ ); + } else __first = __next++; } + + return _GLIBCXX20_ONLY( __removed ); } +#undef _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG +#undef _GLIBCXX20_ONLY + void merge(forward_list&& __list) { diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list index c6aea5d..5b3b88e 100644 --- a/libstdc++-v3/include/debug/list +++ b/libstdc++-v3/include/debug/list @@ -655,66 +655,135 @@ namespace __debug { splice(__position, std::move(__x), __first, __last); } #endif - void + private: +#if __cplusplus > 201703L + typedef size_type __remove_return_type; +# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG \ + __attribute__((__abi_tag__("__cxx20"))) +# define _GLIBCXX20_ONLY(__expr) __expr +#else + typedef void __remove_return_type; +# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG +# define _GLIBCXX20_ONLY(__expr) +#endif + + public: + _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type remove(const _Tp& __value) { - for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) + if (!this->_M_iterators && !this->_M_const_iterators) + return _Base::remove(__value); + + size_type __removed __attribute__((__unused__)) = 0; + _Base_iterator __first = _Base::begin(); + _Base_iterator __last = _Base::end(); + _Base_iterator __extra = __last; + while (__first != __last) { - if (*__x == __value) - __x = _M_erase(__x); + if (*__first == __value) + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 526. Is it undefined if a function in the standard changes + // in parameters? + if (std::__addressof(*__first) != std::__addressof(__value)) + { + __first = _M_erase(__first); + _GLIBCXX20_ONLY( __removed++ ); + } + else + { + __extra = __first; + ++__first; + } else - ++__x; + ++__first; } + + if (__extra != __last) + { + _M_erase(__extra); + _GLIBCXX20_ONLY( __removed++ ); + } + return _GLIBCXX20_ONLY( __removed ); } template - void + __remove_return_type remove_if(_Predicate __pred) { + if (!this->_M_iterators && !this->_M_const_iterators) + return _Base::remove_if(__pred); + + size_type __removed __attribute__((__unused__)) = 0; for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) - { - if (__pred(*__x)) + if (__pred(*__x)) + { __x = _M_erase(__x); - else - ++__x; - } + _GLIBCXX20_ONLY( __removed++ ); + } + else + ++__x; + + return _GLIBCXX20_ONLY( __removed ); } - void + _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type unique() { + if (!this->_M_iterators && !this->_M_const_iterators) + return _Base::unique(); + + if (empty()) + return _GLIBCXX20_ONLY(0); + + size_type __removed __attribute__((__unused__)) = 0; _Base_iterator __first = _Base::begin(); _Base_iterator __last = _Base::end(); - if (__first == __last) - return; - _Base_iterator __next = __first; ++__next; - while (__next != __last) - { - if (*__first == *__next) - __next = _M_erase(__next); - else - __first = __next++; - } + _Base_iterator __next = __first; + while (++__next != __last) + if (*__first == *__next) + { + _M_erase(__next); + __next = __first; + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + + return _GLIBCXX20_ONLY( __removed ); } template - void + __remove_return_type unique(_BinaryPredicate __binary_pred) { + if (!this->_M_iterators && !this->_M_const_iterators) + return _Base::unique(__binary_pred); + + if (empty()) + return _GLIBCXX20_ONLY(0); + + size_type __removed __attribute__((__unused__)) = 0; _Base_iterator __first = _Base::begin(); _Base_iterator __last = _Base::end(); - if (__first == __last) - return; - _Base_iterator __next = __first; ++__next; - while (__next != __last) - { - if (__binary_pred(*__first, *__next)) - __next = _M_erase(__next); - else - __first = __next++; - } + _Base_iterator __next = __first;; + while (++__next != __last) + if (__binary_pred(*__first, *__next)) + { + _M_erase(__next); + __next = __first; + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + + return _GLIBCXX20_ONLY( __removed ); } +#undef _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG +#undef _GLIBCXX20_ONLY + void #if __cplusplus >= 201103L merge(list&& __x)