Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2226653/?format=api
{ "id": 2226653, "url": "http://patchwork.ozlabs.org/api/patches/2226653/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhuns4iz5m.gcc.gcc-TEST.redi.38.1.1@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.hhuns4iz5m.gcc.gcc-TEST.redi.38.1.1@forge-stage.sourceware.org>", "list_archive_url": null, "date": "2026-04-22T18:00:21", "name": "[v1,1/1] libstdc++: Simplify __memcpyable_iterators concept", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "64c99c5f90d9f4ded93ad89ddfa9067424c210ca", "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.hhuns4iz5m.gcc.gcc-TEST.redi.38.1.1@forge-stage.sourceware.org/mbox/", "series": [ { "id": 501059, "url": "http://patchwork.ozlabs.org/api/series/501059/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=501059", "date": "2026-04-22T18:00:20", "name": "libstdc++: Simplify __memcpyable_iterators concept", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/501059/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2226653/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2226653/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=2620:52:6:3111::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\n [IPv6:2620:52:6:3111::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 4g16YM0sHlz1yD5\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 04:04:07 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 1D7394BBC0A6\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 18:04:05 +0000 (GMT)", "from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id 337E34BB5931\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 18:01:40 +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 046A342C13\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 18:01:40 +0000 (UTC)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 1D7394BBC0A6", "OpenDKIM Filter v2.11.0 sourceware.org 337E34BB5931" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 337E34BB5931", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 337E34BB5931", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776880900; cv=none;\n b=tM+vRpnhc6t3QBVBV6TqPS+MGxpPqRumxwB2vBN8fxSDfGpLDUs6FbPXiO0vv4tSQNWPA6BmKXflOkUWboetasq2p1lRMFq5lGRvbT25HhBHVUjvKnqXkPWLAPdC7vB56Veyq4vFhKxG9u6ggZABSV2Zck02lrPgAYy6JAHrteQ=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776880900; c=relaxed/simple;\n bh=eZTw6v5SbVYVb80MqrmxQN+SxNFihkLCI/95sCbl2RQ=;\n h=From:Date:Subject:To:Message-ID;\n b=nnjoGqtPs2a45oM8KYU24WOgEVjRcu5wKOa+n0jKN9+nkQ9nUEDA3CpYbBAdXOgYcUXnlR8IBeYBlPSII8jAT232ZWOTZgN5NufM+KDTWr4euNHLfSrSTg/1JOD4bB9n8tWHCmtxq5Alh7J6+2YfoHKotXs+fl2sXsB479qXtSQ=", "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 18:00:21 +0000", "Subject": "[PATCH v1 1/1] libstdc++: Simplify __memcpyable_iterators concept", "To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>", "Message-ID": "\n <bmm.hhuns4iz5m.gcc.gcc-TEST.redi.38.1.1@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/38", "References": "\n <bmm.hhuns4iz5m.gcc.gcc-TEST.redi.38.1.0@forge-stage.sourceware.org>", "In-Reply-To": "\n <bmm.hhuns4iz5m.gcc.gcc-TEST.redi.38.1.0@forge-stage.sourceware.org>", "X-Patch-URL": "\n https://forge.sourceware.org/redi/gcc/commit/d8b1644caadc53641de5c970761be157c8a9ab8f", "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\nMy P3349R1 paper clarifies that we should be able to lower contiguous\niterators to pointers, without worrying about side effects of individual\nincrement or dereference operations.\n\nWe do need to advance the iterators, and we need to use std::to_address\non the result of advancing them. This ensures that iterators with error\ndetection get a chance to diagnose bugs. If we don't use std::to_address\non the advanced iterator, it would be possible for a memcpy on the\npointers to overflow a buffer. By performing the += or -= operations and\nalso using std::to_address, we give the iterator a chance to abort,\nthrow, or call a violation handler before the buffer overflow happens.\n\nThe new tests only check the std::copy* algorithms, because std::move\nand std::move_backward use the same implementation details.\n\nlibstdc++-v3/ChangeLog:\n\n\t* include/bits/stl_algobase.h (__nothrow_contiguous_iterator):\n\tRemove.\n\t(__memcpyable_iterators): Simplify.\n\t(__copy_move_a2, __copy_n_a, __copy_move_backward_a2): Call\n\tstd::to_address on the iterators after advancing them.\n\t* testsuite/25_algorithms/copy/contiguous.cc: New test.\n\t* testsuite/25_algorithms/copy_backward/contiguous.cc: New test.\n\t* testsuite/25_algorithms/copy_n/contiguous.cc: New test.\n---\n libstdc++-v3/include/bits/stl_algobase.h | 39 +++-----\n .../25_algorithms/copy/contiguous.cc | 87 ++++++++++++++++++\n .../25_algorithms/copy_backward/contiguous.cc | 88 +++++++++++++++++++\n .../25_algorithms/copy_n/contiguous.cc | 87 ++++++++++++++++++\n 4 files changed, 276 insertions(+), 25 deletions(-)\n create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/contiguous.cc\n create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy_backward/contiguous.cc\n create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy_n/contiguous.cc", "diff": "diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h\nindex fc7cc89736a8..119dbe9a0936 100644\n--- a/libstdc++-v3/include/bits/stl_algobase.h\n+++ b/libstdc++-v3/include/bits/stl_algobase.h\n@@ -359,27 +359,13 @@ _GLIBCXX_END_NAMESPACE_CONTAINER\n #endif // HOSTED\n \n #if __cpp_lib_concepts\n- // N.B. this is not the same as nothrow-forward-iterator, which doesn't\n- // require noexcept operations, it just says it's undefined if they throw.\n- // Here we require them to be actually noexcept.\n- template<typename _Iter>\n- concept __nothrow_contiguous_iterator\n- = contiguous_iterator<_Iter> && requires (_Iter __i) {\n-\t// If this operation can throw then the iterator could cause\n-\t// the algorithm to exit early via an exception, in which case\n-\t// we can't use memcpy.\n-\t{ *__i } noexcept;\n- };\n-\n template<typename _OutIter, typename _InIter, typename _Sent = _InIter>\n concept __memcpyable_iterators\n- = __nothrow_contiguous_iterator<_OutIter>\n-\t && __nothrow_contiguous_iterator<_InIter>\n+ = contiguous_iterator<_OutIter> && contiguous_iterator<_InIter>\n \t && sized_sentinel_for<_Sent, _InIter>\n-\t && requires (_OutIter __o, _InIter __i, _Sent __s) {\n+\t && requires (_OutIter __o, _InIter __i) {\n \t requires !!__memcpyable<decltype(std::to_address(__o)),\n \t\t\t\t decltype(std::to_address(__i))>::__value;\n-\t { __i != __s } noexcept;\n \t };\n #endif\n \n@@ -457,9 +443,10 @@ _GLIBCXX_END_NAMESPACE_CONTAINER\n \t void* __dest = std::to_address(__result);\n \t const void* __src = std::to_address(__first);\n \t size_t __nbytes = __n * sizeof(iter_value_t<_InIter>);\n-\t // Advance the iterators first, in case doing so throws.\n-\t __result += __n;\n-\t __first += __n;\n+\t // Advance the iterators and convert to pointers first.\n+\t // This gives the iterators a chance to do bounds checking.\n+\t (void) std::to_address(__result += __n);\n+\t (void) std::to_address(__first += __n);\n \t __builtin_memmove(__dest, __src, __nbytes);\n \t }\n \t else if (__n == 1)\n@@ -579,9 +566,10 @@ _GLIBCXX_END_NAMESPACE_CONTAINER\n \t void* __dest = std::to_address(__result);\n \t const void* __src = std::to_address(__first);\n \t size_t __nbytes = __n * sizeof(iter_value_t<_InputIterator>);\n-\t // Advance the iterators first, in case doing so throws.\n-\t __result += __n;\n-\t __first += __n;\n+\t // Advance the iterators and convert to pointers first.\n+\t // This gives the iterators a chance to do bounds checking.\n+\t (void) std::to_address(__result += __n);\n+\t (void) std::to_address(__first += __n);\n \t __builtin_memmove(__dest, __src, __nbytes);\n \t }\n \t else if (__n == 1)\n@@ -727,9 +715,10 @@ _GLIBCXX_END_NAMESPACE_CONTAINER\n \t if (auto __n = __last - __first; __n > 1) [[likely]]\n \t {\n \t const void* __src = std::to_address(__first);\n-\t // Advance the iterators first, in case doing so throws.\n-\t __result -= __n;\n-\t __first += __n;\n+\t // Advance the iterators and convert to pointers first.\n+\t // This gives the iterators a chance to do bounds checking.\n+\t (void) std::to_address(__result -= __n);\n+\t (void) std::to_address(__first += __n);\n \t void* __dest = std::to_address(__result);\n \t size_t __nbytes = __n * sizeof(iter_value_t<_BI1>);\n \t __builtin_memmove(__dest, __src, __nbytes);\ndiff --git a/libstdc++-v3/testsuite/25_algorithms/copy/contiguous.cc b/libstdc++-v3/testsuite/25_algorithms/copy/contiguous.cc\nnew file mode 100644\nindex 000000000000..0fdce08ece8b\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/25_algorithms/copy/contiguous.cc\n@@ -0,0 +1,87 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <algorithm>\n+#include <iterator>\n+#include <cstdlib>\n+#include <testsuite_hooks.h>\n+\n+const int valid_size = 3;\n+const int out_of_bound = valid_size + 1;\n+// data is larger than valid_size so that `data + out_of_bound` does\n+// not have undefined behaviour, but data[valid_size] is not allowed\n+// to be accessed by Iter.\n+int data[valid_size + 1]{ 1, 2, 3, -999 };\n+\n+struct Iter\n+{\n+ using iterator_category = std::contiguous_iterator_tag;\n+ using value_type = int;\n+ using different_type = int;\n+ using reference = int&;\n+ using pointer = int*;\n+\n+ static inline bool advance_error = false;\n+ static inline bool address_error = false;\n+\n+ int index{};\n+\n+ int& operator*() const\n+ { std::abort(); } // Should not happen if reads/writes are done on pointers.\n+\n+ int* operator->() const\n+ {\n+ if (index < 0 || index > valid_size)\n+ {\n+ address_error = true;\n+ return data + valid_size;\n+ }\n+ return data + index;\n+ }\n+\n+ int& operator[](int n) const { return *(*this + n); }\n+\n+ Iter& operator++() { return *this += 1; }\n+ Iter& operator--() { return *this -= 1; }\n+ Iter operator++(int) { return Iter{index++}; }\n+ Iter operator--(int) { return Iter{index--}; }\n+\n+ bool operator==(const Iter&) const = default;\n+ auto operator<=>(const Iter&) const = default;\n+\n+ Iter& operator+=(int n)\n+ {\n+ index += n;\n+ if (index < 0 || index > valid_size)\n+ advance_error = true;\n+ return *this;\n+ }\n+ Iter& operator-=(int n) { return *this += -n; }\n+\n+ friend Iter operator+(Iter i, int n) { return i += n; }\n+ friend Iter operator+(int n, Iter i) { return i + n; }\n+ friend Iter operator-(Iter i, int n) { return i + -n; }\n+ friend int operator-(Iter i, Iter j) { return i.index - j.index; }\n+};\n+\n+static_assert( std::contiguous_iterator<Iter> );\n+\n+int main()\n+{\n+ // P3349R1 allows std::copy to lower contiguous iterators to pointers,\n+ // but it must still advance the contiguous iterator and use std::to_address\n+ // to get a pointer for both ends of the range.\n+ // This test verifies that Iter::operator-> is called for an out-of-range\n+ // iterator, so that a hardened iterator with error-checking is able to\n+ // detect the error.\n+\n+ int i[out_of_bound];\n+ // Attempt to read from an out-of-bound Iter:\n+ std::copy(Iter{0}, Iter{out_of_bound}, i);\n+ VERIFY( Iter::advance_error );\n+ VERIFY( Iter::address_error );\n+ Iter::advance_error = Iter::address_error = false;\n+ // Attempt to write to an out-of-bound Iter:\n+ std::copy(std::begin(i), std::end(i), Iter{0});\n+ VERIFY( Iter::advance_error );\n+ VERIFY( Iter::address_error );\n+}\ndiff --git a/libstdc++-v3/testsuite/25_algorithms/copy_backward/contiguous.cc b/libstdc++-v3/testsuite/25_algorithms/copy_backward/contiguous.cc\nnew file mode 100644\nindex 000000000000..b8cfa2ea5fdf\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/25_algorithms/copy_backward/contiguous.cc\n@@ -0,0 +1,88 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <algorithm>\n+#include <iterator>\n+#include <cstdlib>\n+#include <testsuite_hooks.h>\n+\n+const int valid_size = 3;\n+const int out_of_bound = valid_size + 1;\n+// array is larger than valid_size so that `data + out_of_bound` and `data - 1`\n+// do not have undefined behaviour, but data[valid_size] and data[-1] are\n+// not allowed to be accessed by Iter.\n+int array[1 + valid_size + 1]{ -999, 1, 2, 3, -999 };\n+int* data = array + 1;\n+\n+struct Iter\n+{\n+ using iterator_category = std::contiguous_iterator_tag;\n+ using value_type = int;\n+ using different_type = int;\n+ using reference = int&;\n+ using pointer = int*;\n+\n+ static inline bool advance_error = false;\n+ static inline bool address_error = false;\n+\n+ int index{};\n+\n+ int& operator*() const\n+ { std::abort(); } // Should not happen if reads/writes are done on pointers.\n+\n+ int* operator->() const\n+ {\n+ if (index < 0 || index > valid_size)\n+ {\n+ address_error = true;\n+ return data;\n+ }\n+ return data + index;\n+ }\n+\n+ int& operator[](int n) const { return *(*this + n); }\n+\n+ Iter& operator++() { return *this += 1; }\n+ Iter& operator--() { return *this -= 1; }\n+ Iter operator++(int) { return Iter{index++}; }\n+ Iter operator--(int) { return Iter{index--}; }\n+\n+ bool operator==(const Iter&) const = default;\n+ auto operator<=>(const Iter&) const = default;\n+\n+ Iter& operator+=(int n)\n+ {\n+ index += n;\n+ if (index < 0 || index > valid_size)\n+ advance_error = true;\n+ return *this;\n+ }\n+ Iter& operator-=(int n) { return *this += -n; }\n+\n+ friend Iter operator+(Iter i, int n) { return i += n; }\n+ friend Iter operator+(int n, Iter i) { return i + n; }\n+ friend Iter operator-(Iter i, int n) { return i + -n; }\n+ friend int operator-(Iter i, Iter j) { return i.index - j.index; }\n+};\n+\n+static_assert( std::contiguous_iterator<Iter> );\n+\n+int main()\n+{\n+ // P3349R1 allows std::copy_backward to lower contiguous iterators to pointers\n+ // but it must still advance the contiguous iterator and use std::to_address\n+ // to get a pointer for both ends of the range.\n+ // This test verifies that Iter::operator-> is called for an out-of-range\n+ // iterator, so that a hardened iterator with error-checking is able to\n+ // detect the error.\n+\n+ int i[out_of_bound];\n+ // Attempt to read from an out-of-bound Iter:\n+ std::copy_backward(Iter{0}, Iter{out_of_bound}, i + out_of_bound);\n+ VERIFY( Iter::advance_error );\n+ VERIFY( Iter::address_error );\n+ Iter::advance_error = Iter::address_error = false;\n+ // Attempt to write to an out-of-bound Iter with index -1:\n+ std::copy_backward(std::begin(i), std::end(i), Iter{valid_size});\n+ VERIFY( Iter::advance_error );\n+ VERIFY( Iter::address_error );\n+}\ndiff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/contiguous.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/contiguous.cc\nnew file mode 100644\nindex 000000000000..b5f00f5d1bc1\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/contiguous.cc\n@@ -0,0 +1,87 @@\n+// { dg-do run { target c++20 } }\n+\n+#include <algorithm>\n+#include <iterator>\n+#include <cstdlib>\n+#include <testsuite_hooks.h>\n+\n+const int valid_size = 3;\n+const int out_of_bound = valid_size + 1;\n+// data is larger than valid_size so that `data + out_of_bound` does\n+// not have undefined behaviour, but data[valid_size] is not allowed\n+// to be accessed by Iter.\n+int data[valid_size + 1]{ 1, 2, 3, -999 };\n+\n+struct Iter\n+{\n+ using iterator_category = std::contiguous_iterator_tag;\n+ using value_type = int;\n+ using different_type = int;\n+ using reference = int&;\n+ using pointer = int*;\n+\n+ static inline bool advance_error = false;\n+ static inline bool address_error = false;\n+\n+ int index{};\n+\n+ int& operator*() const\n+ { std::abort(); } // Should not happen if reads/writes are done on pointers.\n+\n+ int* operator->() const\n+ {\n+ if (index < 0 || index > valid_size)\n+ {\n+ address_error = true;\n+ return data + valid_size;\n+ }\n+ return data + index;\n+ }\n+\n+ int& operator[](int n) const { return *(*this + n); }\n+\n+ Iter& operator++() { return *this += 1; }\n+ Iter& operator--() { return *this -= 1; }\n+ Iter operator++(int) { return Iter{index++}; }\n+ Iter operator--(int) { return Iter{index--}; }\n+\n+ bool operator==(const Iter&) const = default;\n+ auto operator<=>(const Iter&) const = default;\n+\n+ Iter& operator+=(int n)\n+ {\n+ index += n;\n+ if (index < 0 || index > valid_size)\n+ advance_error = true;\n+ return *this;\n+ }\n+ Iter& operator-=(int n) { return *this += -n; }\n+\n+ friend Iter operator+(Iter i, int n) { return i += n; }\n+ friend Iter operator+(int n, Iter i) { return i + n; }\n+ friend Iter operator-(Iter i, int n) { return i + -n; }\n+ friend int operator-(Iter i, Iter j) { return i.index - j.index; }\n+};\n+\n+static_assert( std::contiguous_iterator<Iter> );\n+\n+int main()\n+{\n+ // P3349R1 allows std::copy_n to lower contiguous iterators to pointers,\n+ // but it must still advance the contiguous iterator and use std::to_address\n+ // to get a pointer for both ends of the range.\n+ // This test verifies that Iter::operator-> is called for an out-of-range\n+ // iterator, so that a hardened iterator with error-checking is able to\n+ // detect the error.\n+\n+ int i[out_of_bound];\n+ // Attempt to read from an out-of-bound Iter:\n+ std::copy_n(Iter{0}, out_of_bound, i);\n+ VERIFY( Iter::advance_error );\n+ VERIFY( Iter::address_error );\n+ Iter::advance_error = Iter::address_error = false;\n+ // Attempt to write to an out-of-bound Iter:\n+ std::copy_n(std::begin(i), out_of_bound, Iter{0});\n+ VERIFY( Iter::advance_error );\n+ VERIFY( Iter::address_error );\n+}\n", "prefixes": [ "v1", "1/1" ] }