From patchwork Wed Apr 17 16:40:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1924680 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=hKduCBuC; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VKRXJ102Tz1yZ2 for ; Thu, 18 Apr 2024 02:42:22 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CB105384AB4A for ; Wed, 17 Apr 2024 16:42:20 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 32B573858D20 for ; Wed, 17 Apr 2024 16:41:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 32B573858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 32B573858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713372118; cv=none; b=poi5cDQJR3es8a14yQMfz/kG+z8XxgLzc8jp7JNiJxU9BChAYu6yAszZVuT3AOOaZcU0YOoZ9dPQK+R0nw8JbzvJ95GttBhEUY5/0L5k6BJx9XGthPUTzLCfpQ63+ODwgiCelf/DkkOqZPHde8l//aUSdyJwq+3Rjqlyqek4zD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713372118; c=relaxed/simple; bh=vpbWRF7uesx5wdaU6PZa0zHz1SMCSB+sCDWec6Maw/o=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=r0Ta/g55MzuC6X9MyUTd4ZuLjSPR6mhVGvES2E9gC0920rQFrRsOqLuP47S/vQ0epnQ3PIBoAdr5M64B9MdruJtrC4UK20ggiB2H7ceq8khf0ToE+AIfeJVVXFDE7Dsqhzmz+RlzAQxmB/V+jkiBIi1AxR8VyJ1AygfEqVmMujo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713372116; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=pZu55Nhk9HpC25bmSalaTeEX7FSARl6oB6zOQGvLPaU=; b=hKduCBuC84th0uYnl3ru4f/htfEhHT8a+QbJzINLaYj5UMAKDgzujyYiuAve9/Tse1qB/u lttGIhydGlITtz2YoPR8GNskGM+TjdbIASTer8p/VEOy0UlzgyggO+GFiiUQENjshbRlms ++6bxEvU9i/O4Z9we5vDW48FzHa+Q5o= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-615-CZngnrNcOS-XVT4wpps15g-1; Wed, 17 Apr 2024 12:41:53 -0400 X-MC-Unique: CZngnrNcOS-XVT4wpps15g-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 53C401044572; Wed, 17 Apr 2024 16:41:53 +0000 (UTC) Received: from localhost (unknown [10.42.28.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 22C3F1C0654B; Wed, 17 Apr 2024 16:41:53 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Implement "Printing blank lines with println" for C++23 Date: Wed, 17 Apr 2024 17:40:51 +0100 Message-ID: <20240417164148.1062828-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Tested x86_64-linux and x86_64-freebsd. Pushed to trunk. -- >8 -- This was recently approved for C++26 at the Tokyo meeting. As suggested by Stephan T. Lavavej, I'm defining it as an extension for C++23 mode (when std::print and std::prinln were first added) rather than as a new C++26 feature. Both MSVC and libc++ have agreed to do this too. libstdc++-v3/ChangeLog: * include/std/ostream (println(ostream&)): Define new overload. * include/std/print (println(FILE*), println()): Likewise. * testsuite/27_io/basic_ostream/print/2.cc: New test. * testsuite/27_io/print/1.cc: Remove unused header. * testsuite/27_io/print/3.cc: New test. --- libstdc++-v3/include/std/ostream | 12 +++++ libstdc++-v3/include/std/print | 14 +++++ .../testsuite/27_io/basic_ostream/print/2.cc | 47 ++++++++++++++++ libstdc++-v3/testsuite/27_io/print/1.cc | 1 - libstdc++-v3/testsuite/27_io/print/3.cc | 53 +++++++++++++++++++ 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/27_io/basic_ostream/print/2.cc create mode 100644 libstdc++-v3/testsuite/27_io/print/3.cc diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index a136399ad0b..8a21758d0a3 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -995,6 +995,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::print(__os, "{}\n", std::format(__fmt, std::forward<_Args>(__args)...)); } + + // Defined for C++26, supported as an extension to C++23. + inline void println(ostream& __os) + { +#if defined(_WIN32) && !defined(__CYGWIN__) + if constexpr (__unicode::__literal_encoding_is_utf8()) + std::vprint_unicode(__os, "\n", std::make_format_args()); + else +#endif + __os.put('\n'); + } + #endif // __cpp_lib_print #endif // C++11 diff --git a/libstdc++-v3/include/std/print b/libstdc++-v3/include/std/print index d44033469de..0c259d04de3 100644 --- a/libstdc++-v3/include/std/print +++ b/libstdc++-v3/include/std/print @@ -136,6 +136,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION vprint_nonunicode(string_view __fmt, format_args __args) { std::vprint_nonunicode(stdout, __fmt, __args); } + // Defined for C++26, supported as an extension to C++23. + inline void println(FILE* __stream) + { +#if defined(_WIN32) && !defined(__CYGWIN__) + if constexpr (__unicode::__literal_encoding_is_utf8()) + std::vprint_unicode(__stream, "\n", std::make_format_args()); + else +#endif + if (std::putc('\n', __stream) == EOF) + __throw_system_error(EIO); + } + + inline void println() { std::println(stdout); } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __cpp_lib_print diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/print/2.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/print/2.cc new file mode 100644 index 00000000000..5d1e3efdbf7 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/print/2.cc @@ -0,0 +1,47 @@ +// { dg-additional-options "-lstdc++exp" { target { *-*-mingw* } } } +// { dg-do run { target c++23 } } +// { dg-require-fileio "" } + +#include +#include +#include +#include +#include +#include + +void +test_println_blank_ostream() +{ + char buf[4]; + std::spanstream os(buf); + std::println(os); + std::string_view txt(os.span()); + VERIFY( txt == "\n" ); +} + +void +test_errors() +{ + // Failure to generate output is reported by setting badbit. + std::stringstream in(std::ios::in); + std::println(in); // No exception here. + VERIFY(in.bad()); +#ifdef __cpp_exceptions + in.clear(); + in.exceptions(std::ios::badbit); + try + { + std::println(in); // Should throw now. + VERIFY(false); + } + catch (const std::ios::failure&) + { + } +#endif +} + +int main() +{ + test_println_blank_ostream(); + test_errors(); +} diff --git a/libstdc++-v3/testsuite/27_io/print/1.cc b/libstdc++-v3/testsuite/27_io/print/1.cc index d570f7938be..f6585d9880a 100644 --- a/libstdc++-v3/testsuite/27_io/print/1.cc +++ b/libstdc++-v3/testsuite/27_io/print/1.cc @@ -4,7 +4,6 @@ #include #include -#include #include #include diff --git a/libstdc++-v3/testsuite/27_io/print/3.cc b/libstdc++-v3/testsuite/27_io/print/3.cc new file mode 100644 index 00000000000..ffcf7337ce5 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/print/3.cc @@ -0,0 +1,53 @@ +// { dg-additional-options "-lstdc++exp" { target { *-*-mingw* } } } +// { dg-do run { target c++23 } } +// { dg-require-fileio "" } + +#include +#include +#include +#include + +void +test_println_blank() +{ + std::print("1"); + std::println(); + std::println("2"); + // { dg-output "1\n2" } +} + +void +test_println_blank_file() +{ + __gnu_test::scoped_file f; + FILE* strm = std::fopen(f.path.string().c_str(), "w"); + VERIFY( strm ); + std::println(strm); + std::fclose(strm); + + std::ifstream in(f.path); + std::string txt(std::istreambuf_iterator(in), {}); + VERIFY( txt == "\n" ); +} + +void +test_errors() +{ +#ifdef __cpp_exceptions + try + { + std::println(stdin); + VERIFY(false); + } + catch (const std::system_error&) + { + } +#endif +} + +int main() +{ + test_println_blank(); + test_println_blank_file(); + test_errors(); +}