Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for building without exceptions #164

Merged
merged 5 commits into from
Jun 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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