-
Notifications
You must be signed in to change notification settings - Fork 14.1k
[libc++][format] P3142R0: Printing Blank Lines with println
#87277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++][format] P3142R0: Printing Blank Lines with println
#87277
Conversation
println
println
@llvm/pr-subscribers-libcxx Author: Hristo Hristov (H-G-Hristov) ChangesImplements https://wg21.link/P3142R0 Full diff: https://github.com/llvm/llvm-project/pull/87277.diff 8 Files Affected:
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index dd39c1bbbc78a3..7bf1da91e2abb9 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -42,6 +42,7 @@ Implemented Papers
- P2652R2 - Disallow User Specialization of ``allocator_traits``
- P2819R2 - Add ``tuple`` protocol to ``complex``
- P2495R3 - Interfacing ``stringstream``\s with ``string_view``
+- P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23)
- P2302R4 - ``std::ranges::contains``
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
diff --git a/libcxx/include/ostream b/libcxx/include/ostream
index 42819ceb252c65..d4fc1c58b8a941 100644
--- a/libcxx/include/ostream
+++ b/libcxx/include/ostream
@@ -164,6 +164,7 @@ template<class... Args>
void print(ostream& os, format_string<Args...> fmt, Args&&... args);
template<class... Args> // since C++23
void println(ostream& os, format_string<Args...> fmt, Args&&... args);
+void println(ostream& os); // since C++26
void vprint_unicode(ostream& os, string_view fmt, format_args args); // since C++23
void vprint_nonunicode(ostream& os, string_view fmt, format_args args); // since C++23
@@ -1163,6 +1164,9 @@ _LIBCPP_HIDE_FROM_ABI void println(ostream& __os, format_string<_Args...> __fmt,
# endif // _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 println(ostream& __os) { std::print(__os, "\n"); }
+
#endif // _LIBCPP_STD_VER >= 23
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/print b/libcxx/include/print
index a9f10433a7dc61..e0bcf214ea239b 100644
--- a/libcxx/include/print
+++ b/libcxx/include/print
@@ -15,8 +15,10 @@ namespace std {
// [print.fun], print functions
template<class... Args>
void print(format_string<Args...> fmt, Args&&... args);
+ void println(); // Since C++26
template<class... Args>
void print(FILE* stream, format_string<Args...> fmt, Args&&... args);
+ void println(FILE* stream); // Since C++26
template<class... Args>
void println(format_string<Args...> fmt, Args&&... args);
@@ -356,6 +358,12 @@ _LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt
# endif // _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 println(FILE* __stream) { std::print(__stream, "\n"); }
+
+template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
+_LIBCPP_HIDE_FROM_ABI inline void println() { println(stdout); }
+
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI void println(format_string<_Args...> __fmt, _Args&&... __args) {
std::println(stdout, __fmt, std::forward<_Args>(__args)...);
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
index 6b62e2f1754de5..8edfb90b15b86d 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
@@ -26,6 +26,7 @@
// void print(ostream& os, format_string<Args...> fmt, Args&&... args);
// template<class... Args>
// void println(ostream& os, format_string<Args...> fmt, Args&&... args);
+// void println(ostream& os); // since C++26
//
// void vprint_unicode(ostream& os, string_view fmt, format_args args);
// void vprint_nonunicode(ostream& os, string_view fmt, format_args args);
@@ -86,10 +87,11 @@ test(std::stringstream& stream, std::string expected, test_format_string<char, A
}
// *** println ***
{
- expected += '\n'; // Tested last since it changes the expected value.
+ expected += "\n\n"; // Tested last since it changes the expected value.
stream.str("");
;
std::println(stream, fmt, std::forward<Args>(args)...);
+ std::println(stream);
std::string out = stream.str();
TEST_REQUIRE(out == expected,
TEST_WRITE_CONCATENATED(
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/println.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/println.pass.cpp
index 479a3de0a93c8d..b61fcf174422af 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/println.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/println.pass.cpp
@@ -17,6 +17,7 @@
// template<class... Args>
// void println(ostream& os, format_string<Args...> fmt, Args&&... args);
+// void println(ostream& os); // since C++26
// [ostream.formatted.print]/3
// If the function is vprint_unicode and os is a stream that refers to
@@ -37,10 +38,11 @@
#include "test_macros.h"
auto test_file = []<class... Args>(std::string_view e, test_format_string<char, Args...> fmt, Args&&... args) {
- std::string expected = std::string{e} + '\n';
+ std::string expected = std::string{e} + "\n\n";
std::stringstream sstr;
std::println(sstr, fmt, std::forward<Args>(args)...);
+ std::println(sstr);
std::string out = sstr.str();
TEST_REQUIRE(out == expected,
diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp b/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp
index f502616b677b77..450ca45a6d4b7e 100644
--- a/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp
@@ -25,8 +25,10 @@
// template<class... Args>
// void print(FILE* stream, format_string<Args...> fmt, Args&&... args);
+// void println(); // Since C++26
// template<class... Args>
// void println(FILE* stream, format_string<Args...> fmt, Args&&... args);
+// void println(FILE* stream); // Since C++26
// void vprint_unicode(FILE* stream, string_view fmt, format_args args);
// void vprint_nonunicode(FILE* stream, string_view fmt, format_args args);
@@ -56,11 +58,12 @@ static void test_println() {
assert(file);
std::println(file, "hello world{}", '!');
+ std::println(file);
long pos = std::ftell(file);
std::fclose(file);
assert(pos > 0);
- assert(std::string_view(buffer.data(), pos) == "hello world!\n");
+ assert(std::string_view(buffer.data(), pos) == "hello world!\n\n");
}
static void test_vprint_unicode() {
diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/println.file.pass.cpp b/libcxx/test/std/input.output/iostream.format/print.fun/println.file.pass.cpp
index 07272ebb57e5fc..9e96864aa822dd 100644
--- a/libcxx/test/std/input.output/iostream.format/print.fun/println.file.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/print.fun/println.file.pass.cpp
@@ -112,6 +112,17 @@ static void test_new_line() {
FILE* file = fopen(filename.c_str(), "w");
assert(file);
+ std::println(file);
+#ifndef _WIN32
+ assert(std::ftell(file) == 1);
+#else
+ assert(std::ftell(file) == 2);
+#endif
+ }
+ {
+ FILE* file = fopen(filename.c_str(), "w");
+ assert(file);
+
std::println(file, "");
#ifndef _WIN32
assert(std::ftell(file) == 1);
@@ -124,6 +135,13 @@ static void test_new_line() {
FILE* file = fopen(filename.c_str(), "wb");
assert(file);
+ std::println(file);
+ assert(std::ftell(file) == 1);
+ }
+ {
+ FILE* file = fopen(filename.c_str(), "wb");
+ assert(file);
+
std::println(file, "");
assert(std::ftell(file) == 1);
}
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
index b811b4f2a24933..67343b3a730c54 100644
--- 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
@@ -36,7 +36,7 @@
// FILE_DEPENDENCIES: echo.sh
// RUN: %{build}
-// RUN: %{exec} bash echo.sh -ne "1234 一二三四\ntrue 0x0\n" > %t.expected
+// RUN: %{exec} bash echo.sh -ne "1234 一二三四\ntrue 0x0\n\n" > %t.expected
// RUN: %{exec} "%t.exe" > %t.actual
// RUN: diff -u %t.actual %t.expected
@@ -46,6 +46,7 @@ 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);
+ std::println();
return 0;
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks quite good. A few minor comments. Can you rebase so you can update the status page.
...ormat/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
Outdated
Show resolved
Hide resolved
...ormat/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! LGTM!
@mordante Thank you! |
the
would you take care of it? |
I had a look and a similar test
might solve the issue. @Zingam can you provide a followup patch to make this change? If the suggested solution works we should add comment why we output we do that. |
…-win-x-* configurations Fix for issue: llvm#87277 (comment)
@vvereschaka @mordante I created a PR with the proposed resolution with a slight twist here: #88011 Thank you for the heads-up! I wonder if double |
…-win-x-* configurations (#88011) Fix for issue: #87277 (comment) The test fails on the windows to linux cross builders. The proposed resolution is to print some text. The issue is possibly due to the original test outputting a single `\n` character.
…-win-x-* configurations (#88011) Fix for issue: llvm/llvm-project#87277 (comment) The test fails on the windows to linux cross builders. The proposed resolution is to print some text. The issue is possibly due to the original test outputting a single `\n` character. NOKEYCHECK=True GitOrigin-RevId: ea2392ed33f765018002f833da9a04cd0571ab83
Implements https://wg21.link/P3142R0
Applied retroactively as DR, same as stdlibc++ and MS STL:
STL C++26 Features