From patchwork Tue May 26 19:18:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 1298359 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=lmlJbPpL; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49WkJq2hwMz9shw for ; Wed, 27 May 2020 05:18:34 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DA846394CC08; Tue, 26 May 2020 19:18:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DA846394CC08 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1590520709; bh=R648rJsR6BqxT6hMzkDiGqxX/CyNh/NB0kMVMsS0xqs=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=lmlJbPpL1Ens3lB1CCVbugML+jLUe78LFqTvU9eKWlbNcR5qzkgh+b28faXKQwr0I ttSzXyx7ruB6IAUZhLjKYYd4YZz3INd+8nY9nz1I4NMd1x3/osT/zBnZZIZLqdHMia XlM4wo//pUfJyECDbYuDMbT6nUqI33jrA/jNP/y4= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) by sourceware.org (Postfix) with ESMTP id AD95D389853B for ; Tue, 26 May 2020 19:18:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AD95D389853B Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-268-YwCN_HXhMfS3WrABIUzufQ-1; Tue, 26 May 2020 15:18:23 -0400 X-MC-Unique: YwCN_HXhMfS3WrABIUzufQ-1 Received: by mail-qv1-f71.google.com with SMTP id a7so20728766qvl.2 for ; Tue, 26 May 2020 12:18:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=R648rJsR6BqxT6hMzkDiGqxX/CyNh/NB0kMVMsS0xqs=; b=MLt7QnWlrOyknwBzUK1snbCNwkgrcd1EQ3V9FxHtNRwsBGYeKYZGbZjM4quod4AB1t ++duqW7xLLooqzeFNilznCOJP1AWaYTbBaWbbN0JWr+Tgk7FcpG209lfeKQjrnJy3PwA uSv8gr0zkrHKA5O15DNT4QELY7fN22/frclMp5u31KX2Nh8BctEGl8s+wJ8oBSHVGf1Y D6W5xsA2QO/WJVAK2qqLiZtqutaJJx9PQlVtUZn2yeWUli4DI7vlGyT0ketlvUO6m9y/ WOjWpAYrD/V1MHoEbBR/pLubXS2HwVjNg+uwd/gSiS4sLGQsEJ/RU2lGz5e+W7mmkbtr hcWA== X-Gm-Message-State: AOAM533p3v7oue5lEymGQwnee4zk+9NFcIeBh/k2HLO+Q33Z/1zIExK+ 2Bd8vhL5xz7h+ffWqjao7OCHfHeAthByBkiF03lu4aT9UlkeC9K5nUU6cC9kwVTMAqObS/LUnrG f12I1IjmjEdMD4dhvYg== X-Received: by 2002:a05:6214:aaf:: with SMTP id ew15mr3607450qvb.110.1590520701981; Tue, 26 May 2020 12:18:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxxWypSimhmDz6qqQGAUJVBhNwDTpRrtTr0ZKCFMkl2wjsg+BnKF+MU5/YAjHq+9VxdxRcYWQ== X-Received: by 2002:a05:6214:aaf:: with SMTP id ew15mr3607427qvb.110.1590520701646; Tue, 26 May 2020 12:18:21 -0700 (PDT) Received: from localhost.localdomain (ool-457d493a.dyn.optonline.net. [69.125.73.58]) by smtp.gmail.com with ESMTPSA id n123sm481962qkf.23.2020.05.26.12.18.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 May 2020 12:18:20 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++: Fix common_iterator::operator-> [PR95322] Date: Tue, 26 May 2020 15:18:17 -0400 Message-Id: <20200526191817.3306612-1-ppalka@redhat.com> X-Mailer: git-send-email 2.27.0.rc1.5.gae92ac8ae3 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-17.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_SBL, URIBL_SBL_A autolearn=unavailable autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Patrick Palka via Gcc-patches From: Patrick Palka Reply-To: Patrick Palka Cc: libstdc++@gcc.gnu.org Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This patch fixes the definition of common_iterator::operator-> when the underlying iterator type's operator* returns a non-reference. The first problem is that the class __detail::_Common_iter_proxy is used unqualified. Fixing that revealed another problem: the class's template friend declaration of common_iterator doesn't match up with the definition of common_iterator, because the friend declaration isn't constrained. If we try to make the friend declaration match up by adding constraints, we run into frontend bug PR93467. So we currently can't correctly express this friend relation between __detail::_Common_iter_proxy and common_iterator. As a workaround to this frontend bug, this patch moves the definition of _Common_iter_proxy into the class template of common_iterator so that we could instead express the friend relation via the injected-class-name. (This bug was found when attempting to use views::common to work around the compile failure of the testcase in PR95322.) Tested on x86_64-pc-linux-gnu, does this look OK to commit? libstdc++-v3/ChangeLog: PR libstdc++/95322 * include/bits/stl_iterator.h (__detail::_Common_iter_proxy): Remove and redefine it ... (common_iterator::_Proxy): ... here. (common_iterator::operator->): Use it. * testsuite/24_iterators/common_iterator/95322.cc: New test. * testsuite/std/ranges/adaptors/95322.cc: New test. --- libstdc++-v3/include/bits/stl_iterator.h | 34 +++++----- .../24_iterators/common_iterator/2.cc | 63 +++++++++++++++++++ .../testsuite/std/ranges/adaptors/95322.cc | 50 +++++++++++++++ 3 files changed, 129 insertions(+), 18 deletions(-) create mode 100644 libstdc++-v3/testsuite/24_iterators/common_iterator/2.cc create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/95322.cc diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index fdb1121f823..19b1d53f781 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1568,23 +1568,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __detail { - template - class _Common_iter_proxy - { - iter_value_t<_It> _M_keep; - - _Common_iter_proxy(iter_reference_t<_It>&& __x) - : _M_keep(std::move(__x)) { } - - template - friend class common_iterator; - - public: - const iter_value_t<_It>* - operator->() const - { return std::__addressof(_M_keep); } - }; - template concept __common_iter_has_arrow = indirectly_readable && (requires(const _It& __it) { __it.operator->(); } @@ -1613,6 +1596,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_noexcept() { return _S_noexcept1<_It, _It2>() && _S_noexcept1<_Sent, _Sent2>(); } + class _Proxy + { + iter_value_t<_It> _M_keep; + + _Proxy(iter_reference_t<_It>&& __x) + : _M_keep(std::move(__x)) { } + + friend class common_iterator; + + public: + const iter_value_t<_It>* + operator->() const + { return std::__addressof(_M_keep); } + }; + public: constexpr common_iterator() @@ -1769,7 +1767,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::__addressof(__tmp); } else - return _Common_iter_proxy(*_M_it); + return _Proxy{*_M_it}; } common_iterator& diff --git a/libstdc++-v3/testsuite/24_iterators/common_iterator/2.cc b/libstdc++-v3/testsuite/24_iterators/common_iterator/2.cc new file mode 100644 index 00000000000..270e8eaa91c --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/common_iterator/2.cc @@ -0,0 +1,63 @@ +// Copyright (C) 2020 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +struct value { int n; }; + +struct sentinel { int limit; }; + +struct iterator +{ + using iterator_category = std::input_iterator_tag; + using value_type = value; + using difference_type = std::ptrdiff_t; + using reference = value; + + value operator*() const { return value{counter}; } + + iterator& operator++() { ++counter; return *this; } + + iterator operator++(int) { auto i = *this; ++counter; return i; } + + bool operator==(sentinel s) const { return counter == s.limit; } + + int counter = 0; +}; + +void +test01() +{ + iterator i; + sentinel s{2}; + std::common_iterator begin = i, end = s; + VERIFY( begin->n == 0 ); + ++begin; + VERIFY( begin->n == 1 ); + ++begin; + VERIFY( begin == end ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/95322.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/95322.cc new file mode 100644 index 00000000000..44619d6719a --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/95322.cc @@ -0,0 +1,50 @@ +// Copyright (C) 2020 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +void +test01() +{ + std::list container{1, 2, 3, 4, 5}; + auto v = (container + | views::take(3) + | views::transform(std::negate{}) + | views::common); + auto i = ranges::cbegin(v); + VERIFY( *i == -1 ); + ++i; + VERIFY( *i == -2 ); + ++i; + VERIFY( *i == -3 ); + ++i; + VERIFY( i == ranges::end(v) ); +} + +int +main() +{ + test01(); +}