Skip to content

Commit

Permalink
Merge pull request #164 from chfast/noexceptions
Browse files Browse the repository at this point in the history
Add support for building without exceptions
  • Loading branch information
chfast authored Jun 22, 2020
2 parents cb2878e + d8d5866 commit e648bff
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 19 deletions.
12 changes: 12 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ jobs:
- build_and_test
- benchmark

no-exceptions:
environment:
- BUILD_TYPE: Release
- CMAKE_OPTIONS: -DEXCEPTIONS=OFF -DRTTI=OFF
docker:
- image: ethereum/cpp-build-env:14-gcc-10
steps:
- install_deps
- build_and_test
- benchmark

linux-32bit:
environment:
- BUILD_PARALLEL_JOBS: 4
Expand Down Expand Up @@ -211,6 +222,7 @@ workflows:
- linux-clang-coverage
- linux-clang-asan
- linux-clang-ubsan
- no-exceptions
- linux-32bit
- fuzzing
- macos
Expand Down
16 changes: 14 additions & 2 deletions cmake/CableCompilerSettings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
#
# CHANGELOG
#
# 1.1.0 - 2020-06-18
# - Allow unknown C++ attributes in MSVC compiler
# 1.1.0 - 2020-06-20
# - Allow unknown C++ attributes in MSVC compiler.
# - Option -DEXCEPTIONS=OFF to disable C++ exceptions support (GCC, clang).
# - Option -DRTTI=OFF to disable RTTI support (GCC, clang).
#
# 1.0.1 - 2020-01-30
# - Do not explicitly set -mtune=generic, this is default anyway.
Expand Down Expand Up @@ -135,6 +137,16 @@ macro(cable_configure_compiler)

endif()

option(EXCEPTIONS "Build with exceptions support" ON)
if(NOT EXCEPTIONS)
add_compile_options(-fno-exceptions)
endif()

option(RTTI "Build with RTTI support" ON)
if(NOT RTTI)
add_compile_options(-fno-rtti)
endif()

# Option for arch=native.
option(NATIVE "Build for native CPU" OFF)
if(NATIVE)
Expand Down
27 changes: 20 additions & 7 deletions include/intx/int128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,10 +798,22 @@ struct numeric_limits<intx::uint<N>>

namespace intx
{
template <typename T>
[[noreturn]] inline void throw_(const char* what)
{
#if __cpp_exceptions
throw T{what};
#else
std::fputs(what, stderr);
std::abort();
#endif
}

constexpr inline int from_dec_digit(char c)
{
return (c >= '0' && c <= '9') ? c - '0' :
throw std::invalid_argument{std::string{"Invalid digit: "} + c};
if (c < '0' || c > '9')
throw_<std::invalid_argument>("invalid digit");
return c - '0';
}

constexpr inline int from_hex_digit(char c)
Expand All @@ -814,8 +826,9 @@ constexpr inline int from_hex_digit(char c)
}

template <typename Int>
constexpr Int from_string(const char* s)
constexpr Int from_string(const char* str)
{
auto s = str;
auto x = Int{};
int num_digits = 0;

Expand All @@ -825,7 +838,7 @@ constexpr Int from_string(const char* s)
while (const auto c = *s++)
{
if (++num_digits > int{sizeof(x) * 2})
throw std::overflow_error{"Integer overflow"};
throw_<std::out_of_range>(str);
x = (x << 4) | from_hex_digit(c);
}
return x;
Expand All @@ -834,12 +847,12 @@ constexpr Int from_string(const char* s)
while (const auto c = *s++)
{
if (num_digits++ > std::numeric_limits<Int>::digits10)
throw std::overflow_error{"Integer overflow"};
throw_<std::out_of_range>(str);

const auto d = from_dec_digit(c);
x = constexpr_mul(x, Int{10}) + d;
if (x < d)
throw std::overflow_error{"Integer overflow"};
throw_<std::out_of_range>(str);
}
return x;
}
Expand All @@ -859,7 +872,7 @@ template <unsigned N>
inline std::string to_string(uint<N> x, int base = 10)
{
if (base < 2 || base > 36)
throw std::invalid_argument{"invalid base: " + std::to_string(base)};
throw_<std::invalid_argument>("invalid base");

if (x == 0)
return "0";
Expand Down
44 changes: 36 additions & 8 deletions test/unittests/test_int128.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2019-2020 Pawel Bylica.
// Licensed under the Apache License, Version 2.0.

#include "test_utils.hpp"
#include <gtest/gtest.h>
#include <intx/int128.hpp>

Expand Down Expand Up @@ -355,21 +356,48 @@ TEST(int128, literals)
auto a = 340282366920938463463374607431768211455_u128;
EXPECT_EQ(a, (uint128{0xffffffffffffffff, 0xffffffffffffffff}));

EXPECT_THROW(340282366920938463463374607431768211456_u128, std::overflow_error);
EXPECT_THROW(3402823669209384634633746074317682114550_u128, std::overflow_error);

a = 0xffffffffffffffffffffffffffffffff_u128;
EXPECT_EQ(a, (uint128{0xffffffffffffffff, 0xffffffffffffffff}));

EXPECT_THROW(0x100000000000000000000000000000000_u128, std::overflow_error);
EXPECT_EQ(0xaBc123eFd_u128, 0xAbC123EfD_u128);
}

