[libc++][print] Adds stdout functions.

Implements parts of
- P2093R14 Formatted output
- P2539R4  Should the output of std::print to a terminal be
           synchronized with the underlying stream?

Depends on D150044

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D155262
This commit is contained in:
Mark de Wever 2023-07-12 08:20:26 +02:00
parent c51c607dfc
commit e2953303f4
8 changed files with 218 additions and 4 deletions

View File

@ -47,6 +47,6 @@ Section,Description,Dependencies,Assignee,Status,First released version
`[stacktrace.format] <https://wg21.link/stacktrace.format>`_,"Formatting ``stacktrace``",A ``<stacktrace>`` implementation,Mark de Wever,,
"`P2093R14 <https://wg21.link/P2093R14>`__","Formatted output"
`[print.fun] <https://wg21.link/print.fun>`__,"Output to ``stdout``",,Mark de Wever,|In Progress|,
`[print.fun] <https://wg21.link/print.fun>`__,"Output to ``stdout``",,Mark de Wever,|Complete|, 17.0
`[print.fun] <https://wg21.link/print.fun>`__,"Output to ``FILE*``",,Mark de Wever,|Complete|, 17.0
`[ostream.formatted.print] <https://wg21.link/ostream.formatted.print>`__,"Output to ``ostream``",,Mark de Wever

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -13,14 +13,20 @@
/*
namespace std {
// [print.fun], print functions
template<class... Args>
void print(format_string<Args...> fmt, Args&&... args);
template<class... Args>
void print(FILE* stream, format_string<Args...> fmt, Args&&... args);
template<class... Args>
void println(format_string<Args...> fmt, Args&&... args);
template<class... Args>
void println(FILE* stream, format_string<Args...> 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 @@ _LIBCPP_HIDE_FROM_ABI void print(FILE* __stream, format_string<_Args...> __fmt,
# endif // _LIBCPP_HAS_NO_UNICODE
}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI void print(format_string<_Args...> __fmt, _Args&&... __args) {
std::print(stdout, __fmt, std::forward<_Args>(__args)...);
}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) {
# ifndef _LIBCPP_HAS_NO_UNICODE
@ -343,11 +354,22 @@ _LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt
# endif // _LIBCPP_HAS_NO_UNICODE
}
template <class... _Args>
_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 <class = void> // 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 <class = void> // 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 <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
@ -355,6 +377,11 @@ _LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(FILE* __stream, string_view
__print::__vprint_nonunicode(__stream, __fmt, __args, false);
}
template <class = void> // 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

View File

@ -0,0 +1 @@
echo ${1} ${2}

View File

@ -0,0 +1,47 @@
//===----------------------------------------------------------------------===//
// 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
// <print>
// template<class... Args>
// void print(format_string<Args...> 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<class... Args>
// void print(FILE* stream, format_string<Args...> fmt, Args&&... args);
//
// So do minimal tests for this function and rely on the FILE* overload
// to do more testing.
//
// The testing is based on the testing for std::cout.
// TODO PRINT Use lit builtin echo
// FILE_DEPENDENCIES: echo.sh
// RUN: %{build}
// RUN: %{exec} bash echo.sh -n "1234 一二三四 true 0x0" > %t.expected
// RUN: %{exec} "%t.exe" > %t.actual
// RUN: diff -u %t.actual %t.expected
#include <print>
int main(int, char**) {
// The data is passed as-is so it does not depend on the encoding of the input.
std::print("{} {} ", 1234, "一二三四");
std::print("{} {}", true, nullptr);
return 0;
}

View File

@ -0,0 +1,50 @@
//===----------------------------------------------------------------------===//
// 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
// FIXME PRINT How to test println on Windows?
// XFAIL: msvc, target={{.+}}-windows-gnu
// XFAIL: availability-fp_to_chars-missing
// <print>
// template<class... Args>
// void println(format_string<Args...> 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<class... Args>
// void println(FILE* stream, format_string<Args...> fmt, Args&&... args);
//
// So do minimal tests for this function and rely on the FILE* overload
// to do more testing.
//
// The testing is based on the testing for std::cout.
// TODO PRINT Use lit builtin echo
// FILE_DEPENDENCIES: echo.sh
// RUN: %{build}
// RUN: %{exec} bash echo.sh -ne "1234 一二三四\ntrue 0x0\n" > %t.expected
// RUN: %{exec} "%t.exe" > %t.actual
// RUN: diff -u %t.actual %t.expected
#include <print>
int main(int, char**) {
// The data is passed as-is so it does not depend on the encoding of the input.
std::println("{} {}", 1234, "一二三四");
std::println("{} {}", true, nullptr);
return 0;
}

View File

@ -0,0 +1,45 @@
//===----------------------------------------------------------------------===//
// 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
// <print>
// 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 rely on the FILE* overload
// to do more testing.
//
// The testing is based on the testing for std::cout.
// TODO PRINT Use lit builtin echo
// FILE_DEPENDENCIES: echo.sh
// RUN: %{build}
// RUN: %{exec} bash echo.sh -n "1234 一二三四 true 0x0" > %t.expected
// RUN: %{exec} "%t.exe" > %t.actual
// RUN: diff -u %t.actual %t.expected
#include <print>
int main(int, char**) {
// The data is passed 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;
}

View File

@ -0,0 +1,45 @@
//===----------------------------------------------------------------------===//
// 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
// <print>
// 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 rely on the FILE* overload
// to do more testing.
//
// The testing is based on the testing for std::cout.
// TODO PRINT Use lit builtin echo
// FILE_DEPENDENCIES: echo.sh
// RUN: %{build}
// RUN: %{exec} bash echo.sh -n "1234 一二三四 true 0x0" > %t.expected
// RUN: %{exec} "%t.exe" > %t.actual
// RUN: diff -u %t.actual %t.expected
#include <print>
int main(int, char**) {
// The data is passed 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;
}

View File

@ -238,17 +238,16 @@ check-generated-output)
# Depends on LC_COLLATE set at the top of this script.
! grep -rn '[^ -~]' libcxx/include libcxx/src libcxx/test libcxx/benchmarks \
--exclude '*.dat' \
--exclude '*unicode*.cpp' \
--exclude '*print*.sh.cpp' \
--exclude 'escaped_output.*.pass.cpp' \
--exclude 'fill.unicode.pass.cpp' \
--exclude 'format_tests.h' \
--exclude 'format.functions.tests.h' \
--exclude 'formatter.*.pass.cpp' \
--exclude 'grep.pass.cpp' \
--exclude 'locale-specific_form.pass.cpp' \
--exclude 'ostream.pass.cpp' \
--exclude 'std_format_spec_string_unicode.bench.cpp' \
--exclude 'transcoding.pass.cpp' \
--exclude 'vprint_unicode_windows.pass.cpp' \
--exclude 'underflow.pass.cpp' \
|| false