diff --git a/webrtc/base/ipaddress.cc b/webrtc/base/ipaddress.cc index c92f33c74d..b1d1265ae4 100644 --- a/webrtc/base/ipaddress.cc +++ b/webrtc/base/ipaddress.cc @@ -412,7 +412,9 @@ int CountIPMaskBits(IPAddress mask) { // http://graphics.stanford.edu/~seander/bithacks.html // Counts the trailing 0s in the word. unsigned int zeroes = 32; - word_to_count &= -static_cast(word_to_count); + // This could also be written word_to_count &= -word_to_count, but + // MSVC emits warning C4146 when negating an unsigned number. + word_to_count &= ~word_to_count + 1; // Isolate lowest set bit. if (word_to_count) zeroes--; if (word_to_count & 0x0000FFFF) zeroes -= 16; if (word_to_count & 0x00FF00FF) zeroes -= 8; @@ -522,4 +524,4 @@ IPAddress GetAnyIP(int family) { return rtc::IPAddress(); } -} // Namespace rtc +} // namespace rtc diff --git a/webrtc/base/mathutils.h b/webrtc/base/mathutils.h index e2b21261dd..3c70e765e1 100644 --- a/webrtc/base/mathutils.h +++ b/webrtc/base/mathutils.h @@ -12,9 +12,28 @@ #define WEBRTC_BASE_MATHUTILS_H_ #include +#include + +#include "webrtc/base/checks.h" #ifndef M_PI #define M_PI 3.14159265359f #endif +// Given two numbers |x| and |y| such that x >= y, computes the difference +// x - y without causing undefined behavior due to signed overflow. +template +typename std::make_unsigned::type unsigned_difference(T x, T y) { + static_assert( + std::is_signed::value, + "Function unsigned_difference is only meaningful for signed types."); + RTC_DCHECK_GE(x, y); + typedef typename std::make_unsigned::type unsigned_type; + // int -> unsigned conversion repeatedly adds UINT_MAX + 1 until the number + // can be represented as an unsigned. Since we know that the actual + // difference x - y can be represented as an unsigned, it is sufficient to + // compute the difference modulo UINT_MAX + 1, i.e using unsigned arithmetic. + return static_cast(x) - static_cast(y); +} + #endif // WEBRTC_BASE_MATHUTILS_H_ diff --git a/webrtc/base/random_unittest.cc b/webrtc/base/random_unittest.cc index 3b47a00806..ae1a0a2f51 100644 --- a/webrtc/base/random_unittest.cc +++ b/webrtc/base/random_unittest.cc @@ -14,6 +14,7 @@ #include #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/mathutils.h" // unsigned difference #include "webrtc/base/random.h" namespace webrtc { @@ -118,7 +119,7 @@ void BucketTestSignedInterval(unsigned int bucket_count, ASSERT_GE(high, low); ASSERT_GE(bucket_count, 2u); - uint32_t interval = static_cast(high - low + 1); + uint32_t interval = unsigned_difference(high, low) + 1; uint32_t numbers_per_bucket; if (interval == 0) { // The computation high - low + 1 should be 2^32 but overflowed @@ -134,7 +135,7 @@ void BucketTestSignedInterval(unsigned int bucket_count, int32_t sample = prng->Rand(low, high); EXPECT_LE(low, sample); EXPECT_GE(high, sample); - buckets[static_cast(sample - low) / numbers_per_bucket]++; + buckets[unsigned_difference(sample, low) / numbers_per_bucket]++; } for (unsigned int i = 0; i < bucket_count; i++) { @@ -158,7 +159,7 @@ void BucketTestUnsignedInterval(unsigned int bucket_count, ASSERT_GE(high, low); ASSERT_GE(bucket_count, 2u); - uint32_t interval = static_cast(high - low + 1); + uint32_t interval = high - low + 1; uint32_t numbers_per_bucket; if (interval == 0) { // The computation high - low + 1 should be 2^32 but overflowed @@ -174,7 +175,7 @@ void BucketTestUnsignedInterval(unsigned int bucket_count, uint32_t sample = prng->Rand(low, high); EXPECT_LE(low, sample); EXPECT_GE(high, sample); - buckets[static_cast(sample - low) / numbers_per_bucket]++; + buckets[(sample - low) / numbers_per_bucket]++; } for (unsigned int i = 0; i < bucket_count; i++) { diff --git a/webrtc/base/rollingaccumulator.h b/webrtc/base/rollingaccumulator.h index e105380191..0c8e5fb8bd 100644 --- a/webrtc/base/rollingaccumulator.h +++ b/webrtc/base/rollingaccumulator.h @@ -56,7 +56,7 @@ class RollingAccumulator { // Remove oldest sample. T sample_to_remove = samples_[next_index_]; sum_ -= sample_to_remove; - sum_2_ -= sample_to_remove * sample_to_remove; + sum_2_ -= static_cast(sample_to_remove) * sample_to_remove; if (sample_to_remove >= max_) { max_stale_ = true; } @@ -70,7 +70,7 @@ class RollingAccumulator { // Add new sample. samples_[next_index_] = sample; sum_ += sample; - sum_2_ += sample * sample; + sum_2_ += static_cast(sample) * sample; if (count_ == 1 || sample >= max_) { max_ = sample; max_stale_ = false;