Skip to content
Open
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
56 changes: 41 additions & 15 deletions .github/workflows/CI-unixish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ jobs:
strategy:
matrix:
os: [ubuntu-22.04, macos-15]
int128: [Off, On]
# TODO: remove when GCC build works
exclude:
- os: ubuntu-22.04
int128: On
fail-fast: false # Prefer quick result

runs-on: ${{ matrix.os }}
Expand All @@ -92,7 +97,7 @@ jobs:
- name: ccache
uses: hendrikmuhs/[email protected]
with:
key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}
key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}-${{ matrix.int128 }}

# TODO: move latest compiler to separate step
# TODO: bail out on warnings with latest GCC
Expand Down Expand Up @@ -127,37 +132,62 @@ jobs:
- name: Run CMake on ubuntu (with GUI)
if: contains(matrix.os, 'ubuntu')
run: |
cmake -S . -B cmake.output -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install
cmake -S . -B cmake.output -G "Unix Makefiles" -DUSE_INT128=${{ matrix.int128 }} -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install

- name: Run CMake on macos (with GUI)
if: contains(matrix.os, 'macos')
run: |
cmake -S . -B cmake.output -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install -DQt6_DIR=$(brew --prefix qt@6)/lib/cmake/Qt6
cmake -S . -B cmake.output -G "Unix Makefiles" -DUSE_INT128=${{ matrix.int128 }} -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install -DQt6_DIR=$(brew --prefix qt@6)/lib/cmake/Qt6

- name: Run CMake build
run: |
cmake --build cmake.output -- -j$(nproc)

- name: Run CMake test
if: matrix.int128 == 'Off' # TODO: enable when tests work
run: |
cmake --build cmake.output --target check -- -j$(nproc)

- name: Run CTest
if: matrix.int128 == 'Off' # TODO: enable when tests work
run: |
pushd cmake.output
ctest --output-on-failure -j$(nproc)

- name: Run CMake install
if: matrix.int128 == 'Off'
run: |
cmake --build cmake.output --target install

- name: Run CMake on ubuntu (no CLI)
if: matrix.os == 'ubuntu-22.04'
build_cmake_no_with:

