Avoid undefined behaviour in std::byte operators (LWG 2950)
authorJonathan Wakely <jwakely@redhat.com>
Tue, 18 Jun 2019 11:39:43 +0000 (12:39 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 18 Jun 2019 11:39:43 +0000 (12:39 +0100)
* include/c_global/cstddef (std::byte): Perform arithmetic operations
in unsigned int to avoid promotion (LWG 2950).

From-SVN: r272415

libstdc++-v3/ChangeLog
libstdc++-v3/include/c_global/cstddef

index 40d1b0b..4570ab1 100644 (file)
@@ -1,3 +1,8 @@
+2019-06-18  Jonathan Wakely  <jwakely@redhat.com>
+
+       * include/c_global/cstddef (std::byte): Perform arithmetic operations
+       in unsigned int to avoid promotion (LWG 2950).
+
 2019-06-17  Jonathan Wakely  <jwakely@redhat.com>
 
        * testsuite/20_util/allocator/1.cc: Add sized delete, which fixes a
index 8c779ec..c94c938 100644 (file)
@@ -121,70 +121,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using __byte_op_t = typename __byte_operand<_IntegerType>::__type;
 
   template<typename _IntegerType>
-    constexpr __byte_op_t<_IntegerType>&
-    operator<<=(byte& __b, _IntegerType __shift) noexcept
-    { return __b = byte(static_cast<unsigned char>(__b) << __shift); }
-
-  template<typename _IntegerType>
     constexpr __byte_op_t<_IntegerType>
     operator<<(byte __b, _IntegerType __shift) noexcept
-    { return byte(static_cast<unsigned char>(__b) << __shift); }
-
-  template<typename _IntegerType>
-    constexpr __byte_op_t<_IntegerType>&
-    operator>>=(byte& __b, _IntegerType __shift) noexcept
-    { return __b = byte(static_cast<unsigned char>(__b) >> __shift); }
+    { return (byte)(unsigned char)((unsigned)__b << __shift); }
 
   template<typename _IntegerType>
     constexpr __byte_op_t<_IntegerType>
     operator>>(byte __b, _IntegerType __shift) noexcept
-    { return byte(static_cast<unsigned char>(__b) >> __shift); }
-
-  constexpr byte&
-  operator|=(byte& __l, byte __r) noexcept
-  {
-    return __l =
-      byte(static_cast<unsigned char>(__l) | static_cast<unsigned char>(__r));
-  }
+    { return (byte)(unsigned char)((unsigned)__b >> __shift); }
 
   constexpr byte
   operator|(byte __l, byte __r) noexcept
-  {
-    return
-      byte(static_cast<unsigned char>(__l) | static_cast<unsigned char>(__r));
-  }
-
-  constexpr byte&
-  operator&=(byte& __l, byte __r) noexcept
-  {
-   return __l =
-     byte(static_cast<unsigned char>(__l) & static_cast<unsigned char>(__r));
-  }
+  { return (byte)(unsigned char)((unsigned)__l | (unsigned)__r); }
 
   constexpr byte
   operator&(byte __l, byte __r) noexcept
-  {
-    return
-      byte(static_cast<unsigned char>(__l) & static_cast<unsigned char>(__r));
-  }
-
-  constexpr byte&
-  operator^=(byte& __l, byte __r) noexcept
-  {
-    return __l =
-      byte(static_cast<unsigned char>(__l) ^ static_cast<unsigned char>(__r));
-  }
+  { return (byte)(unsigned char)((unsigned)__l & (unsigned)__r); }
 
   constexpr byte
   operator^(byte __l, byte __r) noexcept
-  {
-    return
-      byte(static_cast<unsigned char>(__l) ^ static_cast<unsigned char>(__r));
-  }
+  { return (byte)(unsigned char)((unsigned)__l ^ (unsigned)__r); }
 
   constexpr byte
   operator~(byte __b) noexcept
-  { return byte(~static_cast<unsigned char>(__b)); }
+  { return (byte)(unsigned char)~(unsigned)__b; }
+
+  template<typename _IntegerType>
+    constexpr __byte_op_t<_IntegerType>&
+    operator<<=(byte& __b, _IntegerType __shift) noexcept
+    { return __b = __b << __shift; }
+
+  template<typename _IntegerType>
+    constexpr __byte_op_t<_IntegerType>&
+    operator>>=(byte& __b, _IntegerType __shift) noexcept
+    { return __b = __b >> __shift; }
+
+  constexpr byte&
+  operator|=(byte& __l, byte __r) noexcept
+  { return __l = __l | __r; }
+
+  constexpr byte&
+  operator&=(byte& __l, byte __r) noexcept
+  { return __l = __l & __r; }
+
+  constexpr byte&
+  operator^=(byte& __l, byte __r) noexcept
+  { return __l = __l ^ __r; }
 
   template<typename _IntegerType>
     constexpr _IntegerType