public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Tom Honermann <tom@honermann.net>
To: "libstdc++@gcc.gnu.org" <libstdc++@gcc.gnu.org>,
	gcc-patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH 2/4]: C++ P1423R3 char8_t remediation: Update feature test macro, add deleted operators, update u8path
Date: Mon, 16 Sep 2019 02:33:00 -0000	[thread overview]
Message-ID: <e4ac300b-93bd-310c-9ad2-9fb11766b4fd@honermann.net> (raw)
In-Reply-To: <05f9b7ab-b89a-4348-e758-e7ef9077261a@honermann.net>

[-- Attachment #1: Type: text/plain, Size: 1658 bytes --]

A revised patch is attached that adds proper preprocessor conditionals 
around the deleted ostream inserters.  Apparently I had previously 
implemented a quick hack for testing purposes, neglected to add a FIXME 
comment, and then forgot about the hack.  Shame on me.

Tom.

On 9/15/19 3:39 PM, Tom Honermann wrote:
> This patch increments the __cpp_lib_char8_t feature test macro, adds 
> deleted operator<< overloads for basic_ostream, and modifies u8path to 
> accept sequences of char8_t for both the C++17 implementation of 
> std::filesystem, and the filesystem TS implementation.
> 
> The implementation mechanism used for u8path differs between the C++17 
> and filesystem TS implementations.  The changes to the former take 
> advantage of C++17 'if constexpr'.  The changes to the latter retain 
> C++11 compatibility and rely on tag dispatching.
> 
> libstdc++-v3/ChangeLog:
> 
> 2019-09-15  Tom Honermann  <tom@honermann.net>
> 
>       * libstdc++-v3/include/bits/c++config: Bumped the value of the
>         __cpp_lib_char8_t feature test macro.
>       * libstdc++-v3/include/bits/fs_path.h (u8path): Modified u8path to
>         accept sequences of char8_t.
>       * libstdc++-v3/include/experimental/bits/fs_path.h (u8path):
>         Modified u8path to accept sequences of char8_t.
>       * libstdc++-v3/include/std/ostream: Added deleted overloads of
>         wchar_t, char8_t, char16_t, and char32_t for ordinary and wide
>         formatted character and string inserters.
> 
> Tom.


[-- Attachment #2: p1423r3-2-2.patch --]
[-- Type: text/x-patch, Size: 12557 bytes --]

diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index c8e099aaadd..5bcf32d95ef 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -620,7 +620,7 @@ namespace std
 # endif
 #endif
 #ifdef _GLIBCXX_USE_CHAR8_T
-# define __cpp_lib_char8_t 201811L
+# define __cpp_lib_char8_t 201907L
 #endif
 
 /* Define if __float128 is supported on this host. */
diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h
index 71354515403..f3f539412fc 100644
--- a/libstdc++-v3/include/bits/fs_path.h
+++ b/libstdc++-v3/include/bits/fs_path.h
@@ -153,9 +153,24 @@ namespace __detail
 
   template<typename _Tp,
 	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
-	   typename _Val = typename std::iterator_traits<_Iter>::value_type>
+	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
+	   typename _UnqualVal = std::remove_const_t<_Val>>
     using __value_type_is_char
-      = std::enable_if_t<std::is_same_v<std::remove_const_t<_Val>, char>>;
+      = std::enable_if_t<std::is_same_v<_UnqualVal, char>,
+			 _UnqualVal>;
+
+  template<typename _Tp,
+	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
+	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
+	   typename _UnqualVal = std::remove_const_t<_Val>>
+    using __value_type_is_char_or_char8_t
+      = std::enable_if_t<__or_v<
+			   std::is_same<_UnqualVal, char>
+#ifdef _GLIBCXX_USE_CHAR8_T
+			   ,std::is_same<_UnqualVal, char8_t>
+#endif
+			   >,
+			 _UnqualVal>;
 
   // @} group filesystem-detail
 } // namespace __detail
@@ -639,29 +654,41 @@ namespace __detail
   /// Create a path from a UTF-8-encoded sequence of char
   template<typename _InputIterator,
 	   typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
-	   typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
+	   typename _CharT =
+	     __detail::__value_type_is_char_or_char8_t<_InputIterator>>
     inline path
     u8path(_InputIterator __first, _InputIterator __last)
     {
 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-      // XXX This assumes native wide encoding is UTF-16.
-      std::codecvt_utf8_utf16<path::value_type> __cvt;
-      path::string_type __tmp;
-      if constexpr (is_pointer_v<_InputIterator>)
+#ifdef _GLIBCXX_USE_CHAR8_T
+      if constexpr (is_same_v<_CharT, char8_t>)
 	{
-	  if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
-	    return path{ __tmp };
+	  return path{ __first, __last };
 	}
       else
 	{
-	  const std::string __u8str{__first, __last};
-	  const char* const __ptr = __u8str.data();
-	  if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt))
-	    return path{ __tmp };
+#endif
+	  // XXX This assumes native wide encoding is UTF-16.
+	  std::codecvt_utf8_utf16<path::value_type> __cvt;
+	  path::string_type __tmp;
+	  if constexpr (is_pointer_v<_InputIterator>)
+	    {
+	      if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
+		return path{ __tmp };
+	    }
+	  else
+	    {
+	      const std::string __u8str{__first, __last};
+	      const char* const __ptr = __u8str.data();
+	      if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt))
+		return path{ __tmp };
+	    }
+	  _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+	      "Cannot convert character sequence",
+	      std::make_error_code(errc::illegal_byte_sequence)));
+#ifdef _GLIBCXX_USE_CHAR8_T
 	}
