Skip to content

Commit 3ac30de

Browse files
committed
added CMake option USE_INT128 and support built-in __int128 / some compilation fixes
1 parent 901a331 commit 3ac30de

File tree

11 files changed

+99
-32
lines changed

11 files changed

+99
-32
lines changed

cmake/compilerDefinitions.cmake

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,24 @@ if(HAVE_RULES)
3737
add_definitions(-DHAVE_RULES)
3838
endif()
3939

40+
# Visual Studio has no native support
41+
if(USE_INT128 AND NOT MSVC)
42+
add_definitions(-DHAVE_INT128)
43+
endif()
44+
4045
if(Boost_FOUND)
4146
add_definitions(-DHAVE_BOOST)
42-
if(USE_BOOST_INT128)
47+
if(USE_INT128 STREQUAL "Boost")
4348
add_definitions(-DHAVE_BOOST_INT128)
4449
endif()
4550
endif()
4651

52+
# Visual Studio falls back to Boost since it has no native 128-bit integer support
53+
if(USE_INT128 STREQUAL "Auto" AND Boost_FOUND)
54+
add_definitions(-DHAVE_INT128)
55+
add_definitions(-DHAVE_BOOST_INT128)
56+
endif()
57+
4758
if(ENABLE_CHECK_INTERNAL)
4859
add_definitions(-DCHECK_INTERNAL)
4960
endif()

cmake/cxx11.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
macro(use_cxx11)
2-
if(USE_BOOST AND USE_BOOST_INT128)
2+
# enable unconditionally for Visual Studio since it is the lowest possible standard to select
3+
if(MSVC OR (USE_BOOST AND USE_INT128 STREQUAL "Boost"))
34
# Boost.Math requires C++14
45
set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard to use")
56
else()

