IMPALA-5031: Remove undefined behavior: left shift of large signed Shifting large positive signed values is undefined when the result is not "representable in the corresponding unsigned type of the result type". Left shift of unsigned values is always defined. See the C++14 standard, section 5.8 [expr.shift], paragraph 2.
Change-Id: I748697cf503e9e717a6e95250c2cbbf031c6352d Reviewed-on: http://gerrit.cloudera.org:8080/6528 Tested-by: Impala Public Jenkins Reviewed-by: Jim Apple <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/a2805ca6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/a2805ca6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/a2805ca6 Branch: refs/heads/master Commit: a2805ca6fa31f6e49f4bb5167225a895c35f8974 Parents: 392c4ba Author: Jim Apple <[email protected]> Authored: Tue Mar 28 15:56:26 2017 -0700 Committer: Jim Apple <[email protected]> Committed: Thu Apr 20 15:02:36 2017 +0000 ---------------------------------------------------------------------- be/src/exprs/bit-byte-functions-ir.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/a2805ca6/be/src/exprs/bit-byte-functions-ir.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/bit-byte-functions-ir.cc b/be/src/exprs/bit-byte-functions-ir.cc index 3464174..3433cb1 100644 --- a/be/src/exprs/bit-byte-functions-ir.cc +++ b/be/src/exprs/bit-byte-functions-ir.cc @@ -148,7 +148,8 @@ static T RotateLeftImpl(T v, int32_t shift) { // Handle wrapping around multiple times shift = shift % (sizeof(T) * 8); - return (v << shift) | BitUtil::ShiftRightLogical(v, sizeof(T) * 8 - shift); + return static_cast<T>((static_cast<std::make_unsigned_t<T>>(v) << shift) + | BitUtil::ShiftRightLogical(v, sizeof(T) * 8 - shift)); } template<typename T> @@ -158,15 +159,14 @@ static T RotateRightImpl(T v, int32_t shift) { // Handle wrapping around multiple times shift = shift % (sizeof(T) * 8); - using UnsignedT = std::make_unsigned_t<T>; - return BitUtil::ShiftRightLogical(v, shift) - | (static_cast<UnsignedT>(v) << (sizeof(T) * 8 - shift)); + return static_cast<T>(BitUtil::ShiftRightLogical(v, shift) + | (static_cast<std::make_unsigned_t<T>>(v) << (sizeof(T) * 8 - shift))); } template<typename T> static T ShiftLeftImpl(T v, int32_t shift) { if (shift < 0) return ShiftRightLogicalImpl(v, -shift); - return v << shift; + return static_cast<T>(static_cast<std::make_unsigned_t<T>>(v) << shift); } // Logical right shift rather than arithmetic right shift