-      _GLIBCXX_THROW_OR_ABORT(filesystem_error(
-	    "Cannot convert character sequence",
-	    std::make_error_code(errc::illegal_byte_sequence)));
+#endif
 #else
       // This assumes native normal encoding is UTF-8.
       return path{ __first, __last };
@@ -671,21 +698,32 @@ namespace __detail
   /// Create a path from a UTF-8-encoded sequence of char
   template<typename _Source,
 	   typename _Require = __detail::_Path<_Source>,
-	   typename _Require2 = __detail::__value_type_is_char<_Source>>
+	   typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>>
     inline path
     u8path(const _Source& __source)
     {
 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-      if constexpr (is_convertible_v<const _Source&, std::string_view>)
+#ifdef _GLIBCXX_USE_CHAR8_T
+      if constexpr (is_same_v<_CharT, char8_t>)
 	{
-	  const std::string_view __s = __source;
-	  return filesystem::u8path(__s.data(), __s.data() + __s.size());
+	  return path{ __source };
 	}
       else
 	{
-	  std::string __s = path::_S_string_from_iter(__source);
-	  return filesystem::u8path(__s.data(), __s.data() + __s.size());
+#endif
+	  if constexpr (is_convertible_v<const _Source&, std::string_view>)
+	    {
+	      const std::string_view __s = __source;
+	      return filesystem::u8path(__s.data(), __s.data() + __s.size());
+	    }
+	  else
+	    {
+	      std::string __s = path::_S_string_from_iter(__source);
+	      return filesystem::u8path(__s.data(), __s.data() + __s.size());
+	    }
+#ifdef _GLIBCXX_USE_CHAR8_T
 	}
+#endif
 #else
       return path{ __source };
 #endif
diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h
index 3f9a69514a1..7a8cd8d20de 100644
--- a/libstdc++-v3/include/experimental/bits/fs_path.h
+++ b/libstdc++-v3/include/experimental/bits/fs_path.h
@@ -169,10 +169,23 @@ namespace __detail
 
   template<typename _Tp,
 	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
-	   typename _Val = typename std::iterator_traits<_Iter>::value_type>
+	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
+	   typename _UnqualVal = typename std::remove_const<_Val>::type>
     using __value_type_is_char = typename std::enable_if<
-      std::is_same<typename std::remove_const<_Val>::type, char>::value
-      >::type;
+      std::is_same<_UnqualVal, char>::value,
+      _UnqualVal>::type;
+
+  template<typename _Tp,
+	   typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
+	   typename _Val = typename std::iterator_traits<_Iter>::value_type,
+	   typename _UnqualVal = typename std::remove_const<_Val>::type>
+    using __value_type_is_char_or_char8_t = typename std::enable_if<
+      __or_<
+	std::is_same<_UnqualVal, char>
+#ifdef _GLIBCXX_USE_CHAR8_T
+	,std::is_same<_UnqualVal, char8_t>
+#endif
+      >::value, _UnqualVal>::type;
 
   // @} group filesystem-ts-detail
 } // namespace __detail
@@ -592,13 +605,11 @@ namespace __detail
     }
 
   /// Create a path from a UTF-8-encoded sequence of char
-  template<typename _InputIterator,
-	   typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
-	   typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  template<typename _InputIterator>
     inline path
