get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2218238/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2218238,
    "url": "http://patchwork.ozlabs.org/api/patches/2218238/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260331184249.2895803-1-ppalka@redhat.com/",
    "project": {
        "id": 17,
        "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api",
        "name": "GNU Compiler Collection",
        "link_name": "gcc",
        "list_id": "gcc-patches.gcc.gnu.org",
        "list_email": "gcc-patches@gcc.gnu.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260331184249.2895803-1-ppalka@redhat.com>",
    "list_archive_url": null,
    "date": "2026-03-31T18:42:48",
    "name": "[1/2] libstdc++: Implement P3725R3 Filter View Extensions for Safer Use",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "239c71a3c3ae623967c7256e9c5ab290c566e2ea",
    "submitter": {
        "id": 78319,
        "url": "http://patchwork.ozlabs.org/api/people/78319/?format=api",
        "name": "Patrick Palka",
        "email": "ppalka@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260331184249.2895803-1-ppalka@redhat.com/mbox/",
    "series": [
        {
            "id": 498240,
            "url": "http://patchwork.ozlabs.org/api/series/498240/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=498240",
            "date": "2026-03-31T18:42:49",
            "name": "[1/2] libstdc++: Implement P3725R3 Filter View Extensions for Safer Use",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/498240/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2218238/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218238/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=BeK3fknl;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=BeK3fknl",
            "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com",
            "sourceware.org; spf=pass smtp.mailfrom=redhat.com",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4flcWV5SMjz1y1q\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 01 Apr 2026 05:45:42 +1100 (AEDT)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 963A84B7A1E0\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 18:45:40 +0000 (GMT)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 9D7FE4B92097\n for <gcc-patches@gcc.gnu.org>; Tue, 31 Mar 2026 18:42:58 +0000 (GMT)",
            "from mail-qv1-f71.google.com (mail-qv1-f71.google.com\n [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-442-hH7QFOBMMIeNJ06eJHglng-1; Tue, 31 Mar 2026 14:42:56 -0400",
            "by mail-qv1-f71.google.com with SMTP id\n 6a1803df08f44-895375da74bso20737486d6.0\n for <gcc-patches@gcc.gnu.org>; Tue, 31 Mar 2026 11:42:55 -0700 (PDT)",
            "from idea ([2600:4040:aa66:bf00:9e8e:99ff:fed1:71f])\n by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-89ecfd520a6sm90371606d6.41.2026.03.31.11.42.52\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 31 Mar 2026 11:42:52 -0700 (PDT)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 963A84B7A1E0",
            "OpenDKIM Filter v2.11.0 sourceware.org 9D7FE4B92097"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 9D7FE4B92097",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 9D7FE4B92097",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774982578; cv=none;\n b=eK/LWHsoK1FrrafiZ1wMerrWKni3wa3BbXIUtyEYJu2GFLusZ5CqMSHE1vPu4YinnbFpjmzpnvQV/Scfb/Y26obZlytNqcmlD5lwMMIzrpfzZZ07NS4r20u8zeEU/GQ+2iGBbYL6r7OduEWQLMJqZbqsUpN5ByJtgq9F6qxONAo=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774982578; c=relaxed/simple;\n bh=Eoo0cA15Kjuy5+djawpVa3FV/hF0uzdLKue7hjDMSww=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=cllJqYHoqO+cTmusXwRuSJ2KXswOYsPmbjbL5kDFgjfgJT3PBslVBnFtLsbwk8WY/nne+qtVivjHKeKPM1nGgbQDW9F0Lnso4ITzIJDcjijPd1N4Zs4WTMdjG5L3K64iV2N/56LubaIDgXB3uK0gr3HiBl89PaVvLmFWUMgSnrA=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1774982578;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding;\n bh=AvzZVRRsJUv+7nF8+JptbargAnlzDAeMLnQPJcImSwI=;\n b=BeK3fknlB0PEZhrgFLKzP32G+lBSKQU8VGNrUL1+98eXPIaidWgXOHibVChvHcpd3V+lhH\n w26zvm5D89DaAQMdNKzAMOPsPDnYTIahyDiX1VT+h0kPjwpqxkFpfv6jL3YNFOYeh6Nzpm\n 2fph9QvFkn4phfwAFCz6m9uS6aGYOws=",
        "X-MC-Unique": "hH7QFOBMMIeNJ06eJHglng-1",
        "X-Mimecast-MFC-AGG-ID": "hH7QFOBMMIeNJ06eJHglng_1774982575",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1774982575; x=1775587375;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=AvzZVRRsJUv+7nF8+JptbargAnlzDAeMLnQPJcImSwI=;\n b=Kucm3mj9BENPgOz9wphEMOowRQESF39a9y9HzyuRqu+JbGrgEvewBwSUsucEPkBVC+\n bzTnAhBrnKQf4sQ1B6B7JgsAHeCMtsRVTRC87AXgCMHfcsUDGS03EWNZ9SkGJVud8Zs9\n jvh1yxZ6SXLlAaTm0yGT/XTx2/8DbHByleNucoKYI8gIgWxubJV9QBm7gdr9GzTpNo3i\n ObKRJ+ASDvWRsavUGexireTH44FoEgX/Qkwy6LMQxFecXAKRmgIvH8Yy7/t/hf9qXYGg\n tuFRa7m6zFVPvnlzUTNIHGzlEmzWNGs5a6LZsFOwtuyXHyx5hFHg1K8EQRrIzw1ipq01\n QBXQ==",
        "X-Gm-Message-State": "AOJu0Yzdh/8IAb8oIFZsaTffO719Jf+5FzMr/YRF04reSGw1Rcp64We1\n 7kFR6nwt54N0crMpu4X5HVEQP8Nk6dZ6KIpF7q/zfQR0HdEQ6eJpz2Ndq+vxzcF+5nFqDjw3rJa\n RiqLNG74/0HXmJaYs07wVxGej43M1xViKVBR8WhNFO96tyrth0f1rZdOolGMlymfqRNF/je2pbv\n uUZOX8jiSsJtTWC/EfYp8og/nbDCrxVF8IgQiB8UOH",
        "X-Gm-Gg": "ATEYQzyopLBph733oSlsbful1KFOZguz+lMApAUd5scs4HKpPSgQp0lqjk3ujAk781/\n 8vDiyP0ZAYxDH7l53Mh/08qQQPWOjtjQVZVIaOh0q5mDbCuiN47ZNiyhbg3NZmRKJWTBDPFYahI\n Z7OWhiOUG7QARKOIvSAh1SGQ/x+GpVzu9XfRDj3TGOdVzBf+xlOfDRh+8Qoe/aY3COYMiPUusib\n 7fUclxN94rwl3fW3WOp702YkwADHs2KVgH2J0Y0k+SAG7XZBEbEYwQfhLGjqjrcBNDRspm7VoCW\n Xl7jvz31XpBxtVnu/8E9RIxV3SiB2hnHiA6+C3vcan7ompQ37k1lyNMgBbsilwWs37N2DL2OaeD\n rcFOItpLrad5M",
        "X-Received": [
            "by 2002:a05:6214:2b08:b0:89c:c7ee:fe96 with SMTP id\n 6a1803df08f44-8a43af36f2bmr7264496d6.8.1774982574350;\n Tue, 31 Mar 2026 11:42:54 -0700 (PDT)",
            "by 2002:a05:6214:2b08:b0:89c:c7ee:fe96 with SMTP id\n 6a1803df08f44-8a43af36f2bmr7263916d6.8.1774982573675;\n Tue, 31 Mar 2026 11:42:53 -0700 (PDT)"
        ],
        "From": "Patrick Palka <ppalka@redhat.com>",
        "To": "gcc-patches@gcc.gnu.org",
        "Cc": "libstdc++@gcc.gnu.org,\n\tPatrick Palka <ppalka@redhat.com>",
        "Subject": "[PATCH 1/2] libstdc++: Implement P3725R3 Filter View Extensions for\n Safer Use",
        "Date": "Tue, 31 Mar 2026 14:42:48 -0400",
        "Message-ID": "<20260331184249.2895803-1-ppalka@redhat.com>",
        "X-Mailer": "git-send-email 2.53.0.764.g270e10ad6d",
        "MIME-Version": "1.0",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "8pzVXHX148kebgId5DQpli7gXUcZqsNpekNEN5kHm2g_1774982575",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Transfer-Encoding": "8bit",
        "content-type": "text/plain; charset=\"US-ASCII\"; x-default=true",
        "X-BeenThere": "gcc-patches@gcc.gnu.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>",
        "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>",
        "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>",
        "List-Post": "<mailto:gcc-patches@gcc.gnu.org>",
        "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>",
        "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>",
        "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"
    },
    "content": "Tested on x86_64-pc-linux-gnu, does this look OK for trunk and\neventually backports?\n\n-- >8 --\n\nThis implements the recently approved C++26 paper P3725R3, which\nwe treat as a Defect Report against C++20.\n\nlibstdc++-v3/ChangeLog:\n\n\t* include/bits/version.def (ranges_filter): Define for C++20.\n\t* include/bits/version.h: Regenerate.\n\t* include/std/ranges: Provide __cpp_lib_ranges_filter.\n\t(filter_view::_Iterator): Add _Const template parameter.\n\t(filter_view::_Iterator::_S_iter_concept): Return\n\tinput_iterator_tag if _Const.\n\t(filter_view::_Iterator::_Parent): New.\n\t(filter_view::_Iterator::_Base): New.\n\t(filter_view::_Iterator::_Vp_iter): Replace with ...\n\t(filter_view::_Iterator::_Base_iter): ... this.\n\t(filter_view::_Iterator::_M_current): Adjust to consider _Const.\n\t(filter_view::_Iterator::_M_parent): Likewise.\n\t(filter_view::_Iterator::value_type): Likewise.\n\t(filter_view::_Iterator::difference_type): Likewise.\n\t(filter_view::_Iterator::_Iterator): Likewise.  Add\n\tconst-converting overload.\n\t(filter_view::_Iterator::base): Adjust to consider _Const.\n\t(filter_view::_Iterator::operator*): Likewise.\n\t(filter_view::_Iterator::operator->): Likewise.\n\t(filter_view::_Iterator::operator++): Likewise.\n\t(filter_view::_Iterator::operator--): Likewise.\n\t(filter_view::_Iterator::iter_move): Likewise.\n\t(filter_view::_Iterator::iter_swap): Likewise.\n\t(filter_view::_Sentinel): Add _Const template parameter.\n\t(filter_view::_Sentinel::_Parent): New.\n\t(filter_view::_Sentinel::_Base): New.\n\t(filter_view::_Sentinel::_M_end): Adjust to consider _Const.\n\t(filter_view::_Sentinel::_Sentinel): Likewise.  Add\n\tconst-converting overload.\n\t(filter_view::_Sentinel::base): Adjust to consider _Const.\n\t(filter_view::_Sentinel::operator==): Likewise.  Inline the\n\thelper member function __equal.\n\t(filter_view::begin): Adjust return type of non-const overload.\n\tNew const overload.\n\t(filter_view::end): Likewise.\n\t* testsuite/std/ranges/adaptors/filter.cc: Verify value of\n\t__cpp_lib_ranges_filter.\n\t(test08): New test.\n---\n libstdc++-v3/include/bits/version.def         |   9 ++\n libstdc++-v3/include/bits/version.h           |  10 ++\n libstdc++-v3/include/std/ranges               | 104 ++++++++++++------\n .../testsuite/std/ranges/adaptors/filter.cc   |  29 ++++-\n 4 files changed, 120 insertions(+), 32 deletions(-)",
    "diff": "diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def\nindex bb513e391d76..d23fb2903e24 100644\n--- a/libstdc++-v3/include/bits/version.def\n+++ b/libstdc++-v3/include/bits/version.def\n@@ -2180,6 +2180,15 @@ ftms = {\n   };\n };\n \n+ftms = {\n+  name = ranges_filter;\n+  values = {\n+    // This is P3725R3, a C++26 change, but we treat it as a DR against C++20.\n+    v = 202603;\n+    cxxmin = 20;\n+  };\n+};\n+\n ftms = {\n   name = ranges_to_input;\n   values = {\ndiff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h\nindex e469944208a7..5a9d7e2bc14e 100644\n--- a/libstdc++-v3/include/bits/version.h\n+++ b/libstdc++-v3/include/bits/version.h\n@@ -2446,6 +2446,16 @@\n #endif /* !defined(__cpp_lib_text_encoding) */\n #undef __glibcxx_want_text_encoding\n \n+#if !defined(__cpp_lib_ranges_filter)\n+# if (__cplusplus >= 202002L)\n+#  define __glibcxx_ranges_filter 202603L\n+#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_filter)\n+#   define __cpp_lib_ranges_filter 202603L\n+#  endif\n+# endif\n+#endif /* !defined(__cpp_lib_ranges_filter) */\n+#undef __glibcxx_want_ranges_filter\n+\n #if !defined(__cpp_lib_ranges_to_input)\n # if (__cplusplus >  202302L)\n #  define __glibcxx_ranges_to_input 202502L\ndiff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges\nindex 95e0109a10cf..80c3f922c201 100644\n--- a/libstdc++-v3/include/std/ranges\n+++ b/libstdc++-v3/include/std/ranges\n@@ -65,6 +65,7 @@\n #define __glibcxx_want_ranges_chunk\n #define __glibcxx_want_ranges_chunk_by\n #define __glibcxx_want_ranges_enumerate\n+#define __glibcxx_want_ranges_filter\n #define __glibcxx_want_ranges_indices\n #define __glibcxx_want_ranges_join_with\n #define __glibcxx_want_ranges_repeat\n@@ -1738,15 +1739,19 @@ namespace views::__adaptor\n     class filter_view : public view_interface<filter_view<_Vp, _Pred>>\n     {\n     private:\n+      template<bool _Const>\n       struct _Sentinel;\n \n+      template<bool _Const>\n       struct _Iterator : __detail::__filter_view_iter_cat<_Vp>\n       {\n       private:\n \tstatic constexpr auto\n \t_S_iter_concept()\n \t{\n-\t  if constexpr (bidirectional_range<_Vp>)\n+\t  if constexpr (_Const)\n+\t    return input_iterator_tag{};\n+\t  else if constexpr (bidirectional_range<_Vp>)\n \t    return bidirectional_iterator_tag{};\n \t  else if constexpr (forward_range<_Vp>)\n \t    return forward_iterator_tag{};\n@@ -1755,42 +1760,52 @@ namespace views::__adaptor\n \t}\n \n \tfriend filter_view;\n+\tfriend _Iterator<!_Const>;\n \n-\tusing _Vp_iter = iterator_t<_Vp>;\n+\tusing _Parent = __maybe_const_t<_Const, filter_view>;\n+\tusing _Base = __maybe_const_t<_Const, _Vp>;\n+\tusing _Base_iter = iterator_t<_Base>;\n \n-\t_Vp_iter _M_current = _Vp_iter();\n-\tfilter_view* _M_parent = nullptr;\n+\t_Base_iter _M_current = _Base_iter();\n+\t_Parent* _M_parent = nullptr;\n \n       public:\n \tusing iterator_concept = decltype(_S_iter_concept());\n \t// iterator_category defined in __filter_view_iter_cat\n-\tusing value_type = range_value_t<_Vp>;\n-\tusing difference_type = range_difference_t<_Vp>;\n+\tusing value_type = range_value_t<_Base>;\n+\tusing difference_type = range_difference_t<_Base>;\n \n-\t_Iterator() requires default_initializable<_Vp_iter> = default;\n+\t_Iterator() requires default_initializable<_Base_iter> = default;\n \n \tconstexpr\n-\t_Iterator(filter_view* __parent, _Vp_iter __current)\n+\t_Iterator(_Parent* __parent, _Base_iter __current)\n \t  : _M_current(std::move(__current)),\n \t    _M_parent(__parent)\n \t{ }\n \n-\tconstexpr const _Vp_iter&\n+\tconstexpr\n+\t_Iterator(_Iterator<!_Const> __i)\n+\t  requires _Const && convertible_to<iterator_t<_Vp>, iterator_t<_Base>>\n+\t  : _M_current(std::move(__i._M_current)),\n+\t    _M_parent(std::move(__i._M_parent))\n+\t{ }\n+\n+\tconstexpr const _Base_iter&\n \tbase() const & noexcept\n \t{ return _M_current; }\n \n-\tconstexpr _Vp_iter\n+\tconstexpr _Base_iter\n \tbase() &&\n \t{ return std::move(_M_current); }\n \n-\tconstexpr range_reference_t<_Vp>\n+\tconstexpr range_reference_t<_Base>\n \toperator*() const\n \t{ return *_M_current; }\n \n-\tconstexpr _Vp_iter\n+\tconstexpr _Base_iter\n \toperator->() const\n-\t  requires __detail::__has_arrow<_Vp_iter>\n-\t    && copyable<_Vp_iter>\n+\t  requires __detail::__has_arrow<_Base_iter>\n+\t    && copyable<_Base_iter>\n \t{ return _M_current; }\n \n \tconstexpr _Iterator&\n@@ -1807,7 +1822,7 @@ namespace views::__adaptor\n \t{ ++*this; }\n \n \tconstexpr _Iterator\n-\toperator++(int) requires forward_range<_Vp>\n+\toperator++(int) requires forward_range<_Base>\n \t{\n \t  auto __tmp = *this;\n \t  ++*this;\n@@ -1815,7 +1830,7 @@ namespace views::__adaptor\n \t}\n \n \tconstexpr _Iterator&\n-\toperator--() requires bidirectional_range<_Vp>\n+\toperator--() requires bidirectional_range<_Base>\n \t{\n \t  do\n \t    --_M_current;\n@@ -1824,7 +1839,7 @@ namespace views::__adaptor\n \t}\n \n \tconstexpr _Iterator\n-\toperator--(int) requires bidirectional_range<_Vp>\n+\toperator--(int) requires bidirectional_range<_Base>\n \t{\n \t  auto __tmp = *this;\n \t  --*this;\n@@ -1833,10 +1848,10 @@ namespace views::__adaptor\n \n \tfriend constexpr bool\n \toperator==(const _Iterator& __x, const _Iterator& __y)\n-\t  requires equality_comparable<_Vp_iter>\n+\t  requires equality_comparable<_Base_iter>\n \t{ return __x._M_current == __y._M_current; }\n \n-\tfriend constexpr range_rvalue_reference_t<_Vp>\n+\tfriend constexpr range_rvalue_reference_t<_Base>\n \titer_move(const _Iterator& __i)\n \t  noexcept(noexcept(ranges::iter_move(__i._M_current)))\n \t{ return ranges::iter_move(__i._M_current); }\n@@ -1844,34 +1859,43 @@ namespace views::__adaptor\n \tfriend constexpr void\n \titer_swap(const _Iterator& __x, const _Iterator& __y)\n \t  noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))\n-\t  requires indirectly_swappable<_Vp_iter>\n+\t  requires indirectly_swappable<_Base_iter>\n \t{ ranges::iter_swap(__x._M_current, __y._M_current); }\n       };\n \n+      template<bool _Const>\n       struct _Sentinel\n       {\n       private:\n-\tsentinel_t<_Vp> _M_end = sentinel_t<_Vp>();\n+\tusing _Parent = __maybe_const_t<_Const, filter_view>;\n+\tusing _Base = __maybe_const_t<_Const, _Vp>;\n+\tsentinel_t<_Base> _M_end = sentinel_t<_Base>();\n \n-\tconstexpr bool\n-\t__equal(const _Iterator& __i) const\n-\t{ return __i._M_current == _M_end; }\n+\tfriend _Sentinel<!_Const>;\n \n       public:\n \t_Sentinel() = default;\n \n \tconstexpr explicit\n-\t_Sentinel(filter_view* __parent)\n+\t_Sentinel(_Parent* __parent)\n \t  : _M_end(ranges::end(__parent->_M_base))\n \t{ }\n \n-\tconstexpr sentinel_t<_Vp>\n+\tconstexpr\n+\t_Sentinel(_Sentinel<!_Const> __i)\n+\t  requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>>\n+\t  : _M_end(std::move(__i._M_end))\n+\t{ }\n+\n+\tconstexpr sentinel_t<_Base>\n \tbase() const\n \t{ return _M_end; }\n \n+\ttemplate<bool _Const2>\n+\t  requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const_t<_Const2, _Vp>>>\n \tfriend constexpr bool\n-\toperator==(const _Iterator& __x, const _Sentinel& __y)\n-\t{ return __y.__equal(__x); }\n+\toperator==(const _Iterator<_Const2>& __x, const _Sentinel& __y)\n+\t{ return __x._M_current == __y._M_end; }\n       };\n \n       _Vp _M_base = _Vp();\n@@ -1900,7 +1924,7 @@ namespace views::__adaptor\n       pred() const\n       { return *_M_pred; }\n \n-      constexpr _Iterator\n+      constexpr _Iterator<false>\n       begin()\n       {\n \tif (_M_cached_begin._M_has_value())\n@@ -1914,14 +1938,32 @@ namespace views::__adaptor\n \treturn {this, std::move(__it)};\n       }\n \n+      constexpr _Iterator<true>\n+      begin() const\n+\trequires (input_range<const _Vp> && !forward_range<const _Vp>\n+\t\t  && indirect_unary_predicate<const _Pred, iterator_t<const _Vp>>)\n+      {\n+\t__glibcxx_assert(_M_pred.has_value());\n+\tauto __it = ranges::find_if(ranges::begin(_M_base),\n+\t\t\t\t    ranges::end(_M_base),\n+\t\t\t\t    std::ref(*_M_pred));\n+\treturn {this, std::move(__it)};\n+      }\n+\n       constexpr auto\n       end()\n       {\n \tif constexpr (common_range<_Vp>)\n-\t  return _Iterator{this, ranges::end(_M_base)};\n+\t  return _Iterator<false>{this, ranges::end(_M_base)};\n \telse\n-\t  return _Sentinel{this};\n+\t  return _Sentinel<false>{this};\n       }\n+\n+      constexpr auto\n+      end() const\n+\trequires (input_range<const _Vp> && !forward_range<const _Vp>\n+\t\t  && indirect_unary_predicate<const _Pred, iterator_t<const _Vp>>)\n+      { return _Sentinel<true>{this}; }\n     };\n \n   template<typename _Range, typename _Pred>\ndiff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc\nindex 7595e43d4e60..4c67651843fb 100644\n--- a/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc\n+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc\n@@ -17,12 +17,18 @@\n \n // { dg-do run { target c++20 } }\n \n-#include <algorithm>\n #include <ranges>\n+\n+#if __cpp_lib_ranges_filter != 202603L // C++ >= 20\n+# error \"Feature-test macro for ranges_filter has wrong value in <ranges>.\"\n+#endif\n+\n+#include <algorithm>\n #include <testsuite_hooks.h>\n #include <testsuite_iterators.h>\n \n using __gnu_test::test_range;\n+using __gnu_test::input_iterator_wrapper;\n using __gnu_test::bidirectional_iterator_wrapper;\n using __gnu_test::forward_iterator_wrapper;\n using __gnu_test::random_access_iterator_wrapper;\n@@ -166,6 +172,26 @@ test07()\n \n static_assert( test07() );\n \n+void\n+test08()\n+{\n+  // P3725R3 Filter View Extensions for Safer Use\n+  int x[] = {1, 2, 3, 4, 5};\n+  __gnu_test::test_range<int, input_iterator_wrapper> rx(x);\n+  auto v = rx | views::filter([](int x) { return (x % 2) == 0; });\n+  using R = decltype(v);\n+  static_assert( ranges::input_range<R> && !ranges::forward_range<R> );\n+  static_assert( ranges::input_range<const R> && !ranges::forward_range<const R> );\n+  const auto& cv = v;\n+  auto it = v.begin();\n+  decltype(cv.begin()) cit = it;\n+  auto sent = v.end();\n+  decltype(cv.end()) csent = sent;\n+  VERIFY( cit == cit && it == cit && cit == it );\n+  VERIFY( cit != csent && it != csent && cit != sent );\n+  VERIFY( ranges::equal(cv, (int[]){2, 4}) );\n+}\n+\n int\n main()\n {\n@@ -177,4 +203,5 @@ main()\n   test05<random_access_iterator_wrapper>();\n   test06();\n   test07();\n+  test08();\n }\n",
    "prefixes": [
        "1/2"
    ]
}