diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv --- a/libcxx/docs/Status/FormatPaper.csv +++ b/libcxx/docs/Status/FormatPaper.csv @@ -47,6 +47,6 @@ `[stacktrace.format] `_,"Formatting ``stacktrace``",A ```` implementation,Mark de Wever,, "`P2093R14 `__","Formatted output" -`[print.fun] `__,"Output to ``stdout``",,Mark de Wever,|In Progress|, +`[print.fun] `__,"Output to ``stdout``",,Mark de Wever,|Complete|, 17.0 `[print.fun] `__,"Output to ``FILE*``",,Mark de Wever,|Complete|, 17.0 `[ostream.formatted.print] `__,"Output to ``ostream``",,Mark de Wever diff --git a/libcxx/include/print b/libcxx/include/print --- a/libcxx/include/print +++ b/libcxx/include/print @@ -13,14 +13,20 @@ /* namespace std { // [print.fun], print functions + template + void print(format_string fmt, Args&&... args); template void print(FILE* stream, format_string fmt, Args&&... args); + template + void println(format_string fmt, Args&&... args); template void println(FILE* stream, format_string fmt, Args&&... args); + void vprint_unicode(string_view fmt, format_args args); void vprint_unicode(FILE* stream, string_view fmt, format_args args); + void vprint_nonunicode(string_view fmt, format_args args); void vprint_nonunicode(FILE* stream, string_view fmt, format_args args); } */ @@ -328,6 +334,11 @@ # endif // _LIBCPP_HAS_NO_UNICODE } +template +_LIBCPP_HIDE_FROM_ABI void print(format_string<_Args...> __fmt, _Args&&... __args) { + std::print(stdout, __fmt, std::forward<_Args>(__args)...); +} + template _LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) { # ifndef _LIBCPP_HAS_NO_UNICODE @@ -343,11 +354,22 @@ # endif // _LIBCPP_HAS_NO_UNICODE } +template +_LIBCPP_HIDE_FROM_ABI void println(format_string<_Args...> __fmt, _Args&&... __args) { + std::println(stdout, __fmt, std::forward<_Args>(__args)...); +} + # ifndef _LIBCPP_HAS_NO_UNICODE template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). _LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(FILE* __stream, string_view __fmt, format_args __args) { __print::__vprint_unicode(__stream, __fmt, __args, false); } + +template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(string_view __fmt, format_args __args) { + std::vprint_unicode(stdout, __fmt, __args); +} + # endif // _LIBCPP_HAS_NO_UNICODE template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). @@ -355,6 +377,11 @@ __print::__vprint_nonunicode(__stream, __fmt, __args, false); } +template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(string_view __fmt, format_args __args) { + std::vprint_nonunicode(stdout, __fmt, __args); +} + #endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/check-stdout.sh b/libcxx/test/std/input.output/iostream.format/print.fun/check-stdout.sh new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/print.fun/check-stdout.sh @@ -0,0 +1,16 @@ +program=${1} +expected_stdout=${2} +${program} 2>stderr.log >stdout.log + +# The expected output for println has "...\n". The escaped newline needs +# to be expanded before comparing the output with the expected output. +echo -ne ${expected_stdout} > expected.log + +echo -n "out [" +cat stdout.log +echo "]" +echo -n "expected [" +cat expected.log +echo "]" + +[ "$(cat expected.log)" == "$(cat stdout.log)" ] diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/print.sh.cpp b/libcxx/test/std/input.output/iostream.format/print.fun/print.sh.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/print.fun/print.sh.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: executor-has-no-bash +// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME + +// XFAIL: availability-fp_to_chars-missing + +// + +// template +// void print(format_string fmt, Args&&... args); + +// Testing this properly is quite hard; the function unconditionally +// writes to stdout. When stdout is redirected to a file it is no longer +// considered a terminal. The function is a small wrapper around +// +// template +// void print(FILE* stream, format_string fmt, Args&&... args); +// +// So do minimal tests for this function and relay on the FILE* overload +// to do more testing. (Note that function is also not easy to test.) +// +// The testing is based on the testing for std::cout. + +// FILE_DEPENDENCIES: check-stdout.sh +// RUN: %{build} +// RUN: %{exec} bash check-stdout.sh "%t.exe" "1234 一二三四 true 0x0" + +#include + +int main(int, char**) { + // The data is passes as-is so it does not depend on the encoding of the input. + std::print("{} {} ", 1234, "一二三四"); + std::print("{} {}", true, nullptr); + + return 0; +} diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/println.sh.cpp b/libcxx/test/std/input.output/iostream.format/print.fun/println.sh.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/print.fun/println.sh.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: executor-has-no-bash +// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME + +// XFAIL: availability-fp_to_chars-missing + +// + +// template +// void println(format_string fmt, Args&&... args); + +// Testing this properly is quite hard; the function unconditionally +// writes to stdout. When stdout is redirected to a file it is no longer +// considered a terminal. The function is a small wrapper around +// +// template +// void println(FILE* stream, format_string fmt, Args&&... args); +// +// So do minimal tests for this function and relay on the FILE* overload +// to do more testing. (Note that function is also not easy to test.) +// +// The testing is based on the testing for std::cout. + +// FILE_DEPENDENCIES: check-stdout.sh +// RUN: %{build} +// RUN: %{exec} bash check-stdout.sh "%t.exe" "1234 一二三四\\ntrue 0x0\n" + +#include + +int main(int, char**) { + // The data is passes as-is so it does not depend on the encoding of the input. + std::println("{} {}", 1234, "一二三四"); + std::println("{} {}", true, nullptr); + + return 0; +} diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/vprint_nonunicode.sh.cpp b/libcxx/test/std/input.output/iostream.format/print.fun/vprint_nonunicode.sh.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/print.fun/vprint_nonunicode.sh.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: executor-has-no-bash +// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME + +// XFAIL: availability-fp_to_chars-missing + +// + +// void vprint_nonunicode(string_view fmt, format_args args); + +// Testing this properly is quite hard; the function unconditionally +// writes to stdout. When stdout is redirected to a file it is no longer +// considered a terminal. The function is a small wrapper around +// +// void vprint_nonunicode(FILE* stream, string_view fmt, format_args args); +// +// So do minimal tests for this function and relay on the FILE* overload +// to do more testing. (Note that function is also not easy to test.) +// +// The testing is based on the testing for std::cout. + +// FILE_DEPENDENCIES: check-stdout.sh +// RUN: %{build} +// RUN: %{exec} bash check-stdout.sh "%t.exe" "1234 一二三四 true 0x0" + +#include + +int main(int, char**) { + // The data is passes as-is so it does not depend on the encoding of the input. + std::vprint_nonunicode("{} {} ", std::make_format_args(1234, "一二三四")); + std::vprint_nonunicode("{} {}", std::make_format_args(true, nullptr)); + + return 0; +} diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/vprint_unicode.sh.cpp b/libcxx/test/std/input.output/iostream.format/print.fun/vprint_unicode.sh.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/print.fun/vprint_unicode.sh.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: executor-has-no-bash +// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME + +// XFAIL: availability-fp_to_chars-missing + +// + +// void vprint_unicode(string_view fmt, format_args args); + +// Testing this properly is quite hard; the function unconditionally +// writes to stdout. When stdout is redirected to a file it is no longer +// considered a terminal. The function is a small wrapper around +// +// void vprint_unicode(FILE* stream, string_view fmt, format_args args); +// +// So do minimal tests for this function and relay on the FILE* overload +// to do more testing. (Note that function is also not easy to test.) +// +// The testing is based on the testing for std::cout. + +// FILE_DEPENDENCIES: check-stdout.sh +// RUN: %{build} +// RUN: %{exec} bash check-stdout.sh "%t.exe" "1234 一二三四 true 0x0" + +#include + +int main(int, char**) { + // The data is passes as-is so it does not depend on the encoding of the input. + std::vprint_unicode("{} {} ", std::make_format_args(1234, "一二三四")); + std::vprint_unicode("{} {}", std::make_format_args(true, nullptr)); + + return 0; +}