Skip to content

Commit

Permalink
Fix left shift of negative value caused by integral promotion
Browse files Browse the repository at this point in the history
  • Loading branch information
milleniumbug committed Jul 4, 2018
1 parent 69ae4f7 commit 0bb564e
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion include/rapidcheck/detail/Utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,17 @@ inline uint64_t avalanche(uint64_t x) {
template <typename T>
constexpr T bitMask(int nbits) {
using UT = typename std::make_unsigned<T>::type;
using UTP = typename std::common_type<UT, unsigned>::type;
// There are two pieces of undefined behavior we're avoiding here,
// 1. Shifting past the width of a type (ex `<< 32` against an `int32_t`)
// 2. Shifting a negative operand (which `~0` is for all signed types)
// First we branch to avoid shifting the past the width of the type, then
// (assuming we are shifting, and aren't just returning `~0`) we cast `0`
// to an explicitly unsigned type before performing bitwise NOT and shift.
// We're ensuring the target type is as big as unsigned, otherwise it will
// be promoted to int before bitwise NOT, producing a negative value.
return nbits < std::numeric_limits<UT>::digits ?
~T(~UT(0) << nbits) :
~T(~UTP(0) << nbits) :
~T(0);
}

Expand Down

0 comments on commit 0bb564e

Please sign in to comment.