@@ -47,24 +47,37 @@ struct bitwise_not_operator {
47
47
}
48
48
};
49
49
50
- // Replace specific reference values to the bigger ones, so we can safely
51
- // substract `m_value` later.
52
- template <typename T> class For_bitwise_not {
53
- T m_value;
54
-
55
- public:
50
+ // Replace specific reference values to lower once.
51
+ template <typename T> struct For_bitwise_not {
56
52
For_bitwise_not () = default ;
57
53
58
54
void operator ()(T &val) {
55
+ static_assert (!type_traits::is_sycl_floating_point_v<T>,
56
+ " Invalid data type." );
59
57
if constexpr (std::is_signed_v<T>) {
60
- if (std::abs (value<T>::lowest () + 1 ) == (value<T>::max () - 1 )) {
61
- if (val == value<T>::max ()) {
58
+ // We could have UB for negative zero in different integral type
59
+ // representations: two's complement, ones' complement and signed
60
+ // magnitude.
61
+ // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2218.htm
62
+ // Note that there is no check for UB with padding bits here, as it would
63
+ // effectively disable any possible check for signed integer bitwise
64
+ // operations.
65
+ static const T max = value<T>::max ();
66
+ static const T lowest = value<T>::lowest ();
67
+ if (std::abs (lowest + 1 ) == (max - 1 )) {
68
+ // C11 standard mentions that it's possible to have a `0b100...0` value
69
+ // as a trap value for twos' complement representation. In such case the
70
+ // condition above would trigger for twos' complement representation
71
+ // also.
72
+ if (val == max) {
73
+ // Would result in trap representation for signed magnitude
62
74
val -= 1 ;
63
75
} else if (val == 0 ) {
76
+ // Would result in trap representation for ones' complement
64
77
val = 1 ;
65
78
}
66
79
}
67
- }
80
+ } // signed integral types
68
81
}
69
82
};
70
83
0 commit comments