[libcxx-commits] [libcxx] [libc++][format] P3142R0: Printing Blank Lines with `println` (PR #87277)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Mon Apr 1 13:21:08 PDT 2024


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/87277

>From 327f8fe8ab2bda7e7f46ba5b2cbfd2a37c51b1cc Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 29 Mar 2024 18:13:32 +0200
Subject: [PATCH 1/2] [libc++][format] P3142R0 - Printing Blank Lines with
 `println`

Implements https://wg21.link/P3142R0
---
 libcxx/docs/ReleaseNotes/19.rst                |  1 +
 libcxx/include/ostream                         |  3 +++
 libcxx/include/print                           |  6 ++++++
 .../locale-specific_form.pass.cpp              |  4 +++-
 .../ostream.formatted.print/println.pass.cpp   |  4 +++-
 .../print.fun/no_file_description.pass.cpp     |  5 ++++-
 .../print.fun/println.file.pass.cpp            | 18 ++++++++++++++++++
 .../iostream.format/print.fun/println.sh.cpp   |  3 ++-
 8 files changed, 40 insertions(+), 4 deletions(-)

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..0c97f48da5c5a4 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,8 @@ _LIBCPP_HIDE_FROM_ABI void println(ostream& __os, format_string<_Args...> __fmt,
 #  endif // _LIBCPP_HAS_NO_UNICODE
 }
 
+_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..e12dfe999c64d7 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,10 @@ _LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt
 #  endif // _LIBCPP_HAS_NO_UNICODE
 }
 
+_LIBCPP_HIDE_FROM_ABI inline void println(FILE* __stream) { std::print(__stream, "\n"); }
+
+_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..24b1062775493a 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,9 +38,10 @@
 #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 = '\n' + std::string{e} + '\n';
 
   std::stringstream sstr;
+  std::println(sstr);
   std::println(sstr, fmt, std::forward<Args>(args)...);
 
   std::string out = sstr.str();
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..5144e61afaec59 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);
 
@@ -55,12 +57,13 @@ static void test_println() {
   FILE* file = fmemopen(buffer.data(), buffer.size(), "wb");
   assert(file);
 
+  std::println(file);
   std::println(file, "hello world{}", '!');
   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) == "\nhello world!\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..b93fa723ee2174 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 "\n1234 一二三四\ntrue 0x0\n" > %t.expected
 // RUN: %{exec} "%t.exe" > %t.actual
 // RUN: diff -u %t.actual %t.expected
 
@@ -44,6 +44,7 @@
 
 int main(int, char**) {
   // The data is passed as-is so it does not depend on the encoding of the input.
+  std::println();
   std::println("{} {}", 1234, "一二三四");
   std::println("{} {}", true, nullptr);
 

>From d39dbbedf29b09a35787841041ca43a8460ed4bf Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 1 Apr 2024 23:20:52 +0300
Subject: [PATCH 2/2] Try to fix Apple CI

---
 libcxx/include/ostream | 1 +
 libcxx/include/print   | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/libcxx/include/ostream b/libcxx/include/ostream
index 0c97f48da5c5a4..d4fc1c58b8a941 100644
--- a/libcxx/include/ostream
+++ b/libcxx/include/ostream
@@ -1164,6 +1164,7 @@ _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
diff --git a/libcxx/include/print b/libcxx/include/print
index e12dfe999c64d7..e0bcf214ea239b 100644
--- a/libcxx/include/print
+++ b/libcxx/include/print
@@ -358,8 +358,10 @@ _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>



More information about the libcxx-commits mailing list