From e1fb35b16ff9fa699257aaf53c942cf123a1b31e Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 6 Jun 2018 18:25:45 +0100 Subject: [PATCH] Fix undefined behaviour when left-shifting negative values by casting to unsigned This silences warning spam from UndefinedBehaviorSanitizer. --- src/core/overflowsafe_type.hpp | 4 +++- src/map_func.h | 2 +- src/tree_map.h | 2 +- src/zoom_func.h | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/overflowsafe_type.hpp b/src/core/overflowsafe_type.hpp index edc25d2755..5689236b30 100644 --- a/src/core/overflowsafe_type.hpp +++ b/src/core/overflowsafe_type.hpp @@ -13,6 +13,7 @@ #define OVERFLOWSAFE_TYPE_HPP #include "math_func.hpp" +#include /** * Overflow safe template for integers, i.e. integers that will never overflow @@ -28,6 +29,7 @@ class OverflowSafeInt private: /** The non-overflow safe backend to store the value in. */ T m_value; + typedef typename std::make_unsigned::type T_unsigned; public: OverflowSafeInt() : m_value(0) { } @@ -103,7 +105,7 @@ public: inline OverflowSafeInt operator % (const int divisor) const { OverflowSafeInt result = *this; result %= divisor; return result; } /* Operators for shifting */ - inline OverflowSafeInt& operator <<= (const int shift) { this->m_value <<= shift; return *this; } + inline OverflowSafeInt& operator <<= (const int shift) { this->m_value = ((T_unsigned) this->m_value) << shift; return *this; } inline OverflowSafeInt operator << (const int shift) const { OverflowSafeInt result = *this; result <<= shift; return result; } inline OverflowSafeInt& operator >>= (const int shift) { this->m_value >>= shift; return *this; } inline OverflowSafeInt operator >> (const int shift) const { OverflowSafeInt result = *this; result >>= shift; return result; } diff --git a/src/map_func.h b/src/map_func.h index 556d057c2a..7d17d6bed6 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -232,7 +232,7 @@ static inline uint TileY(TileIndex tile) */ static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc) { - return (tidc.y << MapLogX()) + tidc.x; + return (((uint) tidc.y) << MapLogX()) + tidc.x; } diff --git a/src/tree_map.h b/src/tree_map.h index e614099fc9..690e15a818 100644 --- a/src/tree_map.h +++ b/src/tree_map.h @@ -166,7 +166,7 @@ static inline uint GetTreeCount(TileIndex t) static inline void AddTreeCount(TileIndex t, int c) { assert(IsTileType(t, MP_TREES)); // XXX incomplete - _m[t].m5 += c << 6; + _m[t].m5 += ((uint) c) << 6; } /** diff --git a/src/zoom_func.h b/src/zoom_func.h index da266e35c6..3aed83eadd 100644 --- a/src/zoom_func.h +++ b/src/zoom_func.h @@ -24,7 +24,7 @@ static inline int ScaleByZoom(int value, ZoomLevel zoom) { assert(zoom >= 0); - return value << zoom; + return ((uint) value) << zoom; } /** @@ -49,7 +49,7 @@ static inline int UnScaleByZoom(int value, ZoomLevel zoom) static inline int ScaleByZoomLower(int value, ZoomLevel zoom) { assert(zoom >= 0); - return value << zoom; + return ((uint) value) << zoom; } /**