strategy:
matrix:
# TODO: also run on macOS?
os: [ubuntu-22.04]
fail-fast: false # Prefer quick result

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- name: Install missing software on ubuntu
if: contains(matrix.os, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install libxml2-utils
# qt6-tools-dev-tools for lprodump
# qt6-l10n-tools for lupdate
sudo apt-get install qt6-base-dev libqt6charts6-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools libglx-dev libgl1-mesa-dev

- name: Run CMake (no CLI)
run: |
cmake -S . -B cmake.output_nocli -G "Unix Makefiles" -DBUILD_CLI=Off

- name: Run CMake on ubuntu (no CLI / with tests)
if: matrix.os == 'ubuntu-22.04'
- name: Run CMake (no CLI / with tests)
run: |
# the test and CLI code are too intertwined so for now we need to reject that
if cmake -S . -B cmake.output_nocli_tests -G "Unix Makefiles" -DBUILD_TESTS=On -DBUILD_CLI=Off; then
Expand All @@ -166,18 +196,15 @@ jobs:
exit 0
fi

- name: Run CMake on ubuntu (no CLI / with GUI)
if: matrix.os == 'ubuntu-22.04'
- name: Run CMake (no CLI / with GUI)
run: |
cmake -S . -B cmake.output_nocli_gui -G "Unix Makefiles" -DBUILD_CLI=Off -DBUILD_GUI=On

- name: Run CMake on ubuntu (no GUI)
if: matrix.os == 'ubuntu-22.04'
- name: Run CMake (no GUI)
run: |
cmake -S . -B cmake.output_nogui -G "Unix Makefiles" -DBUILD_GUI=Off

- name: Run CMake on ubuntu (no GUI / with triage)
if: matrix.os == 'ubuntu-22.04'
- name: Run CMake (no GUI / with triage)
run: |
# cannot build triage without GUI
if cmake -S . -B cmake.output_nogui_triage -G "Unix Makefiles" -DBUILD_GUI=Off -DBUILD_TRIAGE=On; then
Expand All @@ -186,8 +213,7 @@ jobs:
exit 0
fi

- name: Run CMake on ubuntu (no CLI / no GUI)
if: matrix.os == 'ubuntu-22.04'
- name: Run CMake (no CLI / no GUI)
run: |
cmake -S . -B cmake.output_nocli_nogui -G "Unix Makefiles" -DBUILD_GUI=Off

Expand Down
6 changes: 5 additions & 1 deletion cmake/compilerDefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ if(HAVE_RULES)
add_definitions(-DHAVE_RULES)
endif()

if(USE_INT128)
add_definitions(-DHAVE_INT128)
endif()

if(Boost_FOUND)
add_definitions(-DHAVE_BOOST)
if(USE_BOOST_INT128)
if(USE_INT128 AND USE_BOOST_INT128)
add_definitions(-DHAVE_BOOST_INT128)
endif()
Comment on lines +46 to 48
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the logic around USE_BOOST_INT128 is flawed . On is supposed to force the usage of Boost and Auto should provide a fallback to Boost if no built-in type exists but Boost is enabled (i.e. Visual Studio).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm.. how about:

VALUEFLOW_INT128=no
VALUEFLOW_INT128=gcc
VALUEFLOW_INT128=boost

?

endif()
Expand Down
11 changes: 8 additions & 3 deletions cmake/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,16 @@ option(DISALLOW_THREAD_EXECUTOR "Disallow usage of ThreadExecutor for -j"
if(DISALLOW_THREAD_EXECUTOR AND WIN32)
message(FATAL_ERROR "Cannot disable usage of ThreadExecutor on Windows as no other executor implementation is currently available")
endif()
set(USE_INT128 "Off" CACHE STRING "Usage of 128-bit integer type") # TODO: default to Auto when working
set_property(CACHE USE_INT128 PROPERTY STRINGS Auto Off On)
set(USE_BOOST "Auto" CACHE STRING "Usage of Boost")
set_property(CACHE USE_BOOST PROPERTY STRINGS Auto Off On)
option(USE_BOOST_INT128 "Usage of Boost.Multiprecision 128-bit integer for Mathlib" OFF)
if (NOT USE_BOOST AND USE_BOOST_INT128)
message(FATAL_ERROR "USE_BOOST_INT128 requires USE_BOOST to be enabled")
set(USE_BOOST_INT128 "Off" CACHE STRING "Usage of Boost.Multiprecision 128-bit integer for Mathlib") # TODO: default to Auto when working
set_property(CACHE USE_BOOST_INT128 PROPERTY STRINGS Auto Off On)
if (USE_INT128)
if (NOT USE_BOOST AND USE_BOOST_INT128)
message(FATAL_ERROR "USE_BOOST_INT128 requires USE_BOOST to be enabled")
endif()
endif()
option(USE_LIBCXX "Use libc++ instead of libstdc++" OFF)

Expand Down
2 changes: 2 additions & 0 deletions cmake/printInfo.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ if(NOT USE_BUNDLED_TINYXML2)
message(STATUS "tinyxml2_INCLUDE_DIRS = ${tinyxml2_INCLUDE_DIRS}")
endif()
message(STATUS)
message(STATUS "USE_INT128 = ${USE_INT128}")
message(STATUS)
message(STATUS "USE_BOOST = ${USE_BOOST}")
if(USE_BOOST)
message(STATUS "Boost_FOUND = ${Boost_FOUND}")
Expand Down
22 changes: 17 additions & 5 deletions lib/mathlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ MathLib::value MathLib::value::calc(char op, const MathLib::value &v1, const Mat
case '/':
if (v2.mIntValue == 0)
throw InternalError(nullptr, "Internal Error: Division by zero");
if (v1.mIntValue == std::numeric_limits<bigint>::min() && std::abs(v2.mIntValue)<=1)
if (v1.mIntValue == std::numeric_limits<bigint>::min() && MathLib::abs(v2.mIntValue)<=1)
throw InternalError(nullptr, "Internal Error: Division overflow");
temp.mIntValue /= static_cast<unsigned long long>(v2.mIntValue);
break;
Expand Down Expand Up @@ -198,7 +198,7 @@ MathLib::value MathLib::value::calc(char op, const MathLib::value &v1, const Mat
case '/':
if (v2.mIntValue == 0)
throw InternalError(nullptr, "Internal Error: Division by zero");
if (v1.mIntValue == std::numeric_limits<bigint>::min() && std::abs(v2.mIntValue)<=1)
if (v1.mIntValue == std::numeric_limits<bigint>::min() && MathLib::abs(v2.mIntValue)<=1)
throw InternalError(nullptr, "Internal Error: Division overflow");
temp.mIntValue /= v2.mIntValue;
break;
Expand Down Expand Up @@ -537,21 +537,33 @@ double MathLib::toDoubleNumber(const std::string &str, const Token * const tok)

template<> std::string MathLib::toString<MathLib::bigint>(MathLib::bigint value)
{
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
#if defined(HAVE_INT128)
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
std::ostringstream result;
result << value;
return result.str();
# else
// TODO: handle actual 128-bit values
assert(value >= std::numeric_limits<long long>::min() && value <= std::numeric_limits<long long>::max());
return std::to_string(static_cast<long long>(value));
# endif
#else
return std::to_string(value);
#endif
}

template<> std::string MathLib::toString<MathLib::biguint>(MathLib::biguint value)
{
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
#if defined(HAVE_INT128)
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
std::ostringstream result;
result << value;
return result.str();
# else
// TODO: handle actual 128-bit values
assert(value <= std::numeric_limits<unsigned long long>::max());
return std::to_string(static_cast<unsigned long long>(value));
# endif
#else
return std::to_string(value);
#endif
Expand Down Expand Up @@ -1148,7 +1160,7 @@ std::string MathLib::divide(const std::string &first, const std::string &second)
const bigint b = toBigNumber(second);
if (b == 0)
throw InternalError(nullptr, "Internal Error: Division by zero");
if (a == std::numeric_limits<bigint>::min() && std::abs(b)<=1)
if (a == std::numeric_limits<bigint>::min() && MathLib::abs(b)<=1)
throw InternalError(nullptr, "Internal Error: Division overflow");
return MathLib::toString(toBigNumber(first) / b) + intsuffix(first, second);
}
Expand Down
37 changes: 34 additions & 3 deletions lib/mathlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
#include <cstdint>
#include <string>

#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
#include <boost/multiprecision/cpp_int.hpp>
#if defined(HAVE_INT128)
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
# include <boost/multiprecision/cpp_int.hpp>
# endif
#endif

class Token;
Expand All @@ -41,9 +43,18 @@ class CPPCHECKLIB MathLib {
friend class TestMathLib;

public:
#if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
#if defined(HAVE_INT128)
# if defined(HAVE_BOOST) && defined(HAVE_BOOST_INT128)
using bigint = boost::multiprecision::int128_t;
using biguint = boost::multiprecision::uint128_t;
# elif defined(__GNUC__)
SUPPRESS_WARNING_GCC_PUSH("-Wpedantic")
using bigint = __int128;
using biguint = unsigned __int128;
SUPPRESS_WARNING_GCC_POP
# else
#error "no 128-bit type"
# endif
#else
using bigint = long long;
using biguint = unsigned long long;
Expand Down Expand Up @@ -144,6 +155,12 @@ class CPPCHECKLIB MathLib {
static bool isOctalDigit(char c);

static unsigned int encodeMultiChar(const std::string& str);

static bigint abs(bigint i) {
if (i < 0)
return -i;
return i;
}
};

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

// Boost provides stream insertion operators
#if defined(HAVE_INT128) && !defined(HAVE_BOOST_INT128)
inline std::ostream& operator<<(std::ostream& os, MathLib::bigint i)
{
os << MathLib::toString(i);
return os;
}
inline std::ostream& operator<<(std::ostream& os, MathLib::biguint u)
{
os << MathLib::toString(u);
return os;
}
#endif

/// @}
//---------------------------------------------------------------------------
#endif // mathlibH
2 changes: 1 addition & 1 deletion lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2027,7 +2027,7 @@ static bool isAdjacent(const ValueFlow::Value& x, const ValueFlow::Value& y)
return true;
if (x.valueType == ValueFlow::Value::ValueType::FLOAT)
return false;
return std::abs(x.intvalue - y.intvalue) == 1;
return MathLib::abs(x.intvalue - y.intvalue) == 1;
}

static bool removePointValue(std::list<ValueFlow::Value>& values, std::list<ValueFlow::Value>::iterator& x)
Expand Down
2 changes: 1 addition & 1 deletion lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4515,7 +4515,7 @@ struct ConditionHandler {

MathLib::bigint getPath() const
{
assert(std::abs(findPath(true_values) - findPath(false_values)) == 0);
assert(MathLib::abs(findPath(true_values) - findPath(false_values)) == 0);
return findPath(true_values) | findPath(false_values);
}

Expand Down
4 changes: 4 additions & 0 deletions lib/vfvalue.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ namespace ValueFlow
return !(*this == rhs);
}

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

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

#if defined(HAVE_INT128)
long long : 64;
#endif
/** int value (or sometimes bool value?) */
MathLib::bigint intvalue{};

Expand Down
Loading