cmake/options.cmake

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,19 @@ option(DISALLOW_THREAD_EXECUTOR "Disallow usage of ThreadExecutor for -j"
9292
if(DISALLOW_THREAD_EXECUTOR AND WIN32)
9393
message(FATAL_ERROR "Cannot disable usage of ThreadExecutor on Windows as no other executor implementation is currently available")
9494
endif()
95+
96+
set(USE_INT128 "Off" CACHE STRING "Usage of 128-bit integer type") # TODO: default to Auto when working
97+
set_property(CACHE USE_INT128 PROPERTY STRINGS Auto Off Native Boost)
98+
if (USE_INT128 STREQUAL "Native" AND MSVC)
99+
message(FATAL_ERROR "Visual Studio has no native 128-bit integer support")
100+
endif()
101+
95102
set(USE_BOOST "Auto" CACHE STRING "Usage of Boost")
96103
set_property(CACHE USE_BOOST PROPERTY STRINGS Auto Off On)
97-
option(USE_BOOST_INT128 "Usage of Boost.Multiprecision 128-bit integer for Mathlib" OFF)
98-
if (NOT USE_BOOST AND USE_BOOST_INT128)
99-
message(FATAL_ERROR "USE_BOOST_INT128 requires USE_BOOST to be enabled")
104+
if (USE_INT128 STREQUAL "Boost" AND NOT USE_BOOST)
105+
message(FATAL_ERROR "USE_INT128=Boost requires USE_BOOST to be enabled")
100106
endif()
107+
101108
option(USE_LIBCXX "Use libc++ instead of libstdc++" OFF)
102109

103110
option(DISABLE_CRTDBG_MAP_ALLOC "Disable usage of Visual Studio C++ memory leak detection in Debug build" OFF)

cmake/printInfo.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ if(NOT USE_BUNDLED_TINYXML2)
8686
message(STATUS "tinyxml2_INCLUDE_DIRS = ${tinyxml2_INCLUDE_DIRS}")
8787
endif()
8888
message(STATUS)
89+
message(STATUS "USE_INT128 = ${USE_INT128}")
90+
message(STATUS)
8991
message(STATUS "USE_BOOST = ${USE_BOOST}")
9092
if(USE_BOOST)
9193
message(STATUS "Boost_FOUND = ${Boost_FOUND}")
9294
message(STATUS "Boost_VERSION_STRING = ${Boost_VERSION_STRING}")
9395
message(STATUS "Boost_INCLUDE_DIRS = ${Boost_INCLUDE_DIRS}")
94-
message(STATUS "USE_BOOST_INT128 = ${USE_BOOST_INT128}")
9596
endif()
9697
message(STATUS)
9798
message(STATUS "USE_LIBCXX = ${USE_LIBCXX}")

lib/mathlib.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ MathLib::value MathLib::value::calc(char op, const MathLib::value &v1, const Mat
163163
case '/':
164164
if (v2.mIntValue == 0)
165165
throw InternalError(nullptr, "Internal Error: Division by zero");
166-
if (v1.mIntValue == std::numeric_limits<bigint>::min() && std::abs(v2.mIntValue)<=1)
166+
if (v1.mIntValue == std::numeric_limits<bigint>::min() && MathLib::abs(v2.mIntValue)<=1)
167167
throw InternalError(nullptr, "Internal Error: Division overflow");
168168
temp.mIntValue /= static_cast<unsigned long long>(v2.mIntValue);
169169
break;
@@ -198,7 +198,7 @@ MathLib::value MathLib::value::calc(char op, const MathLib::value &v1, const Mat
198198
case '/':
199199
if (v2.mIntValue == 0)
200200
throw InternalError(nullptr, "Internal Error: Division by zero");
201-
if (v1.mIntValue == std::numeric_limits<bigint>::min() && std::abs(v2.mIntValue)<=1)
201+
if (v1.mIntValue == std::numeric_limits<bigint>::min() && MathLib::abs(v2.mIntValue)<=1)
202202
throw InternalError(nullptr, "Internal Error: Division overflow");
203203
temp.mIntValue /= v2.mIntValue;
204204
break;
@@ -537,21 +537,33 @@ double MathLib::toDoubleNumber(const std::string &str, const Token * const tok)
537537

538538
template<> std::string MathLib::toString<MathLib::bigint>(MathLib::bigint value)
539539
{
540-
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
540+
#if defined(HAVE_INT128)
541+
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
541542
std::ostringstream result;
542543
result << value;
543544
return result.str();
545+
# else
546+
// TODO: handle actual 128-bit values
547+
assert(value >= std::numeric_limits<long long>::min() && value <= std::numeric_limits<long long>::max());
548+
return std::to_string(static_cast<long long>(value));
549+
# endif
544550
#else
545551
return std::to_string(value);
546552
#endif
547553
}
548554

549555
template<> std::string MathLib::toString<MathLib::biguint>(MathLib::biguint value)
550556
{
551-
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
557+
#if defined(HAVE_INT128)
558+
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
552559
std::ostringstream result;
553560
result << value;
554561
return result.str();
562+
# else
563+
// TODO: handle actual 128-bit values
564+
assert(value <= std::numeric_limits<unsigned long long>::max());
565+
return std::to_string(static_cast<unsigned long long>(value));
566+
# endif
555567
#else
556568
return std::to_string(value);
557569
#endif
@@ -1148,7 +1160,7 @@ std::string MathLib::divide(const std::string &first, const std::string &second)
11481160
const bigint b = toBigNumber(second);
11491161
if (b == 0)
11501162
throw InternalError(nullptr, "Internal Error: Division by zero");
1151-
if (a == std::numeric_limits<bigint>::min() && std::abs(b)<=1)
1163+
if (a == std::numeric_limits<bigint>::min() && MathLib::abs(b)<=1)
11521164
throw InternalError(nullptr, "Internal Error: Division overflow");
11531165
return MathLib::toString(toBigNumber(first) / b) + intsuffix(first, second);
11541166
}

lib/mathlib.h

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
#include <cstdint>
2727
#include <string>
2828

29-
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
30-
#include <boost/multiprecision/cpp_int.hpp>
29+
#if defined(HAVE_INT128)
30+
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
31+
# include <boost/multiprecision/cpp_int.hpp>
32+
# endif
3133
#endif
3234

3335
class Token;
@@ -41,9 +43,18 @@ class CPPCHECKLIB MathLib {
4143
friend class TestMathLib;
4244

4345
public:
44-
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
46+
#if defined(HAVE_INT128)
47+
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
4548
using bigint = boost::multiprecision::int128_t;
4649
using biguint = boost::multiprecision::uint128_t;
50+
# elif defined(__GNUC__)
51+
SUPPRESS_WARNING_GCC_PUSH("-Wpedantic")
52+
using bigint = __int128;
53+
using biguint = unsigned __int128;
54+
SUPPRESS_WARNING_GCC_POP
55+
# else
56+
#error "no 128-bit type"
57+
# endif
4758
#else
4859
using bigint = long long;
4960
using biguint = unsigned long long;
@@ -144,6 +155,12 @@ class CPPCHECKLIB MathLib {
144155
static bool isOctalDigit(char c);
145156

146157
static unsigned int encodeMultiChar(const std::string& str);
158+
159+
static bigint abs(bigint i) {
160+
if (i < 0)
161+
return -i;
162+
return i;
163+
}
147164
};
148165

149166
MathLib::value operator+(const MathLib::value &v1, const MathLib::value &v2);
@@ -161,6 +178,20 @@ template<> CPPCHECKLIB std::string MathLib::toString<MathLib::bigint>(MathLib::b
161178
template<> CPPCHECKLIB std::string MathLib::toString<MathLib::biguint>(MathLib::biguint value);
162179
template<> CPPCHECKLIB std::string MathLib::toString<double>(double value);
163180

181+
// Boost provides stream insertion operators
182+
#if defined(HAVE_INT128) && !defined(HAVE_BOOST_INT128)
183+
inline std::ostream& operator<<(std::ostream& os, MathLib::bigint i)
184+
{
185+
os << MathLib::toString(i);
186+
return os;
187+
}
188+
inline std::ostream& operator<<(std::ostream& os, MathLib::biguint u)
189+
{
190+
os << MathLib::toString(u);
191+
return os;
192+
}
193+
#endif
194+
164195
/// @}
165196
//---------------------------------------------------------------------------
166197
#endif // mathlibH

lib/token.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2026,7 +2026,7 @@ static bool isAdjacent(const ValueFlow::Value& x, const ValueFlow::Value& y)
20262026
return true;
20272027
if (x.valueType == ValueFlow::Value::ValueType::FLOAT)
20282028
return false;
2029-
return std::abs(x.intvalue - y.intvalue) == 1;
2029+
return MathLib::abs(x.intvalue - y.intvalue) == 1;
20302030
}
20312031

20322032
static bool removePointValue(std::list<ValueFlow::Value>& values, std::list<ValueFlow::Value>::iterator& x)

lib/valueflow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4513,7 +4513,7 @@ struct ConditionHandler {
45134513

45144514
MathLib::bigint getPath() const
45154515
{
4516-
assert(std::abs(findPath(true_values) - findPath(false_values)) == 0);
4516+
assert(MathLib::abs(findPath(true_values) - findPath(false_values)) == 0);
45174517
return findPath(true_values) | findPath(false_values);
45184518
}
45194519

lib/vfvalue.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ namespace ValueFlow
168168
return !(*this == rhs);
169169
}
170170

171+
// TODO: requires check fails with GCC using __int128
171172
template<class T, REQUIRES("T must be an arithmetic type", std::is_arithmetic<T> )>
172173
bool equalTo(const T& x) const {
173174
bool result = false;
@@ -316,6 +317,9 @@ namespace ValueFlow
316317

317318
std::int8_t indirect{}; // TODO: can we reduce the size?
318319

320+
#if defined(HAVE_INT128)
321+
long long : 64;
322+
#endif
319323
/** int value (or sometimes bool value?) */
320324
MathLib::bigint intvalue{};
321325

test/testmathlib.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -358,12 +358,12 @@ class TestMathLib : public TestFixture {
358358
// min/max and out-of-bounds - hex
359359
{
360360
constexpr MathLib::bigint i = 0xFFFFFFFFFFFFFFFF;
361-
ASSERT_EQUALS(i, MathLib::toBigNumber(std::to_string(i)));
361+
ASSERT_EQUALS(i, MathLib::toBigNumber(MathLib::toString(i)));
362362
ASSERT_EQUALS(i, MathLib::toBigNumber("0xFFFFFFFFFFFFFFFF"));
363363
}
364364
{
365365
constexpr MathLib::bigint i = -0xFFFFFFFFFFFFFFFF;
366-
ASSERT_EQUALS(i, MathLib::toBigNumber(std::to_string(i)));
366+
ASSERT_EQUALS(i, MathLib::toBigNumber(MathLib::toString(i)));
367367
ASSERT_EQUALS(i, MathLib::toBigNumber("-0xFFFFFFFFFFFFFFFF"));
368368
}
369369

@@ -373,12 +373,12 @@ class TestMathLib : public TestFixture {
373373
// min/max and out-of-bounds - octal
374374
{
375375
constexpr MathLib::bigint i = 01777777777777777777777;
376-
ASSERT_EQUALS(i, MathLib::toBigNumber(std::to_string(i)));
376+
ASSERT_EQUALS(i, MathLib::toBigNumber(MathLib::toString(i)));
377377
ASSERT_EQUALS(i, MathLib::toBigNumber("01777777777777777777777"));
378378
}
379379
{
380380
constexpr MathLib::bigint i = -01777777777777777777777;
381-
ASSERT_EQUALS(i, MathLib::toBigNumber(std::to_string(i)));
381+
ASSERT_EQUALS(i, MathLib::toBigNumber(MathLib::toString(i)));
382382
ASSERT_EQUALS(i, MathLib::toBigNumber("-01777777777777777777777"));
383383
}
384384

@@ -388,12 +388,12 @@ class TestMathLib : public TestFixture {
388388
// min/max and out-of-range - decimal
389389
{
390390
constexpr MathLib::bigint i = 18446744073709551615ULL;
391-
ASSERT_EQUALS(i, MathLib::toBigNumber(std::to_string(i)));
391+
ASSERT_EQUALS(i, MathLib::toBigNumber(MathLib::toString(i)));
392392
ASSERT_EQUALS(i, MathLib::toBigNumber("18446744073709551615"));
393393
}
394394
{
395395
constexpr MathLib::bigint i = -18446744073709551615ULL;
396-
ASSERT_EQUALS(i, MathLib::toBigNumber(std::to_string(i)));
396+
ASSERT_EQUALS(i, MathLib::toBigNumber(MathLib::toString(i)));
397397
ASSERT_EQUALS(i, MathLib::toBigNumber("-18446744073709551615"));
398398
}
399399

@@ -530,12 +530,12 @@ class TestMathLib : public TestFixture {
530530
// min/max and out-of-bounds - hex
531531
{
532532
constexpr MathLib::biguint u = 0xFFFFFFFFFFFFFFFF;
533-
ASSERT_EQUALS(u, MathLib::toBigUNumber(std::to_string(u)));
533+
ASSERT_EQUALS(u, MathLib::toBigUNumber(MathLib::toString(u)));
534534
ASSERT_EQUALS(u, MathLib::toBigUNumber("0xFFFFFFFFFFFFFFFF"));
535535
}
536536
{
537537
constexpr MathLib::biguint u = -0xFFFFFFFFFFFFFFFF;
538-
ASSERT_EQUALS(u, MathLib::toBigUNumber(std::to_string(u)));
538+
ASSERT_EQUALS(u, MathLib::toBigUNumber(MathLib::toString(u)));
539539
ASSERT_EQUALS(u, MathLib::toBigUNumber("-0xFFFFFFFFFFFFFFFF"));
540540
}
541541

@@ -545,12 +545,12 @@ class TestMathLib : public TestFixture {
545545
// min/max and out-of-bounds - octal
546546
{
547547
constexpr MathLib::biguint u = 01777777777777777777777;
548-
ASSERT_EQUALS(u, MathLib::toBigUNumber(std::to_string(u)));
548+
ASSERT_EQUALS(u, MathLib::toBigUNumber(MathLib::toString(u)));
549549
ASSERT_EQUALS(u, MathLib::toBigUNumber("01777777777777777777777"));
550550
}
551551
{
552552
constexpr MathLib::biguint u = -01777777777777777777777;
553-
ASSERT_EQUALS(u, MathLib::toBigUNumber(std::to_string(u)));
553+
ASSERT_EQUALS(u, MathLib::toBigUNumber(MathLib::toString(u)));
554554
ASSERT_EQUALS(u, MathLib::toBigUNumber("-01777777777777777777777"));
555555
}
556556

@@ -560,12 +560,12 @@ class TestMathLib : public TestFixture {
560560
// min/max and out-of-range - decimal
561561
{
562562
constexpr MathLib::biguint u = 18446744073709551615ULL;
563-
ASSERT_EQUALS(u, MathLib::toBigUNumber(std::to_string(u)));
563+
ASSERT_EQUALS(u, MathLib::toBigUNumber(MathLib::toString(u)));
564564
ASSERT_EQUALS(u, MathLib::toBigUNumber("18446744073709551615"));
565565
}
566566
{
567567
constexpr MathLib::biguint u = -18446744073709551615ULL;
568-
ASSERT_EQUALS(u, MathLib::toBigUNumber(std::to_string(u)));
568+
ASSERT_EQUALS(u, MathLib::toBigUNumber(MathLib::toString(u)));
569569
ASSERT_EQUALS(u, MathLib::toBigUNumber("-18446744073709551615"));
570570
}
571571

0 commit comments

Comments
 (0)