diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index a136399ad0b915acafed9c6abf10cf2e28b8fb38..8a21758d0a337663f37adf448189f6670668a7fe 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 d44033469de2b542434baa2f9102ca66bd1597eb..0c259d04de33dbeb6aa13db13bf88b8f45cd1777 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 0000000000000000000000000000000000000000..5d1e3efdbf78967b036e223a43322d8adabb5559 --- /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 <ostream> +#include <spanstream> +#include <string_view> +#include <iostream> +#include <iomanip> +#include <testsuite_hooks.h> + +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 d570f7938be657c98c50cb3f0a0296bf269ae5e1..f6585d9880ae9cb234e60db6773dde357adcef7a 100644 --- a/libstdc++-v3/testsuite/27_io/print/1.cc +++ b/libstdc++-v3/testsuite/27_io/print/1.cc @@ -4,7 +4,6 @@ #include <print> #include <cstdio> -#include <spanstream> #include <testsuite_hooks.h> #include <testsuite_fs.h> 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 0000000000000000000000000000000000000000..ffcf7337ce5d547089d8addcfbe156ad8684b2f4 --- /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 <print> +#include <cstdio> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +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<char>(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(); +}