get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2226280,
    "url": "http://patchwork.ozlabs.org/api/patches/2226280/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhubjjpeho.gcc.gcc-TEST.redi.25.1.4@forge-stage.sourceware.org/",
    "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": "<bmm.hhubjjpeho.gcc.gcc-TEST.redi.25.1.4@forge-stage.sourceware.org>",
    "list_archive_url": null,
    "date": "2026-04-22T10:36:21",
    "name": "[v1,4/4] libstdc++: Add fancy pointer support to std::forward_list [PR57272]",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "8f73686c6089bb8183f4cdefbad2b1e02376ed8c",
    "submitter": {
        "id": 93210,
        "url": "http://patchwork.ozlabs.org/api/people/93210/?format=api",
        "name": "Jonathan Wakely via Sourceware Forge",
        "email": "forge-bot+redi@forge-stage.sourceware.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhubjjpeho.gcc.gcc-TEST.redi.25.1.4@forge-stage.sourceware.org/mbox/",
    "series": [
        {
            "id": 500985,
            "url": "http://patchwork.ozlabs.org/api/series/500985/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=500985",
            "date": "2026-04-22T10:36:19",
            "name": "libstdc++: Add fancy pointer support to std::list and std::forward_list [PR57272]",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/500985/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2226280/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2226280/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 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; dmarc=none (p=none dis=none)\n header.from=forge-stage.sourceware.org",
            "sourceware.org;\n spf=pass smtp.mailfrom=forge-stage.sourceware.org",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=38.145.34.39"
        ],
        "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 4g0xGr5XFtz1yD5\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 21:05:56 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id CCAD1409F62B\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 11:05:54 +0000 (GMT)",
            "from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id 43CB44BC894D\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 10:37:13 +0000 (GMT)",
            "from forge-stage.sourceware.org (localhost [IPv6:::1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256)\n (No client certificate requested)\n by forge-stage.sourceware.org (Postfix) with ESMTPS id 17DB742B59\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 10:37:13 +0000 (UTC)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org CCAD1409F62B",
            "OpenDKIM Filter v2.11.0 sourceware.org 43CB44BC894D"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 43CB44BC894D",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 43CB44BC894D",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776854233; cv=none;\n b=hXn6xpeViRpZFkgGYJpq8xwRs0Cit8mxp++ouXFmibDoQnf2BijqwkV7Gf40WjByyzGc5PdUYPvu6ndb1rloMg+loAoxG4AtTv+bigpYimX5RP5zLx//JWHlMcgxYqgzeKMRnUNmGMP3AyRIfocQCIrr5qmU3zhUH2eyHTP49s8=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776854233; c=relaxed/simple;\n bh=DYxLKs8fXYMIruY3XoWU591MDounMHrnt6znheloAN8=;\n h=From:Date:Subject:To:Message-ID;\n b=O8Lq0H5kWgkoCEAzzKBk94S6XON2eyq8saNL6jvhUz43lGPs0ONUEBnolFTtmrFWmX6VQkvyf22U7cHIFf5u3GbROOdsdeVB1Efe4gDMNw5Oi2mUJue7EnVCHg7WqLswgbv98e+ohzDSMOeAou3sUhkS0VdW7DduCjasB3nEuFg=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "From": "Jonathan Wakely via Sourceware Forge\n <forge-bot+redi@forge-stage.sourceware.org>",
        "Date": "Wed, 22 Apr 2026 10:36:21 +0000",
        "Subject": "[PATCH v1 4/4] libstdc++: Add fancy pointer support to\n std::forward_list [PR57272]",
        "To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>",
        "Message-ID": "\n <bmm.hhubjjpeho.gcc.gcc-TEST.redi.25.1.4@forge-stage.sourceware.org>",
        "X-Mailer": "batrachomyomachia",
        "X-Pull-Request-Organization": "gcc",
        "X-Pull-Request-Repository": "gcc-TEST",
        "X-Pull-Request": "https://forge.sourceware.org/gcc/gcc-TEST/pulls/25",
        "References": "\n <bmm.hhubjjpeho.gcc.gcc-TEST.redi.25.1.0@forge-stage.sourceware.org>",
        "In-Reply-To": "\n <bmm.hhubjjpeho.gcc.gcc-TEST.redi.25.1.0@forge-stage.sourceware.org>",
        "X-Patch-URL": "\n https://forge.sourceware.org/redi/gcc/commit/b26b7f43502a78f7de364a7015566101929a59d4",
        "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>",
        "Reply-To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>, redi@gcc.gnu.org",
        "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"
    },
    "content": "From: Jonathan Wakely <jwakely@redhat.com>\n\nThis takes a very similar approach to the changes for std::list.\n\nlibstdc++-v3/ChangeLog:\n\n\tPR libstdc++/57272\n\t* include/bits/forward_list.h (_GLIBCXX_USE_ALLOC_PTR_FOR_LIST):\n\tDefine.\n\t(_Fwd_list_node_base::_M_base_ptr): New member functions.\n\t(_Fwd_list_node::_M_node_ptr): New member function.\n\t(_Fwd_list_iterator, _Fwd_list_const_iterator): Make internal\n\tmember functions and data member private. Declare forward_list\n\tand _Fwd_list_base as friends.\n\t(__fwdlist::_Node_base, __fwdlist::_Node, __fwdlist::_Iterator):\n\tNew class templates.\n\t(__fwdlist::_Node_traits): New class template.\n\t(_Fwd_list_base): Use _Node_traits to get types. Use _Base_ptr\n\tinstad of _Fwd_list_node_base*. Use _M_base_ptr() instead of\n\ttaking address of head node.\n\t(forward_list): Likewise.\n\t(_Fwd_list_base::_M_get_node): Do not define for versioned\n\tnamespace.\n\t(_Fwd_list_base::_M_put_node): Only convert pointer if needed.\n\t(_Fwd_list_base::_M_create_node): Use __allocate_guarded_obj.\n\t(_Fwd_list_base::_M_destroy_node): New member function.\n\t* include/bits/forward_list.tcc (_Fwd_list_base::_M_insert_after)\n\t(forward_list::_M_splice_after, forward_list::insert_after): Use\n\tconst_iterator::_M_const_cast() instead of casting pointers.\n\t(_Fwd_list_base::_M_erase_after): Use _M_destroy_node.\n\t(forward_list::remove, forward_list::remove_if): Only do\n\tdowncasts when accessing the value.\n\t(forward_list::sort): Likewise.\n\t* testsuite/23_containers/forward_list/capacity/1.cc: Check\n\tmax_size for new node type.\n\t* testsuite/23_containers/forward_list/capacity/node_sizes.cc:\n\tNew test.\n\t* testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr.cc:\n\tNew test.\n\t* testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr_ignored.cc:\n\tNew test.\n---\n libstdc++-v3/include/bits/forward_list.h      | 428 +++++++++++++++---\n libstdc++-v3/include/bits/forward_list.tcc    | 124 ++---\n .../23_containers/forward_list/capacity/1.cc  |  11 +-\n .../forward_list/capacity/node_sizes.cc       |  24 +\n .../forward_list/requirements/completeness.cc |  19 +\n .../explicit_instantiation/alloc_ptr.cc       |  86 ++++\n .../alloc_ptr_ignored.cc                      |   4 +\n 7 files changed, 579 insertions(+), 117 deletions(-)\n create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/capacity/node_sizes.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/requirements/completeness.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr_ignored.cc",
    "diff": "diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h\nindex c9238cef96fa..e4d24c4b9cac 100644\n--- a/libstdc++-v3/include/bits/forward_list.h\n+++ b/libstdc++-v3/include/bits/forward_list.h\n@@ -40,6 +40,9 @@\n #include <bits/stl_algobase.h>\n #include <bits/stl_function.h>\n #include <bits/allocator.h>\n+#include <bits/allocated_ptr.h>\n+#include <bits/ptr_traits.h>\n+#include <debug/assertions.h>\n #include <ext/alloc_traits.h>\n #include <ext/aligned_buffer.h>\n #if __glibcxx_ranges_to_container // C++ >= 23\n@@ -47,6 +50,10 @@\n # include <bits/ranges_util.h> // ranges::subrange\n #endif\n \n+#if ! defined _GLIBCXX_USE_ALLOC_PTR_FOR_FWD_LIST\n+# define _GLIBCXX_USE_ALLOC_PTR_FOR_FWD_LIST 1\n+#endif\n+\n namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n@@ -54,11 +61,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n   /**\n    *  @brief  A helper basic node class for %forward_list.\n+   *\n    *          This is just a linked list with nothing inside it.\n    *          There are purely list shuffling utility methods here.\n    */\n   struct _Fwd_list_node_base\n   {\n+    using _Base_ptr = _Fwd_list_node_base*;\n+\n     _Fwd_list_node_base() = default;\n     _Fwd_list_node_base(_Fwd_list_node_base&& __x) noexcept\n       : _M_next(__x._M_next)\n@@ -107,6 +117,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t  _M_next->_M_next = __keep;\n \t}\n     }\n+\n+    _Fwd_list_node_base* _M_base_ptr() { return this; }\n+    const _Fwd_list_node_base* _M_base_ptr() const { return this; }\n   };\n \n   /**\n@@ -119,6 +132,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n     struct _Fwd_list_node\n     : public _Fwd_list_node_base\n     {\n+      using _Node_ptr = _Fwd_list_node*;\n+\n       _Fwd_list_node() = default;\n \n       __gnu_cxx::__aligned_buffer<_Tp> _M_storage;\n@@ -130,8 +145,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       const _Tp*\n       _M_valptr() const noexcept\n       { return _M_storage._M_ptr(); }\n+\n+      _Node_ptr\n+      _M_node_ptr()\n+      { return this; }\n     };\n \n+  template<typename _Tp> struct _Fwd_list_const_iterator;\n+\n   /**\n    *   @brief A forward_list::iterator.\n    *\n@@ -199,6 +220,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       { return __x._M_node != __y._M_node; }\n #endif\n \n+    private:\n+      template<typename, typename>\n+\tfriend class forward_list;\n+      template<typename, typename>\n+\tfriend struct _Fwd_list_base;\n+      friend struct _Fwd_list_const_iterator<_Tp>;\n+\n       _Self\n       _M_next() const noexcept\n       {\n@@ -282,6 +310,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       { return __x._M_node != __y._M_node; }\n #endif\n \n+    private:\n+      template<typename, typename>\n+\tfriend class forward_list;\n+      template<typename, typename>\n+\tfriend struct _Fwd_list_base;\n+\n       _Self\n       _M_next() const noexcept\n       {\n@@ -291,23 +325,295 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t  return _Fwd_list_const_iterator(nullptr);\n       }\n \n+      _Fwd_list_iterator<_Tp>\n+      _M_const_cast() const noexcept\n+      {\n+\treturn _Fwd_list_iterator<_Tp>(\n+\t\t const_cast<_Fwd_list_node_base*>(_M_node));\n+      }\n+\n       const _Fwd_list_node_base* _M_node;\n     };\n \n+  template<typename _Tp, typename _Allocator> class forward_list;\n+  template<typename _Tp, typename _Allocator> struct _Fwd_list_base;\n+\n+namespace __fwdlist\n+{\n+#if _GLIBCXX_USE_ALLOC_PTR_FOR_FWD_LIST\n+  /// The node-base type for allocators that use fancy pointers.\n+  template<typename _VoidPtr>\n+    struct _Node_base\n+    {\n+      using _Base_ptr = __ptr_rebind<_VoidPtr, _Node_base>;\n+\n+      _Node_base() = default;\n+\n+      _Node_base(_Node_base&& __x) noexcept\n+      : _M_next(__x._M_next)\n+      { __x._M_next = nullptr; }\n+\n+      _Node_base(const _Node_base&) = delete;\n+      _Node_base& operator=(const _Node_base&) = delete;\n+\n+      _Node_base&\n+      operator=(_Node_base&& __x) noexcept\n+      {\n+\t_M_next = __x._M_next;\n+\t__x._M_next = nullptr;\n+\treturn *this;\n+      }\n+\n+      _Base_ptr _M_next = nullptr;\n+\n+      // Splice (begin,end) before _M_next.\n+      _Base_ptr\n+      _M_transfer_after(_Base_ptr __begin, _Base_ptr __end) noexcept\n+      {\n+\t_Base_ptr __keep = __begin->_M_next;\n+\tif (__end)\n+\t  {\n+\t    __begin->_M_next = __end->_M_next;\n+\t    __end->_M_next = _M_next;\n+\t  }\n+\telse\n+\t  __begin->_M_next = nullptr;\n+\t_M_next = __keep;\n+\treturn __end;\n+      }\n+\n+      void\n+      _M_reverse_after() noexcept\n+      {\n+\t_Base_ptr __tail = _M_next;\n+\tif (!__tail)\n+\t  return;\n+\twhile (_Base_ptr __temp = __tail->_M_next)\n+\t  {\n+\t    _Base_ptr __keep = _M_next;\n+\t    _M_next = __temp;\n+\t    __tail->_M_next = __temp->_M_next;\n+\t    _M_next->_M_next = __keep;\n+\t  }\n+      }\n+\n+      // This is not const-correct, but it's only used in a const access path\n+      // by std::forward_list::empty(), where it doesn't escape, and by\n+      // std::forward_list::before_begin() const, where the pointer is used\n+      // to initialize a const_iterator and so constness is restored.\n+      _Base_ptr\n+      _M_base_ptr() const\n+      {\n+\treturn pointer_traits<_Base_ptr>::\n+\t\t pointer_to(const_cast<_Node_base&>(*this));\n+      }\n+    };\n+\n+  /**\n+   *  @brief  A helper node class for %forward_list.\n+   */\n+  template<typename _ValPtr>\n+    struct _Node\n+    : public _Node_base<__ptr_rebind<_ValPtr, void>>\n+    {\n+      using value_type = typename pointer_traits<_ValPtr>::element_type;\n+      using _Node_ptr = __ptr_rebind<_ValPtr, _Node>;\n+\n+      _Node() { }\n+      ~_Node() { }\n+      _Node(_Node&&) = delete;\n+\n+      union {\n+#if ! _GLIBCXX_INLINE_VERSION\n+\t// For ABI compatibility we need to overalign this member.\n+\talignas(__alignof__(value_type)) // XXX GLIBCXX_ABI Deprecated\n+#endif\n+\tvalue_type _M_data;\n+      };\n+\n+      value_type*\n+      _M_valptr() noexcept\n+      { return std::__addressof(_M_data); }\n+\n+      const value_type*\n+      _M_valptr() const noexcept\n+      { return std::__addressof(_M_data); }\n+\n+      _Node_ptr\n+      _M_node_ptr()\n+      { return pointer_traits<_Node_ptr>::pointer_to(*this); }\n+    };\n+\n+  /// A forward_list iterator when the allocator uses fancy pointers.\n+  template<bool _Const, typename _Ptr>\n+    class _Iterator\n+    {\n+      using _Node = __fwdlist::_Node<_Ptr>;\n+      using _Base_ptr\n+\t= typename __fwdlist::_Node_base<__ptr_rebind<_Ptr, void>>::_Base_ptr;\n+\n+      template<typename _Tp>\n+\tusing __maybe_const = __conditional_t<_Const, const _Tp, _Tp>;\n+\n+    public:\n+      using value_type        = typename pointer_traits<_Ptr>::element_type;\n+      using difference_type   = ptrdiff_t;\n+      using iterator_category = forward_iterator_tag;\n+      using pointer           = __maybe_const<value_type>*;\n+      using reference         = __maybe_const<value_type>&;\n+\n+      constexpr _Iterator() noexcept : _M_node() { }\n+\n+      _Iterator(const _Iterator&) = default;\n+      _Iterator& operator=(const _Iterator&) = default;\n+\n+#ifdef __glibcxx_concepts\n+      constexpr\n+      _Iterator(const _Iterator<false, _Ptr>& __i) requires _Const\n+#else\n+      template<bool _OtherConst,\n+\t       typename = __enable_if_t<_Const && !_OtherConst>>\n+\tconstexpr\n+\t_Iterator(const _Iterator<_OtherConst, _Ptr>& __i)\n+#endif\n+\t: _M_node(__i._M_node) { }\n+\n+      constexpr explicit\n+      _Iterator(_Base_ptr __x) noexcept\n+      : _M_node(__x) { }\n+\n+      [[__nodiscard__]]\n+      constexpr reference\n+      operator*() const noexcept\n+      { return static_cast<_Node&>(*this->_M_node)._M_data; }\n+\n+      [[__nodiscard__]]\n+      constexpr pointer\n+      operator->() const noexcept\n+      { return static_cast<_Node&>(*this->_M_node)._M_valptr(); }\n+\n+      _GLIBCXX14_CONSTEXPR _Iterator&\n+      operator++() noexcept\n+      {\n+\t_M_node = _M_node->_M_next;\n+\treturn *this;\n+      }\n+\n+      _GLIBCXX14_CONSTEXPR _Iterator\n+      operator++(int) noexcept\n+      {\n+\t_Iterator __tmp(*this);\n+\t_M_node = _M_node->_M_next;\n+\treturn __tmp;\n+      }\n+\n+      /**\n+       *  @brief  Forward list iterator equality comparison.\n+       */\n+      [[__nodiscard__]]\n+      friend constexpr bool\n+      operator==(const _Iterator& __x, const _Iterator& __y) noexcept\n+      { return __x._M_node == __y._M_node; }\n+\n+#if __cpp_impl_three_way_comparison < 201907L\n+      /**\n+       *  @brief  Forward list iterator inequality comparison.\n+       */\n+      [[__nodiscard__]]\n+      friend constexpr bool\n+      operator!=(const _Iterator& __x, const _Iterator& __y) noexcept\n+      { return __x._M_node != __y._M_node; }\n+#endif\n+\n+    private:\n+      template<typename _Tp, typename _Allocator>\n+\tfriend class _GLIBCXX_STD_C::forward_list;\n+      template<typename _Tp, typename _Allocator>\n+\tfriend struct _GLIBCXX_STD_C::_Fwd_list_base;\n+\n+      constexpr _Iterator<false, _Ptr>\n+      _M_const_cast() const noexcept\n+      { return _Iterator<false, _Ptr>(_M_node); }\n+\n+      friend _Iterator<!_Const, _Ptr>;\n+\n+      constexpr _Iterator\n+      _M_next() const noexcept\n+      { return _Iterator(_M_node ? _M_node->_M_next : nullptr); }\n+\n+      _Base_ptr _M_node;\n+    };\n+#endif // USE_ALLOC_PTR_FOR_FWD_LIST\n+\n+  // Determine the node and iterator types used by std::forward_list.\n+  template<typename _Tp, typename _Ptr>\n+    struct _Node_traits;\n+\n+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST <= 9000\n+  // Specialization for the simple case where the allocator's pointer type\n+  // is the same type as value_type*.\n+  // For ABI compatibility we can't change the types used for this case.\n+  template<typename _Tp>\n+    struct _Node_traits<_Tp, _Tp*>\n+    {\n+      using _Node_base\t    = _Fwd_list_node_base;\n+      using _Node\t    = _Fwd_list_node<_Tp>;\n+      using _Iterator\t    = _Fwd_list_iterator<_Tp>;\n+      using _Const_iterator = _Fwd_list_const_iterator<_Tp>;\n+    };\n+#endif\n+\n+#if ! _GLIBCXX_USE_ALLOC_PTR_FOR_FWD_LIST\n+  // Always use the T* specialization.\n+  template<typename _Tp, typename _Ptr>\n+    struct _Node_traits\n+    : _Node_traits<_Tp, _Tp*>\n+    { };\n+#else\n+  // Primary template used when the allocator uses fancy pointers.\n+  template<typename _Tp, typename _Ptr>\n+    struct _Node_traits\n+    {\n+    private:\n+      using _VoidPtr = __ptr_rebind<_Ptr, void>;\n+      using _ValPtr = __ptr_rebind<_Ptr, _Tp>;\n+\n+    public:\n+      using _Node_base      = __fwdlist::_Node_base<_VoidPtr>;\n+      using _Node           = __fwdlist::_Node<_ValPtr>;\n+      using _Iterator       = __fwdlist::_Iterator<false, _ValPtr>;\n+      using _Const_iterator = __fwdlist::_Iterator<true, _ValPtr>;\n+    };\n+#endif // USE_ALLOC_PTR_FOR_FWD_LIST\n+} // namespace __fwdlist\n+\n   /**\n    *  @brief  Base class for %forward_list.\n    */\n   template<typename _Tp, typename _Alloc>\n     struct _Fwd_list_base\n     {\n+#if __cplusplus > 201703L || defined __STRICT_ANSI__\n+      // The static_assert in forward_list ensures _Alloc::value_type is _Tp.\n+      using pointer = typename allocator_traits<_Alloc>::pointer;\n+#else\n+      using _Tp_alloc_traits\n+\t= typename allocator_traits<_Alloc>::template rebind_traits<_Tp>;\n+      using pointer = typename _Tp_alloc_traits::pointer;\n+#endif\n+\n     protected:\n-      typedef __alloc_rebind<_Alloc, _Fwd_list_node<_Tp>> _Node_alloc_type;\n-      typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;\n+      using _Node_traits = __fwdlist::_Node_traits<_Tp, pointer>;\n+      using _Node = typename _Node_traits::_Node;\n+      using _Node_alloc_type = __alloc_rebind<_Alloc, _Node>;\n+      using _Node_alloc_traits = __gnu_cxx::__alloc_traits<_Node_alloc_type>;\n+      using _Node_ptr = typename _Node_alloc_traits::pointer;\n+      using _Base_ptr = typename _Node_traits::_Node_base::_Base_ptr;\n \n       struct _Fwd_list_impl\n       : public _Node_alloc_type\n       {\n-\t_Fwd_list_node_base _M_head;\n+\ttypename _Node_traits::_Node_base _M_head;\n \n \t_Fwd_list_impl()\n \t  noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value)\n@@ -328,9 +634,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       _Fwd_list_impl _M_impl;\n \n     public:\n-      typedef _Fwd_list_iterator<_Tp>\t\titerator;\n-      typedef _Fwd_list_const_iterator<_Tp>\tconst_iterator;\n-      typedef _Fwd_list_node<_Tp>\t\t_Node;\n+      using iterator = typename _Node_traits::_Iterator;\n+      using const_iterator = typename _Node_traits::_Const_iterator;\n \n       _Node_alloc_type&\n       _M_get_Node_allocator() noexcept\n@@ -357,54 +662,71 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       _Fwd_list_base(_Fwd_list_base&&) = default;\n \n       ~_Fwd_list_base()\n-      { _M_erase_after(&_M_impl._M_head, nullptr); }\n+      { _M_erase_after(_M_impl._M_head._M_base_ptr(), nullptr); }\n \n     protected:\n+#if ! _GLIBCXX_INLINE_VERSION\n+      // XXX GLIBCXX_ABI Deprecated\n       _Node*\n       _M_get_node()\n       {\n \tauto __ptr = _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);\n \treturn std::__to_address(__ptr);\n       }\n+#endif\n+\n+      void\n+      _M_put_node(_Node_ptr __p)\n+      {\n+#if _GLIBCXX_USE_ALLOC_PTR_FOR_FWD_LIST\n+\t_Node_alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1);\n+#else\n+\ttypedef typename _Node_alloc_traits::pointer _Ptr;\n+\tauto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__p);\n+\t_Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ptr, 1);\n+#endif\n+      }\n \n       template<typename... _Args>\n-\t_Node*\n+\t_Node_ptr\n \t_M_create_node(_Args&&... __args)\n \t{\n-\t  _Node* __node = this->_M_get_node();\n-\t  __try\n-\t    {\n-\t      ::new ((void*)__node) _Node;\n-\t      _Node_alloc_traits::construct(_M_get_Node_allocator(),\n-\t\t\t\t\t    __node->_M_valptr(),\n-\t\t\t\t\t    std::forward<_Args>(__args)...);\n-\t    }\n-\t  __catch(...)\n-\t    {\n-\t      this->_M_put_node(__node);\n-\t      __throw_exception_again;\n-\t    }\n-\t  return __node;\n+\t  auto& __alloc = _M_get_Node_allocator();\n+\t  auto __guard = std::__allocate_guarded_obj(__alloc);\n+\t  _Node_alloc_traits::construct(__alloc, __guard->_M_valptr(),\n+\t\t\t\t\tstd::forward<_Args>(__args)...);\n+\t  auto __p = __guard.release();\n+#if _GLIBCXX_USE_ALLOC_PTR_FOR_FWD_LIST\n+\t  return __p;\n+#else\n+\t  return std::__to_address(__p);\n+#endif\n \t}\n \n-      template<typename... _Args>\n-\t_Fwd_list_node_base*\n-\t_M_insert_after(const_iterator __pos, _Args&&... __args);\n-\n+#pragma GCC diagnostic push\n+#pragma GCC diagnostic ignored \"-Wc++17-extensions\" // if constexpr\n       void\n-      _M_put_node(_Node* __p)\n+      _M_destroy_node(_Node_ptr __p)\n       {\n-\ttypedef typename _Node_alloc_traits::pointer _Ptr;\n-\tauto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__p);\n-\t_Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ptr, 1);\n+\tauto& __alloc = _M_get_Node_allocator();\n+\t// Destroy the element\n+\t_Node_alloc_traits::destroy(__alloc, __p->_M_valptr());\n+\t// Only destroy the node if the pointers require it.\n+\tif constexpr (!is_trivially_destructible<_Base_ptr>::value)\n+\t  __p->~_Node();\n+\t_M_put_node(__p);\n       }\n+#pragma GCC diagnostic pop\n+\n+      template<typename... _Args>\n+\t_Base_ptr\n+\t_M_insert_after(const_iterator __pos, _Args&&... __args);\n \n-      _Fwd_list_node_base*\n-      _M_erase_after(_Fwd_list_node_base* __pos);\n+      _Base_ptr\n+      _M_erase_after(_Base_ptr __pos);\n \n-      _Fwd_list_node_base*\n-      _M_erase_after(_Fwd_list_node_base* __pos,\n-\t\t     _Fwd_list_node_base* __last);\n+      _Base_ptr\n+      _M_erase_after(_Base_ptr __pos, _Base_ptr __last);\n     };\n \n   /**\n@@ -581,12 +903,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \tforward_list(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())\n \t: _Base(_Node_alloc_type(__a))\n \t{\n-\t  _Node_base* __to = &this->_M_impl._M_head;\n+\t  auto __to = this->_M_impl._M_head._M_base_ptr();\n \t  auto __first = ranges::begin(__rg);\n \t  const auto __last = ranges::end(__rg);\n \t  for (; __first != __last; ++__first)\n \t    {\n-\t      __to->_M_next = this->_M_create_node(*__first);\n+\t      __to->_M_next = this->_M_create_node(*__first)->_M_base_ptr();\n \t      __to = __to->_M_next;\n \t    }\n \t}\n@@ -776,7 +1098,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       [[__nodiscard__]]\n       iterator\n       before_begin() noexcept\n-      { return iterator(&this->_M_impl._M_head); }\n+      { return iterator(this->_M_impl._M_head._M_base_ptr()); }\n \n       /**\n        *  Returns a read-only (constant) iterator that points before the\n@@ -786,7 +1108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       [[__nodiscard__]]\n       const_iterator\n       before_begin() const noexcept\n-      { return const_iterator(&this->_M_impl._M_head); }\n+      { return const_iterator(this->_M_impl._M_head._M_base_ptr()); }\n \n       /**\n        *  Returns a read/write iterator that points to the first element\n@@ -845,7 +1167,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       [[__nodiscard__]]\n       const_iterator\n       cbefore_begin() const noexcept\n-      { return const_iterator(&this->_M_impl._M_head); }\n+      { return const_iterator(this->_M_impl._M_head._M_base_ptr()); }\n \n       /**\n        *  Returns a read-only (constant) iterator that points one past\n@@ -884,8 +1206,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       reference\n       front()\n       {\n-\t_Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next);\n-\treturn *__front->_M_valptr();\n+\t_Node& __front = static_cast<_Node&>(*this->_M_impl._M_head._M_next);\n+\treturn *__front._M_valptr();\n       }\n \n       /**\n@@ -896,8 +1218,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       const_reference\n       front() const\n       {\n-\t_Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next);\n-\treturn *__front->_M_valptr();\n+\t_Node& __front = static_cast<_Node&>(*this->_M_impl._M_head._M_next);\n+\treturn *__front._M_valptr();\n       }\n \n       // 23.3.4.5 modifiers:\n@@ -990,7 +1312,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n        */\n       void\n       pop_front()\n-      { this->_M_erase_after(&this->_M_impl._M_head); }\n+      {\n+\t__glibcxx_requires_nonempty();\n+\tthis->_M_erase_after(this->_M_impl._M_head._M_base_ptr());\n+      }\n \n       /**\n        *  @brief  Constructs object in %forward_list after the specified\n@@ -1137,8 +1462,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n        */\n       iterator\n       erase_after(const_iterator __pos)\n-      { return iterator(this->_M_erase_after(const_cast<_Node_base*>\n-\t\t\t\t\t     (__pos._M_node))); }\n+      { return iterator(this->_M_erase_after(__pos._M_const_cast()._M_node)); }\n \n       /**\n        *  @brief  Remove a range of elements.\n@@ -1160,10 +1484,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n        */\n       iterator\n       erase_after(const_iterator __pos, const_iterator __last)\n-      { return iterator(this->_M_erase_after(const_cast<_Node_base*>\n-\t\t\t\t\t     (__pos._M_node),\n-\t\t\t\t\t     const_cast<_Node_base*>\n-\t\t\t\t\t     (__last._M_node))); }\n+      {\n+\treturn iterator(this->_M_erase_after(__pos._M_const_cast()._M_node,\n+\t\t\t\t\t     __last._M_const_cast()._M_node));\n+      }\n \n       /**\n        *  @brief  Swaps data with another %forward_list.\n@@ -1225,7 +1549,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n        */\n       void\n       clear() noexcept\n-      { this->_M_erase_after(&this->_M_impl._M_head, nullptr); }\n+      { this->_M_erase_after(this->_M_impl._M_head._M_base_ptr(), nullptr); }\n \n       // 23.3.4.6 forward_list operations:\n \ndiff --git a/libstdc++-v3/include/bits/forward_list.tcc b/libstdc++-v3/include/bits/forward_list.tcc\nindex 9750c7c0502b..140e9955714e 100644\n--- a/libstdc++-v3/include/bits/forward_list.tcc\n+++ b/libstdc++-v3/include/bits/forward_list.tcc\n@@ -46,47 +46,42 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n   template<typename _Tp, typename _Alloc>\n     template<typename... _Args>\n-      _Fwd_list_node_base*\n+      auto\n       _Fwd_list_base<_Tp, _Alloc>::\n       _M_insert_after(const_iterator __pos, _Args&&... __args)\n+      -> _Base_ptr\n       {\n-\t_Fwd_list_node_base* __to\n-\t  = const_cast<_Fwd_list_node_base*>(__pos._M_node);\n-\t_Node* __thing = _M_create_node(std::forward<_Args>(__args)...);\n+\tauto __to = __pos._M_const_cast()._M_node;\n+\t_Node_ptr __thing = _M_create_node(std::forward<_Args>(__args)...);\n \t__thing->_M_next = __to->_M_next;\n-\t__to->_M_next = __thing;\n+\t__to->_M_next = __thing->_M_base_ptr();\n \treturn __to->_M_next;\n       }\n \n   template<typename _Tp, typename _Alloc>\n-    _Fwd_list_node_base*\n+    auto\n     _Fwd_list_base<_Tp, _Alloc>::\n-    _M_erase_after(_Fwd_list_node_base* __pos)\n+    _M_erase_after(_Base_ptr __pos)\n+    -> _Base_ptr\n     {\n-      _Node* __curr = static_cast<_Node*>(__pos->_M_next);\n-      __pos->_M_next = __curr->_M_next;\n-      _Node_alloc_traits::destroy(_M_get_Node_allocator(),\n-\t\t\t\t  __curr->_M_valptr());\n-      __curr->~_Node();\n-      _M_put_node(__curr);\n+      auto& __curr = static_cast<_Node&>(*__pos->_M_next);\n+      __pos->_M_next = __curr._M_next;\n+      _M_destroy_node(__curr._M_node_ptr());\n       return __pos->_M_next;\n     }\n \n   template<typename _Tp, typename _Alloc>\n-    _Fwd_list_node_base*\n+    auto\n     _Fwd_list_base<_Tp, _Alloc>::\n-    _M_erase_after(_Fwd_list_node_base* __pos,\n-\t\t   _Fwd_list_node_base* __last)\n+    _M_erase_after(_Base_ptr __pos, _Base_ptr __last)\n+    -> _Base_ptr\n     {\n-      _Node* __curr = static_cast<_Node*>(__pos->_M_next);\n+      _Base_ptr __curr = __pos->_M_next;\n       while (__curr != __last)\n \t{\n-\t  _Node* __temp = __curr;\n-\t  __curr = static_cast<_Node*>(__curr->_M_next);\n-\t  _Node_alloc_traits::destroy(_M_get_Node_allocator(),\n-\t\t\t\t      __temp->_M_valptr());\n-\t  __temp->~_Node();\n-\t  _M_put_node(__temp);\n+\t  auto& __node = static_cast<_Node&>(*__curr);\n+\t  __curr = __curr->_M_next;\n+\t  _M_destroy_node(__node._M_node_ptr());\n \t}\n       __pos->_M_next = __last;\n       return __last;\n@@ -99,10 +94,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       forward_list<_Tp, _Alloc>::\n       _M_range_initialize(_InputIterator __first, _InputIterator __last)\n       {\n-\t_Node_base* __to = &this->_M_impl._M_head;\n+\tauto __to = this->_M_impl._M_head._M_base_ptr();\n \tfor (; __first != __last; ++__first)\n \t  {\n-\t    __to->_M_next = this->_M_create_node(*__first);\n+\t    __to->_M_next = this->_M_create_node(*__first)->_M_base_ptr();\n \t    __to = __to->_M_next;\n \t  }\n       }\n@@ -113,10 +108,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n     forward_list<_Tp, _Alloc>::\n     _M_fill_initialize(size_type __n, const value_type& __value)\n     {\n-      _Node_base* __to = &this->_M_impl._M_head;\n+      auto __to = this->_M_impl._M_head._M_base_ptr();\n       for (; __n; --__n)\n \t{\n-\t  __to->_M_next = this->_M_create_node(__value);\n+\t  __to->_M_next = this->_M_create_node(__value)->_M_base_ptr();\n \t  __to = __to->_M_next;\n \t}\n     }\n@@ -126,10 +121,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n     forward_list<_Tp, _Alloc>::\n     _M_default_initialize(size_type __n)\n     {\n-      _Node_base* __to = &this->_M_impl._M_head;\n+      auto __to = this->_M_impl._M_head._M_base_ptr();\n       for (; __n; --__n)\n \t{\n-\t  __to->_M_next = this->_M_create_node();\n+\t  __to->_M_next = this->_M_create_node()->_M_base_ptr();\n \t  __to = __to->_M_next;\n \t}\n     }\n@@ -220,9 +215,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n     _M_splice_after(const_iterator __pos,\n \t\t    const_iterator __before, const_iterator __last)\n     {\n-      _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node);\n-      _Node_base* __b = const_cast<_Node_base*>(__before._M_node);\n-      _Node_base* __end = __b;\n+      auto __tmp = __pos._M_const_cast()._M_node;\n+      auto __b = __before._M_const_cast()._M_node;\n+      auto __end = __b;\n \n       while (__end && __end->_M_next != __last._M_node)\n \t__end = __end->_M_next;\n@@ -245,9 +240,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       if (__pos == __i || __pos == __j)\n \treturn;\n \n-      _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node);\n-      __tmp->_M_transfer_after(const_cast<_Node_base*>(__i._M_node),\n-\t\t\t       const_cast<_Node_base*>(__j._M_node));\n+      auto __tmp = __pos._M_const_cast()._M_node;\n+      __tmp->_M_transfer_after(__i._M_const_cast()._M_node,\n+\t\t\t       __j._M_const_cast()._M_node);\n     }\n \n   template<typename _Tp, typename _Alloc>\n@@ -261,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t  return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end());\n \t}\n       else\n-\treturn iterator(const_cast<_Node_base*>(__pos._M_node));\n+\treturn __pos._M_const_cast();\n     }\n \n   template<typename _Tp, typename _Alloc>\n@@ -275,7 +270,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \tif (!__tmp.empty())\n \t  return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end());\n \telse\n-\t  return iterator(const_cast<_Node_base*>(__pos._M_node));\n+\t  return __pos._M_const_cast();\n       }\n \n #if __cplusplus > 201703L\n@@ -293,8 +288,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       forward_list __to_destroy(get_allocator());\n \n       auto __prev_it = cbefore_begin();\n-      while (_Node* __tmp = static_cast<_Node*>(__prev_it._M_node->_M_next))\n-\tif (*__tmp->_M_valptr() == __val)\n+      while (auto __tmp = __prev_it._M_node->_M_next)\n+\tif (*static_cast<_Node&>(*__tmp)._M_valptr() == __val)\n \t  {\n \t    __to_destroy.splice_after(__to_destroy.cbefore_begin(),\n \t\t\t\t      *this, __prev_it);\n@@ -316,8 +311,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \tforward_list __to_destroy(get_allocator());\n \n \tauto __prev_it = cbefore_begin();\n-\twhile (_Node* __tmp = static_cast<_Node*>(__prev_it._M_node->_M_next))\n-\t  if (__pred(*__tmp->_M_valptr()))\n+\twhile (auto __tmp = __prev_it._M_node->_M_next)\n+\t  if (__pred(*static_cast<_Node&>(*__tmp)._M_valptr()))\n \t    {\n \t      __to_destroy.splice_after(__to_destroy.cbefore_begin(),\n \t\t\t\t\t*this, __prev_it);\n@@ -372,15 +367,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \tif (std::__addressof(__list) == this)\n \t  return;\n \n-\t_Node_base* __node = &this->_M_impl._M_head;\n-\twhile (__node->_M_next && __list._M_impl._M_head._M_next)\n+\tusing _Base_ptr = typename _Node::_Base_ptr;\n+\n+\t_Base_ptr __node = this->_M_impl._M_head._M_base_ptr();\n+\t_Base_ptr __other = __list._M_impl._M_head._M_base_ptr();\n+\twhile (__node->_M_next && __other->_M_next)\n \t  {\n-\t    if (__comp(*static_cast<_Node*>\n-\t\t       (__list._M_impl._M_head._M_next)->_M_valptr(),\n-\t\t       *static_cast<_Node*>\n-\t\t       (__node->_M_next)->_M_valptr()))\n-\t      __node->_M_transfer_after(&__list._M_impl._M_head,\n-\t\t\t\t\t__list._M_impl._M_head._M_next);\n+\t    auto& __l = static_cast<_Node&>(*__other->_M_next);\n+\t    auto& __r = static_cast<_Node&>(*__node->_M_next);\n+\t    if (__comp(*__l._M_valptr(), *__r._M_valptr()))\n+\t      __node->_M_transfer_after(__other, __other->_M_next);\n \t    __node = __node->_M_next;\n \t  }\n \n@@ -416,18 +412,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       forward_list<_Tp, _Alloc>::\n       sort(_Comp __comp)\n       {\n-\t// If `next' is nullptr, return immediately.\n-\t_Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next);\n-\tif (!__list)\n+\tif (empty())\n \t  return;\n \n+\tusing _Base_ptr = typename _Node::_Base_ptr;\n+\n+\t// If `next' is nullptr, return immediately.\n+\t_Base_ptr __list = this->_M_impl._M_head._M_next;\n+\n \tunsigned long __insize = 1;\n \n \twhile (1)\n \t  {\n-\t    _Node* __p = __list;\n+\t    _Base_ptr __p = __list;\n \t    __list = nullptr;\n-\t    _Node* __tail = nullptr;\n+\t    _Base_ptr __tail = nullptr;\n \n \t    // Count number of merges we do in this pass.\n \t    unsigned long __nmerges = 0;\n@@ -437,12 +436,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t\t++__nmerges;\n \t\t// There exists a merge to be done.\n \t\t// Step `insize' places along from p.\n-\t\t_Node* __q = __p;\n+\t\t_Base_ptr __q = __p;\n \t\tunsigned long __psize = 0;\n \t\tfor (unsigned long __i = 0; __i < __insize; ++__i)\n \t\t  {\n \t\t    ++__psize;\n-\t\t    __q = static_cast<_Node*>(__q->_M_next);\n+\t\t    __q = __q->_M_next;\n \t\t    if (!__q)\n \t\t      break;\n \t\t  }\n@@ -454,33 +453,34 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t\twhile (__psize > 0 || (__qsize > 0 && __q))\n \t\t  {\n \t\t    // Decide whether next node of merge comes from p or q.\n-\t\t    _Node* __e;\n+\t\t    _Base_ptr __e;\n \t\t    if (__psize == 0)\n \t\t      {\n \t\t\t// p is empty; e must come from q.\n \t\t\t__e = __q;\n-\t\t\t__q = static_cast<_Node*>(__q->_M_next);\n+\t\t\t__q = __q->_M_next;\n \t\t\t--__qsize;\n \t\t      }\n \t\t    else if (__qsize == 0 || !__q)\n \t\t      {\n \t\t\t// q is empty; e must come from p.\n \t\t\t__e = __p;\n-\t\t\t__p = static_cast<_Node*>(__p->_M_next);\n+\t\t\t__p = __p->_M_next;\n \t\t\t--__psize;\n \t\t      }\n-\t\t    else if (!__comp(*__q->_M_valptr(), *__p->_M_valptr()))\n+\t\t    else if (!__comp(*static_cast<_Node&>(*__q)._M_valptr(),\n+\t\t\t\t     *static_cast<_Node&>(*__p)._M_valptr()))\n \t\t      {\n \t\t\t// First node of q is not lower; e must come from p.\n \t\t\t__e = __p;\n-\t\t\t__p = static_cast<_Node*>(__p->_M_next);\n+\t\t\t__p = __p->_M_next;\n \t\t\t--__psize;\n \t\t      }\n \t\t    else\n \t\t      {\n \t\t\t// First node of q is lower; e must come from q.\n \t\t\t__e = __q;\n-\t\t\t__q = static_cast<_Node*>(__q->_M_next);\n+\t\t\t__q = __q->_M_next;\n \t\t\t--__qsize;\n \t\t      }\n \ndiff --git a/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc\nindex 119bf6ca0274..590bba5bd254 100644\n--- a/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc\n+++ b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc\n@@ -36,13 +36,18 @@ test01()\n   VERIFY(fld.empty() == true);\n \n #ifdef _GLIBCXX_DEBUG\n-  using std::_GLIBCXX_STD_C::_Fwd_list_node;\n+  namespace C = std::_GLIBCXX_STD_C;\n #else\n-  using std::_Fwd_list_node;\n+  namespace C = std;\n #endif\n \n-  std::allocator<_Fwd_list_node<double> > a;\n+  std::allocator<C::_Fwd_list_node<double>> a;\n   VERIFY( fld.max_size() == __gnu_test::max_size(a) );\n+\n+#if _GLIBCXX_FWDLIST_USE_ALLOC_PTR\n+  std::allocator<C::__fwdlist::_Node<double*>> b;\n+  VERIFY( __gnu_test::max_size(b) == __gnu_test::max_size(a) );\n+#endif\n }\n \n int\ndiff --git a/libstdc++-v3/testsuite/23_containers/forward_list/capacity/node_sizes.cc b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/node_sizes.cc\nnew file mode 100644\nindex 000000000000..a709031783b6\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/node_sizes.cc\n@@ -0,0 +1,24 @@\n+// { dg-do compile { target c++11 } }\n+\n+#include <forward_list>\n+\n+#if _GLIBCXX_FWDLIST_USE_ALLOC_PTR\n+\n+#ifdef _GLIBCXX_DEBUG\n+namespace C = std::_GLIBCXX_STD_C;\n+#else\n+namespace C = std;\n+#endif\n+\n+// We use double here because for ADJUST_FIELD_ALIGN targets (like i386)\n+// its alignment differs when used as a data member or as a complete object.\n+static_assert(sizeof(C::_Fwd_list_node<double>)\n+\t      == sizeof(C::__fwdlist::_Node<double*>),\n+\t      \"node types have same size\");\n+static_assert(alignof(C::_Fwd_list_node<double>)\n+\t      == alignof(C::__fwdlist::_Node<double*>),\n+\t      \"node types have same alignment\");\n+static_assert(__alignof(C::_Fwd_list_node<double>)\n+\t      == __alignof(C::__fwdlist::_Node<double*>),\n+\t      \"node types have same preferred alignment\");\n+#endif\ndiff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/completeness.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/completeness.cc\nnew file mode 100644\nindex 000000000000..abc9df504e23\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/completeness.cc\n@@ -0,0 +1,19 @@\n+// { dg-do compile {target c++11 } }\n+\n+// C++17 [forwardlist.overview]\n+// An incomplete type T may be used when instantiating forward_list if the\n+// allocator satisfies the allocator completeness requirements (20.5.3.5.1).\n+// T shall be complete before any member of the resulting specialization\n+// of forward_list is referenced.\n+\n+#include <forward_list>\n+\n+struct Incomplete;\n+\n+// This instantiates std::forward_list, but none of its members.\n+const int sz = sizeof(std::forward_list<Incomplete>);\n+\n+// Technically the following references a member of std::forward_list,\n+// but because our iterators are SCARY it doesn't instantiate any members\n+// of std::forward_list.\n+std::forward_list<Incomplete>::iterator i{};\ndiff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr.cc\nnew file mode 100644\nindex 000000000000..2f382649d92b\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr.cc\n@@ -0,0 +1,86 @@\n+// { dg-do compile { target c++11 } }\n+\n+#include <forward_list>\n+#include <testsuite_allocator.h>\n+\n+// An allocator that uses __gnu_cxx::_Pointer_adapter as its pointer type.\n+template class std::forward_list<int, __gnu_test::CustomPointerAlloc<int>>;\n+\n+// Unlike __gnu_cxx::_Pointer_adapter, this fancy pointer supports neither\n+// implicit nor explicit conversions from raw pointers. The constructor from\n+// a raw pointer is explicit and requires a second parameter. The only way for\n+// containers to construct one of these pointers is pointer_traits::pointer_to.\n+template<typename T>\n+struct Pointer : __gnu_test::PointerBase<Pointer<T>, T>\n+{\n+  using Base = __gnu_test::PointerBase<Pointer<T>, T>;\n+\n+  Pointer() = default;\n+  Pointer(std::nullptr_t) : Base() { }\n+  explicit Pointer(T* p, int) : Base(p) { }\n+\n+  // Allow conversions to const_pointer and to void_pointer\n+  template<typename U, typename = typename std::enable_if<\n+    (!std::is_const<U>::value && std::is_same<T, const U>::value)\n+    || (std::is_void<T>::value && std::is_convertible<U*, T*>::value)\n+    >::type>\n+    Pointer(const Pointer<U>& p) : Base(p.operator->()) { }\n+\n+  template<typename U>\n+    static typename std::enable_if<std::is_same<U, T>::value, Pointer>::type\n+    pointer_to(U& t)\n+    { return Pointer(std::addressof(t), 1); }\n+};\n+\n+// A minimal allocator that uses Pointer as its pointer type.\n+template<typename T>\n+struct Allocator\n+{\n+  using value_type = T;\n+  using pointer = Pointer<T>;\n+\n+  Allocator() = default;\n+  template<typename U>\n+    Allocator(const Allocator<U>&) { }\n+\n+  pointer allocate(std::size_t n)\n+  { return pointer(std::allocator<T>().allocate(n), 1); }\n+\n+  void deallocate(pointer p, std::size_t n)\n+  {\n+    std::allocator<T>().deallocate(p.operator->(), n);\n+  }\n+\n+  bool operator==(const Allocator&) const { return true; }\n+  bool operator!=(const Allocator&) const { return false; }\n+};\n+\n+template class std::forward_list<int, Allocator<int>>;\n+\n+#include <testsuite_iterators.h>\n+\n+void\n+test_template_members(__gnu_test::input_container<short>& c)\n+{\n+  // Use member functions that are not included in explicit instantiations.\n+  std::forward_list<int, Allocator<int>> l(c.begin(), c.end());\n+  l.assign(c.begin(), c.end());\n+  l.insert_after(l.before_begin(), c.begin(), c.end());\n+  l.emplace_front(1);\n+  l.emplace_after(l.before_begin(), 1);\n+  l.remove_if([](int) { return false; });\n+  l.unique([](int, int) { return false; });\n+  l.merge(l, [](int, int) { return false; });\n+  l.merge(std::move(l), [](int, int) { return false; });\n+  l.sort([](int, int) { return false; });\n+\n+#ifdef __glibcxx_ranges_to_container\n+  short arr[2];\n+  __gnu_test::test_input_range<short> r(arr);\n+  std::forward_list<int, Allocator<int>> l2(std::from_range, r);\n+  l2.assign_range(r);\n+  l2.prepend_range(r);\n+  l2.insert_range_after(l2.begin(), r);\n+#endif\n+}\n+\ndiff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr_ignored.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr_ignored.cc\nnew file mode 100644\nindex 000000000000..6205a2ff3bf2\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/explicit_instantiation/alloc_ptr_ignored.cc\n@@ -0,0 +1,4 @@\n+// { dg-options \"-D_GLIBCXX_FWDLIST_USE_ALLOC_PTR=0\" }\n+// { dg-do compile { target c++11 } }\n+\n+#include \"alloc_ptr.cc\"\n",
    "prefixes": [
        "v1",
        "4/4"
    ]
}