Skip to content

Commit

Permalink
Make it possible to disable overflow checks in signed integers
Browse files Browse the repository at this point in the history
If SUS_CHECK_INTEGER_OVERFLOW is defined to false then overflow checks
will be removed in signed integers. Wrapping operations (as with
unsigned integers) will be performed instead of Undefined Behaviour.
  • Loading branch information
danakj committed Nov 29, 2023
1 parent c59c89c commit 2ca796c
Show file tree
Hide file tree
Showing 11 changed files with 638 additions and 186 deletions.
2 changes: 2 additions & 0 deletions sus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ target_sources(subspace PUBLIC
"mem/size_of.h"
"mem/swap.h"
"mem/take.h"
"num/__private/check_integer_overflow.h"
"num/__private/float_consts.inc"
"num/__private/float_methods.inc"
"num/__private/float_methods_impl.inc"
Expand Down Expand Up @@ -298,6 +299,7 @@ if(${SUBSPACE_BUILD_TESTS})
"num/f64_unittest.cc"
"num/i8_unittest.cc"
"num/i16_unittest.cc"
"num/i32_overflow_unittest.cc"
"num/i32_unittest.cc"
"num/i64_unittest.cc"
"num/isize_unittest.cc"
Expand Down
25 changes: 25 additions & 0 deletions sus/num/__private/check_integer_overflow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// IWYU pragma: private
// IWYU pragma: friend "sus/.*"
#pragma once

// SUS_CHECK_INTEGER_OVERFLOW can be defined to false to disable overflow checks
// in integer arithmetic and shifting operations.
#if !defined(SUS_CHECK_INTEGER_OVERFLOW)
#define SUS_CHECK_INTEGER_OVERFLOW true
#endif
static_assert(SUS_CHECK_INTEGER_OVERFLOW == false ||
SUS_CHECK_INTEGER_OVERFLOW == true);
12 changes: 9 additions & 3 deletions sus/num/__private/intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,13 @@ sus_pure_const sus_always_inline constexpr T unchecked_shl(
return static_cast<T>(MathType<T>{x} << y);
}

template <class T>
requires(std::is_integral_v<T> && std::is_signed_v<T>)
sus_pure_const sus_always_inline constexpr T unchecked_shl(
T x, uint64_t y) noexcept {
return static_cast<T>(MathType<T>{x} << y);
}

template <class T>
requires(std::is_integral_v<T> && !std::is_signed_v<T>)
sus_pure_const sus_always_inline constexpr T unchecked_shr(
Expand Down Expand Up @@ -1080,9 +1087,8 @@ sus_pure_const inline constexpr OverflowOut<T> shl_with_overflow(
const bool overflow = shift >= num_bits<T>();
if (overflow) [[unlikely]]
shift = shift & (unchecked_sub(num_bits<T>(), uint32_t{1}));
return OverflowOut sus_clang_bug_56394(<T>){
.overflow = overflow,
.value = into_signed(unchecked_shl(into_unsigned(x), shift))};
return OverflowOut sus_clang_bug_56394(<T>){.overflow = overflow,
.value = unchecked_shl(x, shift)};
}

template <class T>
Expand Down
Loading

0 comments on commit 2ca796c

Please sign in to comment.