TEST(int128, from_string)
{
constexpr auto ka = from_string<uint128>("18446744073709551617");
static_assert(ka == uint128{1, 1}, "");
const auto sa = "18446744073709551617";
const auto a = from_string<uint128>(sa);
EXPECT_EQ(a, uint128(1, 1));

constexpr auto kb = from_string<uint128>("0x300aabbccddeeff99");
static_assert(kb == uint128{3, 0xaabbccddeeff99}, "");
const auto sb = "0x300aabbccddeeff99";
EXPECT_EQ(from_string<uint128>(sb), uint128(3, 0xaabbccddeeff99));
}

TEST(int128, literals_exceptions)
{
EXPECT_THROW_MESSAGE(340282366920938463463374607431768211456_u128, std::out_of_range,
"340282366920938463463374607431768211456");
EXPECT_THROW_MESSAGE(3402823669209384634633746074317682114550_u128, std::out_of_range,
"3402823669209384634633746074317682114550");

EXPECT_THROW_MESSAGE(0x100000000000000000000000000000000_u128, std::out_of_range,
"0x100000000000000000000000000000000");

// Binary literals 0xb... are not supported yet.
EXPECT_THROW(operator""_u128("0b1"), std::invalid_argument);
EXPECT_THROW_MESSAGE(operator""_u128("0b1"), std::invalid_argument, "invalid digit");
EXPECT_THROW_MESSAGE(0b1010_u128, std::invalid_argument, "invalid digit");

EXPECT_THROW(operator""_u128("123x456"), std::invalid_argument);
EXPECT_THROW(operator""_u128("0xabcxdef"), std::invalid_argument);
EXPECT_THROW_MESSAGE(operator""_u128("123x456"), std::invalid_argument, "invalid digit");
EXPECT_THROW_MESSAGE(operator""_u128("0xabcxdef"), std::invalid_argument, "invalid digit");
}

EXPECT_EQ(0xaBc123eFd_u128, 0xAbC123EfD_u128);
TEST(int128, from_string_exceptions)
{
EXPECT_THROW_MESSAGE(from_string<uint128>("123a"), std::invalid_argument, "invalid digit");
EXPECT_THROW_MESSAGE(from_string<uint128>("0xcdefg"), std::invalid_argument, "invalid digit");
}

TEST(int128, to_string)
Expand Down
4 changes: 2 additions & 2 deletions test/unittests/test_intx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,8 +560,8 @@ TYPED_TEST(uint_test, string_conversions)
TYPED_TEST(uint_test, to_string_base)
{
auto x = TypeParam{1024};
EXPECT_THROW(to_string(x, 1), std::invalid_argument);
EXPECT_THROW(to_string(x, 37), std::invalid_argument);
EXPECT_THROW_MESSAGE(to_string(x, 1), std::invalid_argument, "invalid base");
EXPECT_THROW_MESSAGE(to_string(x, 37), std::invalid_argument, "invalid base");
EXPECT_EQ(to_string(x, 10), "1024");
EXPECT_EQ(to_string(x, 16), "400");
EXPECT_EQ(to_string(x, 36), "sg");
Expand Down
17 changes: 17 additions & 0 deletions test/unittests/test_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@

#include <intx/int128.hpp>

#if __cpp_exceptions
#define EXPECT_THROW_MESSAGE(stmt, ex_type, expected) \
try \
{ \
stmt; \
ADD_FAILURE() << "Exception of type " #ex_type " is expected, but none was thrown."; \
} \
catch (const ex_type& exception) \
{ \
EXPECT_STREQ(exception.what(), expected); \
} \
(void)0
#else
#define EXPECT_THROW_MESSAGE(stmt, ex_type, expected) EXPECT_DEATH(stmt, expected)
#endif


struct type_to_name
{
template <typename T>
Expand Down

0 comments on commit e648bff

Please sign in to comment.