Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2224450/?format=api
{ "id": 2224450, "url": "http://patchwork.ozlabs.org/api/patches/2224450/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260417124712.324159-1-jwakely@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": "<20260417124712.324159-1-jwakely@redhat.com>", "list_archive_url": null, "date": "2026-04-17T12:45:36", "name": "[committed,v2] libstdc++: Optionally define std::print functions non-inline [PR124410]", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "0c53d853ea71b23c9d743c7d1475430653e5da53", "submitter": { "id": 48004, "url": "http://patchwork.ozlabs.org/api/people/48004/?format=api", "name": "Jonathan Wakely", "email": "jwakely@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260417124712.324159-1-jwakely@redhat.com/mbox/", "series": [ { "id": 500328, "url": "http://patchwork.ozlabs.org/api/series/500328/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=500328", "date": "2026-04-17T12:45:36", "name": "[committed,v2] libstdc++: Optionally define std::print functions non-inline [PR124410]", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/500328/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2224450/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2224450/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=d0sa8ekW;\n\tdkim-atps=neutral", "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;\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=d0sa8ekW", "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\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 4fxvn154Vwz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 22:48:04 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 1D1F04AA3971\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 12:48:02 +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 7AB434BA2E32\n for <gcc-patches@gcc.gnu.org>; Fri, 17 Apr 2026 12:47:20 +0000 (GMT)", "from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-60-Mg-7o3SGMn-1lsHBdWwOdw-1; Fri,\n 17 Apr 2026 08:47:16 -0400", "from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id A2B5818002C6; Fri, 17 Apr 2026 12:47:15 +0000 (UTC)", "from zen.kayari.org (unknown [10.44.48.52])\n by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id ADC70195608E; Fri, 17 Apr 2026 12:47:13 +0000 (UTC)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 1D1F04AA3971", "OpenDKIM Filter v2.11.0 sourceware.org 7AB434BA2E32" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 7AB434BA2E32", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 7AB434BA2E32", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776430040; cv=none;\n b=Zr4xL54d9tN6HcvIx2eZMAjcPXfGj2MCcS+F3GgK3RwJ4KjUzjUQ/SPstGkKCoNH0dmRYOEFiCVkhHdvS4K9JaHcD+rtBs4gUXIyLsg3IQVASBy8lman8u7OVpzgL1qhWZA5hoI+NNNrIrQrmggmqqqPxY0KEW+jgF1BaNxR5Tg=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776430040; c=relaxed/simple;\n bh=gtHHUg02dKbb7Bak095xjV75oW1QBRv9vg0J4T2tS+c=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=rISQSfh8f2sGId2vBVp2hVm7DfF2bhMGi64RNgQvd6RDz/gPWHIpu7qrzU3ZVJwPGJYOi0RrEJvWVTmwys9lj2MVNl0zg7AW6Xqpl+KePtWMYPHxCYxcINvA5ayMo7evhlwZVM3rMYD75assBOsPXd2FBZEcRL0avdvgO2N1g0Y=", "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=1776430040;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding;\n bh=O9QQMAG9dhbqa4h+bXZEi5ncMAav8MruVHNz694E/Ss=;\n b=d0sa8ekWoN4iq0xPEssmMrtuJ3n43qGjO/2QZYOAuQh2u72VftIXmvrwldSbGCOMAUXSsP\n ooF7T/j9Uh79FmtX10znkX6Ioliql7vgXX8njwXdW6Ib8nSorePJqsfp4fRERbAvL49Ica\n vtXdLicPLZ5qkNT9f5jSsoYre1zWWWI=", "X-MC-Unique": "Mg-7o3SGMn-1lsHBdWwOdw-1", "X-Mimecast-MFC-AGG-ID": "Mg-7o3SGMn-1lsHBdWwOdw_1776430035", "From": "Jonathan Wakely <jwakely@redhat.com>", "To": "libstdc++@gcc.gnu.org,\n\tgcc-patches@gcc.gnu.org", "Subject": "[committed v2] libstdc++: Optionally define std::print functions\n non-inline [PR124410]", "Date": "Fri, 17 Apr 2026 13:45:36 +0100", "Message-ID": "<20260417124712.324159-1-jwakely@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.17", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "r5GtzYF73j-5sjGrhIy2WrVFgAXVHQ_zaW-HEfInWnw_1776430035", "X-Mimecast-Originator": "redhat.com", "Content-Type": "text/plain", "Content-Transfer-Encoding": "quoted-printable", "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": "We don't want to export std::vprint_unicode etc. from libstdc++.so yet,\nbut we can give users the option of improving compile times by getting\nthe definitions of the std::print internals from libstdc++exp.a instead.\n\nThis commit adds a macro, _GLIBCXX_NO_INLINE_PRINT, which disables the\ninline definitions of std::vprint_unicode etc. so that extern\ndefinitions in libstdc++exp.a can be used instead.\n\nWith this change compiling a helloworld using std::print goes from 8s to\nunder 2s with trunk. For release branches with --enable-checking=release\nwe should see even faster times. The object file size is also\ndramatically smaller, because there's just a single call to an extern\nfunction instead of instantiating the entire std::print and std::format\nimplementation inline.\n\nlibstdc++-v3/ChangeLog:\n\n\tPR libstdc++/124410\n\t* doc/html/*: Regenerate.\n\t* doc/xml/manual/using.xml (_GLIBCXX_NO_INLINE_PRINT): Document\n\tmacro.\n\t* include/Makefile.am: Add bits/print.h and bits/ostream_print.h\n\theaders.\n\t* include/Makefile.in: Regenerate.\n\t* include/std/ostream (vprint_nonunicode, vprint_unicode): Move\n\tdefinitions to new bits/ostream_print.h header.\n\t* include/std/print (__format::_File_sink, vprint_nonunicode)\n\t(vprint_nonunicode_buffered, vprint_unicode)\n\t(vprint_unicode_buffered): Move definitions to new bits/print.h\n\theader.\n\t* src/c++23/print.cc: Include new headers to define symbols for\n\tinline print functions.\n\t* include/bits/ostream_print.h: New file.\n\t* include/bits/print.h: New file.\n---\n\nv2: Added a sentence to the docs about linking to the non-inline\ndefinitions from a TU with a non-UTF-8 literal encoding.\n\nTested x86_64-linux, aarch64-linux, sparc-solaris.\nPushed to trunk.\n\n libstdc++-v3/doc/html/index.html | 4 +-\n libstdc++-v3/doc/html/manual/using.html | 2 +\n .../doc/html/manual/using_macros.html | 9 +\n libstdc++-v3/doc/xml/manual/using.xml | 15 +\n libstdc++-v3/include/Makefile.am | 2 +\n libstdc++-v3/include/Makefile.in | 2 +\n libstdc++-v3/include/bits/ostream_print.h | 161 +++++++++\n libstdc++-v3/include/bits/print.h | 339 ++++++++++++++++++\n libstdc++-v3/include/std/ostream | 112 +-----\n libstdc++-v3/include/std/print | 295 ++-------------\n libstdc++-v3/src/c++23/print.cc | 7 +\n 11 files changed, 583 insertions(+), 365 deletions(-)\n create mode 100644 libstdc++-v3/include/bits/ostream_print.h\n create mode 100644 libstdc++-v3/include/bits/print.h", "diff": "diff --git a/libstdc++-v3/doc/html/index.html b/libstdc++-v3/doc/html/index.html\nindex 01d7bb787dce..782f3bbc299c 100644\n--- a/libstdc++-v3/doc/html/index.html\n+++ b/libstdc++-v3/doc/html/index.html\n@@ -1,6 +1,6 @@\n <?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n-<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\"><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /><title>The GNU C++ Library</title><meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\" /><meta name=\"description\" content=\"Short Contents Copyright (C) 2008-2025 FSF Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. This is the top level of the libstdc++ documentation set. The documentation is divided into the following three sections. Manual Frequently Asked Questions API and Source Documentation\" /><meta name=\"keywords\" content=\"ISO C++, runtime, library\" /><link rel=\"home\" href=\"index.html\" title=\"The GNU C++ Library\" /><link rel=\"next\" href=\"manual/index.html\" title=\"The GNU C++ Library Manual\" /></head><body><div class=\"navheader\"><table width=\"100%\" summary=\"Navigation header\"><tr><th colspan=\"3\" align=\"center\">The GNU C++ Library</th></tr><tr><td width=\"20%\" align=\"left\"> </td><th width=\"60%\" align=\"center\"> </th><td width=\"20%\" align=\"right\"> <a accesskey=\"n\" href=\"manual/index.html\">Next</a></td></tr></table><hr /></div><div class=\"set\" lang=\"en\" xml:lang=\"en\"><div class=\"titlepage\"><div><div><h1 class=\"title\"><a id=\"set-index\"></a>The GNU C++ Library</h1></div><div><div class=\"abstract\"><a id=\"contents\"></a><p class=\"title\"><strong>Short Contents</strong></p><p>\n- Copyright (C) 2008-2025\n+<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\"><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /><title>The GNU C++ Library</title><meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\" /><meta name=\"description\" content=\"Short Contents Copyright (C) 2008-2026 FSF Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. This is the top level of the libstdc++ documentation set. The documentation is divided into the following three sections. Manual Frequently Asked Questions API and Source Documentation\" /><meta name=\"keywords\" content=\"ISO C++, runtime, library\" /><link rel=\"home\" href=\"index.html\" title=\"The GNU C++ Library\" /><link rel=\"next\" href=\"manual/index.html\" title=\"The GNU C++ Library Manual\" /></head><body><div class=\"navheader\"><table width=\"100%\" summary=\"Navigation header\"><tr><th colspan=\"3\" align=\"center\">The GNU C++ Library</th></tr><tr><td width=\"20%\" align=\"left\"> </td><th width=\"60%\" align=\"center\"> </th><td width=\"20%\" align=\"right\"> <a accesskey=\"n\" href=\"manual/index.html\">Next</a></td></tr></table><hr /></div><div class=\"set\" lang=\"en\" xml:lang=\"en\"><div class=\"titlepage\"><div><div><h1 class=\"title\"><a id=\"set-index\"></a>The GNU C++ Library</h1></div><div><div class=\"abstract\"><a id=\"contents\"></a><p class=\"title\"><strong>Short Contents</strong></p><p>\n+ Copyright (C) 2008-2026\n <a class=\"link\" href=\"https://www.fsf.org\" target=\"_top\">FSF\n </a>\n </p><p>\ndiff --git a/libstdc++-v3/doc/html/manual/using.html b/libstdc++-v3/doc/html/manual/using.html\nindex fcd1b96de0d7..27f503ecaccc 100644\n--- a/libstdc++-v3/doc/html/manual/using.html\n+++ b/libstdc++-v3/doc/html/manual/using.html\n@@ -34,6 +34,8 @@\n is required for use of experimental C++ library features.\n This currently provides support for the C++23 types defined in the\n <code class=\"filename\"><stacktrace></code> header,\n+\tthe C++23 functions defined in the\n+\t<code class=\"filename\"><print></code> header,\n the Filesystem library extensions defined in the\n <code class=\"filename\"><experimental/filesystem></code>\n header,\ndiff --git a/libstdc++-v3/doc/html/manual/using_macros.html b/libstdc++-v3/doc/html/manual/using_macros.html\nindex b1d05d99d760..f1d8492fb9ef 100644\n--- a/libstdc++-v3/doc/html/manual/using_macros.html\n+++ b/libstdc++-v3/doc/html/manual/using_macros.html\n@@ -147,4 +147,13 @@\n \tmode will revert to the non-conforming implementation used prior to the\n \t<a class=\"link\" href=\"https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112591\" target=\"_top\">PR112591</a>\n \tin GCC-16. Has no impact for C++20 or later modes.\n+ </p></dd><dt><span class=\"term\"><code class=\"code\">_GLIBCXX_NO_INLINE_PRINT</code></span></dt><dd><p>\n+\tUndefined by default. When defined <code class=\"code\">std::print</code> and\n+\t<code class=\"code\">std::println</code> are not implemented using inline functions.\n+\tThis means that code using those functions will compile faster,\n+\tbut <code class=\"option\">-lstdc++exp</code> must be used when linking.\n+\tThe non-inline definitions are compiled using\n+\t<code class=\"option\">-fexec-charset=UTF-8</code> so might give incorrect results\n+\tif called from a source file that uses a non-Unicode encoding,\n+\tespecially for format strings using non-ASCII fill characters.\n </p></dd></dl></div></div><div class=\"navfooter\"><hr /><table width=\"100%\" summary=\"Navigation footer\"><tr><td width=\"40%\" align=\"left\"><a accesskey=\"p\" href=\"using_headers.html\">Prev</a> </td><td width=\"20%\" align=\"center\"><a accesskey=\"u\" href=\"using.html\">Up</a></td><td width=\"40%\" align=\"right\"> <a accesskey=\"n\" href=\"using_dual_abi.html\">Next</a></td></tr><tr><td width=\"40%\" align=\"left\" valign=\"top\">Headers </td><td width=\"20%\" align=\"center\"><a accesskey=\"h\" href=\"../index.html\">Home</a></td><td width=\"40%\" align=\"right\" valign=\"top\"> Dual ABI</td></tr></table></div></body></html>\n\\ No newline at end of file\ndiff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml\nindex 8adfecfe54ba..682669d91d4b 100644\n--- a/libstdc++-v3/doc/xml/manual/using.xml\n+++ b/libstdc++-v3/doc/xml/manual/using.xml\n@@ -83,6 +83,8 @@\n is required for use of experimental C++ library features.\n This currently provides support for the C++23 types defined in the\n <filename class=\"headerfile\"><stacktrace></filename> header,\n+\tthe C++23 functions defined in the\n+\t<filename class=\"headerfile\"><print></filename> header,\n the Filesystem library extensions defined in the\n <filename class=\"headerfile\"><experimental/filesystem></filename>\n header,\n@@ -1363,6 +1365,19 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe\n \tin GCC-16. Has no impact for C++20 or later modes.\n </para>\n </listitem></varlistentry>\n+ <varlistentry><term><code>_GLIBCXX_NO_INLINE_PRINT</code></term>\n+ <listitem>\n+ <para>\n+\tUndefined by default. When defined <code>std::print</code> and\n+\t<code>std::println</code> are not implemented using inline functions.\n+\tThis means that code using those functions will compile faster,\n+\tbut <option>-lstdc++exp</option> must be used when linking.\n+\tThe non-inline definitions are compiled using\n+\t<option>-fexec-charset=UTF-8</option> so might give incorrect results\n+\tif called from a source file that uses a non-Unicode encoding,\n+\tespecially for format strings using non-ASCII fill characters.\n+ </para>\n+ </listitem></varlistentry>\n </variablelist>\n \n </section>\ndiff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am\nindex d0c97370700b..e9e46139da2f 100644\n--- a/libstdc++-v3/include/Makefile.am\n+++ b/libstdc++-v3/include/Makefile.am\n@@ -244,7 +244,9 @@ bits_headers = \\\n \t${bits_srcdir}/node_handle.h \\\n \t${bits_srcdir}/ostream.tcc \\\n \t${bits_srcdir}/ostream_insert.h \\\n+\t${bits_srcdir}/ostream_print.h \\\n \t${bits_srcdir}/postypes.h \\\n+\t${bits_srcdir}/print.h \\\n \t${bits_srcdir}/quoted_string.h \\\n \t${bits_srcdir}/random.h \\\n \t${bits_srcdir}/random.tcc \\\ndiff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in\nindex a57fc00ce742..f3d2f58dbe42 100644\n--- a/libstdc++-v3/include/Makefile.in\n+++ b/libstdc++-v3/include/Makefile.in\n@@ -600,7 +600,9 @@ bits_freestanding = \\\n @GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/node_handle.h \\\n @GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/ostream.tcc \\\n @GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/ostream_insert.h \\\n+@GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/ostream_print.h \\\n @GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/postypes.h \\\n+@GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/print.h \\\n @GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/quoted_string.h \\\n @GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/random.h \\\n @GLIBCXX_HOSTED_TRUE@\t${bits_srcdir}/random.tcc \\\ndiff --git a/libstdc++-v3/include/bits/ostream_print.h b/libstdc++-v3/include/bits/ostream_print.h\nnew file mode 100644\nindex 000000000000..0adf16d4fe3e\n--- /dev/null\n+++ b/libstdc++-v3/include/bits/ostream_print.h\n@@ -0,0 +1,161 @@\n+// Inline implementation details for std::print functions -*- C++ -*-\n+\n+// Copyright The GNU Toolchain Authors.\n+//\n+// This file is part of the GNU ISO C++ Library. This library is free\n+// software; you can redistribute it and/or modify it under the\n+// terms of the GNU General Public License as published by the\n+// Free Software Foundation; either version 3, or (at your option)\n+// any later version.\n+\n+// This library is distributed in the hope that it will be useful,\n+// but WITHOUT ANY WARRANTY; without even the implied warranty of\n+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+// GNU General Public License for more details.\n+\n+// Under Section 7 of GPL version 3, you are granted additional\n+// permissions described in the GCC Runtime Library Exception, version\n+// 3.1, as published by the Free Software Foundation.\n+\n+// You should have received a copy of the GNU General Public License and\n+// a copy of the GCC Runtime Library Exception along with this program;\n+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see\n+// <http://www.gnu.org/licenses/>.\n+\n+/** @file include/bits/ostream_print.h\n+ * This is an internal header file, included by other library headers.\n+ * Do not attempt to use it directly. @headername{ostream}\n+ *\n+ * This file contains the parts of `<ostream>` which are currently defined\n+ * inline, but should be moved into the library eventually.\n+ */\n+\n+#ifndef _GLIBCXX_OSTREAM_PRINT_H\n+#define _GLIBCXX_OSTREAM_PRINT_H 1\n+\n+#ifdef _GLIBCXX_SYSHDR\n+#pragma GCC system_header\n+#endif\n+\n+#include <bits/requires_hosted.h> // for std::format\n+\n+#include <bits/version.h>\n+\n+#ifdef __glibcxx_print // C++ >= 23\n+#include <format>\n+\n+namespace std _GLIBCXX_VISIBILITY(default)\n+{\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+\n+#ifdef _GLIBCXX_NO_INLINE_PRINT\n+# define _GLIBCXX_PRINT_INLINE_USED [[__gnu__::__used__]]\n+#else\n+# define _GLIBCXX_PRINT_INLINE_USED\n+#endif\n+\n+ _GLIBCXX_PRINT_INLINE_USED\n+ inline void\n+ vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args)\n+ {\n+ ostream::sentry __cerb(__os);\n+ if (__cerb)\n+ {\n+\t__format::_Str_sink<char> __buf;\n+\tstd::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);\n+\tauto __out = __buf.view();\n+\n+\t__try\n+\t {\n+\t std::__ostream_write(__os, __out.data(), __out.size());\n+\t }\n+\t__catch(const __cxxabiv1::__forced_unwind&)\n+\t {\n+\t __os._M_setstate(ios_base::badbit);\n+\t __throw_exception_again;\n+\t }\n+\t__catch(...)\n+\t { __os._M_setstate(ios_base::badbit); }\n+ }\n+ }\n+\n+ _GLIBCXX_PRINT_INLINE_USED\n+ inline void\n+ vprint_unicode(ostream& __os, string_view __fmt, format_args __args)\n+ {\n+#if !defined(_WIN32) || defined(__CYGWIN__)\n+ // For most targets we don't need to do anything special to write\n+ // Unicode to a terminal.\n+ std::vprint_nonunicode(__os, __fmt, __args);\n+#else\n+ ostream::sentry __cerb(__os);\n+ if (__cerb)\n+ {\n+\t__format::_Str_sink<char> __buf;\n+\tstd::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);\n+\tauto __out = __buf._M_span();\n+\n+\tvoid* __open_terminal(streambuf*);\n+\terror_code __write_to_terminal(void*, span<char>);\n+\t// If stream refers to a terminal, write a Unicode string to it.\n+\tif (auto __term = __open_terminal(__os.rdbuf()))\n+\t {\n+#if !defined(_WIN32) || defined(__CYGWIN__)\n+\t // For POSIX, __open_terminal(streambuf*) uses fdopen to open a\n+\t // new file, so we would need to close it here. This code is not\n+\t // actually compiled because it's inside an #ifdef _WIN32 group,\n+\t // but just in case that changes in future ...\n+\t struct _Guard\n+\t {\n+\t _Guard(void* __p) : _M_f((FILE*)__p) { }\n+\t ~_Guard() { std::fclose(_M_f); }\n+\t _Guard(_Guard&&) = delete;\n+\t _Guard& operator=(_Guard&&) = delete;\n+\t FILE* _M_f;\n+\t };\n+\t _Guard __g(__term);\n+#endif\n+\n+\t ios_base::iostate __err = ios_base::goodbit;\n+\t __try\n+\t {\n+\t\tif (__os.rdbuf()->pubsync() == -1)\n+\t\t __err = ios::badbit;\n+\t\telse if (auto __e = __write_to_terminal(__term, __out))\n+\t\t if (__e != std::make_error_code(errc::illegal_byte_sequence))\n+\t\t __err = ios::badbit;\n+\t }\n+\t __catch(const __cxxabiv1::__forced_unwind&)\n+\t {\n+\t\t__os._M_setstate(ios_base::badbit);\n+\t\t__throw_exception_again;\n+\t }\n+\t __catch(...)\n+\t { __os._M_setstate(ios_base::badbit); }\n+\n+\t if (__err)\n+\t __os.setstate(__err);\n+\t return;\n+\t }\n+\n+\t// Otherwise just insert the string as vprint_nonunicode does.\n+\t__try\n+\t {\n+\t std::__ostream_write(__os, __out.data(), __out.size());\n+\t }\n+\t__catch(const __cxxabiv1::__forced_unwind&)\n+\t {\n+\t __os._M_setstate(ios_base::badbit);\n+\t __throw_exception_again;\n+\t }\n+\t__catch(...)\n+\t { __os._M_setstate(ios_base::badbit); }\n+ }\n+#endif // _WIN32\n+ }\n+#undef _GLIBCXX_PRINT_INLINE_USED\n+\n+_GLIBCXX_END_NAMESPACE_VERSION\n+} // namespace std\n+#endif // __glibcxx_print\n+#endif // _GLIBCXX_OSTREAM_PRINT_H\ndiff --git a/libstdc++-v3/include/bits/print.h b/libstdc++-v3/include/bits/print.h\nnew file mode 100644\nindex 000000000000..67a5a1729135\n--- /dev/null\n+++ b/libstdc++-v3/include/bits/print.h\n@@ -0,0 +1,339 @@\n+// Inline implementation details for std::print functions -*- C++ -*-\n+\n+// Copyright The GNU Toolchain Authors.\n+//\n+// This file is part of the GNU ISO C++ Library. This library is free\n+// software; you can redistribute it and/or modify it under the\n+// terms of the GNU General Public License as published by the\n+// Free Software Foundation; either version 3, or (at your option)\n+// any later version.\n+\n+// This library is distributed in the hope that it will be useful,\n+// but WITHOUT ANY WARRANTY; without even the implied warranty of\n+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+// GNU General Public License for more details.\n+\n+// Under Section 7 of GPL version 3, you are granted additional\n+// permissions described in the GCC Runtime Library Exception, version\n+// 3.1, as published by the Free Software Foundation.\n+\n+// You should have received a copy of the GNU General Public License and\n+// a copy of the GCC Runtime Library Exception along with this program;\n+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see\n+// <http://www.gnu.org/licenses/>.\n+\n+/** @file include/bits/print.h\n+ * This is an internal header file, included by other library headers.\n+ * Do not attempt to use it directly. @headername{print}\n+ *\n+ * This file contains the parts of `<print>` which are currently defined\n+ * inline, but should be moved into the library eventually.\n+ */\n+\n+#ifndef _GLIBCXX_PRINT_H\n+#define _GLIBCXX_PRINT_H 1\n+\n+#ifdef _GLIBCXX_SYSHDR\n+#pragma GCC system_header\n+#endif\n+\n+#include <bits/requires_hosted.h> // for std::format\n+\n+#include <bits/version.h>\n+\n+#ifdef __glibcxx_print // C++ >= 23\n+\n+#include <format>\n+#include <cstdio> // FILE, EOF, flockfile, etc.\n+#include <cerrno> // EACCES, EIO\n+#include <bits/functexcept.h> // __throw_system_error\n+\n+#ifdef _WIN32\n+# include <system_error> // system_error\n+#endif\n+\n+namespace std _GLIBCXX_VISIBILITY(default)\n+{\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+\n+namespace __format\n+{\n+#if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLIBC_STDIO_EXT\n+ // These are defined in <stdio_ext.h> but we don't want to include that.\n+ extern \"C\" int __fwritable(FILE*) noexcept;\n+ extern \"C\" int __flbf(FILE*) noexcept;\n+ extern \"C\" size_t __fbufsize(FILE*) noexcept;\n+\n+ // A format sink that writes directly to a Glibc FILE.\n+ // The file is locked on construction and its buffer is accessed directly.\n+ class _File_sink final : _Buf_sink<char>\n+ {\n+ struct _File\n+ {\n+ explicit\n+ _File(FILE* __f) : _M_file(__f)\n+ {\n+\t::flockfile(__f);\n+\t// Ensure stream is in write mode\n+\tif (!__fwritable(__f))\n+\t {\n+\t ::funlockfile(__f);\n+\t __throw_system_error(EACCES);\n+\t }\n+\t// Allocate buffer if needed:\n+\tif (_M_write_buf().empty())\n+\t if (::__overflow(__f, EOF) == EOF)\n+\t {\n+\t const int __err = errno;\n+\t ::funlockfile(__f);\n+\t __throw_system_error(__err);\n+\t }\n+ }\n+\n+ ~_File() { ::funlockfile(_M_file); }\n+\n+ _File(_File&&) = delete;\n+\n+ // A span viewing the unused portion of the stream's output buffer.\n+ std::span<char>\n+ _M_write_buf() noexcept\n+ {\n+\treturn {_M_file->_IO_write_ptr,\n+\t\tsize_t(_M_file->_IO_buf_end - _M_file->_IO_write_ptr)};\n+ }\n+\n+ // Flush the output buffer to the file so we can write to it again.\n+ void\n+ _M_flush()\n+ {\n+\tif (::fflush_unlocked(_M_file))\n+\t __throw_system_error(errno);\n+ }\n+\n+ // Update the current position in the output buffer.\n+ void\n+ _M_bump(size_t __n) noexcept\n+ { _M_file->_IO_write_ptr += __n; }\n+\n+ bool\n+ _M_line_buffered() const noexcept\n+ { return __flbf(_M_file); } // Or: _M_file->_flags & 0x200\n+\n+ bool\n+ _M_unbuffered() const noexcept\n+ { return __fbufsize(_M_file) == 1; } // Or: _M_file->_flags & 0x2\n+\n+ FILE* _M_file;\n+ } _M_file;\n+\n+ bool _M_add_newline; // True for std::println, false for std::print.\n+\n+ // Flush the stream's put area so it can be refilled.\n+ void\n+ _M_overflow() override\n+ {\n+ auto __s = this->_M_used();\n+ if (__s.data() == this->_M_buf)\n+\t{\n+\t // Characters in internal buffer need to be transferred to the FILE.\n+\t auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(),\n+\t\t\t\t _M_file._M_file);\n+\t if (__n != __s.size())\n+\t __throw_system_error(errno);\n+\t this->_M_reset(this->_M_buf);\n+\t}\n+ else\n+\t{\n+\t // Characters were written directly to the FILE's output buffer.\n+\t _M_file._M_bump(__s.size());\n+\t _M_file._M_flush();\n+\t this->_M_reset(_M_file._M_write_buf());\n+\t}\n+ }\n+\n+ public:\n+ _File_sink(FILE* __f, bool __add_newline)\n+ : _M_file(__f), _M_add_newline(__add_newline)\n+ {\n+ if (!_M_file._M_unbuffered())\n+\t// Write directly to the FILE's output buffer.\n+\tthis->_M_reset(_M_file._M_write_buf());\n+ }\n+\n+ ~_File_sink() noexcept(false)\n+ {\n+ auto __s = this->_M_used();\n+ if (__s.data() == this->_M_buf) // Unbuffered stream\n+\t{\n+\t _File_sink::_M_overflow();\n+\t if (_M_add_newline)\n+\t ::putc_unlocked('\\n', _M_file._M_file);\n+\t}\n+ else\n+\t{\n+\t _M_file._M_bump(__s.size());\n+\t if (_M_add_newline)\n+\t ::putc_unlocked('\\n', _M_file._M_file);\n+\t else if (_M_file._M_line_buffered() && __s.size()\n+\t\t && (__s.back() == '\\n'\n+\t\t\t || __builtin_memchr(__s.data(), '\\n', __s.size())))\n+\t _M_file._M_flush();\n+\t}\n+ }\n+\n+ using _Sink<char>::out;\n+ };\n+#elif _GLIBCXX_USE_STDIO_LOCKING\n+ // A format sink that buffers output and then copies it to a stdio FILE.\n+ // The file is locked on construction and written to using fwrite_unlocked.\n+ class _File_sink final : _Buf_sink<char>\n+ {\n+ FILE* _M_file;\n+ bool _M_add_newline;\n+\n+ // Transfer buffer contents to the FILE, so buffer can be refilled.\n+ void\n+ _M_overflow() override\n+ {\n+ auto __s = this->_M_used();\n+#if _GLIBCXX_HAVE_FWRITE_UNLOCKED\n+ auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file);\n+ if (__n != __s.size())\n+\t__throw_system_error(errno);\n+#else\n+ for (char __c : __s)\n+\t::putc_unlocked(__c, _M_file);\n+ if (::ferror(_M_file))\n+\t__throw_system_error(errno);\n+#endif\n+ this->_M_reset(this->_M_buf);\n+ }\n+\n+ public:\n+ _File_sink(FILE* __f, bool __add_newline) noexcept\n+ : _Buf_sink<char>(), _M_file(__f), _M_add_newline(__add_newline)\n+ { ::flockfile(__f); }\n+\n+ ~_File_sink() noexcept(false)\n+ {\n+ _File_sink::_M_overflow();\n+ if (_M_add_newline)\n+\t::putc_unlocked('\\n', _M_file);\n+ ::funlockfile(_M_file);\n+ }\n+\n+ using _Sink<char>::out;\n+ };\n+#else\n+ // A wrapper around a format sink that copies the output to a stdio FILE.\n+ // This is not actually a _Sink itself, but it creates one to hold the\n+ // formatted characters and then copies them to the file when finished.\n+ class _File_sink final\n+ {\n+ FILE* _M_file;\n+ _Str_sink<char> _M_sink;\n+ bool _M_add_newline;\n+\n+ public:\n+ _File_sink(FILE* __f, bool __add_newline) noexcept\n+ : _M_file(__f), _M_add_newline(__add_newline)\n+ { }\n+\n+ ~_File_sink() noexcept(false)\n+ {\n+ string __s = std::move(_M_sink).get();\n+ if (_M_add_newline)\n+\t__s += '\\n';\n+ auto __n = std::fwrite(__s.data(), 1, __s.size(), _M_file);\n+ if (__n < __s.size())\n+\t__throw_system_error(EIO);\n+ }\n+\n+ auto out() { return _M_sink.out(); }\n+ };\n+#endif\n+} // namespace __format\n+\n+#ifdef _GLIBCXX_NO_INLINE_PRINT\n+# define _GLIBCXX_PRINT_INLINE_USED [[__gnu__::__used__]]\n+#else\n+# define _GLIBCXX_PRINT_INLINE_USED\n+#endif\n+\n+ _GLIBCXX_PRINT_INLINE_USED\n+ inline void\n+ vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args)\n+ {\n+ std::vformat_to(__format::_File_sink(__stream, false).out(), __fmt, __args);\n+ }\n+\n+ _GLIBCXX_PRINT_INLINE_USED\n+ inline void\n+ vprint_nonunicode_buffered(FILE* __stream, string_view __fmt,\n+\t\t\t format_args __args)\n+ {\n+ __format::_Str_sink<char> __buf;\n+ std::vformat_to(__buf.out(), __fmt, __args);\n+ auto __out = __buf.view();\n+ if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())\n+ __throw_system_error(EIO);\n+ }\n+\n+ _GLIBCXX_PRINT_INLINE_USED\n+ inline void\n+ vprint_unicode(FILE* __stream, string_view __fmt, format_args __args)\n+ {\n+#if !defined(_WIN32) || defined(__CYGWIN__)\n+ // For most targets we don't need to do anything special to write\n+ // Unicode to a terminal.\n+ std::vprint_nonunicode(__stream, __fmt, __args);\n+#else\n+ __format::_Str_sink<char> __buf;\n+ std::vformat_to(__buf.out(), __fmt, __args);\n+ auto __out = __buf._M_span();\n+\n+ void* __open_terminal(FILE*);\n+ error_code __write_to_terminal(void*, span<char>);\n+ // If stream refers to a terminal, write a native Unicode string to it.\n+ if (auto __term = __open_terminal(__stream))\n+ {\n+\terror_code __e;\n+\tif (!std::fflush(__stream))\n+\t {\n+\t __e = __write_to_terminal(__term, __out);\n+\t if (!__e)\n+\t return;\n+\t if (__e == std::make_error_code(errc::illegal_byte_sequence))\n+\t return;\n+\t }\n+\telse\n+\t __e = error_code(errno, generic_category());\n+\t_GLIBCXX_THROW_OR_ABORT(system_error(__e, \"std::vprint_unicode\"));\n+ }\n+\n+ // Otherwise just write the string to the file.\n+ if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())\n+ __throw_system_error(EIO);\n+#endif\n+ }\n+\n+ _GLIBCXX_PRINT_INLINE_USED\n+ inline void\n+ vprint_unicode_buffered(FILE* __stream, string_view __fmt, format_args __args)\n+ {\n+#if !defined(_WIN32) || defined(__CYGWIN__)\n+ // For most targets we don't need to do anything special to write\n+ // Unicode to a terminal. Just use the nonunicode function.\n+ std::vprint_nonunicode_buffered(__stream, __fmt, __args);\n+#else\n+ // For Windows the locking function formats everything first anyway,\n+ // so no formatting happens while a lock is taken. Just use that.\n+ std::vprint_unicode(__stream, __fmt, __args);\n+#endif\n+ }\n+#undef _GLIBCXX_PRINT_INLINE_USED\n+\n+_GLIBCXX_END_NAMESPACE_VERSION\n+} // namespace std\n+#endif // __glibcxx_print\n+#endif // _GLIBCXX_PRINT_H\ndiff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream\nindex e8dcfda2682f..b99c0f92d345 100644\n--- a/libstdc++-v3/include/std/ostream\n+++ b/libstdc++-v3/include/std/ostream\n@@ -40,12 +40,17 @@\n #include <bits/requires_hosted.h> // iostreams\n \n #include <bits/ostream.h>\n-#if __cplusplus > 202002L\n-# include <format>\n+\n+#ifdef __glibcxx_print\n+# include <format> // format_string, make_format_args\n+#endif\n+\n+#ifndef _GLIBCXX_NO_INLINE_PRINT\n+# include <bits/ostream_print.h>\n #endif\n \n # define __glibcxx_want_print\n-#include <bits/version.h> // __glibcxx_syncbuf\n+#include <bits/version.h> // __cpp_lib_print, __glibcxx_syncbuf\n \n namespace std _GLIBCXX_VISIBILITY(default)\n {\n@@ -156,103 +161,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #endif // __glibcxx_syncbuf\n \n #if __cpp_lib_print // C++ >= 23\n- inline void\n- vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args)\n- {\n- ostream::sentry __cerb(__os);\n- if (__cerb)\n- {\n-\t__format::_Str_sink<char> __buf;\n-\tstd::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);\n-\tauto __out = __buf.view();\n+ void\n+ vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args);\n \n-\t__try\n-\t {\n-\t std::__ostream_write(__os, __out.data(), __out.size());\n-\t }\n-\t__catch(const __cxxabiv1::__forced_unwind&)\n-\t {\n-\t __os._M_setstate(ios_base::badbit);\n-\t __throw_exception_again;\n-\t }\n-\t__catch(...)\n-\t { __os._M_setstate(ios_base::badbit); }\n- }\n- }\n-\n- inline void\n- vprint_unicode(ostream& __os, string_view __fmt, format_args __args)\n- {\n-#if !defined(_WIN32) || defined(__CYGWIN__)\n- // For most targets we don't need to do anything special to write\n- // Unicode to a terminal.\n- std::vprint_nonunicode(__os, __fmt, __args);\n-#else\n- ostream::sentry __cerb(__os);\n- if (__cerb)\n- {\n-\t__format::_Str_sink<char> __buf;\n-\tstd::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);\n-\tauto __out = __buf._M_span();\n-\n-\tvoid* __open_terminal(streambuf*);\n-\terror_code __write_to_terminal(void*, span<char>);\n-\t// If stream refers to a terminal, write a Unicode string to it.\n-\tif (auto __term = __open_terminal(__os.rdbuf()))\n-\t {\n-#if !defined(_WIN32) || defined(__CYGWIN__)\n-\t // For POSIX, __open_terminal(streambuf*) uses fdopen to open a\n-\t // new file, so we would need to close it here. This code is not\n-\t // actually compiled because it's inside an #ifdef _WIN32 group,\n-\t // but just in case that changes in future ...\n-\t struct _Guard\n-\t {\n-\t _Guard(void* __p) : _M_f((FILE*)__p) { }\n-\t ~_Guard() { std::fclose(_M_f); }\n-\t _Guard(_Guard&&) = delete;\n-\t _Guard& operator=(_Guard&&) = delete;\n-\t FILE* _M_f;\n-\t };\n-\t _Guard __g(__term);\n-#endif\n-\n-\t ios_base::iostate __err = ios_base::goodbit;\n-\t __try\n-\t {\n-\t\tif (__os.rdbuf()->pubsync() == -1)\n-\t\t __err = ios::badbit;\n-\t\telse if (auto __e = __write_to_terminal(__term, __out))\n-\t\t if (__e != std::make_error_code(errc::illegal_byte_sequence))\n-\t\t __err = ios::badbit;\n-\t }\n-\t __catch(const __cxxabiv1::__forced_unwind&)\n-\t {\n-\t\t__os._M_setstate(ios_base::badbit);\n-\t\t__throw_exception_again;\n-\t }\n-\t __catch(...)\n-\t { __os._M_setstate(ios_base::badbit); }\n-\n-\t if (__err)\n-\t __os.setstate(__err);\n-\t return;\n-\t }\n-\n-\t// Otherwise just insert the string as vprint_nonunicode does.\n-\t__try\n-\t {\n-\t std::__ostream_write(__os, __out.data(), __out.size());\n-\t }\n-\t__catch(const __cxxabiv1::__forced_unwind&)\n-\t {\n-\t __os._M_setstate(ios_base::badbit);\n-\t __throw_exception_again;\n-\t }\n-\t__catch(...)\n-\t { __os._M_setstate(ios_base::badbit); }\n- }\n-#endif // _WIN32\n- }\n+ void\n+ vprint_unicode(ostream& __os, string_view __fmt, format_args __args);\n \n template<typename... _Args>\n inline void\n@@ -294,7 +207,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #endif\n __os.put('\\n');\n }\n-\n #endif // __cpp_lib_print\n \n _GLIBCXX_END_NAMESPACE_VERSION\ndiff --git a/libstdc++-v3/include/std/print b/libstdc++-v3/include/std/print\nindex 1b9e810419f0..459bb9fb7462 100644\n--- a/libstdc++-v3/include/std/print\n+++ b/libstdc++-v3/include/std/print\n@@ -40,284 +40,42 @@\n \n #ifdef __cpp_lib_print // C++ >= 23\n \n-#include <format>\n-#include <cstdio>\n-#include <cerrno>\n-#include <bits/functexcept.h>\n+#include <format> // format_args (TODO: move to bits/formatfwd.h?)\n+#include <cstdio> // FILE, EOF, putc\n+#include <cerrno> // EACCES, EIO\n+#include <bits/functexcept.h> // __throw_system_error\n \n #ifdef _WIN32\n # include <system_error>\n #endif\n \n+#ifndef _GLIBCXX_NO_INLINE_PRINT\n+# include <bits/print.h>\n+#endif\n+\n namespace std _GLIBCXX_VISIBILITY(default)\n {\n _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \n-namespace __format\n-{\n-#if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLIBC_STDIO_EXT\n- // These are defined in <stdio_ext.h> but we don't want to include that.\n- extern \"C\" int __fwritable(FILE*) noexcept;\n- extern \"C\" int __flbf(FILE*) noexcept;\n- extern \"C\" size_t __fbufsize(FILE*) noexcept;\n+ void\n+ vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args);\n \n- // A format sink that writes directly to a Glibc FILE.\n- // The file is locked on construction and its buffer is accessed directly.\n- class _File_sink final : _Buf_sink<char>\n- {\n- struct _File\n- {\n- explicit\n- _File(FILE* __f) : _M_file(__f)\n- {\n-\t::flockfile(__f);\n-\t// Ensure stream is in write mode\n- if (!__fwritable(__f))\n-\t {\n-\t ::funlockfile(__f);\n-\t __throw_system_error(EACCES);\n-\t }\n-\t// Allocate buffer if needed:\n- if (_M_write_buf().empty())\n-\t if (::__overflow(__f, EOF) == EOF)\n-\t {\n-\t const int __err = errno;\n-\t ::funlockfile(__f);\n-\t __throw_system_error(__err);\n-\t }\n- }\n-\n- ~_File() { ::funlockfile(_M_file); }\n-\n- _File(_File&&) = delete;\n-\n- // A span viewing the unused portion of the stream's output buffer.\n- std::span<char>\n- _M_write_buf() noexcept\n- {\n-\treturn {_M_file->_IO_write_ptr,\n-\t\tsize_t(_M_file->_IO_buf_end - _M_file->_IO_write_ptr)};\n- }\n-\n- // Flush the output buffer to the file so we can write to it again.\n- void\n- _M_flush()\n- {\n-\tif (::fflush_unlocked(_M_file))\n-\t __throw_system_error(errno);\n- }\n-\n- // Update the current position in the output buffer.\n- void\n- _M_bump(size_t __n) noexcept\n- { _M_file->_IO_write_ptr += __n; }\n-\n- bool\n- _M_line_buffered() const noexcept\n- { return __flbf(_M_file); } // Or: _M_file->_flags & 0x200\n-\n- bool\n- _M_unbuffered() const noexcept\n- { return __fbufsize(_M_file) == 1; } // Or: _M_file->_flags & 0x2\n-\n- FILE* _M_file;\n- } _M_file;\n-\n- bool _M_add_newline; // True for std::println, false for std::print.\n-\n- // Flush the stream's put area so it can be refilled.\n- void\n- _M_overflow() override\n- {\n- auto __s = this->_M_used();\n- if (__s.data() == this->_M_buf)\n-\t{\n-\t // Characters in internal buffer need to be transferred to the FILE.\n-\t auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(),\n-\t\t\t\t _M_file._M_file);\n-\t if (__n != __s.size())\n-\t __throw_system_error(errno);\n-\t this->_M_reset(this->_M_buf);\n-\t}\n- else\n-\t{\n-\t // Characters were written directly to the FILE's output buffer.\n-\t _M_file._M_bump(__s.size());\n-\t _M_file._M_flush();\n-\t this->_M_reset(_M_file._M_write_buf());\n-\t}\n- }\n-\n- public:\n- _File_sink(FILE* __f, bool __add_newline)\n- : _M_file(__f), _M_add_newline(__add_newline)\n- {\n- if (!_M_file._M_unbuffered())\n-\t// Write directly to the FILE's output buffer.\n-\tthis->_M_reset(_M_file._M_write_buf());\n- }\n-\n- ~_File_sink() noexcept(false)\n- {\n- auto __s = this->_M_used();\n- if (__s.data() == this->_M_buf) // Unbuffered stream\n-\t{\n-\t _File_sink::_M_overflow();\n-\t if (_M_add_newline)\n-\t ::putc_unlocked('\\n', _M_file._M_file);\n-\t}\n- else\n-\t{\n-\t _M_file._M_bump(__s.size());\n-\t if (_M_add_newline)\n-\t ::putc_unlocked('\\n', _M_file._M_file);\n-\t else if (_M_file._M_line_buffered() && __s.size()\n-\t\t && (__s.back() == '\\n'\n-\t\t\t || __builtin_memchr(__s.data(), '\\n', __s.size())))\n-\t _M_file._M_flush();\n-\t}\n- }\n-\n- using _Sink<char>::out;\n- };\n-#elif _GLIBCXX_USE_STDIO_LOCKING\n- // A format sink that buffers output and then copies it to a stdio FILE.\n- // The file is locked on construction and written to using fwrite_unlocked.\n- class _File_sink final : _Buf_sink<char>\n- {\n- FILE* _M_file;\n- bool _M_add_newline;\n-\n- // Transfer buffer contents to the FILE, so buffer can be refilled.\n- void\n- _M_overflow() override\n- {\n- auto __s = this->_M_used();\n-#if _GLIBCXX_HAVE_FWRITE_UNLOCKED\n- auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file);\n- if (__n != __s.size())\n-\t__throw_system_error(errno);\n-#else\n- for (char __c : __s)\n-\t::putc_unlocked(__c, _M_file);\n- if (::ferror(_M_file))\n-\t__throw_system_error(errno);\n-#endif\n- this->_M_reset(this->_M_buf);\n- }\n-\n- public:\n- _File_sink(FILE* __f, bool __add_newline) noexcept\n- : _Buf_sink<char>(), _M_file(__f), _M_add_newline(__add_newline)\n- { ::flockfile(__f); }\n-\n- ~_File_sink() noexcept(false)\n- {\n- _File_sink::_M_overflow();\n- if (_M_add_newline)\n-\t::putc_unlocked('\\n', _M_file);\n- ::funlockfile(_M_file);\n- }\n-\n- using _Sink<char>::out;\n- };\n-#else\n- // A wrapper around a format sink that copies the output to a stdio FILE.\n- // This is not actually a _Sink itself, but it creates one to hold the\n- // formatted characters and then copies them to the file when finished.\n- class _File_sink final\n- {\n- FILE* _M_file;\n- _Str_sink<char> _M_sink;\n- bool _M_add_newline;\n-\n- public:\n- _File_sink(FILE* __f, bool __add_newline) noexcept\n- : _M_file(__f), _M_add_newline(__add_newline)\n- { }\n-\n- ~_File_sink() noexcept(false)\n- {\n- string __s = std::move(_M_sink).get();\n- if (_M_add_newline)\n-\t__s += '\\n';\n- auto __n = std::fwrite(__s.data(), 1, __s.size(), _M_file);\n- if (__n < __s.size())\n-\t__throw_system_error(EIO);\n- }\n-\n- auto out() { return _M_sink.out(); }\n- };\n-#endif\n-} // namespace __format\n-\n- inline void\n- vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args)\n- {\n- std::vformat_to(__format::_File_sink(__stream, false).out(), __fmt, __args);\n- }\n-\n- inline void\n+ void\n vprint_nonunicode_buffered(FILE* __stream, string_view __fmt,\n-\t\t\t format_args __args)\n- {\n- __format::_Str_sink<char> __buf;\n- std::vformat_to(__buf.out(), __fmt, __args);\n- auto __out = __buf.view();\n- if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())\n- __throw_system_error(EIO);\n- }\n+\t\t\t format_args __args);\n \n- inline void\n- vprint_unicode(FILE* __stream, string_view __fmt, format_args __args)\n- {\n-#if !defined(_WIN32) || defined(__CYGWIN__)\n- // For most targets we don't need to do anything special to write\n- // Unicode to a terminal.\n- std::vprint_nonunicode(__stream, __fmt, __args);\n-#else\n- __format::_Str_sink<char> __buf;\n- std::vformat_to(__buf.out(), __fmt, __args);\n- auto __out = __buf._M_span();\n+ void\n+ vprint_unicode(FILE* __stream, string_view __fmt, format_args __args);\n \n- void* __open_terminal(FILE*);\n- error_code __write_to_terminal(void*, span<char>);\n- // If stream refers to a terminal, write a native Unicode string to it.\n- if (auto __term = __open_terminal(__stream))\n- {\n-\terror_code __e;\n-\tif (!std::fflush(__stream))\n-\t {\n-\t __e = __write_to_terminal(__term, __out);\n-\t if (!__e)\n-\t return;\n-\t if (__e == std::make_error_code(errc::illegal_byte_sequence))\n-\t return;\n-\t }\n-\telse\n-\t __e = error_code(errno, generic_category());\n-\t_GLIBCXX_THROW_OR_ABORT(system_error(__e, \"std::vprint_unicode\"));\n- }\n+ void\n+ vprint_unicode_buffered(FILE* __stream, string_view __fmt,\n+\t\t\t format_args __args);\n \n- // Otherwise just write the string to the file.\n- if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())\n- __throw_system_error(EIO);\n-#endif\n- }\n+ void\n+ vprint_unicode_buffered(string_view __fmt, format_args __args);\n \n- inline void\n- vprint_unicode_buffered(FILE* __stream, string_view __fmt, format_args __args)\n- {\n-#if !defined(_WIN32) || defined(__CYGWIN__)\n- // For most targets we don't need to do anything special to write\n- // Unicode to a terminal. Just use the nonunicode function.\n- std::vprint_nonunicode_buffered(__stream, __fmt, __args);\n-#else\n- // For Windows the locking function formats everything first anyway,\n- // so no formatting happens while a lock is taken. Just use that.\n- std::vprint_unicode(__stream, __fmt, __args);\n-#endif\n- }\n+ void\n+ vprint_nonunicode_buffered(string_view __fmt, format_args __args);\n \n template<typename... _Args>\n inline void\n@@ -357,6 +115,7 @@ namespace __format\n // and we know what that would call, so we can call that directly.\n \n auto __fmtargs = std::make_format_args(__args...);\n+\n #if defined(_WIN32) && !defined(__CYGWIN__)\n if constexpr (__unicode::__literal_encoding_is_utf8())\n \t{\n@@ -371,6 +130,15 @@ namespace __format\n else\n #endif\n \n+#ifdef _GLIBCXX_NO_INLINE_PRINT\n+\t{\n+\t string __fmtn;\n+\t __fmtn.reserve(__fmt.get().size() + 1);\n+\t __fmtn = __fmt.get();\n+\t __fmtn += '\\n';\n+\t std::vprint_nonunicode(__stream, __fmtn, __fmtargs);\n+\t}\n+#else\n // For non-Windows and for non-Unicode on Windows, we know that print\n // would call vprint_nonunicode or vprint_nonunicode_buffered with a\n // newline appended to the format-string. Use a _File_sink that adds\n@@ -387,6 +155,7 @@ namespace __format\n \t string_view __s(__buf.view());\n \t __format::_File_sink(__stream, true).out() = __s;\n \t}\n+#endif\n }\n \n template<typename... _Args>\ndiff --git a/libstdc++-v3/src/c++23/print.cc b/libstdc++-v3/src/c++23/print.cc\nindex f34369950096..290e0b8dfa2d 100644\n--- a/libstdc++-v3/src/c++23/print.cc\n+++ b/libstdc++-v3/src/c++23/print.cc\n@@ -22,6 +22,13 @@\n // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see\n // <http://www.gnu.org/licenses/>.\n \n+// We want to emit symbols for the inline functions in bits/print.h here.\n+#define _GLIBCXX_NO_INLINE_PRINT 1\n+#include <ostream>\n+#include <bits/ostream_print.h>\n+#include <print>\n+#include <bits/print.h>\n+\n #include <span>\n #include <string>\n #include <streambuf>\n", "prefixes": [ "committed", "v2" ] }