-    u8path(_InputIterator __first, _InputIterator __last)
+    __u8path(_InputIterator __first, _InputIterator __last, char)
     {
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
       // XXX This assumes native wide encoding is UTF-16.
       std::codecvt_utf8_utf16<path::value_type> __cvt;
       path::string_type __tmp;
@@ -609,21 +620,61 @@ namespace __detail
       _GLIBCXX_THROW_OR_ABORT(filesystem_error(
 	    "Cannot convert character sequence",
 	    std::make_error_code(errc::illegal_byte_sequence)));
+    }
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<typename _InputIterator>
+    inline path
+    __u8path(_InputIterator __first, _InputIterator __last, char8_t)
+    {
+      return path{ __first, __last };
+    }
+#endif // _GLIBCXX_USE_CHAR8_T
+#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
+
+  template<typename _InputIterator,
+	   typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
+	   typename _CharT =
+	     __detail::__value_type_is_char_or_char8_t<_InputIterator>>
+    inline path
+    u8path(_InputIterator __first, _InputIterator __last)
+    {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+      return __u8path(__first, __last, _CharT{});
 #else
       return path{ __first, __last };
 #endif
     }
 
   /// Create a path from a UTF-8-encoded sequence of char
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  template<typename _Source>
+    inline path
+    __u8path(const _Source& __source, char)
+    {
+      std::string __s = path::_S_string_from_iter(__source);
+      return filesystem::u8path(__s.data(), __s.data() + __s.size());
+    }
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<typename _Source>
+    inline path
+    __u8path(const _Source& __source, char8_t)
+    {
+      return path{ __source };
+    }
+#endif // _GLIBCXX_USE_CHAR8_T
+#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
+
   template<typename _Source,
 	   typename _Require = __detail::_Path<_Source>,
-	   typename _Require2 = __detail::__value_type_is_char<_Source>>
+	   typename _CharT =
+	     __detail::__value_type_is_char_or_char8_t<_Source>>
     inline path
     u8path(const _Source& __source)
     {
 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-      std::string __s = path::_S_string_from_iter(__source);
-      return filesystem::u8path(__s.data(), __s.data() + __s.size());
+      return __u8path(__source, _CharT{});
 #else
       return path{ __source };
 #endif
diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
index 2541d978886..771c28db7b7 100644
--- a/libstdc++-v3/include/std/ostream
+++ b/libstdc++-v3/include/std/ostream
@@ -527,6 +527,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline basic_ostream<char, _Traits>&
     operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c)
     { return (__out << static_cast<char>(__c)); }
+
+#if __cplusplus > 201703L
+  // The following deleted overloads prevent formatting character values as
+  // numeric values.
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, wchar_t) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, char8_t) = delete;
+#endif
+
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, char16_t) = delete;
+
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, char32_t) = delete;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<class _Traits>
+    basic_ostream<wchar_t, _Traits>&
+    operator<<(basic_ostream<wchar_t, _Traits>&, char8_t) = delete;
+#endif // _GLIBCXX_USE_CHAR8_T
+
+  template<class _Traits>
+    basic_ostream<wchar_t, _Traits>&
+    operator<<(basic_ostream<wchar_t, _Traits>&, char16_t) = delete;
+
+  template<class _Traits>
+    basic_ostream<wchar_t, _Traits>&
+    operator<<(basic_ostream<wchar_t, _Traits>&, char32_t) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+#endif // C++20
   //@}
 
   //@{
@@ -582,6 +623,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline basic_ostream<char, _Traits> &
     operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s)
     { return (__out << reinterpret_cast<const char*>(__s)); }
+
+#if __cplusplus > 201703L
+   // The following deleted overloads prevent formatting strings as
+   // pointer values.
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, const wchar_t*) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, const char8_t*) = delete;
+#endif // _GLIBCXX_USE_CHAR8_T
+
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, const char16_t*) = delete;
+
+  template<class _Traits>
+    basic_ostream<char, _Traits>&
+    operator<<(basic_ostream<char, _Traits>&, const char32_t*) = delete;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<class _Traits>
+    basic_ostream<wchar_t, _Traits>&
+    operator<<(basic_ostream<wchar_t, _Traits>&, const char8_t*) = delete;
+#endif
+
+  template<class _Traits>
+    basic_ostream<wchar_t, _Traits>&
+    operator<<(basic_ostream<wchar_t, _Traits>&, const char16_t*) = delete;
+
+  template<class _Traits>
+    basic_ostream<wchar_t, _Traits>&
+    operator<<(basic_ostream<wchar_t, _Traits>&, const char32_t*) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+#endif // C++20
   //@}
 
   // Standard basic_ostream manipulators

      reply	other threads:[~2019-09-16  2:33 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-15 19:39 Tom Honermann
2019-09-16  2:33 ` Tom Honermann [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e4ac300b-93bd-310c-9ad2-9fb11766b4fd@honermann.net \
    --to=tom@honermann.net \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=libstdc++@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).