From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id C27123858D39; Wed, 17 Apr 2024 16:40:50 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C27123858D39 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1713372050; bh=GMK7j3Qtoikgr2DoHwOeZvmBbNBaqyB/jTAu/iNKGcM=; h=From:To:Subject:Date:From; b=GFKUsD25PYqGS/7CMpzR8BTEQdRmpy/PJ6uEHRNj//zW7WoBidi4n3G/nZo1FRmr/ wLH/K0sM94whP527Y7TpGv/XCj4DVugxX/0PUTa4gA6OI2fkf1CGwPBAjQevza9oMa gkjHfDMZdFLs7BQ6dqhEu0rlKZv+59n1/OJdhWs4= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r14-10008] libstdc++: Implement "Printing blank lines with println" for C++23 X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/master X-Git-Oldrev: 57056146f4ffc5ea347c03e37e1e2c7cd99261d0 X-Git-Newrev: 7c2a9dbcc2c1cb1563774068c59d5e09edc59f06 Message-Id: <20240417164050.C27123858D39@sourceware.org> Date: Wed, 17 Apr 2024 16:40:50 +0000 (GMT) List-Id: https://gcc.gnu.org/g:7c2a9dbcc2c1cb1563774068c59d5e09edc59f06 commit r14-10008-g7c2a9dbcc2c1cb1563774068c59d5e09edc59f06 Author: Jonathan Wakely Date: Thu Mar 21 23:09:14 2024 +0000 libstdc++: Implement "Printing blank lines with println" for C++23 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. Diff: --- 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(-) 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(); +}