diff --git a/.clang-tidy b/.clang-tidy index e1032aaa5f3..b83436861bd 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -18,18 +18,19 @@ Checks: > -objc-*, -openmp-*, -zircon-*, - cert-err34-c, cppcoreguidelines-pro-type-static-cast-downcast, cppcoreguidelines-rvalue-reference-param-not-moved, google-explicit-constructor, -bugprone-assignment-in-if-condition, -bugprone-branch-clone, + -bugprone-command-processor, -bugprone-easily-swappable-parameters, -bugprone-empty-catch, -bugprone-macro-parentheses, -bugprone-narrowing-conversions, -bugprone-signed-char-misuse, -bugprone-switch-missing-default-case, + -bugprone-throwing-static-initialization, -bugprone-unchecked-optional-access, -clang-analyzer-*, -concurrency-mt-unsafe, @@ -41,7 +42,9 @@ Checks: > -modernize-avoid-c-arrays, -modernize-deprecated-ios-base-aliases, -misc-include-cleaner, + -misc-multiple-inheritance, -misc-unused-using-decls, + -modernize-avoid-c-style-cast, -modernize-loop-convert, -modernize-macro-to-enum, -modernize-raw-string-literal, @@ -67,11 +70,14 @@ Checks: > -readability-identifier-length, -readability-identifier-naming, -readability-implicit-bool-conversion, + -readability-inconsistent-ifelse-braces, -readability-isolate-declaration, -readability-magic-numbers, + -readability-redundant-parentheses, -readability-suspicious-call-argument, -readability-uppercase-literal-suffix, - -readability-use-concise-preprocessor-directives + -readability-use-concise-preprocessor-directives, + -misc-unconventional-assign-operator WarningsAsErrors: '*' HeaderFilterRegex: '(cli|gui|frontend|lib|oss-fuzz|test|triage)\/[a-z_]+\.h' ExcludeHeaderFilterRegex: 'ui_.*.h' @@ -82,3 +88,7 @@ CheckOptions: value: '0' - key: modernize-use-trailing-return-type.TransformFunctions value: false + - key: misc-override-with-different-visibility.DisallowedVisibilityChange + value: widening + - key: misc-use-internal-linkage.AnalyzeTypes + value: false diff --git a/.github/workflows/CI-cygwin.yml b/.github/workflows/CI-cygwin.yml index 445c0953eb5..bf67967c5f8 100644 --- a/.github/workflows/CI-cygwin.yml +++ b/.github/workflows/CI-cygwin.yml @@ -42,8 +42,9 @@ jobs: persist-credentials: false - name: Set up Cygwin - uses: cygwin/cygwin-install-action@master + uses: cygwin/cygwin-install-action@v6 with: + site: https://mirrors.cicku.me/cygwin/ platform: ${{ matrix.platform }} packages: ${{ matrix.packages }} diff --git a/.github/workflows/CI-unixish-docker.yml b/.github/workflows/CI-unixish-docker.yml index 4df9b4e9340..a38feb452f0 100644 --- a/.github/workflows/CI-unixish-docker.yml +++ b/.github/workflows/CI-unixish-docker.yml @@ -20,11 +20,16 @@ jobs: strategy: matrix: - image: ["ubuntu:24.04"] include: - - build_gui: false - image: "ubuntu:24.04" - build_gui: true + with_gui: true + full_build: true + - image: "ubuntu:25.10" + with_gui: true + full_build: true + - image: "alpine:3.23" + with_gui: false # it appears FindQt6.cmake is not provided by any package + full_build: false # FIXME: test-signalhandler.cpp fails to build since feenableexcept() is missing fail-fast: false # Prefer quick result runs-on: ubuntu-22.04 @@ -49,10 +54,15 @@ jobs: apt-get install -y cmake g++ make libxml2-utils libpcre3-dev - name: Install missing software (gui) on latest ubuntu - if: matrix.build_gui + if: contains(matrix.image, 'ubuntu') run: | apt-get install -y qt6-base-dev qt6-charts-dev qt6-tools-dev + - name: Install missing software on Alpine + if: contains(matrix.image, 'alpine') + run: | + apk add cmake make g++ pcre-dev + # needs to be called after the package installation since # - it doesn't call "apt-get update" - name: ccache @@ -60,18 +70,13 @@ jobs: with: key: ${{ github.workflow }}-${{ matrix.image }} - - name: CMake build - if: ${{ !matrix.build_gui }} + - name: Run CMake run: | - mkdir cmake.output - cd cmake.output - cmake -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. - cmake --build . -- -j$(nproc) + cmake -S . -B cmake.output -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=${{ matrix.with_gui }} -DWITH_QCHART=On -DBUILD_TRIAGE=${{ matrix.with_gui }} -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - - name: CMake build (with GUI) - if: matrix.build_gui + - name: CMake build + if: matrix.full_build 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_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache cmake --build cmake.output -- -j$(nproc) - name: Run CMake test @@ -82,7 +87,7 @@ jobs: strategy: matrix: - image: ["ubuntu:24.04"] + image: ["ubuntu:24.04", "ubuntu:25.10", "alpine:3.23"] fail-fast: false # Prefer quick result runs-on: ubuntu-22.04 @@ -101,6 +106,11 @@ jobs: apt-get update apt-get install -y g++ make python3 libxml2-utils libpcre3-dev + - name: Install missing software on Alpine + if: contains(matrix.image, 'alpine') + run: | + apk add make g++ pcre-dev bash python3 libxml2-utils + # needs to be called after the package installation since # - it doesn't call "apt-get update" - name: ccache @@ -108,14 +118,16 @@ jobs: with: key: ${{ github.workflow }}-${{ matrix.image }} + # /usr/lib/ccache/bin - Alpine Linux + - name: Build cppcheck run: | - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + export PATH="/usr/lib/ccache/bin:/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" make -j$(nproc) HAVE_RULES=yes CXXOPTS="-Werror" - name: Build test run: | - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + export PATH="/usr/lib/ccache/bin:/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" make -j$(nproc) HAVE_RULES=yes CXXOPTS="-Werror" testrunner - name: Run test diff --git a/.github/workflows/CI-unixish.yml b/.github/workflows/CI-unixish.yml index 4b2c478ec98..3251a6b5adb 100644 --- a/.github/workflows/CI-unixish.yml +++ b/.github/workflows/CI-unixish.yml @@ -58,13 +58,13 @@ jobs: - name: CMake build on ubuntu (with GUI / system tinyxml2) if: contains(matrix.os, 'ubuntu') run: | - cmake -S . -B cmake.output.tinyxml2 -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_BUNDLED_TINYXML2=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake -S . -B cmake.output.tinyxml2 -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_BUNDLED_TINYXML2=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache cmake --build cmake.output.tinyxml2 -- -j$(nproc) - name: CMake build on macos (with GUI / system tinyxml2) if: contains(matrix.os, 'macos') run: | - cmake -S . -B cmake.output.tinyxml2 -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_BUNDLED_TINYXML2=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DQt6_DIR=$(brew --prefix qt@6)/lib/cmake/Qt6 + cmake -S . -B cmake.output.tinyxml2 -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_BUNDLED_TINYXML2=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DQt6_DIR=$(brew --prefix qt@6)/lib/cmake/Qt6 cmake --build cmake.output.tinyxml2 -- -j$(nproc) - name: Run CMake test (system tinyxml2) @@ -127,12 +127,12 @@ 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_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install + cmake -S . -B cmake.output -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=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_COMPILE_WARNING_AS_ERROR=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 -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=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: | @@ -154,13 +154,13 @@ jobs: - name: Run CMake on ubuntu (no CLI) if: matrix.os == 'ubuntu-22.04' run: | - cmake -S . -B cmake.output_nocli -G "Unix Makefiles" -DBUILD_CLI=Off + cmake -S . -B cmake.output_nocli -Werror=dev -DBUILD_TESTING=Off -DBUILD_CLI=Off - name: Run CMake on ubuntu (no CLI / with tests) if: matrix.os == 'ubuntu-22.04' 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 + if cmake -S . -B cmake.output_nocli_tests -Werror=dev -DBUILD_TESTING=On -DBUILD_CLI=Off; then exit 1 else exit 0 @@ -169,18 +169,18 @@ jobs: - name: Run CMake on ubuntu (no CLI / with GUI) if: matrix.os == 'ubuntu-22.04' run: | - cmake -S . -B cmake.output_nocli_gui -G "Unix Makefiles" -DBUILD_CLI=Off -DBUILD_GUI=On + cmake -S . -B cmake.output_nocli_gui -Werror=dev -DBUILD_TESTING=Off -DBUILD_CLI=Off -DBUILD_GUI=On - name: Run CMake on ubuntu (no GUI) if: matrix.os == 'ubuntu-22.04' run: | - cmake -S . -B cmake.output_nogui -G "Unix Makefiles" -DBUILD_GUI=Off + cmake -S . -B cmake.output_nogui -Werror=dev -DBUILD_TESTING=Off -DBUILD_GUI=Off - name: Run CMake on ubuntu (no GUI / with triage) if: matrix.os == 'ubuntu-22.04' run: | # cannot build triage without GUI - if cmake -S . -B cmake.output_nogui_triage -G "Unix Makefiles" -DBUILD_GUI=Off -DBUILD_TRIAGE=On; then + if cmake -S . -B cmake.output_nogui_triage -Werror=dev -DBUILD_TESTING=Off -DBUILD_GUI=Off -DBUILD_TRIAGE=On; then exit 1 else exit 0 @@ -189,7 +189,70 @@ jobs: - name: Run CMake on ubuntu (no CLI / no GUI) if: matrix.os == 'ubuntu-22.04' run: | - cmake -S . -B cmake.output_nocli_nogui -G "Unix Makefiles" -DBUILD_GUI=Off + cmake -S . -B cmake.output_nocli_nogui -Werror=dev -DBUILD_TESTING=Off -DBUILD_GUI=Off + + build_cmake_cxxstd: + + strategy: + matrix: + os: [ubuntu-22.04, macos-15] + cxxstd: [14, 17, 20] + # FIXME: macos-15 fails to compile with C++20 + # + # /Users/runner/work/cppcheck/cppcheck/cmake.output/gui/test/projectfile/moc_testprojectfile.cpp:84:1: error: 'constinit' specifier is incompatible with C++ standards before C++20 [-Werror,-Wc++20-compat] + # 84 | Q_CONSTINIT const QMetaObject TestProjectFile::staticMetaObject = { { + # | ^ + # /opt/homebrew/opt/qt/lib/QtCore.framework/Headers/qcompilerdetection.h:1409:23: note: expanded from macro 'Q_CONSTINIT' + exclude: + - os: macos-15 + cxxstd: 20 + fail-fast: false # Prefer quick result + + runs-on: ${{ matrix.os }} + + env: + # TODO: figure out why there are cache misses with PCH enabled + CCACHE_SLOPPINESS: pch_defines,time_macros + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}-${{ matrix.cxxstd }} + + - 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 + + # coreutils contains "nproc" + - name: Install missing software on macos + if: contains(matrix.os, 'macos') + run: | + # pcre was removed from runner images in November 2022 + brew install coreutils qt@6 pcre + + - name: Run CMake on ubuntu (with GUI) + if: contains(matrix.os, 'ubuntu') + run: | + cmake -S . -B cmake.output -Werror=dev -DCMAKE_CXX_STANDARD=${{ matrix.cxxstd }} -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + + - name: Run CMake on macos (with GUI) + if: contains(matrix.os, 'macos') + run: | + cmake -S . -B cmake.output -Werror=dev -DCMAKE_CXX_STANDARD=${{ matrix.cxxstd }} -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DQt6_DIR=$(brew --prefix qt@6)/lib/cmake/Qt6 + + - name: Run CMake build + run: | + cmake --build cmake.output -- -j$(nproc) build_uchar: @@ -310,7 +373,7 @@ jobs: run: | # make sure we fail when Boost is requested and not available. # will fail because no package configuration is available. - if cmake -S . -B cmake.output.boost-force-noavail -G "Unix Makefiles" -DUSE_BOOST=On; then + if cmake -S . -B cmake.output.boost-force-noavail -Werror=dev -DBUILD_TESTING=Off -DUSE_BOOST=On; then exit 1 else exit 0 @@ -323,12 +386,12 @@ jobs: - name: Run CMake on macOS (force Boost) run: | - cmake -S . -B cmake.output.boost-force -G "Unix Makefiles" -DUSE_BOOST=On + cmake -S . -B cmake.output.boost-force -Werror=dev -DBUILD_TESTING=Off -DUSE_BOOST=On - name: Run CMake on macOS (no Boost) run: | # make sure Boost is not used when disabled even though it is available - cmake -S . -B cmake.output.boost-no -G "Unix Makefiles" -DUSE_BOOST=Off + cmake -S . -B cmake.output.boost-no -Werror=dev -DBUILD_TESTING=Off -DUSE_BOOST=Off if grep -q '\-DHAVE_BOOST' ./cmake.output.boost-no/compile_commands.json; then exit 1 else @@ -337,13 +400,49 @@ jobs: - name: Run CMake on macOS (with Boost) run: | - cmake -S . -B cmake.output.boost -G "Unix Makefiles" -DBUILD_TESTS=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake -S . -B cmake.output.boost -Werror=dev -DBUILD_TESTING=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache grep -q '\-DHAVE_BOOST' ./cmake.output.boost/compile_commands.json - name: Build with CMake on macOS (with Boost) run: | cmake --build cmake.output.boost -- -j$(nproc) + build_cmake_minimum: # TODO: move to docker workflow? + + runs-on: ubuntu-22.04 # use the oldest available runner + + env: + CMAKE_VERSION: 3.22 + CMAKE_VERSION_FULL: 3.22.6 + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install missing software + 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: Install CMake + run: | + wget https://cmake.org/files/v${{ env.CMAKE_VERSION }}/cmake-${{ env.CMAKE_VERSION_FULL }}-linux-x86_64.tar.gz + tar xf cmake-${{ env.CMAKE_VERSION_FULL }}-linux-x86_64.tar.gz + + - name: Run CMake (without GUI) + run: | + export PATH=cmake-${{ env.CMAKE_VERSION_FULL }}-linux-x86_64/bin:$PATH + cmake -S . -B cmake.output -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On + + - name: Run CMake (with GUI) + run: | + export PATH=cmake-${{ env.CMAKE_VERSION_FULL }}-linux-x86_64/bin:$PATH + cmake -S . -B cmake.output.gui -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On + build: strategy: @@ -497,7 +596,7 @@ jobs: - name: Test Signalhandler run: | - cmake -S . -B build.cmake.signal -G "Unix Makefiles" -DBUILD_TESTS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On + cmake -S . -B build.cmake.signal -Werror=dev -DBUILD_TESTING=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On cmake --build build.cmake.signal --target test-signalhandler -- -j$(nproc) # TODO: how to run this without copying the file? cp build.cmake.signal/bin/test-s* . @@ -508,7 +607,7 @@ jobs: - name: Test Stacktrace if: contains(matrix.os, 'ubuntu') run: | - cmake -S . -B build.cmake.stack -G "Unix Makefiles" -DBUILD_TESTS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On + cmake -S . -B build.cmake.stack -Werror=dev -DBUILD_TESTING=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On cmake --build build.cmake.stack --target test-stacktrace -- -j$(nproc) # TODO: how to run this without copying the file? cp build.cmake.stack/bin/test-s* . @@ -571,6 +670,28 @@ jobs: warnings="-pedantic -Wall -Wextra -Wcast-qual -Wno-deprecated-declarations -Wfloat-equal -Wmissing-declarations -Wmissing-format-attribute -Wno-long-long -Wpacked -Wredundant-decls -Wundef -Wno-shadow -Wno-missing-field-initializers -Wno-missing-braces -Wno-sign-compare -Wno-multichar" g++ $warnings -c -Ilib -Iexternals/tinyxml2 democlient/democlient.cpp + - name: Test disabled executors + if: matrix.os == 'ubuntu-22.04' + run: | + g++ -Ilib -c cli/threadexecutor.cpp -DDISALLOW_THREAD_EXECUTOR + test -z "$(nm threadexecutor.o)" + g++ -Ilib -c cli/processexecutor.cpp -DDISALLOW_PROCESS_EXECUTOR + test -z "$(nm processexecutor.o)" + # TODO: test NO_* defines + + - name: Test execinfo.h detection + run: | + make clean + make cli/stacktrace.o | grep HAVE_EXECINFO_H=1 + test -n "$(nm cli/stacktrace.o)" + + - name: Test testrunner inclusion/exclusion + run: | + ! ./testrunner -d TestUtils | grep -v TestUtils > /dev/null + ! ./testrunner -d TestUtils::trim | grep -v TestUtils::trim > /dev/null + ! ./testrunner -d -x TestUtils | grep TestUtils > /dev/null + ! ./testrunner -d -x TestUtils:trim | grep TestUtils:trim > /dev/null + - name: Show all ignored files if: false # TODO: currently lists all the contents of ignored folders - we only need what actually matched run: | @@ -613,7 +734,7 @@ jobs: - name: CMake run: | - cmake -S . -B cmake.output -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_MATCHCOMPILER=Verify -DENABLE_CHECK_INTERNAL=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On + cmake -S . -B cmake.output -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_MATCHCOMPILER=Verify -DENABLE_CHECK_INTERNAL=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On - name: Generate dependencies run: | @@ -623,31 +744,4 @@ jobs: - name: Self check run: | - selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=file-total -D__GNUC__ --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --inconclusive --enable=style,performance,portability,warning,missingInclude,information --exception-handling --debug-warnings --check-level=exhaustive" - cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2" - gui_options="-DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=68 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt" - ec=0 - - # TODO: add --check-config - - # early exit - if [ $ec -eq 1 ]; then - exit $ec - fi - - # self check externals - ./cppcheck $selfcheck_options externals || ec=1 - # self check lib/cli - mkdir b1 - ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b1 --addon=naming.json frontend || ec=1 - ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b1 --addon=naming.json -Ifrontend cli || ec=1 - ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b1 --addon=naming.json --enable=internal lib || ec=1 - # check gui with qt settings - mkdir b2 - ./cppcheck $selfcheck_options $cppcheck_options $gui_options --cppcheck-build-dir=b2 --addon=naming.json --suppress=simplifyUsing:*/moc_*.cpp -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui || ec=1 - # self check test and tools - ./cppcheck $selfcheck_options $cppcheck_options -Ifrontend -Icli test/*.cpp || ec=1 - ./cppcheck $selfcheck_options $cppcheck_options -Icli tools/dmake/*.cpp || ec=1 - # triage - ./cppcheck $selfcheck_options $cppcheck_options $gui_options -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage || ec=1 - exit $ec + ./selfcheck.sh diff --git a/.github/workflows/CI-windows.yml b/.github/workflows/CI-windows.yml index 55be78ee06e..71d72025cf9 100644 --- a/.github/workflows/CI-windows.yml +++ b/.github/workflows/CI-windows.yml @@ -19,8 +19,6 @@ defaults: run: shell: cmd -# TODO: choose/add a step to bail out on compiler warnings (maybe even the release build) - jobs: build_qt: @@ -55,7 +53,7 @@ jobs: run: | rem TODO: enable rules? rem specify Release build so matchcompiler is used - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DBUILD_ONLINE_HELP=On -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! + cmake -S . -B build -Werror=dev -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DBUILD_TESTING=Off -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DBUILD_ONLINE_HELP=On -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! - name: Build GUI release run: | @@ -73,6 +71,75 @@ jobs: run: | cmake --build build --target install + build_cmake_cxxstd: + strategy: + matrix: + os: [windows-2022, windows-2025] + cxxstd: [14, 17, 20] + fail-fast: false + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up Visual Studio environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Run CMake + run: | + cmake -S . -B build.cxxstd -Werror=dev -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.cxxstd }} -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! + + - name: Build + run: | + cmake --build build.cxxstd --config Debug || exit /b !errorlevel! + + build_cmake_minimum: + + runs-on: windows-2022 # use the oldest available runner + + env: + CMAKE_VERSION: 3.22 + CMAKE_VERSION_FULL: 3.22.6 + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install CMake + run: | + curl -fsSL https://cmake.org/files/v${{ env.CMAKE_VERSION }}/cmake-${{ env.CMAKE_VERSION_FULL }}-windows-x86_64.zip -o cmake.zip || exit /b !errorlevel! + 7z x cmake.zip || exit /b !errorlevel! + + - name: Set up Visual Studio environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: 6.10.0 + modules: 'qtcharts' + setup-python: 'false' + cache: true + aqtversion: '==3.1.*' # TODO: remove when aqtinstall 3.2.2 is available + + - name: Run CMake (without GUI) + run: | + :: TODO: enable DHAVE_RULES? + cmake-${{ env.CMAKE_VERSION_FULL }}-windows-x86_64\bin\cmake.exe -S . -B cmake.output -A x64 -DHAVE_RULES=Off -DBUILD_TESTING=On + + - name: Run CMake (with GUI) + run: | + :: TODO: enable DHAVE_RULES? + cmake-${{ env.CMAKE_VERSION_FULL }}-windows-x86_64\bin\cmake.exe -S . -B cmake.output.gui -A x64 -DHAVE_RULES=Off -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On + build: strategy: matrix: @@ -142,8 +209,6 @@ jobs: python -m pip install pytest-xdist || exit /b !errorlevel! python -m pip install psutil || exit /b !errorlevel! - # TODO: build with CMake - - name: Build CLI debug configuration using MSBuild if: matrix.config == 'debug' run: | @@ -154,7 +219,7 @@ jobs: - name: Run Debug test if: matrix.config == 'debug' - run: .\bin\debug\testrunner.exe || exit /b !errorlevel! + run: .\bin\debug\testrunner.exe -t || exit /b !errorlevel! - name: Build CLI release configuration using MSBuild if: matrix.config == 'release' @@ -207,7 +272,7 @@ jobs: - name: Test SEH wrapper if: matrix.config == 'release' run: | - cmake -S . -B build.cmake.seh -DBUILD_TESTS=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! + cmake -S . -B build.cmake.seh -Werror=dev -DBUILD_TESTING=On -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! cmake --build build.cmake.seh --target test-sehwrapper || exit /b !errorlevel! :: TODO: how to run this without copying the file? copy build.cmake.seh\bin\Debug\test-sehwrapper.exe . || exit /b !errorlevel! diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml deleted file mode 100644 index 70b3a30f0ae..00000000000 --- a/.github/workflows/asan.yml +++ /dev/null @@ -1,158 +0,0 @@ -# Syntax reference https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions -# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners -name: address sanitizer - -on: - push: - branches: - - 'main' - - 'releases/**' - - '2.*' - tags: - - '2.*' - pull_request: - -permissions: - contents: read - -jobs: - build: - - runs-on: ubuntu-22.04 - - env: - QT_VERSION: 6.10.0 - ASAN_OPTIONS: detect_stack_use_after_return=1 - LSAN_OPTIONS: suppressions=lsan-suppr.txt:print_suppressions=0 - # TODO: figure out why there are cache misses with PCH enabled - CCACHE_SLOPPINESS: pch_defines,time_macros - - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 - with: - key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }} - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.14' - check-latest: true - - - name: Install missing software on ubuntu - run: | - sudo apt-get update - sudo apt-get install -y cmake make libpcre3-dev libboost-container-dev libxml2-utils - sudo apt-get install -y libcups2-dev # required for Qt6PrintSupport in CMake since Qt 6.7.3 - - - name: Install clang - run: | - sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 - wget https://apt.llvm.org/llvm.sh - chmod +x llvm.sh - sudo ./llvm.sh 21 - - - name: Install Qt ${{ env.QT_VERSION }} - uses: jurplel/install-qt-action@v4 - with: - version: ${{ env.QT_VERSION }} - modules: 'qtcharts' - setup-python: 'false' - cache: true - - - name: Install missing Python packages - run: | - python3 -m pip install pip --upgrade - python3 -m pip install pytest - python3 -m pip install pytest-timeout - python3 -m pip install pytest-xdist - python3 -m pip install psutil - - - name: CMake - run: | - cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_MATCHCOMPILER=Verify -DANALYZE_ADDRESS=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - env: - CC: clang-21 - CXX: clang++-21 - - - name: Build cppcheck - run: | - cmake --build cmake.output --target cppcheck -- -j $(nproc) - - - name: Build test - run: | - cmake --build cmake.output --target testrunner -- -j $(nproc) - - - name: Build GUI tests - run: | - cmake --build cmake.output --target gui-tests -- -j $(nproc) - - - name: Run tests - run: ./cmake.output/bin/testrunner - - - name: Run cfg tests - run: | - cmake --build cmake.output --target checkcfg -- -j $(nproc) - - - name: Run CTest - run: | - cp lsan-suppr.txt cmake.output/bin - ctest --test-dir cmake.output --output-on-failure -j$(nproc) - - - name: Run test/cli - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - - - name: Run test/cli (-j2) - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - env: - TEST_CPPCHECK_INJECT_J: 2 - - - name: Run test/cli (--clang) - if: false - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - env: - TEST_CPPCHECK_INJECT_CLANG: clang - - - name: Run test/cli (--cppcheck-build-dir) - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - env: - TEST_CPPCHECK_INJECT_BUILDDIR: injected - - - name: Generate dependencies - if: false - run: | - # make sure auto-generated GUI files exist - make -C cmake.output autogen - make -C cmake.output gui-build-deps triage-build-ui-deps - - # TODO: this is currently way too slow (~60 minutes) to enable it - # TODO: only fail the step on sanitizer issues - since we use processes it will only fail the underlying process which will result in an cppcheckError - - name: Self check - if: false - run: | - selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=file-total -D__GNUC__ --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --inconclusive --enable=style,performance,portability,warning,missingInclude,information --exception-handling --debug-warnings --check-level=exhaustive" - cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2" - gui_options="-DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt" - gui_options="$gui_options --suppress=autoNoType:*/moc_*.cpp --suppress=symbolDatabaseWarning:*/moc_*.cpp" - ec=0 - ./cmake.output/bin/cppcheck $selfcheck_options externals || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json frontend || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json -Ifrontend cli || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json --enable=internal lib || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options $gui_options --addon=naming.json --suppress=constVariablePointer:*/moc_*.cpp -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli -Ifrontend test/*.cpp || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli tools/dmake/*.cpp || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options $gui_options -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage || ec=1 - exit $ec diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 7b462c688f0..c54d47da4f1 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -10,7 +10,7 @@ permissions: jobs: Fuzzing: runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'danmar' }} + if: ${{ github.repository_owner == 'cppcheck-opensource' }} steps: - name: Build Fuzzers id: build diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 7b2c4f4e2c7..c4f8cc0cf6b 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -43,8 +43,8 @@ jobs: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 21 - sudo apt-get install -y clang-tidy-21 + sudo ./llvm.sh 22 + sudo apt-get install -y clang-tidy-22 - name: Install Qt ${{ env.QT_VERSION }} uses: jurplel/install-qt-action@v4 @@ -57,14 +57,14 @@ jobs: - name: Verify clang-tidy configuration run: | - clang-tidy-21 --verify-config + clang-tidy-22 --verify-config - name: Prepare CMake run: | - cmake -S . -B cmake.output -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off -DWARNINGS_ARE_ERRORS=On + cmake -S . -B cmake.output -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_COMPILE_WARNING_AS_ERROR=On env: - CC: clang-21 - CXX: clang++-21 + CC: clang-22 + CXX: clang++-22 - name: Prepare CMake dependencies run: | diff --git a/.github/workflows/corpus.yml b/.github/workflows/corpus.yml new file mode 100644 index 00000000000..0c1aeda94de --- /dev/null +++ b/.github/workflows/corpus.yml @@ -0,0 +1,58 @@ +# Syntax reference https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions +# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners +name: corpus + +on: + schedule: + - cron: '0 0 * * 0' + workflow_dispatch: + +permissions: + contents: read + +jobs: + corpus: + runs-on: ubuntu-22.04 + if: ${{ github.repository_owner == 'cppcheck-opensource' }} + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ runner.os }} + + - name: Install missing software on ubuntu + run: | + sudo apt-get update + sudo apt-get install -y fdupes + + - name: build testrunner + run: | + store_dir=$(pwd)/store + mkdir $store_dir + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) CXXOPTS="-Werror" CPPOPTS="-DSTORE_INPUT_DIR=\"\\\"$store_dir\\\"\"" testrunner + + - name: run testrunner + run: | + ./testrunner -q + + - name: de-duplicate files + run: | + set -x + ls -l ./store | wc -l + echo "removing duplicates" + fdupes -qdN ./store > /dev/null + ls -l ./store | wc -l + # print largest size + ls -l ./store | cut -d' ' -f5 | sort -u -n -r | head -n1 + + - uses: actions/upload-artifact@v4 + if: success() + with: + name: corpus + path: ./store diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 3c07b61d7c7..006160c7779 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -12,7 +12,7 @@ permissions: jobs: scan: runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'danmar' }} + if: ${{ github.repository_owner == 'cppcheck-opensource' }} steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/cppcheck-premium.yml b/.github/workflows/cppcheck-premium.yml index 42bca8a6ebb..ed0f2a1bcd5 100644 --- a/.github/workflows/cppcheck-premium.yml +++ b/.github/workflows/cppcheck-premium.yml @@ -33,7 +33,7 @@ jobs: run: | premium_version=${{ inputs.premium_version }} if [ -z $premium_version ]; then - premium_version=25.8.3 + premium_version=26.3.0 #wget https://files.cppchecksolutions.com/devdrop/cppcheckpremium-$premium_version-amd64.tar.gz -O cppcheckpremium.tar.gz wget https://files.cppchecksolutions.com/$premium_version/ubuntu-24.04/cppcheckpremium-$premium_version-amd64.tar.gz -O cppcheckpremium.tar.gz else @@ -45,9 +45,9 @@ jobs: - name: Generate a license file run: | echo cppcheck > cppcheck.lic - echo 251231 >> cppcheck.lic + echo 261231 >> cppcheck.lic echo 80000 >> cppcheck.lic - echo 4f8dc8e7c8bb288f >> cppcheck.lic + echo 4b64673f03fb6230 >> cppcheck.lic echo path:lib >> cppcheck.lic - name: Check diff --git a/.github/workflows/iwyu.yml b/.github/workflows/iwyu.yml index 649991f9373..3b972dca443 100644 --- a/.github/workflows/iwyu.yml +++ b/.github/workflows/iwyu.yml @@ -15,25 +15,22 @@ jobs: strategy: matrix: - # "opensuse/tumbleweed:latest" / "fedora:latest" / "debian:unstable" / "archlinux:latest" + # "opensuse/tumbleweed:latest" / "fedora:rawhide" / "debian:unstable" / "archlinux:latest" include: - os: ubuntu-22.04 - image: "fedora:latest" + image: "fedora:rawhide" stdlib: libstdc++ - clang_inc: '-isystem/usr/lib/clang/20/include' - # TODO: disable because it currently fails with "error: tried including but didn't find libc++'s header." - #- os: ubuntu-22.04 - # image: "fedora:latest" - # stdlib: libc++ - # clang_inc: '-isystem/usr/lib/clang/20/include' - - os: macos-13 + - os: ubuntu-22.04 + image: "fedora:rawhide" + stdlib: libc++ + - os: macos-26 image: "" stdlib: libc++ # no libstdc++ on macOS mapping_file_opt: '-Xiwyu --mapping_file=$(realpath ./macos.imp)' fail-fast: false runs-on: ${{ matrix.os }} - if: ${{ github.repository_owner == 'danmar' }} + if: ${{ github.repository_owner == 'cppcheck-opensource' }} container: image: ${{ matrix.image }} @@ -74,7 +71,7 @@ jobs: - name: Install missing software on Fedora if: contains(matrix.image, 'fedora') run: | - dnf install -y cmake clang pcre-devel + dnf install -y cmake clang dnf install -y libglvnd-devel # fixes missing dependency for Qt in CMake dnf install -y p7zip-plugins # required as fallback for py7zr in Qt installation dnf install -y python3-pip # fixes missing pip module in jurplel/install-qt-action @@ -100,18 +97,21 @@ jobs: if: contains(matrix.os, 'macos') run: | brew install include-what-you-use pcre coreutils - ln -s iwyu_tool.py /usr/local/bin/iwyu_tool + # on Apple Silicon files are symlinked under /opt/homebrew/bin + ln -s /opt/homebrew/bin/iwyu_tool.py /usr/local/bin/iwyu_tool # Fails on OpenSUSE: # Warning: Failed to restore: Tar failed with error: Unable to locate executable file: tar. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable. # Also the shell is broken afterwards: # OCI runtime exec failed: exec failed: unable to start container process: exec: "sh": executable file not found in $PATH: unknown + # + # On macos-26 we need to perform the Python setup because the default installation is managed externally managed - name: Install Qt ${{ env.QT_VERSION }} uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} modules: 'qtcharts' - setup-python: 'false' + setup-python: ${{ contains(matrix.os, 'macos') }} install-deps: false cache: true @@ -125,7 +125,8 @@ jobs: - name: Prepare CMake run: | - cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCPPCHK_GLIBCXX_DEBUG=Off -DUSE_MATCHCOMPILER=Off -DEXTERNALS_AS_SYSTEM=On -DUSE_LIBCXX=${{ matrix.stdlib == 'libc++' }} + # TODO: re-enable HAVE_RULES + cmake -S . -B cmake.output -Werror=dev -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=Off -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCPPCHK_GLIBCXX_DEBUG=Off -DUSE_MATCHCOMPILER=Off -DEXTERNALS_AS_SYSTEM=On -DUSE_LIBCXX=${{ matrix.stdlib == 'libc++' }} env: CC: clang CXX: clang++ @@ -147,8 +148,7 @@ jobs: - name: iwyu_tool run: | - # TODO: remove -stdlib= - it should have been taken from the compilation database - iwyu_tool -p cmake.output -j $(nproc) -- -w -Xiwyu --max_line_length=1024 -Xiwyu --comment_style=long -Xiwyu --quoted_includes_first -Xiwyu --update_comments -stdlib=${{ matrix.stdlib }} ${{ matrix.mapping_file_opt }} ${{ matrix.clang_inc }} > iwyu.log + iwyu_tool -p cmake.output -j $(nproc) -- -w -Xiwyu --max_line_length=1024 -Xiwyu --comment_style=long -Xiwyu --quoted_includes_first -Xiwyu --update_comments ${{ matrix.mapping_file_opt }} ${{ matrix.clang_inc }} > iwyu.log # TODO: run with all configurations - name: test/cfg @@ -193,7 +193,7 @@ jobs: fail-fast: false runs-on: ubuntu-22.04 - if: ${{ github.repository_owner == 'danmar' }} + if: ${{ github.repository_owner == 'cppcheck-opensource' }} env: QT_VERSION: 6.10.0 @@ -214,13 +214,13 @@ jobs: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 21 - sudo apt-get install -y clang-tools-21 + sudo ./llvm.sh 22 + sudo apt-get install -y clang-tools-22 - name: Install libc++ if: matrix.stdlib == 'libc++' run: | - sudo apt-get install -y libc++-21-dev + sudo apt-get install -y libc++-22-dev - name: Install Qt ${{ env.QT_VERSION }} uses: jurplel/install-qt-action@v4 @@ -233,10 +233,11 @@ jobs: - name: Prepare CMake run: | - cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCPPCHK_GLIBCXX_DEBUG=Off -DUSE_MATCHCOMPILER=Off -DEXTERNALS_AS_SYSTEM=On -DUSE_LIBCXX=${{ matrix.use_libcxx }} + # TODO: re-enable HAVE_RULES + cmake -S . -B cmake.output -Werror=dev -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=Off -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCPPCHK_GLIBCXX_DEBUG=Off -DUSE_MATCHCOMPILER=Off -DEXTERNALS_AS_SYSTEM=On -DUSE_LIBCXX=${{ matrix.use_libcxx }} env: - CC: clang-21 - CXX: clang++-21 + CC: clang-22 + CXX: clang++-22 - name: Prepare CMake dependencies run: | @@ -253,7 +254,7 @@ jobs: - name: clang-include-cleaner run: | # TODO: run multi-threaded - find $PWD/cli $PWD/lib $PWD/test $PWD/gui -maxdepth 1 -name "*.cpp" | xargs -t -n 1 clang-include-cleaner-21 --print=changes --extra-arg=-w --extra-arg=-stdlib=${{ matrix.stdlib }} -p cmake.output > clang-include-cleaner.log 2>&1 + find $PWD/cli $PWD/lib $PWD/test $PWD/gui -maxdepth 1 -name "*.cpp" | xargs -t -n 1 clang-include-cleaner-22 --print=changes --extra-arg=-w --extra-arg=-stdlib=${{ matrix.stdlib }} -p cmake.output > clang-include-cleaner.log 2>&1 - uses: actions/upload-artifact@v4 if: success() || failure() diff --git a/.github/workflows/release-windows.yml b/.github/workflows/release-windows.yml index 2836000acc5..f59e77a2dca 100644 --- a/.github/workflows/release-windows.yml +++ b/.github/workflows/release-windows.yml @@ -22,9 +22,10 @@ jobs: build: runs-on: windows-2025 - if: ${{ github.repository_owner == 'danmar' }} + if: ${{ github.repository_owner == 'cppcheck-opensource' }} env: + PYTHON_VERSION: 3.14 # see https://www.pcre.org/original/changelog.txt PCRE_VERSION: 8.45 QT_VERSION: 6.10.0 @@ -35,6 +36,12 @@ jobs: with: persist-credentials: false + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + check-latest: true + - name: Set up Visual Studio environment uses: ilammy/msvc-dev-cmd@v1 @@ -48,8 +55,8 @@ jobs: 7z x pcre-%PCRE_VERSION%.zip || exit /b !errorlevel! cd pcre-%PCRE_VERSION% || exit /b !errorlevel! git apply --ignore-space-change ..\externals\pcre.patch || exit /b !errorlevel! - cmake . -G "Visual Studio 17 2022" -A x64 -DPCRE_BUILD_PCRECPP=OFF -DPCRE_BUILD_PCREGREP=OFF -DPCRE_BUILD_TESTS=OFF -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! - msbuild -m PCRE.sln -p:Configuration=Release -p:Platform=x64 || exit /b !errorlevel! + cmake . -A x64 -DPCRE_BUILD_PCRECPP=OFF -DPCRE_BUILD_PCREGREP=OFF -DPCRE_BUILD_TESTS=OFF -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! + msbuild -m PCRE.slnx -p:Configuration=Release -p:Platform=x64 || exit /b !errorlevel! copy pcre.h ..\externals || exit /b !errorlevel! copy Release\pcre.lib ..\externals\pcre64.lib || exit /b !errorlevel! @@ -65,21 +72,20 @@ jobs: # available modules: https://github.com/miurahr/aqtinstall/blob/master/docs/getting_started.rst#installing-modules # available tools: https://github.com/miurahr/aqtinstall/blob/master/docs/getting_started.rst#installing-tools - - name: Install Qt ${{ env.QT_VERSION }} + - name: Install Qt uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} modules: 'qtcharts' setup-python: 'false' tools: 'tools_opensslv3_x64' - aqtversion: '==3.1.*' # TODO: remove when aqtinstall 3.2.2 is available # TODO: build with multiple threads - name: Build x64 release GUI run: | :: TODO: enable rules? :: specify Release build so matchcompiler is used - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_ONLINE_HELP=On -DUSE_BOOST=ON -DBOOST_INCLUDEDIR=%GITHUB_WORKSPACE%\boost -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! + cmake -S . -B build -Werror=dev -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=Off -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_ONLINE_HELP=On -DUSE_BOOST=ON -DBOOST_INCLUDEDIR=%GITHUB_WORKSPACE%\boost -DCMAKE_COMPILE_WARNING_AS_ERROR=On || exit /b !errorlevel! cmake --build build --target cppcheck-gui --config Release || exit /b !errorlevel! # TODO: package PDBs diff --git a/.github/workflows/ubsan.yml b/.github/workflows/sanitizers.yml similarity index 62% rename from .github/workflows/ubsan.yml rename to .github/workflows/sanitizers.yml index 64eb02a4b25..d7ff31939d0 100644 --- a/.github/workflows/ubsan.yml +++ b/.github/workflows/sanitizers.yml @@ -1,6 +1,6 @@ # Syntax reference https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners -name: undefined behaviour sanitizers +name: sanitizers on: push: @@ -18,10 +18,33 @@ permissions: jobs: build: + strategy: + matrix: + include: + - sanitizer: 'asan' + cmake_opts: '-DANALYZE_ADDRESS=On' + run_ctest: true + inject_executor: 'process' + run_selfcheck: false # TODO: this is currently way too slow (~60 minutes) to enable it + - sanitizer: 'tsan' + cmake_opts: '-DANALYZE_THREAD=On' + run_ctest: false # TODO: test-filelist fails with data race in pthread_cond_destroy + inject_executor: 'thread' + run_selfcheck: false # TODO: disabled for now as it takes around 40 minutes to finish + selfcheck_opts: '--executor=thread --error-exitcode=0' # set --error-exitcode=0 so we only fail on sanitizer issues - since it uses threads for execution it will exit the whole process on the first issue + - sanitizer: 'ubsan' + cmake_opts: '-DANALYZE_UNDEFINED=On' + run_ctest: true + inject_executor: 'process' + run_selfcheck: true + fail-fast: false + runs-on: ubuntu-22.04 env: QT_VERSION: 6.10.0 + ASAN_OPTIONS: detect_stack_use_after_return=1 + TSAN_OPTIONS: halt_on_error=1 UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:report_error_type=1 # TODO: figure out why there are cache misses with PCH enabled CCACHE_SLOPPINESS: pch_defines,time_macros @@ -34,7 +57,7 @@ jobs: - name: ccache uses: hendrikmuhs/ccache-action@v1.2 with: - key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }} + key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}-${{ matrix.sanitizer }} - name: Set up Python uses: actions/setup-python@v5 @@ -53,7 +76,7 @@ jobs: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 21 + sudo ./llvm.sh 22 - name: Install Qt ${{ env.QT_VERSION }} uses: jurplel/install-qt-action@v4 @@ -73,10 +96,10 @@ jobs: - name: CMake run: | - cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_MATCHCOMPILER=Verify -DANALYZE_UNDEFINED=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake -S . -B cmake.output -Werror=dev -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_MATCHCOMPILER=Verify ${{ matrix.cmake_opts }} -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache env: - CC: clang-21 - CXX: clang++-21 + CC: clang-22 + CXX: clang++-22 - name: Build cppcheck run: | @@ -91,13 +114,14 @@ jobs: cmake --build cmake.output --target gui-tests -- -j $(nproc) - name: Run tests - run: ./cmake.output/bin/testrunner + run: ./cmake.output/bin/testrunner -t - name: Run cfg tests run: | cmake --build cmake.output --target checkcfg -- -j $(nproc) - name: Run CTest + if: matrix.run_ctest run: | ctest --test-dir cmake.output --output-on-failure -j$(nproc) @@ -105,6 +129,8 @@ jobs: run: | pwd=$(pwd) TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli + env: + TEST_CPPCHECK_INJECT_EXECUTOR: ${{ matrix.inject_executor }} - name: Run test/cli (-j2) run: | @@ -129,6 +155,7 @@ jobs: TEST_CPPCHECK_INJECT_BUILDDIR: injected - name: Generate dependencies + if: matrix.run_selfcheck run: | # make sure auto-generated GUI files exist make -C cmake.output autogen @@ -136,18 +163,6 @@ jobs: # TODO: only fail the step on sanitizer issues - since we use processes it will only fail the underlying process which will result in an cppcheckError - name: Self check + if: matrix.run_selfcheck run: | - selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=file-total -D__GNUC__ --error-exitcode=1 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --inconclusive --enable=style,performance,portability,warning,missingInclude,information --exception-handling --debug-warnings --check-level=exhaustive" - cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2" - gui_options="-DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt" - gui_options="$gui_options --suppress=autoNoType:*/moc_*.cpp --suppress=symbolDatabaseWarning:*/moc_*.cpp" - ec=0 - ./cmake.output/bin/cppcheck $selfcheck_options externals || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json frontend || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json -Ifrontend cli || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json --enable=internal lib || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options $gui_options --addon=naming.json --suppress=constVariablePointer:*/moc_*.cpp -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli -Ifrontend test/*.cpp || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli tools/dmake/*.cpp || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options $gui_options -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage || ec=1 - exit $ec + ./selfcheck_san.sh ./cmake.output ${{ matrix.selfcheck_opts }} diff --git a/.github/workflows/scriptcheck.yml b/.github/workflows/scriptcheck.yml index 66e54ddff98..844b1d5c2f3 100644 --- a/.github/workflows/scriptcheck.yml +++ b/.github/workflows/scriptcheck.yml @@ -87,7 +87,7 @@ jobs: python -m pip install pip --upgrade python -m pip install natsort python -m pip install pexpect - python -m pip install 'pylint<=3.3.0' + python -m pip install 'pylint<4.1.0' python -m pip install unittest2 python -m pip install pytest python -m pip install pytest-xdist diff --git a/.github/workflows/selfcheck.yml b/.github/workflows/selfcheck.yml index f667dc78451..cfd1107e92d 100644 --- a/.github/workflows/selfcheck.yml +++ b/.github/workflows/selfcheck.yml @@ -16,7 +16,6 @@ permissions: contents: read jobs: - # TODO: enable information build: runs-on: ubuntu-22.04 @@ -65,7 +64,7 @@ jobs: # unusedFunction - start - name: CMake run: | - cmake -S . -B cmake.output -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=ON -DWITH_QCHART=ON -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off + cmake -S . -B cmake.output -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=On -DBUILD_GUI=ON -DWITH_QCHART=ON -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off - name: Generate dependencies run: | @@ -77,11 +76,10 @@ jobs: # make sure the auto-generated GUI dependencies exist make -C cmake.output gui-build-deps - # TODO: find a way to report unmatched suppressions without need to add information checks - name: Self check (unusedFunction) if: false # TODO: fails with preprocessorErrorDirective - see #10667 run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -92,7 +90,7 @@ jobs: # unusedFunction notest - start - name: CMake (no test) run: | - cmake -S . -B cmake.output.notest -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=Off -DBUILD_GUI=ON -DBUILD_TRIAGE=On -DWITH_QCHART=ON -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off + cmake -S . -B cmake.output.notest -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=Off -DBUILD_GUI=ON -DBUILD_TRIAGE=On -DWITH_QCHART=ON -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off - name: Generate dependencies (no test) run: | @@ -103,10 +101,9 @@ jobs: # make sure the auto-generated GUI dependencies exist make -C cmake.output.notest gui-build-deps - # TODO: find a way to report unmatched suppressions without need to add information checks - name: Self check (unusedFunction / no test) run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -115,17 +112,17 @@ jobs: # unusedFunction notest nogui - start - name: CMake (no test / no gui) run: | - cmake -S . -B cmake.output.notest_nogui -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=Off -DENABLE_CHECK_INTERNAL=On -DCPPCHK_GLIBCXX_DEBUG=Off + cmake -S . -B cmake.output.notest_nogui -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=Off -DENABLE_CHECK_INTERNAL=On -DCPPCHK_GLIBCXX_DEBUG=Off - name: Generate dependencies (no test / no gui) run: | # make sure the precompiled headers exist make -C cmake.output.notest_nogui lib/CMakeFiles/cppcheck-core.dir/cmake_pch.hxx.cxx - # TODO: find a way to report unmatched suppressions without need to add information checks - name: Self check (unusedFunction / no test / no gui) run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1665 --suppress=unusedFunction:lib/importproject.cpp:1689" + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -134,7 +131,7 @@ jobs: # unusedFunction notest nocli - start - name: CMake (no test / no cli) run: | - cmake -S . -B cmake.output.notest_nocli -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=Off -DBUILD_CLI=Off -DBUILD_GUI=ON -DWITH_QCHART=ON -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off + cmake -S . -B cmake.output.notest_nocli -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=Off -DBUILD_CLI=Off -DBUILD_GUI=ON -DWITH_QCHART=ON -DBUILD_TRIAGE=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off - name: Generate dependencies (no test / no cli) run: | @@ -145,11 +142,10 @@ jobs: # make sure the auto-generated GUI dependencies exist make -C cmake.output.notest_nocli gui-build-deps - # TODO: find a way to report unmatched suppressions without need to add information checks - name: Self check (unusedFunction / no test / no cli) if: false # TODO: the findings are currently too intrusive run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nocli/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nocli/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -158,18 +154,17 @@ jobs: # unusedFunction notest nocli nogui - start - name: CMake (no test / no cli / no gui) run: | - cmake -S . -B cmake.output.notest_nocli_nogui -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=Off -DBUILD_CLI=Off -DBUILD_GUI=Off -DENABLE_CHECK_INTERNAL=On -DCPPCHK_GLIBCXX_DEBUG=Off + cmake -S . -B cmake.output.notest_nocli_nogui -Werror=dev -DHAVE_RULES=On -DBUILD_TESTING=Off -DBUILD_CLI=Off -DBUILD_GUI=Off -DENABLE_CHECK_INTERNAL=On -DCPPCHK_GLIBCXX_DEBUG=Off - name: Generate dependencies (no test / no cli / no gui) run: | # make sure the precompiled headers exist make -C cmake.output.notest_nocli_nogui lib/CMakeFiles/cppcheck-core.dir/cmake_pch.hxx.cxx - # TODO: find a way to report unmatched suppressions without need to add information checks - name: Self check (unusedFunction / no test / no cli / no gui) if: false # TODO: the findings are currently too intrusive run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nocli_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nocli_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -177,12 +172,12 @@ jobs: - name: Fetch corpus run: | - wget https://github.com/danmar/cppcheck/archive/refs/tags/2.8.tar.gz + wget https://github.com/cppcheck-opensource/cppcheck/archive/refs/tags/2.8.tar.gz tar xvf 2.8.tar.gz - name: CMake (corpus / no test) run: | - cmake -S cppcheck-2.8 -B cmake.output.corpus -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=Off -DBUILD_GUI=ON -DUSE_QT6=On -DWITH_QCHART=ON -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + cmake -S cppcheck-2.8 -B cmake.output.corpus -DHAVE_RULES=On -DBUILD_TESTING=Off -DBUILD_GUI=ON -DUSE_QT6=On -DWITH_QCHART=ON -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_POLICY_VERSION_MINIMUM=3.5 - name: Generate dependencies (corpus) run: | @@ -193,11 +188,10 @@ jobs: # make sure the auto-generated GUI dependencies exist make -C cmake.output.corpus gui-build-deps - # TODO: find a way to report unmatched suppressions without need to add information checks - name: Self check (unusedFunction / corpus / no test / callgrind) run: | # TODO: fix -rp so the suppressions actually work - valgrind --tool=callgrind ./cppcheck --template=selfcheck --error-exitcode=0 --library=cppcheck-lib --library=qt -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.corpus/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr 2>callgrind.log || (cat callgrind.log && false) + valgrind --tool=callgrind ./cppcheck --template=selfcheck --error-exitcode=0 --library=cppcheck-lib --library=qt -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.corpus/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr 2>callgrind.log || (cat callgrind.log && false) cat callgrind.log callgrind_annotate --auto=no > callgrind.annotated.log head -50 callgrind.annotated.log @@ -208,3 +202,16 @@ jobs: with: name: Callgrind Output path: ./callgrind.* + + - name: Self check (unusedFunction / corpus / no test / memcheck) + run: | + # TODO: fix -rp so the suppressions actually work + valgrind --error-limit=yes --leak-check=full --num-callers=50 --show-reachable=yes --track-origins=yes --gen-suppressions=all --log-fd=9 --error-exitcode=42 ./cppcheck --template=selfcheck --error-exitcode=0 --library=cppcheck-lib --library=qt -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.corpus/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr 9>memcheck.log || (cat memcheck.log && false) + cat memcheck.log + env: + DISABLE_VALUEFLOW: 1 + + - uses: actions/upload-artifact@v4 + with: + name: Memcheck Output + path: ./memcheck.* diff --git a/.github/workflows/tsan.yml b/.github/workflows/tsan.yml deleted file mode 100644 index 27ed6606386..00000000000 --- a/.github/workflows/tsan.yml +++ /dev/null @@ -1,160 +0,0 @@ -# Syntax reference https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions -# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners -name: thread sanitizer - -on: - push: - branches: - - 'main' - - 'releases/**' - - '2.*' - tags: - - '2.*' - pull_request: - -permissions: - contents: read - -jobs: - build: - - runs-on: ubuntu-22.04 - - env: - QT_VERSION: 6.10.0 - TSAN_OPTIONS: halt_on_error=1 - # TODO: figure out why there are cache misses with PCH enabled - CCACHE_SLOPPINESS: pch_defines,time_macros - - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 - with: - key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }} - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.14' - check-latest: true - - - name: Install missing software on ubuntu - run: | - sudo apt-get update - sudo apt-get install -y cmake make libpcre3-dev libboost-container-dev libxml2-utils - sudo apt-get install -y libcups2-dev # required for Qt6PrintSupport in CMake since Qt 6.7.3 - - - name: Install clang - run: | - sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 - wget https://apt.llvm.org/llvm.sh - chmod +x llvm.sh - sudo ./llvm.sh 21 - - - name: Install Qt ${{ env.QT_VERSION }} - uses: jurplel/install-qt-action@v4 - with: - version: ${{ env.QT_VERSION }} - modules: 'qtcharts' - setup-python: 'false' - cache: true - - - name: Install missing Python packages - run: | - python3 -m pip install pip --upgrade - python3 -m pip install pytest - python3 -m pip install pytest-timeout - python3 -m pip install pytest-xdist - python3 -m pip install psutil - - - name: CMake - run: | - cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DUSE_MATCHCOMPILER=Verify -DANALYZE_THREAD=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_COMPILE_WARNING_AS_ERROR=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - env: - CC: clang-21 - CXX: clang++-21 - - - name: Build cppcheck - run: | - cmake --build cmake.output --target cppcheck -- -j $(nproc) - - - name: Build test - run: | - cmake --build cmake.output --target testrunner -- -j $(nproc) - - - name: Build GUI tests - run: | - cmake --build cmake.output --target gui-tests -- -j $(nproc) - - - name: Run tests - run: ./cmake.output/bin/testrunner - - - name: Run cfg tests - run: | - cmake --build cmake.output --target checkcfg -- -j $(nproc) - - - name: Run CTest - if: false # TODO: test-filelist fails with data race in pthread_cond_destroy - run: | - ctest --test-dir cmake.output --output-on-failure -j$(nproc) - - - name: Run test/cli - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - env: - TEST_CPPCHECK_INJECT_EXECUTOR: thread - - - name: Run test/cli (-j2) - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - env: - TEST_CPPCHECK_INJECT_J: 2 - - - name: Run test/cli (--clang) - if: false - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - env: - TEST_CPPCHECK_INJECT_CLANG: clang - - - name: Run test/cli (--cppcheck-build-dir) - run: | - pwd=$(pwd) - TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv -n auto test/cli - env: - TEST_CPPCHECK_INJECT_BUILDDIR: injected - - - name: Generate dependencies - if: false - run: | - # make sure auto-generated GUI files exist - make -C cmake.output autogen - make -C cmake.output gui-build-deps triage-build-ui-deps - - # TODO: disabled for now as it takes around 40 minutes to finish - # set --error-exitcode=0 so we only fail on sanitizer issues - since it uses threads for execution it will exit the whole process on the first issue - - name: Self check - if: false - run: | - selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=file-total -D__GNUC__ --error-exitcode=0 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --inconclusive --enable=style,performance,portability,warning,missingInclude,information --exception-handling --debug-warnings --check-level=exhaustive" - selfcheck_options="$selfcheck_options --executor=thread" - cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2" - gui_options="-DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt" - gui_options="$gui_options --suppress=autoNoType:*/moc_*.cpp --suppress=symbolDatabaseWarning:*/moc_*.cpp" - ec=0 - ./cmake.output/bin/cppcheck $selfcheck_options externals || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json frontend || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json -Ifrontend cli || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json --enable=internal lib || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options $gui_options --addon=naming.json --suppress=constVariablePointer:*/moc_*.cpp -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli -Ifrontend test/*.cpp || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli tools/dmake/*.cpp || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options $gui_options -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage || ec=1 - exit $ec diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml index 9a6026aa25b..3e4a02dbb48 100644 --- a/.github/workflows/valgrind.yml +++ b/.github/workflows/valgrind.yml @@ -51,7 +51,13 @@ jobs: - name: Run valgrind run: | ec=0 - valgrind --error-limit=yes --leak-check=full --num-callers=50 --show-reachable=yes --track-origins=yes --suppressions=valgrind/testrunner.supp --gen-suppressions=all --log-fd=9 --error-exitcode=42 ./testrunner TestGarbage TestOther TestSimplifyTemplate 9>memcheck.log || ec=1 + # disabled all tests invoking processes because the child processes fail with still reachable memory. + # some of the TestProcessExecutor* tests are also extremely slow. + excluded_tests="TestProcessExecutorFS \ + TestProcessExecutorFiles \ + TestSuppressions::suppressionsSettingsProcessesFiles \ + TestSuppressions::suppressionsSettingsProcessesFS" + valgrind --error-limit=yes --leak-check=full --num-callers=50 --show-reachable=yes --track-origins=yes --suppressions=valgrind/testrunner.supp --gen-suppressions=all -s --log-fd=9 --error-exitcode=42 ./testrunner -t -x $excluded_tests 9>memcheck.log || ec=1 cat memcheck.log exit $ec # TODO: debuginfod.ubuntu.com is currently not responding to any requests causing it to run into a 40(!) minute timeout diff --git a/.pylintrc b/.pylintrc index 9b14fa2d00e..0ca3480c06f 100644 --- a/.pylintrc +++ b/.pylintrc @@ -63,4 +63,3 @@ reports=no ignored-classes=SQLObject,_socketobject [MASTER] init-hook='import sys; sys.path.append("./addons")' -suggestion-mode=yes diff --git a/.selfcheck_suppressions b/.selfcheck_suppressions index b6b43bdcb2a..f21492e783a 100644 --- a/.selfcheck_suppressions +++ b/.selfcheck_suppressions @@ -3,18 +3,53 @@ missingIncludeSystem checkersReport # warnings in Qt generated code we cannot fix +funcArgNamesDifferentUnnamed:*/moc_aboutdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_applicationdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_applicationlist.cpp funcArgNamesDifferent:*/moc_checkthread.cpp +funcArgNamesDifferentUnnamed:*/moc_checkthread.cpp +funcArgNamesDifferentUnnamed:*/moc_codeeditor.cpp funcArgNamesDifferent:*/moc_codeeditstylecontrols.cpp +funcArgNamesDifferentUnnamed:*/moc_codeeditstylecontrols.cpp +funcArgNamesDifferentUnnamed:*/moc_compliancereportdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_codeeditstyledialog.cpp +funcArgNamesDifferentUnnamed:*/moc_fileviewdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_helpdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_libraryaddfunctiondialog.cpp +funcArgNamesDifferentUnnamed:*/moc_librarydialog.cpp +funcArgNamesDifferentUnnamed:*/moc_libraryeditargdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_mainwindow.cpp +funcArgNamesDifferentUnnamed:*/moc_newsuppressiondialog.cpp +funcArgNamesDifferentUnnamed:*/moc_platforms.cpp +funcArgNamesDifferentUnnamed:*/moc_projectfile.cpp +funcArgNamesDifferentUnnamed:*/moc_projectfiledialog.cpp funcArgNamesDifferent:*/moc_resultstree.cpp +funcArgNamesDifferentUnnamed:*/moc_resultstree.cpp funcArgNamesDifferent:*/moc_resultsview.cpp +funcArgNamesDifferentUnnamed:*/moc_resultsview.cpp +funcArgNamesDifferentUnnamed:*/moc_scratchpad.cpp +funcArgNamesDifferentUnnamed:*/moc_settingsdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_statsdialog.cpp +funcArgNamesDifferentUnnamed:*/moc_testcppchecklibrarydata.cpp +funcArgNamesDifferentUnnamed:*/moc_testfilelist.cpp +funcArgNamesDifferentUnnamed:*/moc_testprojectfile.cpp +funcArgNamesDifferentUnnamed:*/moc_testresultstree.cpp +funcArgNamesDifferentUnnamed:*/moc_testtranslationhandler.cpp +funcArgNamesDifferentUnnamed:*/moc_testxmlreportv2.cpp +funcArgNamesDifferentUnnamed:*/moc_threaddetails.cpp funcArgNamesDifferent:*/moc_threadhandler.cpp +funcArgNamesDifferentUnnamed:*/moc_threadhandler.cpp funcArgNamesDifferent:*/moc_threadresult.cpp +funcArgNamesDifferentUnnamed:*/moc_threadresult.cpp +funcArgNamesDifferentUnnamed:*/moc_translationhandler.cpp +funcArgNamesDifferentUnnamed:*/moc_txtreport.cpp naming-varname:*/gui/ui_*.h -functionStatic:*/ui_fileview.h +functionStatic:*/gui/ui_*.h # --debug-warnings suppressions valueFlowBailout valueFlowBailoutIncompleteVar +valueFlowMaxIterations:gui/resultstree.cpp autoNoType:externals/simplecpp/simplecpp.cpp autoNoType:cli/*.cpp autoNoType:lib/*.cpp @@ -36,5 +71,11 @@ invalidPrintfArgType_sint:externals/tinyxml2/tinyxml2.h naming-privateMemberVariable:externals/tinyxml2/tinyxml2.h functionStatic:externals/tinyxml2/tinyxml2.cpp funcArgNamesDifferent:externals/tinyxml2/tinyxml2.cpp +funcArgNamesDifferentUnnamed:externals/tinyxml2/tinyxml2.cpp +funcArgNamesDifferentUnnamed:externals/tinyxml2/tinyxml2.h nullPointerRedundantCheck:externals/tinyxml2/tinyxml2.cpp +knownConditionTrueFalse:externals/tinyxml2/tinyxml2.cpp useStlAlgorithm:externals/simplecpp/simplecpp.cpp +funcArgNamesDifferentUnnamed:externals/simplecpp/simplecpp.h +missingMemberCopy:externals/simplecpp/simplecpp.h +shadowFunction:externals/simplecpp/simplecpp.h diff --git a/.selfcheck_unused_suppressions b/.selfcheck_unused_suppressions index ce685d8ab10..5da7c225dfa 100644 --- a/.selfcheck_unused_suppressions +++ b/.selfcheck_unused_suppressions @@ -1,8 +1,8 @@ +# should not be reported - see #13387 +checkersReport + # we are not using all methods of their interfaces unusedFunction:externals/*/* -# usage is disabled -unusedFunction:lib/symboldatabase.cpp - # Q_OBJECT functions which are not called in our code unusedFunction:cmake.output.notest/gui/cppcheck-gui_autogen/*/moc_aboutdialog.cpp diff --git a/AUTHORS b/AUTHORS index c3472d7e2a2..04cff0891a9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -105,6 +105,7 @@ Debrard Sebastien Deepak Gupta Degen's Regens dencat +Devansh Varshney Diego de las Heras Dirk Jagdmann Dirk Mueller @@ -131,6 +132,7 @@ Felix Faber Felix Geyer Felix Passenberg Felix Wolff +Florian Mueller Florin Iucha flovent Francesc Elies @@ -139,6 +141,7 @@ Frank Winklmeier Frank Zingsheim Frederik Schwarzer fu7mu4 +Gaël Bonithon Galimov Albert Garrett Bodily Gary Leutheuser @@ -192,6 +195,7 @@ Jim Zhou jlguardi Joel Johnson Johan Bertrand +Johan Crone Johan Samuelson John Marshall John-Paul Ore @@ -251,6 +255,7 @@ Maarten van der Schrieck Maksim Derbasov Malcolm Parsons Marc-Antoine Perennou +Marcel Petrick Marcel Raad Marco Trevisan Marek Zmysłowski @@ -277,6 +282,7 @@ Matthias Schmieder Matt Johnson Maurice Gilden Mavik +Melroy van den Berg Michael Drake Michael Løiten Miika-Petteri Matikainen @@ -299,6 +305,7 @@ Nicolás Alvarez Nicolas Le Cam Nilesh Kumar Ogawa KenIchi +Ola Söder Oleksandr Labetskyi Oleksandr Redko Oliver Schode @@ -341,6 +348,7 @@ Robert Habrich Robert Morin Roberto Martelloni Robert Reif +Robin Getz rofl0r Roman Zaytsev Borisovich Ronald Hiemstra @@ -422,6 +430,7 @@ Vesa Pikki Ville-Pekka Vahteala Ville Skyttä Vincent Le Garrec +Vít Kučera Vladimir Petrigo Wang Haoyu Wang Yang diff --git a/CMakeLists.txt b/CMakeLists.txt index 3595154f7ae..3c037a10b36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.13) -project(Cppcheck VERSION 2.18.99 LANGUAGES CXX) +cmake_minimum_required(VERSION 3.22) +project(Cppcheck VERSION 2.20.99 LANGUAGES CXX) include(cmake/options.cmake) @@ -11,11 +11,13 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(GNUInstallDirs) +include(CTest) include(cmake/compilerCheck.cmake) include(cmake/versions.cmake) include(cmake/findDependencies.cmake) include(cmake/compileroptions.cmake) +include(cmake/includechecks.cmake) include(cmake/compilerDefinitions.cmake) include(cmake/buildFiles.cmake) if(BUILD_GUI) @@ -77,10 +79,6 @@ endif() # - Cygwin handling # - MinGW handling -if(BUILD_TESTS) - enable_testing() -endif() - add_custom_target(copy_cfg ALL ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/cfg" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/cfg" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 715a913b6fc..09e88f021e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ These are some guidelines *any* contributor should follow. They will help to mak ## Code Changes -Code contributions are handled via GitHub pull requests: https://github.com/danmar/cppcheck/pulls. +Code contributions are handled via GitHub pull requests: https://github.com/cppcheck-opensource/cppcheck/pulls. If you file a pull request you might not get a reply immediately. We are a very small team and it might not fit in the current scope or time. @@ -18,7 +18,7 @@ Also after you filed a pull request please be ready to reply to questions and fe Please do not be discouraged if your change was rejected or if the review process might not have been as smooth as it could have been. -Each change should be accompanied with a unit ([C++](https://github.com/danmar/cppcheck/tree/main/test)) or integration ([Python](https://github.com/danmar/cppcheck/tree/main/test/cli)) test to ensure that it doesn't regress with future changes. Negative tests (testing the opposite behavior) would be favorable but might not be required or might already exist depending on the change. Tests which introduce `TODO_ASSERT_` or `@pytest.mark.skip`/`@pytest.mark.xfail` should have tickets filed. +Each change should be accompanied with a unit ([C++](https://github.com/cppcheck-opensource/cppcheck/tree/main/test)) or integration ([Python](https://github.com/cppcheck-opensource/cppcheck/tree/main/test/cli)) test to ensure that it doesn't regress with future changes. Negative tests (testing the opposite behavior) would be favorable but might not be required or might already exist depending on the change. Tests which introduce `TODO_ASSERT_` or `@pytest.mark.skip`/`@pytest.mark.xfail` should have tickets filed. If the change is modifying existing behavior (i.e. adding a feature or fixing a bug) it should be accompanied by an issue in the [tracker](https://trac.cppcheck.net) (if you do not have access we can assist with that). Depending on the change it might also warrant an entry in `releasenotes.txt`. @@ -56,7 +56,7 @@ So if you start spending a lot of time on these, you might want to get into touc ## simplecpp -At its core Cppcheck is relying on the `simplecpp` library which is a preprocessor implementation which was spun off into its [separate project](https://github.com/danmar/simplecpp) with its own [bug tracker](https://github.com/danmar/simplecpp/issues). This is also maintained by the Cppcheck developers and contributions to it are also welcome. +At its core Cppcheck is relying on the `simplecpp` library which is a preprocessor implementation which was spun off into its [separate project](https://github.com/cppcheck-opensource/simplecpp) with its own [bug tracker](https://github.com/cppcheck-opensource/simplecpp/issues). This is also maintained by the Cppcheck developers and contributions to it are also welcome. ## Translations diff --git a/Makefile b/Makefile index 22dd52216b2..684e79179cf 100644 --- a/Makefile +++ b/Makefile @@ -155,6 +155,15 @@ else ifneq ($(HAVE_RULES),) $(error invalid HAVE_RULES value '$(HAVE_RULES)') endif +# older make versions do not support # in $(shell) and newer ones handle the escape sequence literally +REQUIRE_ESCAPE=$(shell echo "\#define DEF" | $(CXX) -c -xc - 2> /dev/null && echo "1" || echo "0") +ifeq ($(REQUIRE_ESCAPE),1) + HAVE_EXECINFO_H=$(shell echo "\#include " | $(CXX) -c -xc - 2> /dev/null && echo "1" || echo "0") +else + HAVE_EXECINFO_H=$(shell echo "#include " | $(CXX) -c -xc - 2> /dev/null && echo "1" || echo "0") +endif +override CPPFLAGS += -DHAVE_EXECINFO_H=$(HAVE_EXECINFO_H) + override CXXFLAGS += $(CXXOPTS) override CPPFLAGS += $(CPPOPTS) override LDFLAGS += $(LDOPTS) @@ -199,7 +208,6 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/addoninfo.o \ $(libcppdir)/analyzerinfo.o \ $(libcppdir)/astutils.o \ - $(libcppdir)/check.o \ $(libcppdir)/check64bit.o \ $(libcppdir)/checkassert.o \ $(libcppdir)/checkautovariables.o \ @@ -212,6 +220,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/checkersreport.o \ $(libcppdir)/checkexceptionsafety.o \ $(libcppdir)/checkfunctions.o \ + $(libcppdir)/checkimpl.o \ $(libcppdir)/checkinternal.o \ $(libcppdir)/checkio.o \ $(libcppdir)/checkleakautovar.o \ @@ -219,6 +228,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/checknullpointer.o \ $(libcppdir)/checkother.o \ $(libcppdir)/checkpostfixoperator.o \ + $(libcppdir)/checks.o \ $(libcppdir)/checksizeof.o \ $(libcppdir)/checkstl.o \ $(libcppdir)/checkstring.o \ @@ -294,6 +304,7 @@ TESTOBJ = test/fixture.o \ test/testbufferoverrun.o \ test/testcharvar.o \ test/testcheck.o \ + test/testcheckersreport.o \ test/testclangimport.o \ test/testclass.o \ test/testcmdlineparser.o \ @@ -472,13 +483,13 @@ check-nonneg: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkers.h lib/checkuninitvar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyzers.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkuninitvar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/regex.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyzers.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp -$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/tokenize.cpp -$(libcppdir)/symboldatabase.o: lib/symboldatabase.cpp lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/keywords.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/symboldatabase.o: lib/symboldatabase.cpp lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/keywords.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/symboldatabase.cpp $(libcppdir)/addoninfo.o: lib/addoninfo.cpp externals/picojson/picojson.h lib/addoninfo.h lib/config.h lib/json.h lib/path.h lib/standards.h lib/utils.h @@ -487,31 +498,28 @@ $(libcppdir)/addoninfo.o: lib/addoninfo.cpp externals/picojson/picojson.h lib/ad $(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/mathlib.h lib/path.h lib/platform.h lib/standards.h lib/utils.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/analyzerinfo.cpp -$(libcppdir)/astutils.o: lib/astutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/config.h lib/errortypes.h lib/findtoken.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h +$(libcppdir)/astutils.o: lib/astutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/findtoken.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/astutils.cpp -$(libcppdir)/check.o: lib/check.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check.cpp - -$(libcppdir)/check64bit.o: lib/check64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/check64bit.o: lib/check64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check64bit.cpp -$(libcppdir)/checkassert.o: lib/checkassert.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkassert.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkassert.o: lib/checkassert.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkassert.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkassert.cpp -$(libcppdir)/checkautovariables.o: lib/checkautovariables.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkautovariables.o: lib/checkautovariables.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkautovariables.cpp -$(libcppdir)/checkbool.o: lib/checkbool.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbool.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkbool.o: lib/checkbool.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbool.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbool.cpp -$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h lib/xml.h +$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/checkimpl.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbufferoverrun.cpp -$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h lib/xml.h +$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkclass.cpp -$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkcondition.h lib/checkers.h lib/checkother.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkcondition.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkcondition.cpp $(libcppdir)/checkers.o: lib/checkers.cpp lib/checkers.h lib/config.h @@ -520,73 +528,79 @@ $(libcppdir)/checkers.o: lib/checkers.cpp lib/checkers.h lib/config.h $(libcppdir)/checkersidmapping.o: lib/checkersidmapping.cpp lib/checkers.h lib/config.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersidmapping.cpp -$(libcppdir)/checkersreport.o: lib/checkersreport.cpp lib/addoninfo.h lib/checkers.h lib/checkersreport.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h +$(libcppdir)/checkersreport.o: lib/checkersreport.cpp lib/addoninfo.h lib/checkers.h lib/checkersreport.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersreport.cpp -$(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkexceptionsafety.cpp -$(libcppdir)/checkfunctions.o: lib/checkfunctions.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkfunctions.o: lib/checkfunctions.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/checkimpl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkfunctions.cpp -$(libcppdir)/checkinternal.o: lib/checkinternal.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkinternal.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkimpl.o: lib/checkimpl.cpp lib/addoninfo.h lib/checkers.h lib/checkimpl.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkimpl.cpp + +$(libcppdir)/checkinternal.o: lib/checkinternal.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkinternal.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkinternal.cpp -$(libcppdir)/checkio.o: lib/checkio.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkio.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkio.o: lib/checkio.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkio.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkio.cpp -$(libcppdir)/checkleakautovar.o: lib/checkleakautovar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkleakautovar.o: lib/checkleakautovar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkleakautovar.cpp -$(libcppdir)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkmemoryleak.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkmemoryleak.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkmemoryleak.cpp -$(libcppdir)/checknullpointer.o: lib/checknullpointer.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checknullpointer.o: lib/checknullpointer.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checknullpointer.cpp -$(libcppdir)/checkother.o: lib/checkother.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkother.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkother.o: lib/checkother.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkother.cpp -$(libcppdir)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkpostfixoperator.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkpostfixoperator.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkpostfixoperator.cpp -$(libcppdir)/checksizeof.o: lib/checksizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checksizeof.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checks.o: lib/checks.cpp lib/check.h lib/check64bit.h lib/checkassert.h lib/checkautovariables.h lib/checkbool.h lib/checkbufferoverrun.h lib/checkclass.h lib/checkcondition.h lib/checkexceptionsafety.h lib/checkfunctions.h lib/checkimpl.h lib/checkinternal.h lib/checkio.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/checkother.h lib/checkpostfixoperator.h lib/checks.h lib/checksizeof.h lib/checkstl.h lib/checkstring.h lib/checktype.h lib/checkuninitvar.h lib/checkunusedvar.h lib/checkvaarg.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/standards.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checks.cpp + +$(libcppdir)/checksizeof.o: lib/checksizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checksizeof.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checksizeof.cpp -$(libcppdir)/checkstl.o: lib/checkstl.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/checkstl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/pathanalysis.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkstl.o: lib/checkstl.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/checkstl.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/pathanalysis.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstl.cpp -$(libcppdir)/checkstring.o: lib/checkstring.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkstring.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkstring.o: lib/checkstring.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstring.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstring.cpp -$(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checktype.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checktype.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checktype.cpp -$(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkuninitvar.cpp -$(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h +$(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/astutils.h lib/checkers.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedfunctions.cpp -$(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedvar.cpp -$(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkvaarg.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkvaarg.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkvaarg.cpp -$(libcppdir)/clangimport.o: lib/clangimport.cpp lib/addoninfo.h lib/checkers.h lib/clangimport.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/clangimport.o: lib/clangimport.cpp lib/clangimport.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/clangimport.cpp $(libcppdir)/color.o: lib/color.cpp lib/color.h lib/config.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/color.cpp -$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/clangimport.h lib/color.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h lib/vfvalue.h lib/xml.h +$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checks.h lib/checkunusedfunctions.h lib/clangimport.h lib/color.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/cppcheck.cpp -$(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h +$(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/ctu.cpp -$(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h +$(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/errorlogger.cpp $(libcppdir)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h lib/utils.h @@ -595,13 +609,13 @@ $(libcppdir)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h lib/ $(libcppdir)/findtoken.o: lib/findtoken.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/findtoken.h lib/library.h lib/mathlib.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/findtoken.cpp -$(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueptr.h lib/vfvalue.h +$(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueptr.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/forwardanalyzer.cpp -$(libcppdir)/fwdanalysis.o: lib/fwdanalysis.cpp lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h +$(libcppdir)/fwdanalysis.o: lib/fwdanalysis.cpp lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/fwdanalysis.cpp -$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h +$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/importproject.cpp $(libcppdir)/infer.o: lib/infer.cpp lib/calculate.h lib/config.h lib/errortypes.h lib/infer.h lib/mathlib.h lib/smallvector.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueptr.h lib/vfvalue.h @@ -625,328 +639,331 @@ $(libcppdir)/pathanalysis.o: lib/pathanalysis.cpp lib/astutils.h lib/config.h li $(libcppdir)/pathmatch.o: lib/pathmatch.cpp lib/config.h lib/path.h lib/pathmatch.h lib/standards.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/pathmatch.cpp -$(libcppdir)/platform.o: lib/platform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/mathlib.h lib/path.h lib/platform.h lib/standards.h lib/xml.h +$(libcppdir)/platform.o: lib/platform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/mathlib.h lib/path.h lib/platform.h lib/standards.h lib/utils.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/platform.cpp -$(libcppdir)/preprocessor.o: lib/preprocessor.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h +$(libcppdir)/preprocessor.o: lib/preprocessor.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/preprocessor.cpp -$(libcppdir)/programmemory.o: lib/programmemory.cpp lib/addoninfo.h lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h +$(libcppdir)/programmemory.o: lib/programmemory.cpp lib/addoninfo.h lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/programmemory.cpp $(libcppdir)/regex.o: lib/regex.cpp lib/config.h lib/regex.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/regex.cpp -$(libcppdir)/reverseanalyzer.o: lib/reverseanalyzer.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/platform.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueptr.h lib/vfvalue.h +$(libcppdir)/reverseanalyzer.o: lib/reverseanalyzer.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueptr.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/reverseanalyzer.cpp -$(libcppdir)/sarifreport.o: lib/sarifreport.cpp externals/picojson/picojson.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/platform.h lib/sarifreport.h lib/settings.h lib/standards.h lib/utils.h +$(libcppdir)/sarifreport.o: lib/sarifreport.cpp externals/picojson/picojson.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/sarifreport.h lib/settings.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/sarifreport.cpp -$(libcppdir)/settings.o: lib/settings.cpp externals/picojson/picojson.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/utils.h lib/vfvalue.h +$(libcppdir)/settings.o: lib/settings.cpp externals/picojson/picojson.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/settings.cpp $(libcppdir)/standards.o: lib/standards.cpp externals/simplecpp/simplecpp.h lib/config.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/standards.cpp -$(libcppdir)/summaries.o: lib/summaries.cpp lib/addoninfo.h lib/analyzerinfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/summaries.o: lib/summaries.cpp lib/addoninfo.h lib/analyzerinfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/summaries.cpp -$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h +$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/suppressions.cpp -$(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/addoninfo.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/addoninfo.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/templatesimplifier.cpp -$(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h lib/utils.h +$(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/timer.cpp -$(libcppdir)/token.o: lib/token.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/token.o: lib/token.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/valueflow.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/token.cpp -$(libcppdir)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/keywords.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/keywords.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/tokenlist.cpp $(libcppdir)/utils.o: lib/utils.cpp lib/config.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/utils.cpp -$(libcppdir)/vf_analyzers.o: lib/vf_analyzers.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyzers.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h +$(libcppdir)/vf_analyzers.o: lib/vf_analyzers.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyzers.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_analyzers.cpp -$(libcppdir)/vf_common.o: lib/vf_common.cpp lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h +$(libcppdir)/vf_common.o: lib/vf_common.cpp lib/addoninfo.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_common.cpp -$(libcppdir)/vf_settokenvalue.o: lib/vf_settokenvalue.cpp lib/addoninfo.h lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h +$(libcppdir)/vf_settokenvalue.o: lib/vf_settokenvalue.cpp lib/addoninfo.h lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_settokenvalue.cpp $(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/smallvector.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vfvalue.cpp -frontend/frontend.o: frontend/frontend.cpp frontend/frontend.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h +frontend/frontend.o: frontend/frontend.cpp frontend/frontend.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_FE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ frontend/frontend.cpp -cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h lib/xml.h +cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/checks.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp -cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h cli/sehwrapper.h cli/signalhandler.h cli/singleexecutor.h cli/threadexecutor.h externals/picojson/picojson.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/sarifreport.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h +cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h cli/sehwrapper.h cli/signalhandler.h cli/singleexecutor.h cli/threadexecutor.h externals/picojson/picojson.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/sarifreport.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp -cli/executor.o: cli/executor.cpp cli/executor.h lib/addoninfo.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h +cli/executor.o: cli/executor.cpp cli/executor.h lib/addoninfo.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/executor.cpp cli/filelister.o: cli/filelister.cpp cli/filelister.h lib/config.h lib/filesettings.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/filelister.cpp -cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/config.h lib/errortypes.h lib/filesettings.h lib/mathlib.h lib/path.h lib/platform.h lib/standards.h +cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/config.h lib/filesettings.h lib/mathlib.h lib/path.h lib/platform.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/main.cpp -cli/processexecutor.o: cli/processexecutor.cpp cli/executor.h cli/processexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h +cli/processexecutor.o: cli/processexecutor.cpp cli/executor.h cli/processexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/processexecutor.cpp cli/sehwrapper.o: cli/sehwrapper.cpp cli/sehwrapper.h lib/config.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/sehwrapper.cpp -cli/signalhandler.o: cli/signalhandler.cpp cli/signalhandler.h cli/stacktrace.h lib/config.h lib/utils.h +cli/signalhandler.o: cli/signalhandler.cpp cli/signalhandler.h cli/stacktrace.h lib/config.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/signalhandler.cpp -cli/singleexecutor.o: cli/singleexecutor.cpp cli/executor.h cli/singleexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/timer.h lib/utils.h +cli/singleexecutor.o: cli/singleexecutor.cpp cli/executor.h cli/singleexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/timer.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/singleexecutor.cpp cli/stacktrace.o: cli/stacktrace.cpp cli/stacktrace.h lib/config.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/stacktrace.cpp -cli/threadexecutor.o: cli/threadexecutor.cpp cli/executor.h cli/threadexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h +cli/threadexecutor.o: cli/threadexecutor.cpp cli/executor.h cli/threadexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/threadexecutor.cpp -test/fixture.o: test/fixture.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/fixture.h test/helpers.h test/options.h test/redirect.h +test/fixture.o: test/fixture.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/fixture.h test/helpers.h test/options.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/fixture.cpp -test/helpers.o: test/helpers.cpp cli/filelister.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/helpers.h +test/helpers.o: test/helpers.cpp cli/filelister.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/checkers.h lib/config.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/helpers.cpp -test/main.o: test/main.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h test/options.h +test/main.o: test/main.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/main.cpp -test/options.o: test/options.cpp test/options.h +test/options.o: test/options.cpp lib/config.h lib/timer.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/options.cpp -test/test64bit.o: test/test64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/test64bit.o: test/test64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/test64bit.cpp -test/testanalyzerinformation.o: test/testanalyzerinformation.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h lib/xml.h test/fixture.h +test/testanalyzerinformation.o: test/testanalyzerinformation.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h lib/xml.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testanalyzerinformation.cpp -test/testassert.o: test/testassert.cpp lib/addoninfo.h lib/check.h lib/checkassert.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testassert.o: test/testassert.cpp lib/addoninfo.h lib/check.h lib/checkassert.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testassert.cpp -test/testastutils.o: test/testastutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testastutils.o: test/testastutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testastutils.cpp -test/testautovariables.o: test/testautovariables.cpp lib/addoninfo.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testautovariables.o: test/testautovariables.cpp lib/addoninfo.h lib/check.h lib/checkautovariables.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testautovariables.cpp -test/testbool.o: test/testbool.cpp lib/addoninfo.h lib/check.h lib/checkbool.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testbool.o: test/testbool.cpp lib/addoninfo.h lib/check.h lib/checkbool.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testbool.cpp -test/testbufferoverrun.o: test/testbufferoverrun.cpp lib/addoninfo.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testbufferoverrun.o: test/testbufferoverrun.cpp lib/addoninfo.h lib/check.h lib/checkbufferoverrun.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testbufferoverrun.cpp -test/testcharvar.o: test/testcharvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testcharvar.o: test/testcharvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcharvar.cpp -test/testcheck.o: test/testcheck.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/testcheck.o: test/testcheck.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcheck.cpp -test/testclangimport.o: test/testclangimport.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/clangimport.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h +test/testcheckersreport.o: test/testcheckersreport.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h + $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcheckersreport.cpp + +test/testclangimport.o: test/testclangimport.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/clangimport.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclangimport.cpp -test/testclass.o: test/testclass.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testclass.o: test/testclass.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclass.cpp -test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h +test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcmdlineparser.cpp -test/testcolor.o: test/testcolor.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/testcolor.o: test/testcolor.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcolor.cpp -test/testcondition.o: test/testcondition.cpp lib/addoninfo.h lib/check.h lib/checkcondition.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testcondition.o: test/testcondition.cpp lib/addoninfo.h lib/check.h lib/checkcondition.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcondition.cpp -test/testconstructors.o: test/testconstructors.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testconstructors.o: test/testconstructors.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testconstructors.cpp -test/testcppcheck.o: test/testcppcheck.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h +test/testcppcheck.o: test/testcppcheck.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcppcheck.cpp -test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/fixture.h test/helpers.h +test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/xml.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testerrorlogger.cpp -test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkexceptionsafety.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testexceptionsafety.cpp -test/testexecutor.o: test/testexecutor.cpp cli/executor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testexecutor.o: test/testexecutor.cpp cli/executor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testexecutor.cpp -test/testfilelister.o: test/testfilelister.cpp cli/filelister.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/testfilelister.o: test/testfilelister.cpp cli/filelister.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfilelister.cpp -test/testfilesettings.o: test/testfilesettings.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/testfilesettings.o: test/testfilesettings.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfilesettings.cpp -test/testfrontend.o: test/testfrontend.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/testfrontend.o: test/testfrontend.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfrontend.cpp -test/testfunctions.o: test/testfunctions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testfunctions.o: test/testfunctions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkfunctions.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfunctions.cpp -test/testgarbage.o: test/testgarbage.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testgarbage.o: test/testgarbage.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testgarbage.cpp -test/testimportproject.o: test/testimportproject.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h test/fixture.h test/redirect.h +test/testimportproject.o: test/testimportproject.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h test/fixture.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testimportproject.cpp -test/testincompletestatement.o: test/testincompletestatement.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testincompletestatement.o: test/testincompletestatement.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testincompletestatement.cpp -test/testinternal.o: test/testinternal.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkinternal.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testinternal.o: test/testinternal.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkinternal.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testinternal.cpp -test/testio.o: test/testio.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkio.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testio.o: test/testio.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkio.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testio.cpp -test/testleakautovar.o: test/testleakautovar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkleakautovar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testleakautovar.o: test/testleakautovar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkleakautovar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testleakautovar.cpp -test/testlibrary.o: test/testlibrary.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testlibrary.o: test/testlibrary.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testlibrary.cpp -test/testmathlib.o: test/testmathlib.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h +test/testmathlib.o: test/testmathlib.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testmathlib.cpp -test/testmemleak.o: test/testmemleak.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkmemoryleak.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testmemleak.o: test/testmemleak.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkmemoryleak.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testmemleak.cpp -test/testnullpointer.o: test/testnullpointer.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testnullpointer.o: test/testnullpointer.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checknullpointer.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testnullpointer.cpp -test/testoptions.o: test/testoptions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h test/options.h +test/testoptions.o: test/testoptions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testoptions.cpp -test/testother.o: test/testother.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testother.o: test/testother.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testother.cpp -test/testpath.o: test/testpath.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testpath.o: test/testpath.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpath.cpp -test/testpathmatch.o: test/testpathmatch.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/testpathmatch.o: test/testpathmatch.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpathmatch.cpp -test/testplatform.o: test/testplatform.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h lib/xml.h test/fixture.h +test/testplatform.o: test/testplatform.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h lib/xml.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testplatform.cpp -test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkpostfixoperator.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkpostfixoperator.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpostfixoperator.cpp -test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpreprocessor.cpp -test/testprocessexecutor.o: test/testprocessexecutor.cpp cli/executor.h cli/processexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h +test/testprocessexecutor.o: test/testprocessexecutor.cpp cli/executor.h cli/processexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testprocessexecutor.cpp -test/testprogrammemory.o: test/testprogrammemory.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testprogrammemory.o: test/testprogrammemory.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testprogrammemory.cpp test/testregex.o: test/testregex.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testregex.cpp -test/testsarifreport.o: test/testsarifreport.cpp externals/picojson/picojson.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/sarifreport.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testsarifreport.o: test/testsarifreport.cpp externals/picojson/picojson.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/json.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/sarifreport.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsarifreport.cpp -test/testsettings.o: test/testsettings.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testsettings.o: test/testsettings.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsettings.cpp -test/testsimplifytemplate.o: test/testsimplifytemplate.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testsimplifytemplate.o: test/testsimplifytemplate.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifytemplate.cpp -test/testsimplifytokens.o: test/testsimplifytokens.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testsimplifytokens.o: test/testsimplifytokens.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifytokens.cpp -test/testsimplifytypedef.o: test/testsimplifytypedef.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testsimplifytypedef.o: test/testsimplifytypedef.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifytypedef.cpp -test/testsimplifyusing.o: test/testsimplifyusing.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testsimplifyusing.o: test/testsimplifyusing.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifyusing.cpp -test/testsingleexecutor.o: test/testsingleexecutor.cpp cli/executor.h cli/singleexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h +test/testsingleexecutor.o: test/testsingleexecutor.cpp cli/executor.h cli/singleexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsingleexecutor.cpp -test/testsizeof.o: test/testsizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checksizeof.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testsizeof.o: test/testsizeof.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checksizeof.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsizeof.cpp -test/teststandards.o: test/teststandards.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/teststandards.o: test/teststandards.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststandards.cpp -test/teststl.o: test/teststl.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkstl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/teststl.o: test/teststl.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststl.cpp -test/teststring.o: test/teststring.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkstring.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/teststring.o: test/teststring.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkstring.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststring.cpp -test/testsummaries.o: test/testsummaries.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testsummaries.o: test/testsummaries.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/summaries.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsummaries.cpp -test/testsuppressions.o: test/testsuppressions.cpp cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testsuppressions.o: test/testsuppressions.cpp cli/cppcheckexecutor.h cli/executor.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsuppressions.cpp -test/testsymboldatabase.o: test/testsymboldatabase.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testsymboldatabase.o: test/testsymboldatabase.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsymboldatabase.cpp -test/testthreadexecutor.o: test/testthreadexecutor.cpp cli/executor.h cli/threadexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h +test/testthreadexecutor.o: test/testthreadexecutor.cpp cli/executor.h cli/threadexecutor.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testthreadexecutor.cpp -test/testtimer.o: test/testtimer.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/timer.h lib/utils.h test/fixture.h +test/testtimer.o: test/testtimer.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/timer.h lib/utils.h test/fixture.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtimer.cpp -test/testtoken.o: test/testtoken.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testtoken.o: test/testtoken.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtoken.cpp -test/testtokenize.o: test/testtokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testtokenize.o: test/testtokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenize.cpp -test/testtokenlist.o: test/testtokenlist.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testtokenlist.o: test/testtokenlist.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenlist.cpp -test/testtokenrange.o: test/testtokenrange.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testtokenrange.o: test/testtokenrange.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenrange.cpp -test/testtype.o: test/testtype.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checktype.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testtype.o: test/testtype.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checktype.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtype.cpp -test/testuninitvar.o: test/testuninitvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testuninitvar.o: test/testuninitvar.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testuninitvar.cpp -test/testunusedfunctions.o: test/testunusedfunctions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testunusedfunctions.o: test/testunusedfunctions.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedfunctions.cpp -test/testunusedprivfunc.o: test/testunusedprivfunc.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testunusedprivfunc.o: test/testunusedprivfunc.cpp lib/addoninfo.h lib/check.h lib/checkclass.h lib/checkers.h lib/checkimpl.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedprivfunc.cpp -test/testunusedvar.o: test/testunusedvar.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/checkunusedvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testunusedvar.o: test/testunusedvar.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkunusedvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedvar.cpp -test/testutils.o: test/testutils.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h +test/testutils.o: test/testutils.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testutils.cpp -test/testvaarg.o: test/testvaarg.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkvaarg.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h +test/testvaarg.o: test/testvaarg.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/checkimpl.h lib/checkvaarg.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvaarg.cpp -test/testvalueflow.o: test/testvalueflow.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testvalueflow.o: test/testvalueflow.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvalueflow.cpp -test/testvarid.o: test/testvarid.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testvarid.o: test/testvarid.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/regex.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvarid.cpp -test/testvfvalue.o: test/testvfvalue.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h lib/vfvalue.h test/fixture.h +test/testvfvalue.o: test/testvfvalue.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/regex.h lib/settings.h lib/standards.h lib/utils.h lib/vfvalue.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvfvalue.cpp externals/simplecpp/simplecpp.o: externals/simplecpp/simplecpp.cpp externals/simplecpp/simplecpp.h diff --git a/TUNING.md b/TUNING.md index 4643e7d506a..ba1f7f49738 100644 --- a/TUNING.md +++ b/TUNING.md @@ -46,7 +46,7 @@ In our case Clang is mostly faster than GCC. See https://trac.cppcheck.net/ticke ### Use More Advanced Optimizations -By default we enforce the `-O2` optimization level. Even when using the `Release` build type in CMake which defaults to `-O3`. It might be possible that building with `-O3` might yield a perfomance increase. +By default we enforce the `-O2` optimization level. Even when using the `Release` build type in CMake which defaults to `-O3`. It might be possible that building with `-O3` might yield a performance increase. There are also no additional code generation flags provided so the resulting binary can run on any system. You might be able to tune this and apply more optimization which is tailored to the system you will be running the binary on. diff --git a/addons/README.md b/addons/README.md index 8df8229b970..05502f547b6 100644 --- a/addons/README.md +++ b/addons/README.md @@ -4,19 +4,19 @@ Addons are scripts that analyses Cppcheck dump files to check compatibility with ## Supported addons -+ [misra.py](https://github.com/danmar/cppcheck/blob/main/addons/misra.py) - Used to verify compliance with MISRA C 2012 - a proprietary set of guidelines to avoid such questionable code, developed for embedded systems. Since this standard is proprietary, cppcheck does not display error text by specifying only the number of violated rules (for example, [c2012-21.3]). If you want to display full texts for violated rules, you will need to create a text file containing MISRA rules, which you will have to pass when calling the script with `--rule-texts` key. Some examples of rule texts files available in [tests directory](https://github.com/danmar/cppcheck/blob/main/addons/test/misra/). -+ [y2038.py](https://github.com/danmar/cppcheck/blob/main/addons/y2038.py) - Checks code for [year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) safety. See complete description [here](https://github.com/danmar/cppcheck/blob/main/addons/doc/y2038.md). -+ [threadsafety.py](https://github.com/danmar/cppcheck/blob/main/addons/threadsafety.py) ++ [misra.py](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/misra.py) + Used to verify compliance with MISRA C 2012 - a proprietary set of guidelines to avoid such questionable code, developed for embedded systems. Since this standard is proprietary, cppcheck does not display error text by specifying only the number of violated rules (for example, [c2012-21.3]). If you want to display full texts for violated rules, you will need to create a text file containing MISRA rules, which you will have to pass when calling the script with `--rule-texts` key. Some examples of rule texts files available in [tests directory](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/test/misra/). ++ [y2038.py](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/y2038.py) + Checks code for [year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) safety. See complete description [here](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/doc/y2038.md). ++ [threadsafety.py](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/threadsafety.py) Analyse Cppcheck dump files to locate threadsafety issues like static local objects used by multiple threads. -+ [naming.py](https://github.com/danmar/cppcheck/blob/main/addons/naming.py) ++ [naming.py](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/naming.py) Enforces naming conventions across the code. -+ [namingng.py](https://github.com/danmar/cppcheck/blob/main/addons/namingng.py) ++ [namingng.py](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/namingng.py) Enforces naming conventions across the code. Enhanced version with support for type prefixes in variable and function names. -+ [findcasts.py](https://github.com/danmar/cppcheck/blob/main/addons/findcasts.py) ++ [findcasts.py](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/findcasts.py) Locates casts in the code. -+ [misc.py](https://github.com/danmar/cppcheck/blob/main/addons/misc.py) ++ [misc.py](https://github.com/cppcheck-opensource/cppcheck/blob/main/addons/misc.py) Performs miscellaneous checks. ### Other files @@ -68,5 +68,5 @@ This allows you to add additional parameters when calling the script (for exampl When using the graphical interface `cppcheck-gui`, the selection and configuration of addons is carried out on the tab `Addons and tools` in the project settings (`Edit Project File`): -![Screenshot](https://raw.githubusercontent.com/danmar/cppcheck/main/addons/doc/img/cppcheck-gui-addons.png) +![Screenshot](https://raw.githubusercontent.com/cppcheck-opensource/cppcheck/main/addons/doc/img/cppcheck-gui-addons.png) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index dbe36d56a57..06028e2005c 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -274,7 +274,7 @@ class Token: astParent ast parent astOperand1 ast operand1 astOperand2 ast operand2 - orriginalName orriginal name of the token + orriginalName original name of the token valueType type information: container/.. file file name linenr line number @@ -1003,7 +1003,7 @@ def isMatch(self, file, line, message, errorId): and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) and fnmatch(errorId, self.errorId)): return True - # Other Suppression (Globaly set via suppression file or cli command) + # Other Suppression (Globally set via suppression file or cli command) if ((self.fileName is None or fnmatch(file, self.fileName)) and (self.suppressionType is None) and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) diff --git a/addons/misra.py b/addons/misra.py index cea5596d47d..933ef4c2025 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -803,8 +803,7 @@ def get_function_pointer_type(tok): ret += '(' tok = tok.next.next while tok and (tok.str not in '()'): - if tok.varId is None: - ret += ' ' + tok.str + ret += ' ' + tok.str tok = tok.next if (tok is None) or tok.str != ')': return None @@ -2460,20 +2459,38 @@ def get_category(essential_type): if essential_type.split(' ')[0] in ('unsigned', 'signed'): return essential_type.split(' ')[0] return None + for tok in cfg.tokenlist: - if tok.isAssignmentOp: - lhs = getEssentialType(tok.astOperand1) - rhs = getEssentialType(tok.astOperand2) - #print(lhs) - #print(rhs) - if lhs is None or rhs is None: + if not tok.isAssignmentOp: + continue + + lhs = getEssentialType(tok.astOperand1) + rhs = getEssentialType(tok.astOperand2) + if lhs is None or rhs is None: + continue + + find_std = cfg.standards.c if cfg.standards and cfg.standards.c else self.stdversion + + rhs_tok = tok.astOperand2 + rhs_macro_name = rhs_tok.macroName if rhs_tok else None + rhs_spelling = rhs_macro_name if rhs_macro_name in ('true', 'false') else rhs_tok.str + + rhs_is_source_bool_literal = rhs_spelling in ('true', 'false') + rhs_is_source_int_literal_0_1 = rhs_spelling in ('0', '1') + + if lhs == 'bool': + if rhs_is_source_bool_literal: continue - lhs_category = get_category(lhs) - rhs_category = get_category(rhs) - if lhs_category and rhs_category and lhs_category != rhs_category and rhs_category not in ('signed','unsigned'): - self.reportError(tok, 10, 3) - if bitsOfEssentialType(lhs) < bitsOfEssentialType(rhs) and (lhs != "bool" or tok.astOperand2.str not in ('0','1')): - self.reportError(tok, 10, 3) + if find_std == 'c89' and rhs_is_source_int_literal_0_1: + continue + + lhs_category = get_category(lhs) + rhs_category = get_category(rhs) + if lhs_category and rhs_category and lhs_category != rhs_category and rhs_category not in ('signed', 'unsigned'): + self.reportError(tok, 10, 3) + + if bitsOfEssentialType(lhs) < bitsOfEssentialType(rhs): + self.reportError(tok, 10, 3) def misra_10_4(self, data): op = {'+', '-', '*', '/', '%', '&', '|', '^', '+=', '-=', ':'} diff --git a/addons/test/misra/crash10.c b/addons/test/misra/crash10.c index 455d86e57ec..65e3a14ac96 100644 --- a/addons/test/misra/crash10.c +++ b/addons/test/misra/crash10.c @@ -2,7 +2,7 @@ extern uint32_t end; -//#define KEEP // if uncomment this then wont crash +//#define KEEP // if uncomment this then won't crash KEEP static const int32_t ptr_to_end = &end; diff --git a/addons/test/misra/misra-test-c11.c b/addons/test/misra/misra-test-c11.c index 031bc361e5f..aa00b2f0b42 100644 --- a/addons/test/misra/misra-test-c11.c +++ b/addons/test/misra/misra-test-c11.c @@ -2,6 +2,7 @@ // ~/cppcheck/cppcheck --dump misra/misra-test-c11.c --std=c11 // ~/cppcheck/cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra/misra-test-c11.c --std=c11 --platform=unix64 && python3 ../misra.py -verify misra/misra-test-c11.c.dump +#include #include typedef unsigned int UINT_TYPEDEF; @@ -23,3 +24,15 @@ static void misra6_1_fn(void) { struct_with_bitfields s; s.h = 61; } + +static void misra_10_3_c11(void) { + bool b = false; + bool b0 = 0; // 10.3 + bool b1 = 1; // 10.3 + bool bf = false; // no-warning + bool bt = true; // no-warning + b = 0; // 10.3 + b = 1; // 10.3 + b = false; // no-warning + b = true; // no-warning +} diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 743637117a5..6b6f52342aa 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -726,6 +726,10 @@ static void misra_10_3(uint32_t u32a, uint32_t u32b) { const char c = '0'; // no-warning bool b = true; // no-warning uint32_t u = UINT32_C(10); // no-warning + bool b0 = 0; // no-warning + bool b1 = 1; // no-warning + b = 0; // no-warning + b = 1; // no-warning } static void misra_10_4(u32 x, s32 y) { diff --git a/cfg/boost.cfg b/cfg/boost.cfg index d181860f0bc..722c4c83cd7 100644 --- a/cfg/boost.cfg +++ b/cfg/boost.cfg @@ -83,12 +83,12 @@ - + - + - - + + diff --git a/cfg/cairo.cfg b/cfg/cairo.cfg index e077c2fc40d..d766abffc2e 100644 --- a/cfg/cairo.cfg +++ b/cfg/cairo.cfg @@ -21,6 +21,7 @@ + diff --git a/cfg/googletest.cfg b/cfg/googletest.cfg index 36dd8a40669..c32eef7274b 100644 --- a/cfg/googletest.cfg +++ b/cfg/googletest.cfg @@ -29,11 +29,11 @@ - - - - - + + + + + diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg index 722efb6b76b..14cd032945e 100644 --- a/cfg/gtk.cfg +++ b/cfg/gtk.cfg @@ -10,10 +10,24 @@ + + + + + + + + + + + + + + @@ -234,6 +248,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + g_thread_new g_thread_try_new @@ -807,7 +901,6 @@ g_app_info_get_default_for_uri_scheme g_application_new g_application_get_dbus_connection - g_application_get_default g_buffered_input_stream_new g_buffered_output_stream_new g_cancellable_new @@ -910,7 +1003,6 @@ g_zlib_decompressor_new g_object_ref g_object_unref - gtk_widget_destroy g_tree_new @@ -926,6 +1018,17 @@ g_file_attribute_matcher_ref g_file_attribute_matcher_unref + + gtk_window_new + gtk_widget_destroy + gtk_window_destroy + + + + false + + + true @@ -8761,7 +8864,7 @@ false - + @@ -9688,6 +9791,14 @@ false + + + false + + + + false @@ -21130,10 +21241,6 @@ false - - - false - false @@ -21790,6 +21897,13 @@ false + + false + + + + + false @@ -22967,6 +23081,13 @@ + + + + + + + @@ -23079,4 +23200,8 @@ + + + + diff --git a/cfg/libcurl.cfg b/cfg/libcurl.cfg index 381fbb237d7..949b6de0282 100644 --- a/cfg/libcurl.cfg +++ b/cfg/libcurl.cfg @@ -167,7 +167,7 @@ - + diff --git a/cfg/qt.cfg b/cfg/qt.cfg index 00cb66c1909..66f6e78b3b6 100644 --- a/cfg/qt.cfg +++ b/cfg/qt.cfg @@ -2319,10 +2319,28 @@ + + + + + false + + + + + + + + + + false + + + - + false @@ -2338,6 +2356,68 @@ + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + false + + + + + + + false @@ -2346,8 +2426,9 @@ - + false + @@ -2356,17 +2437,11 @@ - - - false - - - - false + @@ -2375,6 +2450,34 @@ + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + diff --git a/cfg/selinux.cfg b/cfg/selinux.cfg index e2d7ac34dc3..31a48c6da5e 100644 --- a/cfg/selinux.cfg +++ b/cfg/selinux.cfg @@ -219,7 +219,7 @@ false - + diff --git a/cfg/std.cfg b/cfg/std.cfg index 84cffb79828..ec5fbb72548 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -3,16 +3,16 @@ - - + + - - - + + + - - + + @@ -1665,7 +1665,7 @@ false - + @@ -1929,7 +1929,7 @@ false - + @@ -2255,7 +2255,7 @@ false - + @@ -3993,7 +3993,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -4100,7 +4100,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -4121,7 +4121,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -4411,7 +4411,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + @@ -4444,7 +4444,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + @@ -4861,7 +4861,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -4911,7 +4911,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -5044,7 +5044,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -5433,7 +5433,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -7130,6 +7130,16 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + + + + + + + + + false + @@ -7137,6 +7147,13 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + + + + + + false + @@ -8734,7 +8751,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init false - + @@ -8742,7 +8759,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init false - + @@ -9009,6 +9026,16 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + + + + + + diff --git a/cfg/windows.cfg b/cfg/windows.cfg index 343e12b3906..6a0bd111afa 100644 --- a/cfg/windows.cfg +++ b/cfg/windows.cfg @@ -3504,7 +3504,7 @@ HFONT CreateFont( - + @@ -3559,7 +3559,7 @@ HFONT CreateFont( - + @@ -4120,7 +4120,7 @@ HFONT CreateFont( - + @@ -5595,7 +5595,7 @@ HFONT CreateFont( arg1 false - + @@ -5963,7 +5963,7 @@ HFONT CreateFont( - + @@ -6009,7 +6009,7 @@ HFONT CreateFont( - + @@ -7191,7 +7191,7 @@ HFONT CreateFont( - + @@ -13345,9 +13345,9 @@ HFONT CreateFont( - - - + + + diff --git a/cfg/wxwidgets.cfg b/cfg/wxwidgets.cfg index e09b19e15af..9dea60761d1 100644 --- a/cfg/wxwidgets.cfg +++ b/cfg/wxwidgets.cfg @@ -7253,6 +7253,15 @@ This function is deprecated, use 'wxPGProperty::GetValueAsString()' instead. + + + + false + + + + + @@ -10352,6 +10361,14 @@ + + + false + + + + + false @@ -11384,6 +11401,12 @@ + + + false + + + @@ -11680,7 +11703,8 @@ - + + false @@ -12503,7 +12527,8 @@ - + + false @@ -15807,7 +15832,8 @@ wxItemKind kind = wxITEM_NORMAL) --> - + + false @@ -16097,6 +16123,30 @@ wxItemKind kind = wxITEM_NORMAL) --> + + + + false + + + + + + + + false + + + + + + + + false + + + + false @@ -16115,7 +16165,9 @@ wxItemKind kind = wxITEM_NORMAL) --> - + + + false @@ -17023,12 +17075,28 @@ wxItemKind kind = wxITEM_NORMAL) --> + - + + false + + + + false + + + + + + + + false + + diff --git a/clang-tidy.md b/clang-tidy.md index 72df0375ca1..f00a39cde12 100644 --- a/clang-tidy.md +++ b/clang-tidy.md @@ -130,6 +130,10 @@ Does not improve the readability. `modernize-use-designated-initializers`
`readability-enum-initial-value`
`modernize-use-trailing-return-type`
+`misc-unconventional-assign-operator`
+`bugprone-throwing-static-initialization`
+`bugprone-command-processor`
+`misc-multiple-inheritance`
To be evaluated (need to remove exclusion). @@ -156,6 +160,22 @@ These apply to codebases which use later standards then C++11 (C++17 is used whe We are not interested in this. +`readability-redundant-parentheses`
+ +Reports false positives - see https://github.com/llvm/llvm-project/issues/164125. + +`readability-inconsistent-ifelse-braces`
+ +The suggestions are too intrusive. + +`modernize-avoid-c-style-cast`
+ +Currently flags functional casts - see https://github.com/llvm/llvm-project/issues/186784. + +`misc-use-internal-linkage.AnalyzeTypes`
+ +Adding anonymous namespaces requires identation which is too instrusive right now. Would require changes to our fomatting configuration. + ### Disabled for performance reasons `portability-std-allocator-const`
@@ -180,7 +200,7 @@ We are currently using our own `naming.json` to enforce naming schemes. Also dis `portability-simd-intrinsics`
-We are not using SIMD instructions and it suggests to use `std::experiemental::` features which might not be commonly available. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. +We are not using SIMD instructions and it suggests to use `std::experimental::` features which might not be commonly available. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. `modernize-macro-to-enum`
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 2664a29a65d..f63f3291849 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -1,4 +1,3 @@ - file(GLOB hdrs "*.h") file(GLOB srcs "*.cpp") file(GLOB mainfile "main.cpp") diff --git a/cli/cli.vcxproj b/cli/cli.vcxproj index 5d4ee25b0e3..05d1cf2916d 100644 --- a/cli/cli.vcxproj +++ b/cli/cli.vcxproj @@ -89,7 +89,7 @@ true ProgramDatabase Disabled - CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level4 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 @@ -118,7 +118,7 @@ true ProgramDatabase Disabled - CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level4 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 @@ -146,7 +146,7 @@ ..\lib;..\frontend;..\externals;..\externals\picojson;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) false MaxSpeed - CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;NDEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;NDEBUG;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDLL Level4 AnySuitable @@ -184,7 +184,7 @@ ..\lib;..\frontend;..\externals;..\externals\picojson;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) false MaxSpeed - CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;NDEBUG;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;NDEBUG;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDLL Level4 AnySuitable diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 2a07fecf219..27cfe08d871 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "addoninfo.h" #include "check.h" +#include "checks.h" #include "checkers.h" #include "color.h" #include "config.h" @@ -36,14 +37,12 @@ #include "settings.h" #include "standards.h" #include "suppressions.h" -#include "timer.h" #include "utils.h" #include "frontend.h" #include #include -#include #include #include // EXIT_FAILURE #include @@ -77,9 +76,7 @@ static bool addFilesToList(const std::string& fileList, std::vector files = &infile; } std::string fileName; - // cppcheck-suppress accessMoved - FP while (std::getline(*files, fileName)) { // next line - // cppcheck-suppress accessMoved - FP if (!fileName.empty()) { pathNames.emplace_back(std::move(fileName)); } @@ -93,7 +90,6 @@ static bool addIncludePathsToList(const std::string& fileList, std::list fileSettings; if (!mSettings.fileFilters.empty()) { // filter only for the selected filenames from all project files @@ -226,6 +220,8 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) fileSettings = fileSettingsRef; } + // TODO: de-duplicate + mFileSettings.clear(); frontend::applyLang(fileSettings, mSettings, mEnforcedLang); @@ -266,19 +262,6 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) return false; } - // de-duplicate files - { - auto it = filesResolved.begin(); - while (it != filesResolved.end()) { - const std::string& name = it->path(); - // TODO: log if duplicated files were dropped - filesResolved.erase(std::remove_if(std::next(it), filesResolved.end(), [&](const FileWithDetails& entry) { - return entry.path() == name; - }), filesResolved.end()); - ++it; - } - } - std::list files; if (!mSettings.fileFilters.empty()) { files = filterFiles(mSettings.fileFilters, filesResolved); @@ -292,6 +275,19 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) files = std::move(filesResolved); } + // de-duplicate files + { + auto it = files.begin(); + while (it != files.end()) { + const std::string& absname = it->abspath(); + // TODO: log if duplicated files were dropped + files.erase(std::remove_if(std::next(it), files.end(), [&](const FileWithDetails& entry) { + return entry.abspath() == absname; + }), files.end()); + ++it; + } + } + frontend::applyLang(files, mSettings, mEnforcedLang); // sort the markup last @@ -354,7 +350,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a return Result::Fail; if (argc <= 1) { - printHelp(mSettings.premium); + printHelp(); return Result::Exit; } @@ -364,9 +360,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a if (std::strcmp(argv[i], "--doc") == 0) { std::ostringstream doc; // Get documentation.. - for (const Check * it : Check::instances()) { - const std::string& name(it->name()); - const std::string info(it->classInfo()); + for (const Check * const c : CheckInstances::get()) { + const std::string& name(c->name()); + const std::string info(c->classInfo()); if (!name.empty() && !info.empty()) doc << "## " << name << " ##\n" << info << "\n"; @@ -389,7 +385,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a // Print help if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { - printHelp(mSettings.premium); + printHelp(); return Result::Exit; } @@ -407,8 +403,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } - bool def = false; - bool maxconfigs = false; bool debug = false; bool inputAsFilter = false; // set by: --file-filter=+ @@ -421,7 +415,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a std::vector lookupPaths{ Path::getCurrentPath(), // TODO: do we want to look in CWD? - Path::getPathFromFilename(argv[0]) + Path::getPathFromFilename(mSettings.exename), }; bool executorAuto = true; @@ -457,8 +451,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a if (!mSettings.userDefines.empty()) mSettings.userDefines += ";"; mSettings.userDefines += define; - - def = true; } // -E @@ -626,6 +618,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.cppHeaderProbe = true; } + else if (std::strcmp(argv[i], "--debug-analyzerinfo") == 0) + mSettings.debugainfo = true; + else if (std::strcmp(argv[i], "--debug-ast") == 0) mSettings.debugast = true; @@ -637,6 +632,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strcmp(argv[i], "--debug-ignore") == 0) mSettings.debugignore = true; + else if (std::strcmp(argv[i], "--debug-ipc") == 0) + mSettings.debugipc = true; + // Show --debug output after the first simplifications else if (std::strcmp(argv[i], "--debug") == 0 || std::strcmp(argv[i], "--debug-normal") == 0) @@ -758,6 +756,15 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } + else if (std::strncmp(argv[i], "--exitcode-suppress=", 20) == 0) { + const std::string suppression = argv[i]+20; + const std::string errmsg(mSuppressions.nofail.addSuppressionLine(suppression)); + if (!errmsg.empty()) { + mLogger.printError(errmsg); + return Result::Fail; + } + } + // Filter errors else if (std::strncmp(argv[i], "--exitcode-suppressions=", 24) == 0) { // exitcode-suppressions=filename.txt @@ -801,8 +808,10 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } // Force checking of files that have "too many" configurations - else if (std::strcmp(argv[i], "-f") == 0 || std::strcmp(argv[i], "--force") == 0) + else if (std::strcmp(argv[i], "-f") == 0 || std::strcmp(argv[i], "--force") == 0) { mSettings.force = true; + mSettings.maxConfigsOption = Settings::maxConfigsNotAssigned; + } else if (std::strcmp(argv[i], "--fsigned-char") == 0) defaultSign = 's'; @@ -974,9 +983,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a return Result::Fail; } - mSettings.maxConfigs = tmp; + mSettings.maxConfigsOption = tmp; mSettings.force = false; - maxconfigs = true; } // max ctu depth @@ -1119,7 +1127,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a "misra-c++-2023", "misra-cpp-2023", "bughunting", - "safety", // TODO: deprecate in favor of the regular --saftey/--no-safety + "safety", // TODO: deprecate in favor of the regular --safety/--no-safety + "safety-profiles", "debug-progress"}; // valid options --premium-..= const std::set valid2{ @@ -1137,12 +1146,17 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.premiumArgs += " "; const std::string p(argv[i] + 10); const std::string p2(p.find('=') != std::string::npos ? p.substr(0, p.find('=')) : ""); - const bool isCodingStandard = startsWith(p, "autosar") || startsWith(p,"cert-") || startsWith(p,"misra-"); + const bool isCodingStandard = startsWith(p, "autosar") || startsWith(p,"cert-") || startsWith(p,"misra-") || p == "safety-profiles"; const std::string p3(endsWith(p,":all") && isCodingStandard ? p.substr(0,p.rfind(':')) : p); if (!valid.count(p3) && !valid2.count(p2)) { mLogger.printError("invalid --premium option '" + (p2.empty() ? p : p2) + "'."); return Result::Fail; } + if (p2 == "cert-c-int-precision") { + int tmp; + if (!parseNumberArg(argv[i], 31, tmp, true)) + return Result::Fail; + } mSettings.premiumArgs += "--" + p; if (isCodingStandard) { // All checkers related to the coding standard should be enabled. The coding standards @@ -1160,7 +1174,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a return Result::Fail; } - mSettings.checkAllConfigurations = false; // Can be overridden with --max-configs or --force std::string projectFile = argv[i]+10; projectType = project.import(projectFile, &mSettings, &mSuppressions); if (projectType == ImportProject::Type::CPPCHECK_GUI) { @@ -1187,7 +1200,11 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } } - if (projectType == ImportProject::Type::VS_SLN || projectType == ImportProject::Type::VS_VCXPROJ) { + if (projectType == ImportProject::Type::COMPILE_DB) + mSettings.maxConfigsProject = 1; + if (projectType == ImportProject::Type::VS_SLN || + projectType == ImportProject::Type::VS_SLNX || + projectType == ImportProject::Type::VS_VCXPROJ) { mSettings.libraries.emplace_back("windows"); } for (const auto &error : project.errors) @@ -1213,7 +1230,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mLogger.printError("--project-configuration parameter is empty."); return Result::Fail; } - if (projectType != ImportProject::Type::VS_SLN && projectType != ImportProject::Type::VS_VCXPROJ) { + if (projectType != ImportProject::Type::VS_SLN && + projectType != ImportProject::Type::VS_SLNX && + projectType != ImportProject::Type::VS_VCXPROJ) { mLogger.printError("--project-configuration has no effect - no Visual Studio project provided."); return Result::Fail; } @@ -1293,7 +1312,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } std::string regex_err; - auto regex = Regex::create(rule.pattern, regex_err); + auto regex = Regex::create(rule.pattern, Regex::Engine::Pcre, regex_err); if (!regex) { mLogger.printError("failed to compile rule pattern '" + rule.pattern + "' (" + regex_err + ")."); return Result::Fail; @@ -1350,6 +1369,16 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } } + else if (std::strcmp(subname, "engine") == 0) { + const char * const engine = empty_if_null(subtext); + if (std::strcmp(engine, "pcre") == 0) { + rule.engine = Regex::Engine::Pcre; + } + else { + mLogger.printError(std::string("unknown regex engine '") + engine + "'."); + return Result::Fail; + } + } else { mLogger.printError("unable to load rule-file '" + ruleFile + "' - unknown element '" + subname + "' encountered in 'rule'."); return Result::Fail; @@ -1377,7 +1406,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } std::string regex_err; - auto regex = Regex::create(rule.pattern, regex_err); + auto regex = Regex::create(rule.pattern, rule.engine, regex_err); if (!regex) { mLogger.printError("unable to load rule-file '" + ruleFile + "' - pattern '" + rule.pattern + "' failed to compile (" + regex_err + ")."); return Result::Fail; @@ -1409,17 +1438,17 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strncmp(argv[i], "--showtime=", 11) == 0) { const std::string showtimeMode = argv[i] + 11; if (showtimeMode == "file") - mSettings.showtime = SHOWTIME_MODES::SHOWTIME_FILE; + mSettings.showtime = Settings::ShowTime::FILE; else if (showtimeMode == "file-total") - mSettings.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL; + mSettings.showtime = Settings::ShowTime::FILE_TOTAL; else if (showtimeMode == "summary") - mSettings.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY; + mSettings.showtime = Settings::ShowTime::SUMMARY; else if (showtimeMode == "top5_file") - mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE; + mSettings.showtime = Settings::ShowTime::TOP5_FILE; else if (showtimeMode == "top5_summary") - mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY; + mSettings.showtime = Settings::ShowTime::TOP5_SUMMARY; else if (showtimeMode == "none") - mSettings.showtime = SHOWTIME_MODES::SHOWTIME_NONE; + mSettings.showtime = Settings::ShowTime::NONE; else if (showtimeMode.empty()) { mLogger.printError("no mode provided for --showtime"); return Result::Fail; @@ -1591,14 +1620,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a substituteTemplateFormatStatic(mSettings.templateFormat, !mSettings.outputFile.empty()); substituteTemplateLocationStatic(mSettings.templateLocation, !mSettings.outputFile.empty()); - if (mSettings.force || maxconfigs) - mSettings.checkAllConfigurations = true; - - if (mSettings.force) - mSettings.maxConfigs = INT_MAX; - else if ((def || mSettings.preprocessOnly) && !maxconfigs) - mSettings.maxConfigs = 1U; - if (debug) { mSettings.debugnormal = true; mSettings.debugvalueflow = true; @@ -1656,7 +1677,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.platform.defaultSign = defaultSign; if (!mSettings.analyzeAllVsConfigs) { - if (projectType != ImportProject::Type::VS_SLN && projectType != ImportProject::Type::VS_VCXPROJ) { + if (projectType != ImportProject::Type::VS_SLN && + projectType != ImportProject::Type::VS_SLNX && + projectType != ImportProject::Type::VS_VCXPROJ) { if (mAnalyzeAllVsConfigsSetOnCmdLine) { mLogger.printError("--no-analyze-all-vs-configs has no effect - no Visual Studio project provided."); return Result::Fail; @@ -1711,13 +1734,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a return Result::Success; } -void CmdLineParser::printHelp(bool premium) const +void CmdLineParser::printHelp() const { - // TODO: fetch URL from config like product name? - const std::string manualUrl(premium ? - "https://files.cppchecksolutions.com/manual.pdf" : - "https://cppcheck.sourceforge.io/manual.pdf"); - std::ostringstream oss; // TODO: display product name oss << "Cppcheck - A tool for static C/C++ code analysis\n" @@ -1807,6 +1825,9 @@ void CmdLineParser::printHelp(bool premium) const " provided. Note that your operating system can modify\n" " this value, e.g. '256' can become '0'.\n" " --errorlist Print a list of all the error messages in XML format.\n" + " --exitcode-suppress=\n" + " Used to specify an error ID which should not result in\n" + " a non-zero exitcode." " --exitcode-suppressions=\n" " Used when certain messages should be displayed but\n" " should not cause a non-zero exitcode.\n" @@ -1837,9 +1858,13 @@ void CmdLineParser::printHelp(bool premium) const " this is not needed.\n" " --include=\n" " Force inclusion of a file before the checked file.\n" - " -i Exclude source files or directories matching str from\n" - " the check. This applies only to source files so header\n" - " files included by source files are not matched.\n" + " -i Ignore files that match . can be a filename\n" + " or directory and can contain *,**,?. A file that is\n" + " ignored will not be checked directly (the whole\n" + " translation unit is skipped completely). Header files\n" + " are checked indirectly when they are #include'd.\n" + " Note: If you want to prevent warnings in some headers,\n" + " use suppressions instead.\n" " --inconclusive Allow that Cppcheck reports even though the analysis is\n" " inconclusive.\n" " There are false positives with this option. Each result\n" @@ -1913,7 +1938,7 @@ void CmdLineParser::printHelp(bool premium) const " --plist-output=\n" " Generate Clang-plist output files in folder.\n"; - if (premium) { + if (mSettings.premium) { oss << " --premium=
\n" ""; - /*const*/ Settings settings = settingsBuilder().libraryxml(xmldata).severity(Severity::warning).build(); - settings.platform.sizeof_wchar_t = 4; + // use a platform which has wchar_t with a sizeof 4 + const Settings settings = settingsBuilder().libraryxml(xmldata).severity(Severity::warning).platform(Platform::Unix32).build(); + ASSERT_EQUALS(4, settings.platform.sizeof_wchar_t); check("void f() {\n" " char c[10];\n" " mymemset(c, 0, 10);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " char c[10];\n" " mymemset(c, 0, 11);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:14]: (error) Buffer is accessed out of bounds: c [bufferAccessOutOfBounds]\n", errout_str()); check("struct S {\n" @@ -4303,13 +4345,13 @@ class TestBufferOverrun : public TestFixture { "void f() {\n" " S s;\n" " mymemset(s.a, 0, 10);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:6:15]: (error) Buffer is accessed out of bounds: s.a [bufferAccessOutOfBounds]\n", errout_str()); check("void foo() {\n" " char s[10];\n" " mymemset(s, 0, '*');\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); TODO_ASSERT_EQUALS("[test.cpp:3]: (warning) The size argument is given as a char constant.\n" "[test.cpp:3:14]: (error) Buffer is accessed out of bounds: s [bufferAccessOutOfBounds]\n", "[test.cpp:3:14]: (error) Buffer is accessed out of bounds: s [bufferAccessOutOfBounds]\n", errout_str()); @@ -4317,65 +4359,65 @@ class TestBufferOverrun : public TestFixture { check("void f(void) {\n" " char a[10];\n" " mymemset(a+5, 0, 10);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); TODO_ASSERT_EQUALS("[test.cpp:3:13]: (error) Buffer is accessed out of bounds: a [bufferAccessOutOfBounds]\n", "", errout_str()); // Ticket #909 check("void f(void) {\n" " char str[] = \"abcd\";\n" " mymemset(str, 0, 6);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:14]: (error) Buffer is accessed out of bounds: str [bufferAccessOutOfBounds]\n", errout_str()); check("void f(void) {\n" " char str[] = \"abcd\";\n" " mymemset(str, 0, 5);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f(void) {\n" " wchar_t str[] = L\"abcd\";\n" " mymemset(str, 0, 21);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:14]: (error) Buffer is accessed out of bounds: str [bufferAccessOutOfBounds]\n", errout_str()); check("void f(void) {\n" " wchar_t str[] = L\"abcd\";\n" " mymemset(str, 0, 20);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); // ticket #1659 - overflowing variable when using memcpy check("void f(void) {\n" " char c;\n" " mymemset(&c, 0, 4);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:12]: (error) Buffer is accessed out of bounds: &c [bufferAccessOutOfBounds]\n", errout_str()); // ticket #2121 - buffer access out of bounds when using uint32_t check("void f(void) {\n" " unknown_type_t buf[4];\n" " mymemset(buf, 0, 100);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); // #3124 - multidimensional array check("int main() {\n" " char b[5][6];\n" " mymemset(b, 0, 5 * 6);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("int main() {\n" " char b[5][6];\n" " mymemset(b, 0, 6 * 6);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:14]: (error) Buffer is accessed out of bounds: b [bufferAccessOutOfBounds]\n", errout_str()); check("int main() {\n" " char b[5][6];\n" " mymemset(b, 0, 31);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:14]: (error) Buffer is accessed out of bounds: b [bufferAccessOutOfBounds]\n", errout_str()); // #4968 - not standard function @@ -4384,26 +4426,26 @@ class TestBufferOverrun : public TestFixture { " foo.mymemset(str, 0, 100);\n" " foo::mymemset(str, 0, 100);\n" " std::mymemset(str, 0, 100);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); TODO_ASSERT_EQUALS("[test.cpp:5:15]: (error) Buffer is accessed out of bounds: str [bufferAccessOutOfBounds]\n", "", errout_str()); // #5257 - check strings check("void f() {\n" " mymemset(\"abc\", 0, 20);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Buffer is accessed out of bounds.\n", "", errout_str()); check("void f() {\n" " mymemset(temp, \"abc\", 4);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f() {\n" // #6816 - fp when array has known string value " char c[10] = \"c\";\n" " mymemset(c, 0, 10);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); } @@ -4425,43 +4467,43 @@ class TestBufferOverrun : public TestFixture { check("void f() {\n" " char c[7];\n" " mystrncpy(c, \"hello\", 7);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " char c[6];\n" " mystrncpy(c,\"hello\",6);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " char c[5];\n" " mystrncpy(c,\"hello\",6);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:12]: (error) Buffer is accessed out of bounds: c [bufferAccessOutOfBounds]\n", errout_str()); check("void f() {\n" " char c[6];\n" " mystrncpy(c,\"hello!\",7);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:15]: (error) Buffer is accessed out of bounds: c [bufferAccessOutOfBounds]\n", errout_str()); check("void f(unsigned int addr) {\n" " memset((void *)addr, 0, 1000);\n" - "}", dinit(CheckOptions, $.s = &settings0)); + "}", settings0); // TODO: use settings? ASSERT_EQUALS("", errout_str()); check("struct AB { char a[10]; };\n" "void foo(AB *ab) {\n" " mystrncpy(x, ab->a, 100);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void a(char *p) { mystrncpy(p,\"hello world!\",10); }\n" // #3168 "void b() {\n" " char buf[5];\n" " a(buf);" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); TODO_ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (error) Buffer is accessed out of bounds: buf\n", "", errout_str()); @@ -4487,13 +4529,13 @@ class TestBufferOverrun : public TestFixture { check("void f() {\n" " char str[3];\n" " mysprintf(str, \"test\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:15]: (error) Buffer is accessed out of bounds: str [bufferAccessOutOfBounds]\n", errout_str()); check("void f() {\n" " char str[5];\n" " mysprintf(str, \"%s\", \"abcde\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:15]: (error) Buffer is accessed out of bounds: str [bufferAccessOutOfBounds]\n", errout_str()); check("int getnumber();\n" @@ -4501,51 +4543,51 @@ class TestBufferOverrun : public TestFixture { "{\n" " char str[5];\n" " mysprintf(str, \"%d: %s\", getnumber(), \"abcde\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:5:15]: (error) Buffer is accessed out of bounds: str [bufferAccessOutOfBounds]\n", errout_str()); check("void f() {\n" " char str[5];\n" " mysprintf(str, \"test%s\", \"\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " char *str = new char[5];\n" " mysprintf(str, \"abcde\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:15]: (error) Buffer is accessed out of bounds: str [bufferAccessOutOfBounds]\n", errout_str()); check("void f(int condition) {\n" " char str[5];\n" " mysprintf(str, \"test%s\", condition ? \"12\" : \"34\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f(int condition) {\n" " char str[5];\n" " mysprintf(str, \"test%s\", condition ? \"12\" : \"345\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); TODO_ASSERT_EQUALS("error", "", errout_str()); check("struct Foo { char a[1]; };\n" "void f() {\n" " struct Foo x;\n" " mysprintf(x.a, \"aa\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:4:14]: (error) Buffer is accessed out of bounds: x.a [bufferAccessOutOfBounds]\n", errout_str()); // ticket #900 check("void f() {\n" " char *a = new char(30);\n" " mysprintf(a, \"a\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:13]: (error) Buffer is accessed out of bounds: a [bufferAccessOutOfBounds]\n", errout_str()); check("void f(char value) {\n" " char *a = new char(value);\n" " mysprintf(a, \"a\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:13]: (error) Buffer is accessed out of bounds: a [bufferAccessOutOfBounds]\n", errout_str()); // This is out of bounds if 'sizeof(ABC)' is 1 (No padding) @@ -4553,21 +4595,21 @@ class TestBufferOverrun : public TestFixture { "void f() {\n" " struct Foo *x = malloc(sizeof(Foo));\n" " mysprintf(x->a, \"aa\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); TODO_ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Buffer is accessed out of bounds: x.a\n", "", errout_str()); check("struct Foo { char a[1]; };\n" "void f() {\n" " struct Foo *x = malloc(sizeof(Foo) + 10);\n" " mysprintf(x->a, \"aa\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("struct Foo { char a[1]; };\n" "void f() {\n" " struct Foo x;\n" " mysprintf(x.a, \"aa\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:4:14]: (error) Buffer is accessed out of bounds: x.a [bufferAccessOutOfBounds]\n", errout_str()); check("struct Foo {\n" // #6668 - unknown size @@ -4576,8 +4618,43 @@ class TestBufferOverrun : public TestFixture { "};" "void Foo::f() {\n" " mysprintf(a, \"abcd\");\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); + + check("void f() {\n" // #901 + " const char b[] = \"b\";\n" + " char a[1];\n" + " sprintf(a, \"%s\", b);\n" + "}\n" + "void g() {\n" + " const char* b = \"b\";\n" + " char a[1];\n" + " sprintf(a, \"%s\", b);\n" + "}\n" + "void h() {\n" + " const std::string b = \"b\";\n" + " char a[1];\n" + " sprintf(a, \"%s\", b.c_str());\n" + "}\n" + "void i() {\n" + " const char b[] = \"b\";\n" + " char a[2];\n" + " sprintf(a, \"%s\", b);\n" + "}\n" + "void j() {\n" + " const char* b = \"b\";\n" + " char a[2];\n" + " sprintf(a, \"%s\", b);\n" + "}\n" + "void k() {\n" + " const std::string b = \"b\";\n" + " char a[2];\n" + " sprintf(a, \"%s\", b.c_str());\n" + "}\n", settings0); + ASSERT_EQUALS("[test.cpp:4:13]: (error) Buffer is accessed out of bounds: a [bufferAccessOutOfBounds]\n" + "[test.cpp:9:13]: (error) Buffer is accessed out of bounds: a [bufferAccessOutOfBounds]\n" + "[test.cpp:14:13]: (error) Buffer is accessed out of bounds: a [bufferAccessOutOfBounds]\n", + errout_str()); } void minsize_mul() { @@ -4597,13 +4674,13 @@ class TestBufferOverrun : public TestFixture { check("void f() {\n" " char c[5];\n" " myfread(c, 1, 5, stdin);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " char c[5];\n" " myfread(c, 1, 6, stdin);\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:13]: (error) Buffer is accessed out of bounds: c [bufferAccessOutOfBounds]\n", errout_str()); } @@ -5092,7 +5169,8 @@ class TestBufferOverrun : public TestFixture { void getErrorMessages() { // Ticket #2292: segmentation fault when using --errorlist - const Check& c = getCheck(); + CheckBufferOverrun check; + const Check& c = getCheck(check); c.getErrorMessages(this, nullptr); // we are not interested in the output - just consume it ignore_errout(); @@ -5265,29 +5343,29 @@ class TestBufferOverrun : public TestFixture { check("void f() {\n" " char arr[10];\n" " char *p = arr + 20;\n" - "}"); + "}", settings0_p); ASSERT_EQUALS("[test.cpp:3:19]: (portability) Undefined behaviour, pointer arithmetic 'arr+20' is out of bounds. [pointerOutOfBounds]\n", errout_str()); check("char(*g())[1];\n" // #7950 "void f() {\n" " int a[2];\n" " int* b = a + sizeof(*g());\n" - "}\n"); + "}\n", settings0_p); ASSERT_EQUALS("", errout_str()); } -#define ctu(code) ctu_(code, __FILE__, __LINE__) +#define ctu(...) ctu_(__FILE__, __LINE__, __VA_ARGS__) template - void ctu_(const char (&code)[size], const char* file, int line) { + void ctu_(const char* file, int line, const char (&code)[size]) { // Tokenize.. SimpleTokenizer tokenizer(settings0, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); CTU::FileInfo *ctu = CTU::getFileInfo(tokenizer); - // Check code.. std::list fileInfo; - Check& c = getCheck(); + CheckBufferOverrun check; + Check& c = getCheck(check); fileInfo.push_back(c.getFileInfo(tokenizer, settings0, "")); c.analyseWholeProgram(*ctu, fileInfo, settings0, *this); // TODO: check result while (!fileInfo.empty()) { @@ -5329,6 +5407,15 @@ class TestBufferOverrun : public TestFixture { " f(a);\n" "}\n"); ASSERT_EQUALS("[test.cpp:7:12] -> [test.cpp:9:6] -> [test.cpp:3:12]: (error) Array index out of bounds; 'p' buffer size is 4 and it is accessed at offset 20. [ctuArrayIndex]\n", errout_str()); + + ctu("void bar(int *p) { p[4] = 42; }\n" // #13403 + "void f() {\n" + " int *p = (int*)malloc(4 * sizeof(int));\n" + " if (!p) return;\n" + " bar(p);\n" + " free(p);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:12] -> [test.cpp:4:9] -> [test.cpp:5:8] -> [test.cpp:1:20]: (error) Array index out of bounds; 'p' buffer size is 16 and it is accessed at offset 16. [ctuArrayIndex]\n", errout_str()); } void ctu_array() { @@ -5493,6 +5580,19 @@ class TestBufferOverrun : public TestFixture { " f(s);\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + setMultiline(); + ctu("void g(char* p) {\n" + " memset(p + 10, 0, 10);\n" + "}\n" + "void f() {\n" + " char a[10] = {};\n" + " g(a);\n" + "}"); + ASSERT_EQUALS("[test.cpp:2:12]: error: Pointer arithmetic overflow; 'p' buffer size is 10 [ctuPointerArith]\n" + "[test.cpp:6:6]: note: Calling function g, 1st argument is accessed out of bounds\n" + "[test.cpp:2:12]: note: Using argument p\n", + errout_str()); } void objectIndex() { @@ -5729,7 +5829,7 @@ class TestBufferOverrun : public TestFixture { "if (pipe(pipefd) == -1) {\n" " return;\n" " }\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:10]: (error) Buffer is accessed out of bounds: pipefd [bufferAccessOutOfBounds]\n", errout_str()); check("void f(){\n" @@ -5737,7 +5837,7 @@ class TestBufferOverrun : public TestFixture { "if (pipe(pipefd) == -1) {\n" " return;\n" " }\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); check("void f(){\n" @@ -5745,7 +5845,7 @@ class TestBufferOverrun : public TestFixture { "if (pipe((int*)pipefd) == -1) {\n" " return;\n" " }\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("[test.cpp:3:10]: (error) Buffer is accessed out of bounds: (int*)pipefd [bufferAccessOutOfBounds]\n", errout_str()); check("void f(){\n" @@ -5753,7 +5853,7 @@ class TestBufferOverrun : public TestFixture { "if (pipe((int*)pipefd) == -1) {\n" " return;\n" " }\n" - "}", dinit(CheckOptions, $.s = &settings)); + "}", settings); ASSERT_EQUALS("", errout_str()); } }; diff --git a/test/testcharvar.cpp b/test/testcharvar.cpp index 624efcff539..bb98dfad48d 100644 --- a/test/testcharvar.cpp +++ b/test/testcharvar.cpp @@ -47,7 +47,7 @@ class TestCharVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check char variable usage.. - CheckOther checkOther(&tokenizer, &settings, this); + CheckOtherImpl checkOther(&tokenizer, &settings, this); checkOther.checkCharVariable(); } diff --git a/test/testcheck.cpp b/test/testcheck.cpp index 8ea4cef38d8..3ae2cad3d8f 100644 --- a/test/testcheck.cpp +++ b/test/testcheck.cpp @@ -17,6 +17,7 @@ */ #include "check.h" +#include "checks.h" #include "fixture.h" #include @@ -28,23 +29,12 @@ class TestCheck : public TestFixture { private: void run() override { - TEST_CASE(instancesSorted); TEST_CASE(classInfoFormat); } - void instancesSorted() const { - for (auto i = Check::instances().cbegin(); i != Check::instances().cend(); ++i) { - auto j = i; - ++j; - if (j != Check::instances().cend()) { - ASSERT_EQUALS(true, (*i)->name() < (*j)->name()); - } - } - } - void classInfoFormat() const { - for (auto i = Check::instances().cbegin(); i != Check::instances().cend(); ++i) { - const std::string info = (*i)->classInfo(); + for (const Check * const c : CheckInstances::get()) { + const std::string info = c->classInfo(); if (!info.empty()) { ASSERT('\n' != info[0]); // No \n in the beginning ASSERT('\n' == info.back()); // \n at end diff --git a/test/testcheckersreport.cpp b/test/testcheckersreport.cpp new file mode 100644 index 00000000000..eafe7b8848f --- /dev/null +++ b/test/testcheckersreport.cpp @@ -0,0 +1,56 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2025 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "addoninfo.h" +#include "checkersreport.h" +#include "fixture.h" +#include "settings.h" + +class TestCheckersReport : public TestFixture { +public: + TestCheckersReport() : TestFixture("TestCheckersReport") {} + +private: + void run() final { + // AddonInfo::checkers + TEST_CASE(addonInfoCheckers); + } + + void addonInfoCheckers() const { + AddonInfo a; + a.name = "test"; + a.checkers["abcdefghijklmnopqrstuvwxyz::abcdefghijklmnopqrstuvwxyz"] = "123"; + Settings s; + s.addonInfos.emplace_back(a); + const std::set activeCheckers; + CheckersReport r(s, activeCheckers); + const std::string report = r.getReport(""); + const auto pos = report.rfind("\n\n"); + ASSERT(pos != std::string::npos); + + const char expected[] = + "test checkers\n" + "-------------\n" + "No abcdefghijklmnopqrstuvwxyz::abcdefghijklmnopqrstuvwxyz require:123\n"; + + ASSERT_EQUALS(expected, report.substr(pos+2)); + } +}; + +REGISTER_TEST(TestCheckersReport) diff --git a/test/testclangimport.cpp b/test/testclangimport.cpp index c67767db0ba..6a39b563982 100644 --- a/test/testclangimport.cpp +++ b/test/testclangimport.cpp @@ -1,5 +1,5 @@ // Cppcheck - A tool for static C/C++ code analysis -// Copyright (C) 2007-2025 Cppcheck team. +// Copyright (C) 2007-2026 Cppcheck team. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -1328,7 +1328,7 @@ class TestClangImport : public TestFixture { const Token *tok = Token::findsimplematch(tokenizer.tokens(), "\"hello\""); ASSERT(!!tok); ASSERT(!!tok->valueType()); - ASSERT_EQUALS("const signed char *", tok->valueType()->str()); + ASSERT_EQUALS("const char *", tok->valueType()->str()); } void stdinLoc() { diff --git a/test/testclass.cpp b/test/testclass.cpp index aa28ab96fb2..35994e98cf4 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,7 @@ class TestClass : public TestFixture { private: const Settings settings0 = settingsBuilder().severity(Severity::style).library("std.cfg").build(); + const Settings settings0_i = settingsBuilder(settings0).certainty(Certainty::inconclusive).build(); const Settings settings1 = settingsBuilder().severity(Severity::warning).library("std.cfg").build(); const Settings settings2 = settingsBuilder().severity(Severity::style).library("std.cfg").certainty(Certainty::inconclusive).build(); const Settings settings3 = settingsBuilder().severity(Severity::style).library("std.cfg").severity(Severity::warning).build(); @@ -194,6 +195,7 @@ class TestClass : public TestFixture { TEST_CASE(const98); TEST_CASE(const99); TEST_CASE(const100); + TEST_CASE(const101); TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_passThisToMemberOfOtherClass); @@ -268,7 +270,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkCopyCtorAndEqOperator)(); } @@ -369,7 +371,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings0, this); + CheckClassImpl checkClass(&tokenizer, &settings0, this); (checkClass.checkExplicitConstructors)(); } @@ -526,7 +528,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); (checkClass.checkDuplInheritedMembers)(); } @@ -733,6 +735,13 @@ class TestClass : public TestFixture { " void Two() = delete;\n" "};\n"); ASSERT_EQUALS("", errout_str()); + + checkDuplInheritedMembers("struct B { void f(); };\n" // #14583 + "struct D : B {\n" + " template \n" + " void f();\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); } #define checkCopyConstructor(...) checkCopyConstructor_( __FILE__, __LINE__, __VA_ARGS__) @@ -743,7 +752,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings3, this); + CheckClassImpl checkClass(&tokenizer, &settings3, this); checkClass.copyconstructors(); } @@ -1214,7 +1223,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings0, this); + CheckClassImpl checkClass(&tokenizer, &settings0, this); checkClass.operatorEqRetRefThis(); } @@ -1685,7 +1694,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); checkClass.operatorEqToSelf(); } @@ -2648,7 +2657,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &s, this); + CheckClassImpl checkClass(&tokenizer, &s, this); checkClass.virtualDestructor(); } @@ -2985,7 +2994,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); checkClass.checkMemset(); } @@ -3631,7 +3640,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); checkClass.thisSubtraction(); } @@ -3655,20 +3664,23 @@ class TestClass : public TestFixture { struct CheckConstOptions { - const Settings *s = nullptr; bool inconclusive = true; }; #define checkConst(...) checkConst_(__FILE__, __LINE__, __VA_ARGS__) template void checkConst_(const char* file, int line, const char (&code)[size], const CheckConstOptions& options = make_default_obj()) { - const Settings settings = settingsBuilder(options.s ? *options.s : settings0).certainty(Certainty::inconclusive, options.inconclusive).build(); + const Settings& settings = options.inconclusive ? settings0_i : settings0; - // Tokenize.. + checkConst_(file, line, code, settings); + } + + template + void checkConst_(const char* file, int line, const char (&code)[size], const Settings& settings) { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkConst)(); } @@ -3682,13 +3694,13 @@ class TestClass : public TestFixture { checkConst("class Fred {\n" " const std::string foo() { return \"\"; }\n" "};"); - ASSERT_EQUALS("[test.cpp:2:23]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:23]: (style) The member function 'Fred::foo' can be static. [functionStatic]\n", errout_str()); checkConst("class Fred {\n" " std::string s;\n" " const std::string & foo() { return \"\"; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:25]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:25]: (style) The member function 'Fred::foo' can be static. [functionStatic]\n", errout_str()); // constructors can't be const.. checkConst("class Fred {\n" @@ -3727,7 +3739,7 @@ class TestClass : public TestFixture { " int x;\n" " void b() { a(); }\n" "};"); - ASSERT_EQUALS("[test.cpp:4:10]: (performance, inconclusive) Technically the member function 'Fred::b' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:10]: (style) The member function 'Fred::b' can be static. [functionStatic]\n", errout_str()); // static functions can't be const.. checkConst("class foo\n" @@ -3741,7 +3753,7 @@ class TestClass : public TestFixture { checkConst("class Fred {\n" " const std::string foo() const throw() { return \"\"; }\n" "};"); - ASSERT_EQUALS("[test.cpp:2:23]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:23]: (style) The member function 'Fred::foo' can be static. [functionStatic]\n", errout_str()); } void const2() { @@ -3853,7 +3865,7 @@ class TestClass : public TestFixture { " const std::string & foo();\n" "};\n" "const std::string & Fred::foo() { return \"\"; }"); - ASSERT_EQUALS("[test.cpp:3:25] -> [test.cpp:5:27]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:25] -> [test.cpp:5:27]: (style) The member function 'Fred::foo' can be static. [functionStatic]\n", errout_str()); // functions with a function call to a non-const member can't be const.. (#1305) checkConst("class Fred\n" @@ -3989,7 +4001,7 @@ class TestClass : public TestFixture { "void Fred::foo() { }" "void Fred::foo(std::string & a) { a = s; }" "void Fred::foo(const std::string & a) { s = a; }"); - ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:7:12]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" + ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:7:12]: (style) The member function 'Fred::foo' can be static. [functionStatic]\n" "[test.cpp:4:10] -> [test.cpp:7:32]: (style, inconclusive) Technically the member function 'Fred::foo' can be const. [functionConst]\n", errout_str()); // check functions with different or missing parameter names @@ -4006,11 +4018,11 @@ class TestClass : public TestFixture { "void Fred::foo3(int a, int b) { }\n" "void Fred::foo4(int a, int b) { }\n" "void Fred::foo5(int, int) { }"); - ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:9:12]: (performance, inconclusive) Technically the member function 'Fred::foo1' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" - "[test.cpp:4:10] -> [test.cpp:10:12]: (performance, inconclusive) Technically the member function 'Fred::foo2' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" - "[test.cpp:5:10] -> [test.cpp:11:12]: (performance, inconclusive) Technically the member function 'Fred::foo3' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" - "[test.cpp:6:10] -> [test.cpp:12:12]: (performance, inconclusive) Technically the member function 'Fred::foo4' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" - "[test.cpp:7:10] -> [test.cpp:13:12]: (performance, inconclusive) Technically the member function 'Fred::foo5' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:9:12]: (style) The member function 'Fred::foo1' can be static. [functionStatic]\n" + "[test.cpp:4:10] -> [test.cpp:10:12]: (style) The member function 'Fred::foo2' can be static. [functionStatic]\n" + "[test.cpp:5:10] -> [test.cpp:11:12]: (style) The member function 'Fred::foo3' can be static. [functionStatic]\n" + "[test.cpp:6:10] -> [test.cpp:12:12]: (style) The member function 'Fred::foo4' can be static. [functionStatic]\n" + "[test.cpp:7:10] -> [test.cpp:13:12]: (style) The member function 'Fred::foo5' can be static. [functionStatic]\n", errout_str()); // check nested classes checkConst("class Fred {\n" @@ -4241,7 +4253,7 @@ class TestClass : public TestFixture { "public:\n" " void foo() { }\n" "};"); - ASSERT_EQUALS("[test.cpp:4:10]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:10]: (style) The member function 'Fred::foo' can be static. [functionStatic]\n", errout_str()); checkConst("struct fast_string\n" "{\n" @@ -4678,7 +4690,7 @@ class TestClass : public TestFixture { "public:\n" " void set(int i) { x = i; }\n" "};"); - ASSERT_EQUALS("[test.cpp:4:10]: (performance, inconclusive) Technically the member function 'Fred::set' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:10]: (style) The member function 'Fred::set' can be static. [functionStatic]\n", errout_str()); } void const19() { @@ -4918,7 +4930,7 @@ class TestClass : public TestFixture { " UnknownScope::x = x_;\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:4:17]: (performance, inconclusive) Technically the member function 'AA::vSetXPos' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:17]: (style) The member function 'AA::vSetXPos' can be static. [functionStatic]\n", errout_str()); } @@ -5093,7 +5105,7 @@ class TestClass : public TestFixture { "public:\n" " void f(){}\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Either there is a missing 'override', or the member function 'derived::f' can be static. [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) Either there is a missing 'override', or the member function 'derived::f' can be static. [functionStatic]\n", errout_str()); } void const34() { // ticket #1964 @@ -5346,7 +5358,7 @@ class TestClass : public TestFixture { "{\n" "}"); - ASSERT_EQUALS("[test.cpp:5:10] -> [test.cpp:7:12]: (performance, inconclusive) Technically the member function 'Fred::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:5:10] -> [test.cpp:7:12]: (style) The member function 'Fred::f' can be static. [functionStatic]\n", errout_str()); checkConst("class Fred\n" "{\n" @@ -5360,7 +5372,7 @@ class TestClass : public TestFixture { "{\n" "}"); - ASSERT_EQUALS("[test.cpp:7:10] -> [test.cpp:9:12]: (performance, inconclusive) Technically the member function 'Fred::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:7:10] -> [test.cpp:9:12]: (style) The member function 'Fred::f' can be static. [functionStatic]\n", errout_str()); checkConst("namespace NS {\n" " class Fred\n" @@ -5376,7 +5388,7 @@ class TestClass : public TestFixture { " }\n" "}"); - ASSERT_EQUALS("[test.cpp:8:14] -> [test.cpp:10:16]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:8:14] -> [test.cpp:10:16]: (style) The member function 'NS::Fred::f' can be static. [functionStatic]\n", errout_str()); checkConst("namespace NS {\n" " class Fred\n" @@ -5392,7 +5404,7 @@ class TestClass : public TestFixture { "{\n" "}"); - ASSERT_EQUALS("[test.cpp:8:14] -> [test.cpp:11:16]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:8:14] -> [test.cpp:11:16]: (style) The member function 'NS::Fred::f' can be static. [functionStatic]\n", errout_str()); checkConst("class Foo {\n" " class Fred\n" @@ -5408,7 +5420,7 @@ class TestClass : public TestFixture { "{\n" "}"); - ASSERT_EQUALS("[test.cpp:8:14] -> [test.cpp:11:17]: (performance, inconclusive) Technically the member function 'Foo::Fred::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:8:14] -> [test.cpp:11:17]: (style) The member function 'Foo::Fred::f' can be static. [functionStatic]\n", errout_str()); } void const43() { // ticket 2377 @@ -5497,7 +5509,7 @@ class TestClass : public TestFixture { " };\n" "}"); - ASSERT_EQUALS("[test.cpp:8:13]: (performance, inconclusive) Technically the member function 'tools::WorkspaceControl::toGrid' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:8:13]: (style) The member function 'tools::WorkspaceControl::toGrid' can be static. [functionStatic]\n", errout_str()); } void const46() { // ticket 2663 @@ -5512,8 +5524,8 @@ class TestClass : public TestFixture { " }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:9]: (performance, inconclusive) Technically the member function 'Altren::fun1' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" - "[test.cpp:7:9]: (performance, inconclusive) Technically the member function 'Altren::fun2' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:9]: (style) The member function 'Altren::fun1' can be static. [functionStatic]\n" + "[test.cpp:7:9]: (style) The member function 'Altren::fun2' can be static. [functionStatic]\n", errout_str()); } void const47() { // ticket 2670 @@ -5524,7 +5536,7 @@ class TestClass : public TestFixture { " void bar() { foo(); }\n" "};"); - ASSERT_EQUALS("[test.cpp:4:8]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:8]: (style) The member function 'Altren::foo' can be static. [functionStatic]\n", errout_str()); checkConst("class Altren {\n" "public:\n" @@ -5533,7 +5545,7 @@ class TestClass : public TestFixture { " void bar() { foo(1); }\n" "};"); - ASSERT_EQUALS("[test.cpp:4:8]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" + ASSERT_EQUALS("[test.cpp:4:8]: (style) The member function 'Altren::foo' can be static. [functionStatic]\n" "[test.cpp:5:8]: (style, inconclusive) Technically the member function 'Altren::bar' can be const. [functionConst]\n", errout_str()); } @@ -5624,7 +5636,7 @@ class TestClass : public TestFixture { "private:\n" " int bar;\n" "};"); - ASSERT_EQUALS("[test.cpp:2:10]: (performance, inconclusive) Technically the member function 'foo::DoSomething' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:10]: (style) The member function 'foo::DoSomething' can be static. [functionStatic]\n", errout_str()); } void const53() { // ticket 3049 @@ -5668,7 +5680,7 @@ class TestClass : public TestFixture { " switch (x) { }\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'MyObject::foo' can be static. [functionStatic]\n", errout_str()); checkConst("class A\n" "{\n" @@ -5708,7 +5720,7 @@ class TestClass : public TestFixture { "\n" " return RET_NOK;\n" "}"); - ASSERT_EQUALS("[test.cpp:4:24] -> [test.cpp:9:19]: (performance, inconclusive) Technically the member function 'A::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:24] -> [test.cpp:9:19]: (style) The member function 'A::f' can be static. [functionStatic]\n", errout_str()); checkConst("class MyObject {\n" "public:\n" @@ -5716,7 +5728,7 @@ class TestClass : public TestFixture { " for (int i = 0; i < 5; i++) { }\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'MyObject::foo' can be static. [functionStatic]\n", errout_str()); } void const57() { // tickets #2669 and #2477 @@ -5741,9 +5753,9 @@ class TestClass : public TestFixture { "private:\n" " MyGUI::IntCoord mCoordValue;\n" "};"); - TODO_ASSERT_EQUALS("[test.cpp:7:13]: (performance, inconclusive) Technically the member function 'MyGUI::types::TCoord::size' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" + TODO_ASSERT_EQUALS("[test.cpp:7:13]: (style) The member function 'MyGUI::types::TCoord::size' can be static. [functionStatic]\n" "[test.cpp:15]: (style, inconclusive) Technically the member function 'SelectorControl::getSize' can be const.\n", - "[test.cpp:7:13]: (performance, inconclusive) Technically the member function 'MyGUI::types::TCoord::size' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + "[test.cpp:7:13]: (style) The member function 'MyGUI::types::TCoord::size' can be static. [functionStatic]\n", errout_str()); checkConst("struct Foo {\n" " Bar b;\n" @@ -5774,7 +5786,7 @@ class TestClass : public TestFixture { " b.run();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:2:10]: (performance, inconclusive) Technically the member function 'Bar::run' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" + ASSERT_EQUALS("[test.cpp:2:10]: (style) The member function 'Bar::run' can be static. [functionStatic]\n" "[test.cpp:6:10]: (style, inconclusive) Technically the member function 'Foo::foo' can be const. [functionConst]\n", errout_str()); } @@ -5784,14 +5796,14 @@ class TestClass : public TestFixture { " f.clear();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:2:10]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:10]: (style) The member function 'MyObject::foo' can be static. [functionStatic]\n", errout_str()); checkConst("struct MyObject {\n" " int foo(Foo f) {\n" " return f.length();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:2:9]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:9]: (style) The member function 'MyObject::foo' can be static. [functionStatic]\n", errout_str()); checkConst("struct MyObject {\n" " Foo f;\n" @@ -5879,7 +5891,7 @@ class TestClass : public TestFixture { " inherited::set(inherited::Key(key));\n" " }\n" "};\n", dinit(CheckConstOptions, $.inconclusive = false)); - ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:4:23]: (performance, inconclusive) Either there is a missing 'override', or the member function 'MixerParticipant::GetAudioFrame' can be static. [functionStatic]\n", + ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:4:23]: (style) Either there is a missing 'override', or the member function 'MixerParticipant::GetAudioFrame' can be static. [functionStatic]\n", errout_str()); } @@ -6198,7 +6210,7 @@ class TestClass : public TestFixture { " if (N::i) {}\n" " }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:4:10]: (performance, inconclusive) Technically the member function 'S::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:10]: (style) The member function 'S::f' can be static. [functionStatic]\n", errout_str()); checkConst("int i = 0;\n" "struct S {\n" @@ -6207,7 +6219,7 @@ class TestClass : public TestFixture { " if (::i) {}\n" " }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:4:10]: (performance, inconclusive) Technically the member function 'S::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:10]: (style) The member function 'S::f' can be static. [functionStatic]\n", errout_str()); checkConst("namespace N {\n" " struct S {\n" @@ -6230,7 +6242,7 @@ class TestClass : public TestFixture { "void S::f(const T* t) {\n" " const_cast(t)->e();\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:7:9]: (performance, inconclusive) Technically the member function 'S::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", + ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:7:9]: (style) The member function 'S::f' can be static. [functionStatic]\n", errout_str()); } @@ -6276,7 +6288,7 @@ class TestClass : public TestFixture { " return nullptr;\n" " }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3:11]: (performance, inconclusive) Technically the member function 'A::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", + ASSERT_EQUALS("[test.cpp:3:11]: (style) The member function 'A::f' can be static. [functionStatic]\n", errout_str()); } @@ -6307,10 +6319,10 @@ class TestClass : public TestFixture { "void S::n() {\n" " this->h();\n" "}\n"); - ASSERT_EQUALS("[test.cpp:4:10] -> [test.cpp:11:9]: (performance, inconclusive) Technically the member function 'S::g' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" - "[test.cpp:5:10] -> [test.cpp:14:9]: (performance, inconclusive) Technically the member function 'S::h' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" + ASSERT_EQUALS("[test.cpp:4:10] -> [test.cpp:11:9]: (style) The member function 'S::g' can be static. [functionStatic]\n" + "[test.cpp:5:10] -> [test.cpp:14:9]: (style) The member function 'S::h' can be static. [functionStatic]\n" "[test.cpp:6:10] -> [test.cpp:17:9]: (style, inconclusive) Technically the member function 'S::k' can be const. [functionConst]\n" - "[test.cpp:7:10] -> [test.cpp:21:9]: (performance, inconclusive) Technically the member function 'S::m' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", + "[test.cpp:7:10] -> [test.cpp:21:9]: (style) The member function 'S::m' can be static. [functionStatic]\n", errout_str()); } @@ -6670,7 +6682,7 @@ class TestClass : public TestFixture { " }\n" "};\n"); ASSERT_EQUALS("[test.cpp:3:9]: (style, inconclusive) Technically the member function 'S::f' can be const. [functionConst]\n" - "[test.cpp:8:9]: (performance, inconclusive) Technically the member function 'S::g' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", + "[test.cpp:8:9]: (style) The member function 'S::g' can be static. [functionStatic]\n", errout_str()); checkConst("class C {\n" // #11653 @@ -6681,7 +6693,7 @@ class TestClass : public TestFixture { " if (b)\n" " f(false);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:5:9]: (performance, inconclusive) Technically the member function 'C::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", + ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:5:9]: (style) The member function 'C::f' can be static. [functionStatic]\n", errout_str()); } @@ -6727,6 +6739,7 @@ class TestClass : public TestFixture { "struct S<0> {};\n" "struct D : S<150> {};\n"); // don't hang + ignore_errout(); } void const93() { // #12162 @@ -6781,6 +6794,52 @@ class TestClass : public TestFixture { " B::g(0);\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + checkConst("struct S {\n" // #14366 + " void f();\n" + "};\n" + "struct T : U {\n" + " void g(S* s) {\n" + " s->f();\n" + " }\n" + " void h() {\n" + " S s;\n" + " s.f();\n" + " }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:5:10]: (style) Either there is a missing 'override', or the member function 'T::g' can be static. [functionStatic]\n" + "[test.cpp:8:10]: (style) Either there is a missing 'override', or the member function 'T::h' can be static. [functionStatic]\n", + errout_str()); + + checkConst("enum E { E0 };\n" + "int f();\n" + "struct S : U {\n" + " E g() {\n" + " return E0;\n" + " }\n" + " int h() {\n" + " return f();\n" + " }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:4:7]: (style) Either there is a missing 'override', or the member function 'S::g' can be static. [functionStatic]\n" + "[test.cpp:7:9]: (style) Either there is a missing 'override', or the member function 'S::h' can be static. [functionStatic]\n", + errout_str()); + + checkConst("namespace N {\n" // #14391 + " void f();\n" + "}\n" + "struct S : U {\n" + " void g() { N::f(); }\n" + " void h() { ::N::f(); }\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:5:10]: (style) Either there is a missing 'override', or the member function 'S::g' can be static. [functionStatic]\n" + "[test.cpp:6:10]: (style) Either there is a missing 'override', or the member function 'S::h' can be static. [functionStatic]\n", + errout_str()); + + checkConst("struct S : U {\n" // #14425 + " void f() { this->g(); }\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); } void const97() { // #13301 @@ -6914,6 +6973,31 @@ class TestClass : public TestFixture { ASSERT_EQUALS("", errout_str()); // don't crash } + void const101() { + checkConst("struct error {\n" // #14450 + " error() = default;\n" + "};\n" + "struct S : U {\n" + " int f() { return this->error(); }\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + + checkConst("struct S {\n" // #14702 + " int i;\n" + " void f() {\n" + " S& r = *this;\n" + " r.i = 0;\n" + " }\n" + "};\n" + "struct T : std::array {\n" + " void g() {\n" + " for (int& r : *this)\n" + " r = 0;\n" + " }\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + } + void const_handleDefaultParameters() { checkConst("struct Foo {\n" " void foo1(int i, int j = 0) {\n" @@ -6944,8 +7028,8 @@ class TestClass : public TestFixture { " return foo3();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:11:9]: (performance, inconclusive) Technically the member function 'Foo::bar3' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" - "[test.cpp:14:9]: (performance, inconclusive) Technically the member function 'Foo::bar4' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:11:9]: (style) The member function 'Foo::bar3' can be static. [functionStatic]\n" + "[test.cpp:14:9]: (style) The member function 'Foo::bar4' can be static. [functionStatic]\n", errout_str()); } void const_passThisToMemberOfOtherClass() { @@ -6963,7 +7047,7 @@ class TestClass : public TestFixture { " f.foo();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:2:10]: (performance, inconclusive) Technically the member function 'Foo::foo' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:10]: (style) The member function 'Foo::foo' can be static. [functionStatic]\n", errout_str()); checkConst("struct A;\n" // #5839 - operator() "struct B {\n" @@ -7031,25 +7115,25 @@ class TestClass : public TestFixture { "class Fred {\n" " void nextA() { return ++a; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return --a; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a++; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a--; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("struct S {\n" // #10077 " int i{};\n" @@ -7095,31 +7179,31 @@ class TestClass : public TestFixture { "class Fred {\n" " void nextA() { return a=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a-=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a+=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a*=-1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a/=-2; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); } void constassign2() { @@ -7151,31 +7235,31 @@ class TestClass : public TestFixture { "class Fred {\n" " void nextA() { return s.a=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a-=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a+=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a*=-1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a/=-2; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("struct A { int a; };\n" "class Fred {\n" @@ -7243,25 +7327,25 @@ class TestClass : public TestFixture { "class Fred {\n" " void nextA() { return ++a[0]; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return --a[0]; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]++; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]--; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); } void constassignarray() { @@ -7299,31 +7383,31 @@ class TestClass : public TestFixture { "class Fred {\n" " void nextA() { return a[0]=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]-=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]+=1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]*=-1; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]/=-2; }\n" "};"); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'Fred::nextA' can be static. [functionStatic]\n", errout_str()); } // return pointer/reference => not const @@ -7350,7 +7434,7 @@ class TestClass : public TestFixture { checkConst("class Fred {\n" " UNKNOWN a() { return 0; };\n" "};"); - TODO_ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::a' can be static.\n", "", errout_str()); + TODO_ASSERT_EQUALS("[test.cpp:2]: (style) The member function 'Fred::a' can be static.\n", "", errout_str()); // #1579 - HDC checkConst("class Fred {\n" @@ -7366,7 +7450,7 @@ class TestClass : public TestFixture { " void f() const { };\n" " void a() { f(); };\n" "};"); - ASSERT_EQUALS("[test.cpp:2:10]: (performance, inconclusive) Technically the member function 'Fred::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n" + ASSERT_EQUALS("[test.cpp:2:10]: (style) The member function 'Fred::f' can be static. [functionStatic]\n" "[test.cpp:3:10]: (style, inconclusive) Technically the member function 'Fred::a' can be const. [functionConst]\n", errout_str()); // ticket #1593 @@ -7627,10 +7711,10 @@ class TestClass : public TestFixture { "};"; checkConst(code); - ASSERT_EQUALS("[test.cpp:3:10]: (performance, inconclusive) Technically the member function 'foo::f' can be static (but you may consider moving to unnamed namespace). [functionStatic]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'foo::f' can be static. [functionStatic]\n", errout_str()); - checkConst(code, dinit(CheckConstOptions, $.inconclusive = false)); // TODO: Set inconclusive to true (preprocess it) - ASSERT_EQUALS("", errout_str()); + checkConst(code, dinit(CheckConstOptions, $.inconclusive = false)); + ASSERT_EQUALS("[test.cpp:3:10]: (style) The member function 'foo::f' can be static. [functionStatic]\n", errout_str()); } void constFriend() { // ticket #1921 @@ -7690,6 +7774,19 @@ class TestClass : public TestFixture { " }\n" "};"); ASSERT_EQUALS("[test.cpp:8:10]: (style, inconclusive) Technically the member function 'Fred::f2' can be const. [functionConst]\n", errout_str()); + + checkConst("struct T {\n" // #14390 + " std::vector v;\n" + " void f() {\n" + " for (const auto& p : v)\n" + " *p = 0;\n" + " }\n" + " void g() {\n" + " for (auto* p : v)\n" + " *p = 0;\n" + " }\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); } void const_shared_ptr() { // #8674 @@ -7747,7 +7844,7 @@ class TestClass : public TestFixture { } void qualifiedNameMember() { // #10872 - const Settings s = settingsBuilder().severity(Severity::style).debugwarnings().library("std.cfg").build(); + const Settings s = settingsBuilder().severity(Severity::style).debugwarnings().library("std.cfg").certainty(Certainty::inconclusive).build(); checkConst("struct data {};\n" " struct S {\n" " std::vector std;\n" @@ -7755,7 +7852,7 @@ class TestClass : public TestFixture { "};\n" "void S::f() {\n" " std::vector::const_iterator end = std.end();\n" - "}\n", dinit(CheckConstOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("[test.cpp:4:10] -> [test.cpp:6:9]: (style, inconclusive) Technically the member function 'S::f' can be const. [functionConst]\n", errout_str()); } @@ -7766,7 +7863,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings2, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings2, this); + CheckClassImpl checkClass(&tokenizer, &settings2, this); checkClass.initializerListOrder(); } @@ -7920,7 +8017,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); checkClass.initializationListUsage(); } @@ -8144,7 +8241,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings0, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings0, this); + CheckClassImpl checkClass(&tokenizer, &settings0, this); (checkClass.checkSelfInitialization)(); } @@ -8254,7 +8351,7 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); checkClass.checkVirtualFunctionCallInConstructor(); } @@ -8599,7 +8696,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkOverride)(); } @@ -8771,6 +8868,16 @@ class TestClass : public TestFixture { "};\n"); ASSERT_EQUALS("[test.cpp:2:14] -> [test.cpp:5:6]: (style) The destructor '~D' overrides a destructor in a base class but is not marked with a 'override' specifier. [missingOverride]\n", errout_str()); + + checkOverride("struct B {\n" // #14581 + " virtual void f();\n" + "};\n" + "struct D : B {\n" + " void f() override;\n" + " template \n" + " void f();\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); } void overrideCVRefQualifiers() { @@ -8801,7 +8908,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkUselessOverride)(); } @@ -8991,7 +9098,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkUnsafeClassRefMember)(); } @@ -9009,7 +9116,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); (checkClass.checkThisUseAfterFree)(); } @@ -9171,7 +9278,8 @@ class TestClass : public TestFixture { void ctu(const std::vector &code) { - Check &check = getCheck(); + CheckClass checkClass; + Check &check = getCheck(checkClass); // getFileInfo std::list fileInfo; @@ -9223,8 +9331,8 @@ class TestClass : public TestFixture { SimpleTokenizer tokenizer(settings1, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check.. - const Check& c = getCheck(); + CheckClass check; + const Check& c = getCheck(check); Check::FileInfo * fileInfo = (c.getFileInfo)(tokenizer, settings1, ""); delete fileInfo; @@ -9245,7 +9353,7 @@ class TestClass : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check.. - CheckClass checkClass(&tokenizer, &settings, this); + CheckClassImpl checkClass(&tokenizer, &settings, this); (checkClass.checkReturnByReference)(); } diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 5970943d6d5..135b7c782be 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +31,6 @@ #include "settings.h" #include "standards.h" #include "suppressions.h" -#include "timer.h" #include "utils.h" #include @@ -49,7 +48,7 @@ class TestCmdlineParser : public TestFixture { {} private: - class CmdLineLoggerTest : public CmdLineLogger + class CmdLineLoggerTest final : public CmdLineLogger { public: CmdLineLoggerTest() = default; @@ -91,7 +90,7 @@ class TestCmdlineParser : public TestFixture { std::string buf; }; - class CmdLineParserTest : public CmdLineParser + class CmdLineParserTest final : public CmdLineParser { friend class TestCmdlineParser; public: @@ -300,10 +299,14 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(suppressionsNoFile1); TEST_CASE(suppressionsNoFile2); TEST_CASE(suppressionsNoFile3); - TEST_CASE(suppressionSingle); - TEST_CASE(suppressionSingleFile); - TEST_CASE(suppressionTwo); - TEST_CASE(suppressionTwoSeparate); + TEST_CASE(suppressSingle); + TEST_CASE(suppressSingleFile); + TEST_CASE(suppressTwo); + TEST_CASE(suppressTwoSeparate); + TEST_CASE(exitcodeSuppressSingle); + TEST_CASE(exitcodeSuppressSingleFile); + TEST_CASE(exitcodeSuppressTwo); + TEST_CASE(exitcodeSuppressTwoSeparate); TEST_CASE(templates); TEST_CASE(templatesGcc); TEST_CASE(templatesVs); @@ -414,6 +417,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(ruleFileInvalidSeverity1); TEST_CASE(ruleFileInvalidSeverity2); TEST_CASE(ruleFileInvalidPattern); + TEST_CASE(ruleFileInvalidEngine); #else TEST_CASE(ruleFileNotSupported); #endif @@ -493,6 +497,8 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(safetyOverride); TEST_CASE(noSafety); TEST_CASE(noSafetyOverride); + TEST_CASE(debugAnalyzerinfo); + TEST_CASE(debugIpc); TEST_CASE(ignorepaths1); TEST_CASE(ignorepaths2); @@ -551,7 +557,8 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), "{\n" - "\"productName\": \"Cppcheck Premium\"" + "\"productName\": \"Cppcheck Premium\"," + "\"manualUrl\": \"https://docs.notcppcheck.com/manual.pdf\"" "}\n"); const char * const argv[] = {"cppcheck"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parseFromArgs(argv)); @@ -559,7 +566,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(file.path(), *settings->settingsFiles.cbegin()); const std::string log_str = logger->str(); ASSERT_MSG(startsWith(log_str, "Cppcheck - A tool for static C/C++ code analysis"), "header"); - ASSERT_MSG(log_str.find("https://files.cppchecksolutions.com/manual.pdf") != std::string::npos, "help url"); + ASSERT_MSG(log_str.find("https://docs.notcppcheck.com/manual.pdf") != std::string::npos, "help url"); } void nooptionsWithInvalidCfg() { @@ -589,7 +596,8 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), "{\n" - "\"productName\": \"Cppcheck Premium\"" + "\"productName\": \"Cppcheck Premium\"," + "\"manualUrl\": \"https://docs.notcppcheck.com/manual.pdf\"" "}\n"); const char * const argv[] = {"cppcheck", "-h"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parseFromArgs(argv)); @@ -597,7 +605,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(file.path(), *settings->settingsFiles.cbegin()); const std::string log_str = logger->str(); ASSERT_MSG(startsWith(log_str, "Cppcheck - A tool for static C/C++ code analysis"), "header"); - ASSERT_MSG(log_str.find("https://files.cppchecksolutions.com/manual.pdf") != std::string::npos, "help url"); + ASSERT_MSG(log_str.find("https://docs.notcppcheck.com/manual.pdf") != std::string::npos, "help url"); } void helplong() { @@ -618,7 +626,8 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), "{\n" - "\"productName\": \"Cppcheck Premium\"" + "\"productName\": \"Cppcheck Premium\"," + "\"manualUrl\": \"https://docs.notcppcheck.com/manual.pdf\"" "}\n"); const char * const argv[] = {"cppcheck", "--help"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parseFromArgs(argv)); @@ -626,7 +635,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(file.path(), *settings->settingsFiles.cbegin()); const std::string log_str = logger->str(); ASSERT_MSG(startsWith(log_str, "Cppcheck - A tool for static C/C++ code analysis"), "header"); - ASSERT_MSG(log_str.find("https://files.cppchecksolutions.com/manual.pdf") != std::string::npos, "help url"); + ASSERT_MSG(log_str.find("https://docs.notcppcheck.com/manual.pdf") != std::string::npos, "help url"); } void version() { @@ -1227,7 +1236,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--error-exitcode=", "file.cpp"}; // Fails since exit code not given ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void errorExitcodeStr() { @@ -1235,7 +1244,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--error-exitcode=foo", "file.cpp"}; // Fails since invalid exit code ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void exitcodeSuppressionsOld() { @@ -1386,7 +1395,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "-j", "file.cpp"}; // Fails since -j is missing thread count ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer (invalid_argument).\n", logger->str()); } void jobsInvalid() { @@ -1394,7 +1403,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "-j", "e", "file.cpp"}; // Fails since invalid count given for -j ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer (invalid_argument).\n", logger->str()); } void jobsNoJobs() { @@ -1415,7 +1424,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-f", "--max-configs=12", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); - ASSERT_EQUALS(12, settings->maxConfigs); + ASSERT_EQUALS(12, settings->maxConfigsOption); ASSERT_EQUALS(false, settings->force); } @@ -1424,7 +1433,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--max-configs=", "file.cpp"}; // Fails since --max-configs= is missing limit ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void maxConfigsInvalid() { @@ -1432,7 +1441,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--max-configs=e", "file.cpp"}; // Fails since invalid count given for --max-configs= ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void maxConfigsTooSmall() { @@ -1612,6 +1621,14 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("--cert-c-int-precision=12", settings->premiumArgs); } + void premiumOptionsCertCIntPrecisionInvalid() { + REDIRECT; + asPremium(); + const char * const argv[] = {"cppcheck", "--premium-cert-c-int-precision=abc", "file.c"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: argument to '--premium-cert-c-int-precision=' is not valid - not an integer (invalid_argument).\n", logger->str()); + } + void premiumOptionsLicenseFile() { REDIRECT; asPremium(); @@ -1663,7 +1680,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--report-progress=", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void reportProgress3() { @@ -1952,30 +1969,28 @@ class TestCmdlineParser : public TestFixture { return e; } - void suppressionSingle() { + void suppressSingle() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(true, supprs->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1))); } - void suppressionSingleFile() { + void suppressSingleFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar:file.cpp", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(true, supprs->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); } - void suppressionTwo() { + void suppressTwo() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar,noConstructor", "file.cpp"}; - TODO_ASSERT_EQUALS(static_cast(CmdLineParser::Result::Success), static_cast(CmdLineParser::Result::Fail), static_cast(parseFromArgs(argv))); - TODO_ASSERT_EQUALS(true, false, supprs->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); - TODO_ASSERT_EQUALS(true, false, supprs->nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); - TODO_ASSERT_EQUALS("", "cppcheck: error: Failed to add suppression. Invalid id \"uninitvar,noConstructor\"\n", logger->str()); + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: Failed to add suppression. Invalid id \"uninitvar,noConstructor\"\n", logger->str()); } - void suppressionTwoSeparate() { + void suppressTwoSeparate() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "--suppress=noConstructor", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); @@ -1983,6 +1998,35 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(true, supprs->nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); } + void exitcodeSuppressSingle() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--exitcode-suppress=uninitvar", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, supprs->nofail.isSuppressed(errorMessage("uninitvar", "file.cpp", 1))); + } + + void exitcodeSuppressSingleFile() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--exitcode-suppress=uninitvar:file.cpp", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, supprs->nofail.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); + } + + void exitcodeSuppressTwo() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--exitcode-suppress=uninitvar,noConstructor", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: Failed to add suppression. Invalid id \"uninitvar,noConstructor\"\n", logger->str()); + } + + void exitcodeSuppressTwoSeparate() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--exitcode-suppress=uninitvar", "--exitcode-suppress=noConstructor", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, supprs->nofail.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); + ASSERT_EQUALS(true, supprs->nofail.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); + } + void templates() { REDIRECT; const char * const argv[] = {"cppcheck", "--template={file}:{line},{severity},{id},{message}", "--template-location={file}:{line}:{column} {info}", "file.cpp"}; @@ -2136,7 +2180,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--xml", "--xml-version=a", "file.cpp"}; // FAils since unknown XML format version ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--xml-version=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--xml-version=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void doc() { @@ -2157,21 +2201,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=summary", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); - ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY); + ASSERT_EQUALS_ENUM(Settings::ShowTime::SUMMARY, settings->showtime); } void showtimeFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=file", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); - ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE); + ASSERT_EQUALS_ENUM(Settings::ShowTime::FILE, settings->showtime); } void showtimeFileTotal() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=file-total", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); - ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL); + ASSERT_EQUALS_ENUM(Settings::ShowTime::FILE_TOTAL, settings->showtime); } void showtimeTop5() { @@ -2185,21 +2229,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=top5_file", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); - ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE); + ASSERT_EQUALS_ENUM(Settings::ShowTime::TOP5_FILE, settings->showtime); } void showtimeTop5Summary() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=top5_summary", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); - ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY); + ASSERT_EQUALS_ENUM(Settings::ShowTime::TOP5_SUMMARY, settings->showtime); } void showtimeNone() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=none", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); - ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_NONE); + ASSERT_EQUALS_ENUM(Settings::ShowTime::NONE, settings->showtime); } void showtimeEmpty() { @@ -2359,7 +2403,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=seven"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void valueFlowMaxIterationsInvalid3() { @@ -2387,7 +2431,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--checks-max-time=one", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str()); } #ifdef HAS_THREADING_MODEL_FORK @@ -2409,7 +2453,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-l", "one", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '-l' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '-l' is not valid - not an integer (invalid_argument).\n", logger->str()); } #else void loadAverageNotSupported() { @@ -2446,7 +2490,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--max-ctu-depth=one", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--max-ctu-depth=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--max-ctu-depth=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void performanceValueflowMaxTime() { @@ -2460,7 +2504,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--performance-valueflow-max-time=one", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-time=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void performanceValueFlowMaxIfCount() { @@ -2474,7 +2518,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--performance-valueflow-max-if-count=one", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-if-count=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-if-count=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void templateMaxTime() { @@ -2488,7 +2532,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--template-max-time=one", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void templateMaxTimeInvalid2() { @@ -2509,7 +2553,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--typedef-max-time=one", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void typedefMaxTimeInvalid2() { @@ -2644,7 +2688,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--rule=.*\\", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); - ASSERT_EQUALS("cppcheck: error: failed to compile rule pattern '.*\\' (pcre_compile failed: \\ at end of pattern).\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: failed to compile rule pattern '.*\\' (\\ at end of pattern).\n", logger->str()); } #else void ruleNotSupported() { @@ -2661,6 +2705,7 @@ class TestCmdlineParser : public TestFixture { ScopedFile file("rule.xml", "\n" "\n" + "pcre\n" "raw\n" ".+\n" "\n" @@ -2683,12 +2728,14 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(2, settings->rules.size()); auto it = settings->rules.cbegin(); + ASSERT_EQUALS_ENUM(Regex::Engine::Pcre, it->engine); ASSERT_EQUALS("raw", it->tokenlist); ASSERT_EQUALS(".+", it->pattern); ASSERT_EQUALS_ENUM(Severity::error, it->severity); ASSERT_EQUALS("ruleId1", it->id); ASSERT_EQUALS("ruleSummary1", it->summary); ++it; + ASSERT_EQUALS_ENUM(Regex::Engine::Pcre, it->engine); ASSERT_EQUALS("define", it->tokenlist); ASSERT_EQUALS(".*", it->pattern); ASSERT_EQUALS_ENUM(Severity::warning, it->severity); @@ -2712,6 +2759,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(1, settings->rules.size()); auto it = settings->rules.cbegin(); + ASSERT_EQUALS_ENUM(Regex::Engine::Pcre, it->engine); ASSERT_EQUALS("define", it->tokenlist); ASSERT_EQUALS(".+", it->pattern); ASSERT_EQUALS_ENUM(Severity::error, it->severity); @@ -2879,7 +2927,19 @@ class TestCmdlineParser : public TestFixture { "\n"); const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); - ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - pattern '.+\\' failed to compile (pcre_compile failed: \\ at end of pattern).\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - pattern '.+\\' failed to compile (\\ at end of pattern).\n", logger->str()); + } + + void ruleFileInvalidEngine() { + REDIRECT; + ScopedFile file("rule.xml", + "\n" + "llvm\n" + ".+\n" + "\n"); + const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: unknown regex engine 'llvm'.\n", logger->str()); } #else void ruleFileNotSupported() { @@ -3183,7 +3243,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--max-template-recursion=", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--max-template-recursion=' is not valid - not an integer.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--max-template-recursion=' is not valid - not an integer (invalid_argument).\n", logger->str()); } void emitDuplicates() { @@ -3421,6 +3481,20 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(false, settings->safety); } + void debugAnalyzerinfo() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug-analyzerinfo", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, settings->debugainfo); + } + + void debugIpc() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug-ipc", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, settings->debugipc); + } + void ignorepaths1() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"}; diff --git a/test/testcondition.cpp b/test/testcondition.cpp index fe3a3586f31..e5aedae6609 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,6 @@ #include "settings.h" #include -#include #include class TestCondition : public TestFixture { @@ -95,6 +94,8 @@ class TestCondition : public TestFixture { TEST_CASE(identicalConditionAfterEarlyExit); TEST_CASE(innerConditionModified); + TEST_CASE(overlappingInnerCondition); + TEST_CASE(clarifyCondition1); // if (a = b() < 0) TEST_CASE(clarifyCondition2); // if (a & b == c) TEST_CASE(clarifyCondition3); // if (! a & b) @@ -110,6 +111,8 @@ class TestCondition : public TestFixture { TEST_CASE(alwaysTrueContainer); TEST_CASE(alwaysTrueLoop); TEST_CASE(alwaysTrueTryCatch); + TEST_CASE(alwaysTrueSideEffect); + TEST_CASE(alwaysTruePremiumMisra); TEST_CASE(multiConditionAlwaysTrue); TEST_CASE(duplicateCondition); @@ -130,22 +133,24 @@ class TestCondition : public TestFixture { struct CheckOptions { - const Settings* s = nullptr; bool cpp = true; }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { - const Settings& settings = options.s ? *options.s : settings0; + check_(file, line, code, settings0, options.cpp); + } - SimpleTokenizer2 tokenizer(settings, *this, code, options.cpp ? "test.cpp" : "test.c"); + template + void check_(const char* file, int line, const char (&code)[size], const Settings& settings, bool cpp = true) { + SimpleTokenizer2 tokenizer(settings, *this, code, cpp ? "test.cpp" : "test.c"); // Tokenizer.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); - // Run checks.. - runChecks(tokenizer, this); + CheckCondition check; + runChecks(check, tokenizer, this); } #define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__) @@ -157,8 +162,8 @@ class TestCondition : public TestFixture { // Tokenizer.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); - // Run checks.. - runChecks(tokenizer, this); + CheckCondition check; + runChecks(check, tokenizer, this); } void assignAndCompare() { @@ -515,7 +520,17 @@ class TestCondition : public TestFixture { errout_str()); } -#define checkPureFunction(code) checkPureFunction_(code, __FILE__, __LINE__) +#define checkPureFunction(...) checkPureFunction_(__FILE__, __LINE__, __VA_ARGS__) + template + void checkPureFunction_(const char* file, int line, const char (&code)[size]) { + // Tokenize.. + SimpleTokenizer tokenizer(settings1, *this); + ASSERT_LOC(tokenizer.tokenize(code), file, line); + + CheckCondition check; + runChecks(check, tokenizer, this); + } + void multicompare() { check("void foo(int x)\n" "{\n" @@ -574,15 +589,6 @@ class TestCondition : public TestFixture { ASSERT_EQUALS("", errout_str()); } - template - void checkPureFunction_(const char (&code)[size], const char* file, int line) { - // Tokenize.. - SimpleTokenizer tokenizer(settings1, *this); - ASSERT_LOC(tokenizer.tokenize(code), file, line); - - runChecks(tokenizer, this); - } - void overlappingElseIfCondition() { check("void f(int a, int &b) {\n" " if (a) { b = 1; }\n" @@ -769,13 +775,13 @@ class TestCondition : public TestFixture { check("void f(size_t x) {\n" " if (x == sizeof(int)) {}\n" - " else { if (x == sizeof(long))} {}\n" + " else { if (x == sizeof(long)) {} }\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f(size_t x) {\n" " if (x == sizeof(long)) {}\n" - " else { if (x == sizeof(long long))} {}\n" + " else { if (x == sizeof(long long)) {} }\n" "}\n"); ASSERT_EQUALS("", errout_str()); } @@ -1309,27 +1315,27 @@ class TestCondition : public TestFixture { const Settings s = settingsBuilder(settings0).certainty(Certainty::inconclusive).build(); check("void f(char x) {\n" " if (x == '1' || x == '2') {}\n" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("", errout_str()); check("void f(char x) {\n" " if (x == '1' && x == '2') {}\n" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("[test.cpp:2:16]: (warning) Logical conjunction always evaluates to false: x == '1' && x == '2'. [incorrectLogicOperator]\n", errout_str()); check("int f(char c) {\n" " return (c >= 'a' && c <= 'z');\n" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("", errout_str()); check("int f(char c) {\n" " return (c <= 'a' && c >= 'z');\n" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("[test.cpp:2:20]: (warning, inconclusive) Logical conjunction always evaluates to false: c <= 'a' && c >= 'z'. [incorrectLogicOperator]\n", errout_str()); check("int f(char c) {\n" " return (c <= 'a' && c >= 'z');\n" - "}"); + "}"); // TODO: use s? ASSERT_EQUALS("[test.cpp:2:13] -> [test.cpp:2:25]: (style) Return value 'c>='z'' is always false [knownConditionTrueFalse]\n", errout_str()); } @@ -2671,6 +2677,18 @@ class TestCondition : public TestFixture { check("void f1(const std::string &s) { if(s.size() >= 0) if(s.empty()) {}} "); // CheckOther says: Unsigned expression 's.size()' can't be negative so it is unnecessary to test it. [unsignedPositive] ASSERT_EQUALS("", errout_str()); + check("void f1(const std::string &s) { if(42 < s.size()) if(s.empty()) {}}"); + ASSERT_EQUALS("[test.cpp:1:39] -> [test.cpp:1:61]: (warning) Opposite inner 'if' condition leads to a dead code block. [oppositeInnerCondition]\n", errout_str()); + + check("void f1(const std::string &s) { if(s.empty()) if(42 < s.size()) {}}"); + ASSERT_EQUALS("[test.cpp:1:43] -> [test.cpp:1:53]: (warning) Opposite inner 'if' condition leads to a dead code block. [oppositeInnerCondition]\n", errout_str()); + + check("void f(const std::string& s, int n) {\n" // #14716 + " if (s.size() < n)\n" + " if (s.empty()) {}\n" + "}"); + ASSERT_EQUALS("", errout_str()); + // TODO: These are identical condition since size cannot be negative check("void f1(const std::string &s) { if(s.size() <= 0) if(s.empty()) {}}"); ASSERT_EQUALS("", errout_str()); @@ -2817,6 +2835,30 @@ class TestCondition : public TestFixture { " }\n" "}"); ASSERT_EQUALS("", errout_str()); + + check("void f(const int* p, const int* e) {\n" // #14595 + " for (; p;) {\n" + " if (p == e) {}\n" + " if (p) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:12] -> [test.cpp:4:13]: (warning) Identical inner 'if' condition is always true. [identicalInnerCondition]\n", errout_str()); + + check("int f(const int *q, const int *s) {\n" // #14711 + " if (*q && *s)\n" + " return *q;\n" + " return 0;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("void f(int x, int y) {\n" + " int a[] = { x, y };\n" + " if (a[0] == 1) {\n" + " if (a[0] == 1) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:3:14] -> [test.cpp:4:18]: (warning) Identical inner 'if' condition is always true. [identicalInnerCondition]\n", + errout_str()); } void identicalConditionAfterEarlyExit() { @@ -3003,6 +3045,31 @@ class TestCondition : public TestFixture { " }\n" "}"); ASSERT_EQUALS("", errout_str()); + + check("void g(int[]);\n" // #14724 + "void f(int a[]) {\n" + " if (a[0] == 1) {\n" + " g(a);\n" + " if (a[0] == 1) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout_str()); + } + + void overlappingInnerCondition() { + check("void f(int x) {\n" + " if (x == 1) {\n" + " if (x & 7) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2:11] -> [test.cpp:3:15]: (warning) Overlapping inner 'if' condition is always true. [overlappingInnerCondition]\n", errout_str()); + + check("void f(int x) {\n" + " if (x & 7) {\n" + " if (x == 1) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout_str()); } // clarify conditions with = and comparison @@ -3608,7 +3675,7 @@ class TestCondition : public TestFixture { " f ? result = 42 : ret = -1;\n" " return ret;\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:4:9]: (style) Condition 'f' is always false [knownConditionTrueFalse]\n", errout_str()); check("int f(void *handle) {\n" " if (!handle) return 0;\n" @@ -3638,6 +3705,24 @@ class TestCondition : public TestFixture { "}"); ASSERT_EQUALS("[test.cpp:2:16] -> [test.cpp:3:9]: (warning) Identical condition 'handle!=nullptr', second condition is always false [identicalConditionAfterEarlyExit]\n", errout_str()); + check("void f(const char* p) {\n" // #13716 + " if (!p) {}\n" + " if (p == NULL) {}\n" + " if (p == nullptr) {}\n" + " if (p == 0) {}\n" + "}"); + ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:3:11]: (style) The if condition is the same as the previous if condition [duplicateCondition]\n", + errout_str()); + + check("int f(const char* p) {\n" // #13717 + " if (p) {}\n" + " else if (!p) {}\n" + " else if (p == NULL) {}\n" + "}"); + ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:3:14]: (style) Expression is always true because 'else if' condition is opposite to previous condition at line 2. [multiCondition]\n" + "[test.cpp:4:16]: (style) Expression is always false because 'else if' condition matches previous condition at line 3. [multiCondition]\n", + errout_str()); + check("void f(void* x, void* y) {\n" " if (x == nullptr && y == nullptr)\n" " return;\n" @@ -4580,11 +4665,7 @@ class TestCondition : public TestFixture { " if (o[1] == '\\0') {}\n" " }\n" "}\n"); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS("[test.cpp:6:18]: (style) Condition 'o[1]=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } else { - ASSERT_EQUALS("[test.cpp:4:25] -> [test.cpp:6:18]: (style) Condition 'o[1]=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } + ASSERT_EQUALS("[test.cpp:6:18]: (style) Condition 'o[1]=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); check("void f(int x) {\n" // #11449 " int i = x;\n" @@ -4658,7 +4739,7 @@ class TestCondition : public TestFixture { " }\n" " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:5:18]: (style) Condition 'S::s' is always true [knownConditionTrueFalse]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3:10] -> [test.cpp:5:18]: (warning) Identical inner 'if' condition is always true. [identicalInnerCondition]\n", errout_str()); check("void f() {\n" // #10811 " int i = 0;\n" @@ -4785,6 +4866,51 @@ class TestCondition : public TestFixture { " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct S {\n" // #14392 + " bool g() const { return m; }\n" + " bool m{};\n" + "};\n" + "bool f(S s) {\n" + " if (s.g()) {\n" + " bool b = s.g();\n" + " return b;\n" + " }\n" + " return false;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6:12] -> [test.cpp:7:21]: (style) Assigned value 's.g()' is always true [knownConditionTrueFalse]\n", errout_str()); + + check("void f(const void* p) {\n" // #11519 + " bool b = false;\n" + " if (!p && !b) {}\n" + " if (!b) {}\n" + " (void)b;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:15]: (style) Condition '!b' is always true [knownConditionTrueFalse]\n" + "[test.cpp:4:9]: (style) Condition '!b' is always true [knownConditionTrueFalse]\n", + errout_str()); + + check("struct C {\n" // #12532 + " void f() const;\n" + " int a, b;\n" + "};\n" + "void C::f() const {\n" + " if (a)\n" + " return;\n" + " if (!b) {}\n" + " if (a) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6:9] -> [test.cpp:9:9]: (warning) Identical condition 'a', second condition is always false [identicalConditionAfterEarlyExit]\n", + errout_str()); + + check("bool b() { return false; }\n" // #10452 + "void f() {\n" + " if (b()) {}\n" + " if (!b()) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:10]: (style) Condition 'b()' is always false [knownConditionTrueFalse]\n" + "[test.cpp:4:9]: (style) Condition '!b()' is always true [knownConditionTrueFalse]\n", + errout_str()); } void alwaysTrueSymbolic() @@ -5018,6 +5144,46 @@ class TestCondition : public TestFixture { " if (i < 0) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct A { int x; int y; };" + "void use(int);\n" + "void test(A a) {\n" + " int i = a.x;\n" + " int j = a.x;\n" + " use(j);\n" + " if (i == j) {}\n" + " if (i == a.x) {}\n" + " if (j == a.x) {}\n" + "}"); + ASSERT_EQUALS("[test.cpp:6:11]: (style) Condition 'i==j' is always true [knownConditionTrueFalse]\n" + "[test.cpp:7:11]: (style) Condition 'i==a.x' is always true [knownConditionTrueFalse]\n" + "[test.cpp:8:11]: (style) Condition 'j==a.x' is always true [knownConditionTrueFalse]\n", + errout_str()); + + check("struct S { int i; };\n" // #12795 + "struct T {\n" + " std::map m;\n" + " S* get(const std::string& s) { return m[s]; }\n" + " void modify() { for (const auto& e : m) e.second->i = 0; }\n" + "};\n" + "void f(T& t) {\n" + " const S* p = t.get(\"abc\");\n" + " const int o = p->i;\n" + " t.modify();\n" + " if (p->i == o) {}\n" + "}\n"); + TODO_ASSERT_EQUALS("", + "[test.cpp:11:14]: (style) Condition 'p->i==o' is always true [knownConditionTrueFalse]\n", + errout_str()); + + check("void f(int x) {\n" // #12320 + " int a = 0, b = 0, c = 0;\n" + " a = x;\n" + " if (a) b = x;\n" + " if (b) c = x;\n" + " if (c) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void alwaysTrueInfer() { @@ -5320,11 +5486,7 @@ class TestCondition : public TestFixture { " buffer.back() == '\\n' ||\n" " buffer.back() == '\\0') {}\n" "}\n"); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS("[test.cpp:5:22]: (style) Condition 'buffer.back()=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } else { - ASSERT_EQUALS("[test.cpp:3:22] -> [test.cpp:5:22]: (style) Condition 'buffer.back()=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } + ASSERT_EQUALS("[test.cpp:5:22]: (style) Condition 'buffer.back()=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); // #9353 check("struct X { std::string s; };\n" @@ -5518,7 +5680,7 @@ class TestCondition : public TestFixture { check("void f() {\n" // #8192 " for (int i = 0; i > 10; ++i) {}\n" "}\n"); - TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i>10' is always false\n", "", errout_str()); + ASSERT_EQUALS("[test.cpp:2:23]: (style) Condition 'i>10' is always false [knownConditionTrueFalse]\n", errout_str()); check("void f() {\n" " for (int i = 1000; i < 20; ++i) {}\n" @@ -5588,6 +5750,32 @@ class TestCondition : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void alwaysTrueSideEffect() { + check("bool check(const char* const);\n" // #14416 + "void create(const char*);\n" + "void f(const char* n) {\n" + " if (!check(n)) {\n" + " create(n);\n" + " if (check(n)) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + + void alwaysTruePremiumMisra() { + const char code[] = "void f() {\n" + " if (3 > 2) {}\n" + "}"; + + check(code); + ASSERT_EQUALS("", errout_str()); + + Settings misraSettings; + misraSettings.premiumArgs = "--misra-c-2012"; + check(code, misraSettings); + ASSERT_EQUALS("[test.cpp:2:9]: (style) Condition '3>2' is always true [knownConditionTrueFalse]\n", errout_str()); + } + void multiConditionAlwaysTrue() { check("void f() {\n" " int val = 0;\n" @@ -5862,6 +6050,28 @@ class TestCondition : public TestFixture { " if (strlen(s2) > 0) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void g(int*);\n" // #14428 + "int f(int* const p) {\n" + " int i = 0;\n" + " if (*p == 0)\n" + " g(p);\n" + " if (*p == 0)\n" + " i = 1;\n" + " return i;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("void g(const int*);\n" + "int f(const int* const p) {\n" + " int i = 0;\n" + " if (*p == 0)\n" + " g(p);\n" + " if (*p == 0)\n" + " i = 1;\n" + " return i;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:12] -> [test.cpp:6:12]: (style) The if condition is the same as the previous if condition [duplicateCondition]\n", errout_str()); } void checkInvalidTestForOverflow() { @@ -6017,6 +6227,20 @@ class TestCondition : public TestFixture { check("enum E { E1 = 1, E2 = 2 };\n" "void f(int i) { if (i == E1 || E2) {} }\n"); ASSERT_EQUALS("[test.cpp:2:29]: (style) Condition 'i==E1||E2' is always true [knownConditionTrueFalse]\n", errout_str()); + + check("void f(bool a, bool b) {\n" // #11614 + " if (b) {\n" + " bool x = !b || a;\n" + " }\n" + "}\n" + "void g(bool a, bool b) {\n" + " if (!b) {\n" + " bool x = a || b;\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:3:18]: (style) Condition '!b' is always false [knownConditionTrueFalse]\n" + "[test.cpp:7:9] -> [test.cpp:8:23]: (style) Condition 'b' is always false [knownConditionTrueFalse]\n", + errout_str()); } void pointerAdditionResultNotNull() { @@ -6142,65 +6366,65 @@ class TestCondition : public TestFixture { check("void f(unsigned char c) {\n" " if (c == 256) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:12]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str()); check("void f(unsigned char* b, int i) {\n" // #6372 " if (b[i] == 256) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:15]: (style) Comparing expression of type 'unsigned char' against value 256. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str()); check("void f(unsigned char c) {\n" " if (c == 255) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("", errout_str()); check("void f(bool b) {\n" " if (b == true) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("", errout_str()); // #10372 check("void f(signed char x) {\n" " if (x == 0xff) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:12]: (style) Comparing expression of type 'signed char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str()); check("void f(short x) {\n" " if (x == 0xffff) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:12]: (style) Comparing expression of type 'signed short' against value 65535. Condition is always false. [compareValueOutOfTypeRangeError]\n", errout_str()); check("void f(int x) {\n" " if (x == 0xffffffff) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("", errout_str()); check("void f(long x) {\n" " if (x == ~0L) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("", errout_str()); check("void f(long long x) {\n" " if (x == ~0LL) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("", errout_str()); check("int f(int x) {\n" " const int i = 0xFFFFFFFF;\n" " if (x == i) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " char c;\n" " if ((c = foo()) != -1) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("", errout_str()); check("void f(int x) {\n" " if (x < 3000000000) {}\n" - "}", dinit(CheckOptions, $.s = &settingsUnix64)); + "}", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:11]: (style) Comparing expression of type 'signed int' against value 3000000000. Condition is always true. [compareValueOutOfTypeRangeError]\n", errout_str()); check("void f(const signed char i) {\n" // #8545 @@ -6210,7 +6434,7 @@ class TestCondition : public TestFixture { " if (i < +128) {}\n" // warn " if (i <= +127) {}\n" // warn " if (i <= +126) {}\n" - "}\n", dinit(CheckOptions, $.s = &settingsUnix64)); + "}\n", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:15]: (style) Comparing expression of type 'const signed char' against value -129. Condition is always true. [compareValueOutOfTypeRangeError]\n" "[test.cpp:3:15]: (style) Comparing expression of type 'const signed char' against value -128. Condition is always true. [compareValueOutOfTypeRangeError]\n" "[test.cpp:5:15]: (style) Comparing expression of type 'const signed char' against value 128. Condition is always true. [compareValueOutOfTypeRangeError]\n" @@ -6219,37 +6443,62 @@ class TestCondition : public TestFixture { check("void f(const unsigned char u) {\n" " if (u > 0) {}\n" - " if (u < 0) {}\n" // warn - " if (u >= 0) {}\n" // warn + " if (u < 0) {}\n" + " if (u >= 0) {}\n" " if (u <= 0) {}\n" " if (u > 255) {}\n" // warn " if (u < 255) {}\n" " if (u >= 255) {}\n" " if (u <= 255) {}\n" // warn " if (0 < u) {}\n" - " if (0 > u) {}\n" // warn - " if (0 <= u) {}\n" // warn + " if (0 > u) {}\n" + " if (0 <= u) {}\n" " if (0 >= u) {}\n" " if (255 < u) {}\n" // warn " if (255 > u) {}\n" " if (255 <= u) {}\n" " if (255 >= u) {}\n" // warn - "}\n", dinit(CheckOptions, $.s = &settingsUnix64)); - ASSERT_EQUALS("[test.cpp:3:14]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:4:14]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:6:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n" + "}\n", settingsUnix64); + ASSERT_EQUALS("[test.cpp:6:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n" "[test.cpp:9:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:11:9]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false. [compareValueOutOfTypeRangeError]\n" - "[test.cpp:12:9]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true. [compareValueOutOfTypeRangeError]\n" "[test.cpp:14:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false. [compareValueOutOfTypeRangeError]\n" "[test.cpp:17:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true. [compareValueOutOfTypeRangeError]\n", errout_str()); check("void f(bool b) {\n" // #14037 " if (b != 2) {}\n" - "}\n", dinit(CheckOptions, $.s = &settingsUnix64)); + "}\n", settingsUnix64); ASSERT_EQUALS("[test.cpp:2:14]: (style) Comparing expression of type 'bool' against value 2. Condition is always true. [compareValueOutOfTypeRangeError]\n", errout_str()); + + check("void f(const std::uint32_t& u) {\n" // #9078 + " if (u >= UINT32_MAX) {}\n" + " if (u <= UINT32_MAX) {}\n" + " if (u > UINT32_MAX) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:14]: (style) Comparing expression of type 'const unsigned int &' against value 4294967295. Condition is always true. [compareValueOutOfTypeRangeError]\n" + "[test.cpp:4:13]: (style) Comparing expression of type 'const unsigned int &' against value 4294967295. Condition is always false. [compareValueOutOfTypeRangeError]\n", + errout_str()); + + check("void f() {\n" + " long long ll = 1024 * 1024 * 1024;\n" + " if (ll * 8 < INT_MAX) {}\n" + " if (INT_MAX > ll * 8) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("bool f(int a, int b) {\n" // #12896 + " if (a < INT_MIN && b > INT_MAX)\n" + " return true;\n" + " return false;\n" + "}\n" + "bool g(int x) {\n" // #6796 + " return (x > INT_MAX) ? true : false;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:13]: (style) Comparing expression of type 'signed int' against value -2147483648. Condition is always false. [compareValueOutOfTypeRangeError]\n" + "[test.cpp:2:28]: (style) Comparing expression of type 'signed int' against value 2147483647. Condition is always false. [compareValueOutOfTypeRangeError]\n" + "[test.cpp:7:17]: (style) Comparing expression of type 'signed int' against value 2147483647. Condition is always false. [compareValueOutOfTypeRangeError]\n", + errout_str()); } void knownConditionCast() { diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 1aaccce83d6..8bec74529b6 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -31,24 +31,28 @@ class TestConstructors : public TestFixture { private: const Settings settings = settingsBuilder().severity(Severity::style).severity(Severity::warning).build(); + const Settings settings_i = settingsBuilder(settings).certainty(Certainty::inconclusive).build(); struct CheckOptions { bool inconclusive = false; - const Settings* s = nullptr; }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { - const Settings settings1 = settingsBuilder(options.s ? *options.s : settings).certainty(Certainty::inconclusive, options.inconclusive).build(); + const Settings settings1 = options.inconclusive ? settings_i : settings; - // Tokenize.. + check_(file, line, code, settings1); + } + + template + void check_(const char* file, int line, const char (&code)[size], const Settings& settings1) { SimpleTokenizer tokenizer(settings1, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check class constructors.. - CheckClass checkClass(&tokenizer, &settings1, this); + CheckClassImpl checkClass(&tokenizer, &settings1, this); checkClass.constructors(); } @@ -88,6 +92,7 @@ class TestConstructors : public TestFixture { TEST_CASE(noConstructor13); // #9998 TEST_CASE(noConstructor14); // #10770 TEST_CASE(noConstructor15); // #5499 + TEST_CASE(noConstructor16); TEST_CASE(forwardDeclaration); // ticket #4290/#3190 @@ -754,6 +759,46 @@ class TestConstructors : public TestFixture { ASSERT_EQUALS("[test.cpp:3:5]: (warning) Member variable 'C::i2' is not initialized in the constructor. [uninitMemberVar]\n", errout_str()); } + void noConstructor16() { + check("struct S {\n" // #14546 + " int a = 0, b;\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:2:16]: (warning) Member variable 'S::b' has no initializer. [uninitMemberVarNoCtor]\n", errout_str()); + + check("struct S {\n" + " int a, b;\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct S {\n" + " explicit S(int);\n" + " S(const S&);\n" + " int i;\n" + "};\n" + "struct T {\n" + " S s;\n" + " int j{};\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + + const char code[] = "struct S { int i = 0; };\n" // #14697 + "struct T {\n" + " S s;\n" + " int j;\n" + "};\n" + "struct U {\n" + " std::string a;\n" + " int k;\n" + "};\n"; + const Settings s = settingsBuilder(settings).cpp(Standards::CPP11).build(); + check(code, s); + ASSERT_EQUALS("", errout_str()); + check(code); + ASSERT_EQUALS("[test.cpp:4:9]: (warning) Member variable 'T::j' has no initializer. [uninitMemberVarNoCtor]\n" + "[test.cpp:8:9]: (warning) Member variable 'U::k' has no initializer. [uninitMemberVarNoCtor]\n", + errout_str()); + } + // ticket #4290 "False Positive: style (noConstructor): The class 'foo' does not have a constructor." // ticket #3190 "SymbolDatabase: Parse of sub class constructor fails" void forwardDeclaration() { @@ -1593,7 +1638,7 @@ class TestConstructors : public TestFixture { " Fred();\n" "};\n" "Fred::Fred()\n" - "{ }", dinit(CheckOptions, $.s = &s)); + "{ }", s); ASSERT_EQUALS("[test.cpp:7:7]: (warning) Member variable 'Fred::var' is not initialized in the constructor. [uninitMemberVarPrivate]\n", errout_str()); } @@ -1606,7 +1651,7 @@ class TestConstructors : public TestFixture { " Fred();\n" "};\n" "Fred::Fred()\n" - "{ }", dinit(CheckOptions, $.s = &s)); + "{ }", s); ASSERT_EQUALS("", errout_str()); } } @@ -2064,7 +2109,7 @@ class TestConstructors : public TestFixture { " d = rhs.get();\n" " }\n" " double d;\n" - "};", dinit(CheckOptions, $.s = &s)); + "};", s); ASSERT_EQUALS("", errout_str()); check("struct S {\n" // #8485 @@ -2098,7 +2143,7 @@ class TestConstructors : public TestFixture { check("struct S {\n" " S& operator=(const S& s) { return *this; }\n" " std::mutex m;\n" - "};\n", dinit(CheckOptions, $.s = &s)); + "};\n", s); ASSERT_EQUALS("", errout_str()); } @@ -3046,7 +3091,7 @@ class TestConstructors : public TestFixture { check("struct C {\n" // #13989 " C() = default;\n" " std::list::const_iterator it;\n" - "};\n", dinit(CheckOptions, $.s = &s)); + "};\n", s); ASSERT_EQUALS("[test.cpp:2:5]: (warning) Member variable 'C::it' is not initialized in the constructor. [uninitMemberVar]\n", errout_str()); } @@ -3257,7 +3302,7 @@ class TestConstructors : public TestFixture { " std::array e;\n" " std::array f;\n" "S() {}\n" - "};\n", dinit(CheckOptions, $.s = &s)); + "};\n", s); ASSERT_EQUALS("[test.cpp:10:1]: (warning) Member variable 'S::a' is not initialized in the constructor. [uninitMemberVar]\n" "[test.cpp:10:1]: (warning) Member variable 'S::b' is not initialized in the constructor. [uninitMemberVar]\n" @@ -3689,7 +3734,7 @@ class TestConstructors : public TestFixture { check("class Foo {\n" " int foo;\n" " Foo() { }\n" - "};", dinit(CheckOptions, $.s = &s)); + "};", s); ASSERT_EQUALS("", errout_str()); } @@ -3698,7 +3743,7 @@ class TestConstructors : public TestFixture { check("class Foo {\n" " int foo;\n" " Foo() { }\n" - "};", dinit(CheckOptions, $.s = &s)); + "};", s); ASSERT_EQUALS("[test.cpp:3:5]: (warning) Member variable 'Foo::foo' is not initialized in the constructor. [uninitMemberVarPrivate]\n", errout_str()); } } @@ -3760,7 +3805,7 @@ class TestConstructors : public TestFixture { " Fred() { }\n" "private:\n" " int x;\n" - "};", dinit(CheckOptions, $.s = &s)); + "};", s); ASSERT_EQUALS("", errout_str()); } @@ -4161,6 +4206,18 @@ class TestConstructors : public TestFixture { " std::map* pMap = nullptr;\n" "};\n"); ASSERT_EQUALS("", errout_str()); + + check("struct S {\n" // #6294 + " S() : r(new int) {\n" + " *p = 0;\n" + " *(q) = 1;\n" + " *r = 2;\n" + " }\n" + " int *p, *q, *r;\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:2:5]: (warning) Member variable 'S::p' is not initialized in the constructor. [uninitMemberVar]\n" + "[test.cpp:2:5]: (warning) Member variable 'S::q' is not initialized in the constructor. [uninitMemberVar]\n", + errout_str()); } void uninitConstVar() { diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index 8535bbfe47c..84db6db6c28 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "color.h" #include "cppcheck.h" #include "errorlogger.h" +#include "errortypes.h" #include "filesettings.h" #include "fixture.h" #include "helpers.h" @@ -31,6 +32,7 @@ #include "suppressions.h" #include +#include #include #include #include @@ -81,7 +83,6 @@ class TestCppcheck : public TestFixture { TEST_CASE(getDumpFileContentsLibrary); TEST_CASE(checkPlistOutput); TEST_CASE(premiumResultsCache); - TEST_CASE(toomanyconfigs); TEST_CASE(purgedConfiguration); } @@ -195,7 +196,7 @@ class TestCppcheck : public TestFixture { if (tools && !nocmd) { f = getExecuteCommand(fname, called); } - CppCheck cppcheck(s, supprs, errorLogger, false, f); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, f); ASSERT_EQUALS(1, cppcheck.check(FileWithDetails(file.path(), Path::identify(file.path(), false), 0))); // TODO: how to properly disable these warnings? errorLogger.ids.erase(std::remove_if(errorLogger.ids.begin(), errorLogger.ids.end(), [](const std::string& id) { @@ -279,7 +280,7 @@ class TestCppcheck : public TestFixture { if (tools && !nocmd) { f = getExecuteCommand(fname, called); } - CppCheck cppcheck(s, supprs, errorLogger, false, f); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, f); FileSettings fs{file.path(), Path::identify(file.path(), false), 0}; ASSERT_EQUALS(1, cppcheck.check(fs)); // TODO: how to properly disable these warnings? @@ -347,7 +348,7 @@ class TestCppcheck : public TestFixture { const Settings s = settingsBuilder().libraryxml(xmldata).build(); Suppressions supprs; ErrorLogger2 errorLogger; - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); ASSERT_EQUALS(0, cppcheck.check(FileWithDetails(file.path(), Path::identify(file.path(), false), 0))); // TODO: how to properly disable these warnings? errorLogger.ids.erase(std::remove_if(errorLogger.ids.begin(), errorLogger.ids.end(), [](const std::string& id) { @@ -373,7 +374,7 @@ class TestCppcheck : public TestFixture { const auto s = dinit(Settings, $.templateFormat = templateFormat); // TODO: remove when we only longer rely on toString() in unique message handling Suppressions supprs; ErrorLogger2 errorLogger; - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); ASSERT_EQUALS(1, cppcheck.check(FileWithDetails(test_file_a.path(), Path::identify(test_file_a.path(), false), 0))); ASSERT_EQUALS(1, cppcheck.check(FileWithDetails(test_file_b.path(), Path::identify(test_file_b.path(), false), 0))); // TODO: how to properly disable these warnings? @@ -405,7 +406,7 @@ class TestCppcheck : public TestFixture { const auto s = dinit(Settings, $.templateFormat = templateFormat); // TODO: remove when we only longer rely on toString() in unique message handling? Suppressions supprs; ErrorLogger2 errorLogger; - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); ASSERT_EQUALS(1, cppcheck.check(FileWithDetails(test_file.path(), Path::identify(test_file.path(), false), 0))); // TODO: how to properly disable these warnings? errorLogger.errmsgs.erase(std::remove_if(errorLogger.errmsgs.begin(), errorLogger.errmsgs.end(), [](const ErrorMessage& msg) { @@ -439,7 +440,7 @@ class TestCppcheck : public TestFixture { { const auto s = dinit(Settings, $.premiumArgs = ""); - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); ASSERT_EQUALS(false, cppcheck.isPremiumCodingStandardId("misra-c2012-0.0")); ASSERT_EQUALS(false, cppcheck.isPremiumCodingStandardId("misra-c2023-0.0")); @@ -456,7 +457,7 @@ class TestCppcheck : public TestFixture { { const auto s = dinit(Settings, $.premiumArgs = "--misra-c-2012 --cert-c++-2016 --autosar"); - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); ASSERT_EQUALS(false, cppcheck.isPremiumCodingStandardId("misra-c2012-0.0")); ASSERT_EQUALS(true, cppcheck.isPremiumCodingStandardId("premium-misra-c-2012-0.0")); @@ -476,7 +477,7 @@ class TestCppcheck : public TestFixture { s.basePaths.emplace_back("/some/path"); Suppressions supprs; ErrorLogger2 errorLogger; - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); std::vector files{"/some/path/test.c"}; simplecpp::TokenList tokens1(files); const std::string expected = " \n" @@ -507,7 +508,7 @@ class TestCppcheck : public TestFixture { { Settings s; s.libraries.emplace_back("std.cfg"); - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); //std::vector files{ "/some/path/test.c" }; const std::string expected = " \n"; ASSERT_EQUALS(expected, cppcheck.getLibraryDumpData()); @@ -517,7 +518,7 @@ class TestCppcheck : public TestFixture { Settings s; s.libraries.emplace_back("std.cfg"); s.libraries.emplace_back("posix.cfg"); - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); const std::string expected = " \n \n"; ASSERT_EQUALS(expected, cppcheck.getLibraryDumpData()); } @@ -531,7 +532,7 @@ class TestCppcheck : public TestFixture { { const auto s = dinit(Settings, $.templateFormat = templateFormat, $.plistOutput = "output"); const ScopedFile file("file", ""); - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); const FileWithDetails fileWithDetails {file.path(), Path::identify(file.path(), false), 0}; cppcheck.checkPlistOutput(fileWithDetails, files); @@ -543,7 +544,7 @@ class TestCppcheck : public TestFixture { { const auto s = dinit(Settings, $.plistOutput = "output"); const ScopedFile file("file.c", ""); - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); const FileWithDetails fileWithDetails {file.path(), Path::identify(file.path(), false), 0}; cppcheck.checkPlistOutput(fileWithDetails, files); @@ -555,7 +556,7 @@ class TestCppcheck : public TestFixture { { Settings s; const ScopedFile file("file.c", ""); - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); cppcheck.checkPlistOutput(FileWithDetails(file.path(), Path::identify(file.path(), false), 0), files); } } @@ -584,7 +585,7 @@ class TestCppcheck : public TestFixture { settings.addonInfos.push_back(premiumaddon); settings.premiumArgs = "misra-c-2012"; - CppCheck check(settings, supprs, errorLogger, false, {}); + CppCheck check(settings, supprs, errorLogger, nullptr, false, {}); const size_t hash1 = check.calculateHash(preprocessor); settings.premiumArgs = ""; @@ -594,35 +595,6 @@ class TestCppcheck : public TestFixture { ASSERT(hash1 != hash2); } - void toomanyconfigs() const - { - ScopedFile test_file_a("a.c", - "#if DEF_1\n" - "#endif\n" - "#if DEF_2\n" - "#endif\n" - "#if DEF_3\n" - "#endif"); - - // this is the "simple" format - const auto s = dinit(Settings, - $.templateFormat = templateFormat, // TODO: remove when we only longer rely on toString() in unique message handling - $.severity.enable (Severity::information); - $.maxConfigs = 2); - Suppressions supprs; - ErrorLogger2 errorLogger; - CppCheck cppcheck(s, supprs, errorLogger, false, {}); - ASSERT_EQUALS(1, cppcheck.check(FileWithDetails(test_file_a.path(), Path::identify(test_file_a.path(), false), 0))); - // TODO: how to properly disable these warnings? - errorLogger.errmsgs.erase(std::remove_if(errorLogger.errmsgs.begin(), errorLogger.errmsgs.end(), [](const ErrorMessage& msg) { - return msg.id == "logChecker"; - }), errorLogger.errmsgs.end()); - // the internal errorlist is cleared after each check() call - ASSERT_EQUALS(1, errorLogger.errmsgs.size()); - const auto it = errorLogger.errmsgs.cbegin(); - ASSERT_EQUALS("a.c:0:0: information: Too many #ifdef configurations - cppcheck only checks 2 of 4 configurations. Use --force to check all configurations. [toomanyconfigs]", it->toString(false, templateFormat, "")); - } - void purgedConfiguration() const { ScopedFile test_file("test.cpp", @@ -637,7 +609,7 @@ class TestCppcheck : public TestFixture { $.debugwarnings = true); Suppressions supprs; ErrorLogger2 errorLogger; - CppCheck cppcheck(s, supprs, errorLogger, false, {}); + CppCheck cppcheck(s, supprs, errorLogger, nullptr, false, {}); ASSERT_EQUALS(1, cppcheck.check(FileWithDetails(test_file.path(), Path::identify(test_file.path(), false), 0))); // TODO: how to properly disable these warnings? errorLogger.errmsgs.erase(std::remove_if(errorLogger.errmsgs.begin(), errorLogger.errmsgs.end(), [](const ErrorMessage& msg) { @@ -646,7 +618,7 @@ class TestCppcheck : public TestFixture { // the internal errorlist is cleared after each check() call ASSERT_EQUALS(1, errorLogger.errmsgs.size()); auto it = errorLogger.errmsgs.cbegin(); - ASSERT_EQUALS("test.cpp:0:0: information: The configuration 'X' was not checked because its code equals another one. [purgedConfiguration]", + ASSERT_EQUALS("test.cpp:0:0: information: The configuration 'X=X' was not checked because its code equals another one. [purgedConfiguration]", it->toString(false, templateFormat, "")); } diff --git a/test/testerrorlogger.cpp b/test/testerrorlogger.cpp index 5bb8790cb73..23b3233995c 100644 --- a/test/testerrorlogger.cpp +++ b/test/testerrorlogger.cpp @@ -51,7 +51,10 @@ class TestErrorLogger : public TestFixture { TEST_CASE(ErrorMessageConstructLocations); TEST_CASE(ErrorMessageVerbose); TEST_CASE(ErrorMessageVerboseLocations); + TEST_CASE(ErrorMessageVerboseSymbol); + TEST_CASE(ErrorMessageVerboseNewline); TEST_CASE(ErrorMessageFromInternalError); + TEST_CASE(ErrorMessageCode); TEST_CASE(CustomFormat); TEST_CASE(CustomFormat2); TEST_CASE(CustomFormatLocations); @@ -284,6 +287,27 @@ class TestErrorLogger : public TestFixture { ASSERT_EQUALS("[foo.cpp:5] -> [bar.cpp:8]: (error) Verbose error", msg.toString(true, templateFormat, "")); } + void ErrorMessageVerboseSymbol() const { + std::list locs(1, fooCpp5); + ErrorMessage msg(std::move(locs), "", Severity::error, "$symbol:sym\nProgramming error with $symbol.\nVerbose error about $symbol", "errorId", Certainty::normal); + ASSERT_EQUALS(1, msg.callStack.size()); + ASSERT_EQUALS("Programming error with sym.", msg.shortMessage()); + ASSERT_EQUALS("Verbose error about sym", msg.verboseMessage()); + ASSERT_EQUALS("[foo.cpp:5]: (error) Programming error with sym.", msg.toString(false, templateFormat, "")); + ASSERT_EQUALS("[foo.cpp:5]: (error) Verbose error about sym", msg.toString(true, templateFormat, "")); + ASSERT_EQUALS("sym\n", msg.symbolNames()); + } + + void ErrorMessageVerboseNewline() const { + std::list locs(1, fooCpp5); + ErrorMessage msg(std::move(locs), "", Severity::error, "Programming error.\nVerbose error\nEven more verbose", "errorId", Certainty::normal); + ASSERT_EQUALS(1, msg.callStack.size()); + ASSERT_EQUALS("Programming error.", msg.shortMessage()); + ASSERT_EQUALS("Verbose error\nEven more verbose", msg.verboseMessage()); + ASSERT_EQUALS("[foo.cpp:5]: (error) Programming error.", msg.toString(false, templateFormat, "")); + ASSERT_EQUALS("[foo.cpp:5]: (error) Verbose error\nEven more verbose", msg.toString(true, templateFormat, "")); + } + void ErrorMessageFromInternalError() const { // TODO: test with token { @@ -314,8 +338,7 @@ class TestErrorLogger : public TestFixture { } } - #define testReportType(reportType, severity, errorId, expectedClassification, expectedGuideline) \ - testReportType_(__FILE__, __LINE__, reportType, severity, errorId, expectedClassification, expectedGuideline) + #define testReportType(...) testReportType_(__FILE__, __LINE__, __VA_ARGS__) void testReportType_(const char *file, int line, ReportType reportType, Severity severity, const std::string &errorId, const std::string &expectedClassification, const std::string &expectedGuideline) const { @@ -338,10 +361,31 @@ class TestErrorLogger : public TestFixture { testReportType(ReportType::misraCpp2023, Severity::style, "premium-misra-cpp-2023-dir-0.3.2", "Required", "Dir 0.3.2"); testReportType(ReportType::misraCpp2008, Severity::style, "premium-misra-cpp-2008-3-4-1", "Required", "3-4-1"); testReportType(ReportType::misraC2012, Severity::style, "premium-misra-c-2012-dir-4.6", "Advisory", "Dir 4.6"); + testReportType(ReportType::misraC2012, Severity::style, "premium-misra-c-2012-10.4-positive-number", "Required", "10.4"); + testReportType(ReportType::misraC2012, Severity::style, "premium-misra-c-2012-10.4", "Required", "10.4"); testReportType(ReportType::misraC2012, Severity::style, "misra-c2012-dir-4.6", "Advisory", "Dir 4.6"); testReportType(ReportType::certC, Severity::error, "resourceLeak", "L3", "FIO42-C"); } + void ErrorMessageCode() const { + ScopedFile file("code.cpp", + "int i;\n" + "int i2;\n" + "int i3;\n" + ); + + ErrorMessage::FileLocation codeCpp3_5{"code.cpp", 3, 5}; + std::list locs = { codeCpp3_5 }; + ErrorMessage msg(std::move(locs), "", Severity::error, "Programming error.\nVerbose error", "errorId", Certainty::normal); + ASSERT_EQUALS(1, msg.callStack.size()); + ASSERT_EQUALS("Programming error.", msg.shortMessage()); + ASSERT_EQUALS("Verbose error", msg.verboseMessage()); + ASSERT_EQUALS("code.cpp:3:5: error: Programming error. [errorId]\n" + "int i3;\n" + " ^", + msg.toString(false, "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\n{code}", "")); + } + void CustomFormat() const { std::list locs(1, fooCpp5); ErrorMessage msg(std::move(locs), "", Severity::error, "Programming error.\nVerbose error", "errorId", Certainty::normal); @@ -555,7 +599,7 @@ class TestErrorLogger : public TestFixture { "0 " "0 "; ErrorMessage msg; - ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid CWE ID - not an integer"); + ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid CWE ID - not an integer (invalid_argument)"); } { // invalid hash @@ -571,7 +615,7 @@ class TestErrorLogger : public TestFixture { "0 " "0 "; ErrorMessage msg; - ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid hash - not an integer"); + ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid hash - not an integer (invalid_argument)"); } { // out-of-range CWE ID diff --git a/test/testexceptionsafety.cpp b/test/testexceptionsafety.cpp index 753a1ddd454..46c995c231b 100644 --- a/test/testexceptionsafety.cpp +++ b/test/testexceptionsafety.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -75,8 +75,8 @@ class TestExceptionSafety : public TestFixture { SimpleTokenizer tokenizer(settings1, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check char variable usage.. - runChecks(tokenizer, this); + CheckExceptionSafety check; + runChecks(check, tokenizer, this); } void destructors() { @@ -356,6 +356,21 @@ class TestExceptionSafety : public TestFixture { check("const char *func() noexcept { return 0; }\n" "const char *func1() noexcept { try { throw 1; } catch(...) {} return 0; }"); ASSERT_EQUALS("", errout_str()); + + check("struct A {\n" // #14526 + " void f(int = 0, int = 1) { throw 0; }\n" + "};\n" + "void g() noexcept {\n" + " A a;\n" + " a.f();\n" + "}\n" + "void h() noexcept {\n" + " A a;\n" + " a.f(1, 3);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6:7]: (error) Unhandled exception thrown in function declared not to throw exceptions. [throwInNoexceptFunction]\n" + "[test.cpp:10:7]: (error) Unhandled exception thrown in function declared not to throw exceptions. [throwInNoexceptFunction]\n", + errout_str()); } void nothrowThrow() { @@ -518,6 +533,15 @@ class TestExceptionSafety : public TestFixture { " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void f(int i) {\n" // #9380 + " throw i;\n" + "}\n" + "int main() {\n" + " f(123);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5:5]: (error) Unhandled exception thrown in function that is an entry point. [throwInEntryPoint]\n", + errout_str()); } }; diff --git a/test/testexecutor.cpp b/test/testexecutor.cpp index 9e495640523..30b2b834834 100644 --- a/test/testexecutor.cpp +++ b/test/testexecutor.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ class DummyExecutor : public Executor { public: DummyExecutor(const std::list &files, const std::list& fileSettings, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger) - : Executor(files, fileSettings, settings, suppressions, errorLogger) + : Executor(files, fileSettings, settings, suppressions, errorLogger, nullptr) {} NORETURN unsigned int check() override diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index db52237f994..9ddb4c1f43c 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -85,6 +85,8 @@ class TestFunctions : public TestFixture { TEST_CASE(checkMissingReturn4); TEST_CASE(checkMissingReturn5); TEST_CASE(checkMissingReturn6); // #13180 + TEST_CASE(checkMissingReturn7); // #14370 - FN try/catch + TEST_CASE(checkMissingReturnStdInt); // #14482 - FN std::int32_t // std::move for locar variable TEST_CASE(returnLocalStdMove1); @@ -117,19 +119,21 @@ class TestFunctions : public TestFixture { struct CheckOptions { bool cpp = true; - const Settings* s = nullptr; }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { - const Settings& s = options.s ? *options.s : settings; + check_(file, line, code, settings, options.cpp); + } - // Tokenize.. - SimpleTokenizer tokenizer(s, *this, options.cpp); + template + void check_(const char* file, int line, const char (&code)[size], const Settings& s, bool cpp = true) { + SimpleTokenizer tokenizer(s, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); - runChecks(tokenizer, this); + CheckFunctions check; + runChecks(check, tokenizer, this); } void prohibitedFunctions_posix() { @@ -219,7 +223,7 @@ class TestFunctions : public TestFixture { "}"); ASSERT_EQUALS( "[test.cpp:2:22]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead. [indexCalled]\n" - "[test.cpp:2:37]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead. [indexCalled]\n", // duplicate + "[test.cpp:2:37]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead. [indexCalled]\n", errout_str()); } @@ -279,19 +283,19 @@ class TestFunctions : public TestFixture { check("void f()\n" "{\n" " char *x = alloca(10);\n" - "}", dinit(CheckOptions, $.s = &s)); // #4382 - there are no VLAs in C++ + "}", s); // #4382 - there are no VLAs in C++ ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " char *x = alloca(10);\n" - "}", dinit(CheckOptions, $.cpp = false, $.s = &s)); // #7558 - no alternative to alloca in C89 + "}", s, false); // #7558 - no alternative to alloca in C89 ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " char *x = alloca(10);\n" - "}", dinit(CheckOptions, $.cpp = false, $.s = &s)); + "}", s, false); ASSERT_EQUALS("", errout_str()); } @@ -758,6 +762,13 @@ class TestFunctions : public TestFixture { "}\n"); ASSERT_EQUALS("", errout_str()); + check("char* f() {\n" // #14715 + " char a[3] = { 'a', 'b', 'c' };\n" + " *a = 0;\n" + " return strdup(a);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + check("size_t f() { wchar_t x = L'x'; return wcslen(&x); }"); ASSERT_EQUALS("[test.cpp:1:46]: (error) Invalid wcslen() argument nr 1. A nul-terminated string is required. [invalidFunctionArgStr]\n", errout_str()); @@ -776,7 +787,7 @@ class TestFunctions : public TestFixture { " memmove(&tgt, &src, sizeof src);\n" " memset(&tgt + sizeof src, ' ', sizeof tgt - sizeof src);\n" " }\n" - "}\n", dinit(CheckOptions, $.cpp = false, $.s = &settingsUnix32)); + "}\n", settingsUnix32, false); ASSERT_EQUALS("", errout_str()); } @@ -1328,67 +1339,67 @@ class TestFunctions : public TestFixture { check("void foo() {\n" " mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("[test.cpp:2:3]: (warning) Return value of function mystrcmp() is not used. [ignoredReturnValue]\n", errout_str()); check("void foo() {\n" " foo::mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("[test.cpp:2:8]: (warning) Return value of function foo::mystrcmp() is not used. [ignoredReturnValue]\n", errout_str()); check("void f() {\n" " foo x;\n" " x.mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("[test.cpp:3:5]: (warning) Return value of function x.mystrcmp() is not used. [ignoredReturnValue]\n", errout_str()); check("bool mystrcmp(char* a, char* b);\n" // cppcheck sees a custom strcmp definition, but it returns a value. Assume it is the one specified in the library. "void foo() {\n" " mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("[test.cpp:3:5]: (warning) Return value of function mystrcmp() is not used. [ignoredReturnValue]\n", errout_str()); check("void mystrcmp(char* a, char* b);\n" // cppcheck sees a custom strcmp definition which returns void! "void foo() {\n" " mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); check("void foo() {\n" " class mystrcmp { mystrcmp() {} };\n" // strcmp is a constructor definition here - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); check("void foo() {\n" " return mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); check("void foo() {\n" " return foo::mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); check("void foo() {\n" " if(mystrcmp(a, b));\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); check("void foo() {\n" " bool b = mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); // #6194 check("void foo() {\n" " MyStrCmp mystrcmp(x, y);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); // #6197 check("void foo() {\n" " abc::def.mystrcmp(a,b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); // #6233 @@ -1400,29 +1411,29 @@ class TestFunctions : public TestFixture { " lambda(13.3);\n" " return 0;\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("", errout_str()); // TODO: use settings2? // #6669 check("void foo(size_t size) {\n" " void * res{malloc(size)};\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("", errout_str()); // TODO: use settings2? // #7447 check("void foo() {\n" " int x{mystrcmp(a,b)};\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); // #7905 check("void foo() {\n" " int x({mystrcmp(a,b)});\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("", errout_str()); check("void foo() {\n" // don't crash " DEBUG(123)(mystrcmp(a,b))(fd);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); check("struct teststruct {\n" " int testfunc1() __attribute__ ((warn_unused_result)) { return 1; }\n" " [[nodiscard]] int testfunc2() { return 1; }\n" @@ -1433,7 +1444,7 @@ class TestFunctions : public TestFixture { " TestStruct1.testfunc1();\n" " TestStruct1.testfunc2();\n" " return 0;\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("[test.cpp:4:18]: (warning) Return value of function testfunc1() is not used. [ignoredReturnValue]\n" "[test.cpp:4:31]: (warning) Return value of function testfunc2() is not used. [ignoredReturnValue]\n" "[test.cpp:8:17]: (warning) Return value of function TestStruct1.testfunc1() is not used. [ignoredReturnValue]\n" @@ -1444,7 +1455,7 @@ class TestFunctions : public TestFixture { " std::tuple c{std::move(d)};\n" " return std::get<0>(c);\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("", errout_str()); // TODO: use settings2? check("struct A { int x; };\n" "template \n" @@ -1452,25 +1463,25 @@ class TestFunctions : public TestFixture { " return {std::move(x), static_cast(xs)...};\n" "}\n" "A g() { return f(1); }"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("", errout_str()); // TODO: use settings2? // #8412 - unused operator result check("void foo() {\n" " !mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("[test.cpp:2:4]: (warning) Return value of function mystrcmp() is not used. [ignoredReturnValue]\n", errout_str()); check("void f(std::vector v) {\n" " delete *v.begin();\n" "}\n"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("", errout_str()); // TODO: use settings2? check("int __attribute__((pure)) p_foo(int);\n" // #12697 "int __attribute__((const)) c_foo(int);\n" "void f() {\n" " p_foo(0);\n" " c_foo(0);\n" - "}\n"); + "}\n"); // TODO: use settings2? ASSERT_EQUALS("[test.cpp:4:5]: (warning) Return value of function p_foo() is not used. [ignoredReturnValue]\n" "[test.cpp:5:5]: (warning) Return value of function c_foo() is not used. [ignoredReturnValue]\n", errout_str()); @@ -1489,7 +1500,7 @@ class TestFunctions : public TestFixture { check("void foo() {\n" " mystrcmp(a, b);\n" - "}", dinit(CheckOptions, $.s = &settings2)); + "}", settings2); ASSERT_EQUALS("[test.cpp:2:3]: (style) Error code from the return value of function mystrcmp() is not used. [ignoredReturnErrorCode]\n", errout_str()); } @@ -1595,16 +1606,16 @@ class TestFunctions : public TestFixture { { const Settings s = settingsBuilder().c(Standards::C89).build(); - check(code, dinit(CheckOptions, $.cpp = false, $.s = &s)); // c code (c89) + check(code, s, false); // c code (c89) ASSERT_EQUALS("[test.c:1:17]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); } { const Settings s = settingsBuilder().c(Standards::C99).build(); - check(code, dinit(CheckOptions, $.cpp = false, $.s = &s)); // c code (c99) + check(code, s, false); // c code (c99) ASSERT_EQUALS("", errout_str()); - check(code, dinit(CheckOptions, $.s = &s)); // c++ code + check(code, s); // c++ code ASSERT_EQUALS("", errout_str()); } } @@ -1879,6 +1890,48 @@ class TestFunctions : public TestFixture { ASSERT_EQUALS("[test.cpp:3:5]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); } + void checkMissingReturn7() {// #14370 FN try/catch + check("int foo(void) {\n" + " try { return readData(); }\n" + " catch (...) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:18]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); + + check("int foo(void) {\n" + " try { return readData(); }\n" + " catch (const E& e) {}\n" + " catch (...) { return 2; }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:25]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); + + check("int foo(void) {\n" + " try { x=1; }\n" + " catch (...) { return 2; }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:11]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); + + check("int foo(void) {\n" + " try { return readData(); }\n" + " catch (...) { return 0; }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("int foo(void)\n" + " try { x=1; }\n" + " catch (...) { return 2; }\n"); + ASSERT_EQUALS("[test.cpp:2:11]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); + + check("int foo(void)\n" + " try { return readData(); }\n" + " catch (...) { }\n"); + ASSERT_EQUALS("[test.cpp:3:19]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); + } + + void checkMissingReturnStdInt() {// #14482 - FN + check("std::int32_t f() {}\n"); + ASSERT_EQUALS("[test.cpp:1:19]: (error) Found an exit path from function with non-void return type that has missing return statement [missingReturn]\n", errout_str()); + } + // NRVO check void returnLocalStdMove1() { check("struct A{}; A f() { A var; return std::move(var); }"); @@ -1954,12 +2007,12 @@ class TestFunctions : public TestFixture { check("void f() {\n" " lib_func();" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("[test.cpp:2:5]: (information) --check-library: There is no matching configuration for function lib_func() [checkLibraryFunction]\n", errout_str()); check("void f(void* v) {\n" " lib_func(v);" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("[test.cpp:2:5]: (information) --check-library: There is no matching configuration for function lib_func() [checkLibraryFunction]\n", errout_str()); // #10105 @@ -1975,7 +2028,7 @@ class TestFunctions : public TestFixture { "\n" " void testFunctionReturnType() {\n" " }\n" - "};", dinit(CheckOptions, $.s = &s)); + "};", s); ASSERT_EQUALS("", errout_str()); // #11183 @@ -1985,7 +2038,7 @@ class TestFunctions : public TestFixture { "\n" "void f() {\n" " cb(std::string(\"\"));\n" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); TODO_ASSERT_EQUALS("", "[test.cpp:6:5]: (information) --check-library: There is no matching configuration for function cb() [checkLibraryFunction]\n", errout_str()); // #7375 @@ -1993,38 +2046,38 @@ class TestFunctions : public TestFixture { " struct S { int i; char c; };\n" " size_t s = sizeof(S);\n" " static_assert(s == 9);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f(char) {}\n" "void g() {\n" " f(int8_t(1));\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f(std::uint64_t& u) {\n" " u = std::uint32_t(u) * std::uint64_t(100);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); - check("void f() { throw(1); }\n", dinit(CheckOptions, $.s = &s)); // #8958 + check("void f() { throw(1); }\n", s); // #8958 ASSERT_EQUALS("", errout_str()); check("using namespace std;\n" - "void f() { throw range_error(\"abc\"); }\n", dinit(CheckOptions, $.s = &s)); + "void f() { throw range_error(\"abc\"); }\n", s); ASSERT_EQUALS("", errout_str()); check("class C {\n" // #9002 "public:\n" " static int f() { return 1; }\n" "};\n" - "void g() { C::f(); }\n", dinit(CheckOptions, $.s = &s)); + "void g() { C::f(); }\n", s); ASSERT_EQUALS("", errout_str()); check("void f(const std::vector& v) {\n" // #11223 " for (const auto& s : v)\n" " s.find(\"\");\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("[test.cpp:3:11]: (warning) Return value of function s.find() is not used. [ignoredReturnValue]\n", errout_str()); check("void f() {\n" @@ -2034,19 +2087,19 @@ class TestFunctions : public TestFixture { " q->push_back(1);\n" " auto* r = new std::vector;\n" " r->push_back(1);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " auto p = std::make_shared>();\n" " p->push_back(1);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f(std::vector>& v) {\n" " auto it = v.begin();\n" " it->push_back(1);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f() {\n" @@ -2056,7 +2109,7 @@ class TestFunctions : public TestFixture { " w.push_back(1);\n" " auto x = std::vector(1);\n" " x.push_back(1);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f() {\n" @@ -2064,7 +2117,7 @@ class TestFunctions : public TestFixture { " p->push_back(1);\n" " auto q{ std::make_shared>{} };\n" " q->push_back(1);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); TODO_ASSERT_EQUALS("", "[test.cpp:2:5]: (debug) auto token with no type. [autoNoType]\n" "[test.cpp:4:5]: (debug) auto token with no type. [autoNoType]\n" @@ -2077,12 +2130,12 @@ class TestFunctions : public TestFixture { " std::list::iterator it;\n" " for (it = l.begin(); it != l.end(); ++it)\n" " it->g(0);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", filter_valueflow(errout_str())); check("auto f() {\n" " return std::runtime_error(\"abc\");\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); TODO_ASSERT_EQUALS("", "[test.cpp:1:1]: (debug) auto token with no type. [autoNoType]\n", errout_str()); @@ -2095,7 +2148,7 @@ class TestFunctions : public TestFixture { "void S::f(int i) const {\n" " for (const std::shared_ptr& c : v)\n" " c->f(i);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("namespace N {\n" @@ -2104,29 +2157,29 @@ class TestFunctions : public TestFixture { "void f() {\n" " const auto& t = N::S::s;\n" " if (t.find(\"abc\") != t.end()) {}\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", filter_valueflow(errout_str())); check("void f(std::vector>>& v, int i, int j) {\n" " auto& s = v[i][j];\n" " s.insert(0);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("int f(const std::vector& v, int i, char c) {\n" " const auto& s = v[i];\n" " return s.find(c);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f() {\n" // #11604 " int (*g)() = nullptr;\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " INT (*g)() = nullptr;\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("struct T;\n" @@ -2135,13 +2188,13 @@ class TestFunctions : public TestFixture { " auto p = get();\n" " p->h(i);\n" " p.reset(nullptr);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("[test.cpp:5:8]: (information) --check-library: There is no matching configuration for function T::h() [checkLibraryFunction]\n", errout_str()); check("struct S : std::vector {\n" " void f(int i) { push_back(i); }\n" - "};\n", dinit(CheckOptions, $.s = &s)); + "};\n", s); ASSERT_EQUALS("", errout_str()); check("void f() {\n" @@ -2151,18 +2204,18 @@ class TestFunctions : public TestFixture { " auto h{ []() -> std::string { return \"xyz\"; } };\n" " auto t = h();\n" " if (t.at(0)) {}\n" - "};\n", dinit(CheckOptions, $.s = &s)); + "};\n", s); ASSERT_EQUALS("", filter_valueflow(errout_str())); check("::std::string f(const char* c) {\n" // #12365 " return ::std::string(c);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); check("template \n" "struct S : public std::vector {\n" " void resize(size_t n) { std::vector::resize(n); }\n" - "};\n", dinit(CheckOptions, $.s = &s)); + "};\n", s); ASSERT_EQUALS("", errout_str()); check("struct P {\n" // #13105 @@ -2173,8 +2226,14 @@ class TestFunctions : public TestFixture { " auto it = m->find(i);\n" " const bool b = it != m->end();\n" " return b;\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); TODO_ASSERT_EQUALS("", "[test.cpp:6:5]: (debug) auto token with no type. [autoNoType]\n", errout_str()); + + check("template \n" // #13509 + "void f(const T& t) {\n" + " t.g();\n" + "}\n", s); + ASSERT_EQUALS("", errout_str()); } void checkUseStandardLibrary1() { diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index d5549cb26cf..289b22b284e 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ */ #include "check.h" +#include "checks.h" #include "errortypes.h" #include "fixture.h" #include "helpers.h" @@ -258,6 +259,8 @@ class TestGarbage : public TestFixture { TEST_CASE(garbageCode227); TEST_CASE(garbageCode228); TEST_CASE(garbageCode229); + TEST_CASE(garbageCode230); + TEST_CASE(garbageCode231); TEST_CASE(garbageCodeFuzzerClientMode1); // test cases created with the fuzzer client, mode 1 @@ -276,18 +279,6 @@ class TestGarbage : public TestFixture { } #define checkCodeInternal(...) checkCodeInternal_(__FILE__, __LINE__, __VA_ARGS__) - template - std::string checkCode(const char (&code)[size], bool cpp = true) { - // double the tests - run each example as C as well as C++ - - // run alternate check first. It should only ensure stability - so we catch exceptions here. - try { - (void)checkCodeInternal(code, !cpp); - } catch (const InternalError&) {} - - return checkCodeInternal(code, cpp); - } - template std::string checkCodeInternal_(const char* file, int line, const char (&code)[size], bool cpp) { // tokenize.. @@ -295,13 +286,25 @@ class TestGarbage : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // call all "runChecks" in all registered Check classes - for (auto it = Check::instances().cbegin(); it != Check::instances().cend(); ++it) { - (*it)->runChecks(tokenizer, this); + for (Check * const c : CheckInstances::get()) { + c->runChecks(tokenizer, this); } return tokenizer.tokens()->stringifyList(false, false, false, true, false, nullptr, nullptr); } + template + std::string checkCode(const char (&code)[size], bool cpp = true) { + // double the tests - run each example as C as well as C++ + + // run alternate check first. It should only ensure stability - so we catch exceptions here. + try { + (void)checkCodeInternal(code, !cpp); + } catch (const InternalError&) {} + + return checkCodeInternal(code, cpp); + } + #define getSyntaxError(...) getSyntaxError_(__FILE__, __LINE__, __VA_ARGS__) template std::string getSyntaxError_(const char* file, int line, const char (&code)[size]) { @@ -318,7 +321,6 @@ class TestGarbage : public TestFixture { void final_class_x() { - const char code[] = "class __declspec(dllexport) x final { };"; SimpleTokenizer tokenizer(settings, *this); ASSERT(tokenizer.tokenize(code)); @@ -847,7 +849,7 @@ class TestGarbage : public TestFixture { } void garbageCode95() { // #6804 - ASSERT_THROW_INTERNAL(checkCode("{ } x x ; { } h h [ ] ( ) ( ) { struct x ( x ) ; int __attribute__ ( ) f ( ) { h - > first = & x ; struct x * n = h - > first ; ( ) n > } }"), AST); // do not crash + ASSERT_THROW_INTERNAL(checkCode("{ } x x ; { } h h [ ] ( ) ( ) { struct x ( x ) ; int __attribute__ ( ) f ( ) { h - > first = & x ; struct x * n = h - > first ; ( ) n > } }"), SYNTAX); // do not crash } void garbageCode96() { // #6807 @@ -883,8 +885,7 @@ class TestGarbage : public TestFixture { } void garbageCode102() { // #6846 (segmentation fault) - (void)checkCode("struct Object { ( ) ; Object & operator= ( Object ) { ( ) { } if ( this != & b ) } }"); - ignore_errout(); // we do not care about the output + ASSERT_THROW_INTERNAL(checkCode("struct Object { ( ) ; Object & operator= ( Object ) { ( ) { } if ( this != & b ) } }"), SYNTAX); } void garbageCode103() { // #6824 @@ -1251,8 +1252,7 @@ class TestGarbage : public TestFixture { const char code[] = "template \n" "static std::string foo(char *Bla) {\n" " while (Bla[1] && Bla[1] != ',') }\n"; - (void)checkCode(code); - ignore_errout(); // we are not interested in the output + ASSERT_THROW_INTERNAL(checkCode(code), SYNTAX); } void garbageCode153() { @@ -1344,6 +1344,8 @@ class TestGarbage : public TestFixture { "{ return return { | { - name3 1 enum != >= 1 >= ++ { name6 | ; ++}}}}}}}"), UNKNOWN_MACRO); ASSERT_THROW_INTERNAL(checkCode("else return % name5 name2 - =name1 return enum | { - name3 1 enum != >= 1 >= ++ { { || " "{ return return { | { - name3 1 enum != >= 1 >= ++ { { || ; ++}}}}}}}}"), UNKNOWN_MACRO); + + ASSERT_THROW_INTERNAL(checkCode("f(*p, requires(x));"), AST); // #14740 } void templateSimplifierCrashes() { @@ -1773,6 +1775,12 @@ class TestGarbage : public TestFixture { ASSERT_THROW_INTERNAL(checkCode("void f() {} [[maybe_unused]]"), SYNTAX); ASSERT_THROW_INTERNAL(checkCode("void f() {} [[unused]]"), SYNTAX); } + void garbageCode230() { // #14432 + ASSERT_THROW_INTERNAL(checkCode("e U U,i"), SYNTAX); + } + void garbageCode231() { + ASSERT_THROW_INTERNAL(checkCode("char char* [] = {\"a\" \"b\"}"), SYNTAX); + } void syntaxErrorFirstToken() { @@ -1891,6 +1899,12 @@ class TestGarbage : public TestFixture { // #13892 ASSERT_NO_THROW(checkCode("void foovm(int x[const *]);")); + + // #14676 + ASSERT_NO_THROW(checkCode("int main() {\n" + " auto value = m[1 + qRow<>];\n" + "}\n")); + ignore_errout(); } }; diff --git a/test/testimportproject.cpp b/test/testimportproject.cpp index ee6a031711a..6f8633dbeea 100644 --- a/test/testimportproject.cpp +++ b/test/testimportproject.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,16 +28,20 @@ #include #include #include +#include #include #include #include -class TestImporter : public ImportProject { +class TestImporter final : public ImportProject { public: using ImportProject::importCompileCommands; using ImportProject::importCppcheckGuiProject; using ImportProject::importVcxproj; using ImportProject::SharedItemsProject; + using ImportProject::collectArgs; + using ImportProject::fsSetDefines; + using ImportProject::fsSetIncludePaths; }; @@ -66,6 +70,7 @@ class TestImportProject : public TestFixture { TEST_CASE(importCompileCommands12); // #13040: "directory" is parent directory, relative include paths TEST_CASE(importCompileCommands13); // #13333: duplicate file entries TEST_CASE(importCompileCommands14); // #14156 + TEST_CASE(importCompileCommands15); // #14306 TEST_CASE(importCompileCommandsArgumentsSection); // Handle arguments section TEST_CASE(importCompileCommandsNoCommandSection); // gracefully handles malformed json TEST_CASE(importCompileCommandsDirectoryMissing); // 'directory' field missing @@ -74,21 +79,29 @@ class TestImportProject : public TestFixture { TEST_CASE(importCppcheckGuiProjectPremiumMisra); TEST_CASE(ignorePaths); TEST_CASE(testVcxprojUnicode); + TEST_CASE(testCollectArgs1); + TEST_CASE(testCollectArgs2); + TEST_CASE(testCollectArgs3); + TEST_CASE(testCollectArgs4); + TEST_CASE(testCollectArgs5); + TEST_CASE(testCollectArgs6); + TEST_CASE(testCollectArgs7); + TEST_CASE(testVcxprojConditions); } void setDefines() const { FileSettings fs{"test.cpp", Standards::Language::CPP, 0}; - ImportProject::fsSetDefines(fs, "A"); + TestImporter::fsSetDefines(fs, "A"); ASSERT_EQUALS("A=1", fs.defines); - ImportProject::fsSetDefines(fs, "A;B;"); + TestImporter::fsSetDefines(fs, "A;B;"); ASSERT_EQUALS("A=1;B=1", fs.defines); - ImportProject::fsSetDefines(fs, "A;;B;"); + TestImporter::fsSetDefines(fs, "A;;B;"); ASSERT_EQUALS("A=1;B=1", fs.defines); - ImportProject::fsSetDefines(fs, "A;;B"); + TestImporter::fsSetDefines(fs, "A;;B"); ASSERT_EQUALS("A=1;B=1", fs.defines); } @@ -96,7 +109,7 @@ class TestImportProject : public TestFixture { FileSettings fs{"test.cpp", Standards::Language::CPP, 0}; std::list in(1, "../include"); std::map variables; - ImportProject::fsSetIncludePaths(fs, "abc/def/", in, variables); + TestImporter::fsSetIncludePaths(fs, "abc/def/", in, variables); ASSERT_EQUALS(1U, fs.includePaths.size()); ASSERT_EQUALS("abc/include/", fs.includePaths.front()); } @@ -106,7 +119,7 @@ class TestImportProject : public TestFixture { std::list in(1, "$(SolutionDir)other"); std::map variables; variables["SolutionDir"] = "c:/abc/"; - ImportProject::fsSetIncludePaths(fs, "/home/fred", in, variables); + TestImporter::fsSetIncludePaths(fs, "/home/fred", in, variables); ASSERT_EQUALS(1U, fs.includePaths.size()); ASSERT_EQUALS("c:/abc/other/", fs.includePaths.front()); } @@ -116,7 +129,7 @@ class TestImportProject : public TestFixture { std::list in(1, "$(SOLUTIONDIR)other"); std::map variables; variables["SolutionDir"] = "c:/abc/"; - ImportProject::fsSetIncludePaths(fs, "/home/fred", in, variables); + TestImporter::fsSetIncludePaths(fs, "/home/fred", in, variables); ASSERT_EQUALS(1U, fs.includePaths.size()); ASSERT_EQUALS("c:/abc/other/", fs.includePaths.front()); } @@ -362,8 +375,8 @@ class TestImportProject : public TestFixture { ASSERT_EQUALS(2, importer.fileSettings.size()); const FileSettings &fs1 = importer.fileSettings.front(); const FileSettings &fs2 = importer.fileSettings.back(); - ASSERT_EQUALS(0, fs1.fileIndex); - ASSERT_EQUALS(1, fs2.fileIndex); + ASSERT_EQUALS(0, fs1.file.fsFileId()); + ASSERT_EQUALS(1, fs2.file.fsFileId()); } void importCompileCommands14() const { // #14156 @@ -389,6 +402,26 @@ class TestImportProject : public TestFixture { ASSERT_EQUALS("TFS_LINUX_MODULE_NAME=\"tfs_linux\"", fs.defines); } + void importCompileCommands15() const { // #14306 + REDIRECT; + constexpr char json[] = + R"([ + { + "directory": "C:\\Users\\abcd\\efg\\hijk", + "command": "gcc \"-Ipath\\123\" \"-c\" test.c", + "file": "test.c", + "output": "test.obj" + } + ])"; + std::istringstream istr(json); + TestImporter importer; + ASSERT_EQUALS(true, importer.importCompileCommands(istr)); + ASSERT_EQUALS(1, importer.fileSettings.size()); + const FileSettings &fs = importer.fileSettings.front(); + ASSERT_EQUALS(1, fs.includePaths.size()); + ASSERT_EQUALS("C:/Users/abcd/efg/hijk/path/123/", fs.includePaths.front()); + } + void importCompileCommandsArgumentsSection() const { REDIRECT; constexpr char json[] = "[ { \"directory\": \"/tmp/\"," @@ -449,6 +482,7 @@ class TestImportProject : public TestFixture { " \n" " \n" " \n" + " gcc-macros.h\n" " \n" " \n" " \n" @@ -464,6 +498,8 @@ class TestImportProject : public TestFixture { ASSERT_EQUALS("cli/", project.guiProject.pathNames[0]); ASSERT_EQUALS(1, s.includePaths.size()); ASSERT_EQUALS("lib/", s.includePaths.front()); + ASSERT_EQUALS(1, s.userIncludes.size()); + ASSERT_EQUALS("gcc-macros.h", s.userIncludes.front()); ASSERT_EQUALS(true, s.inlineSuppressions); } @@ -558,28 +594,131 @@ class TestImportProject : public TestFixture { ASSERT_EQUALS(project.fileSettings.back().useMfc, true); } + void testCollectArgs1() const + { + std::vector args; + const std::string cmd = " gcc -o main main.c "; + const std::string error = TestImporter::collectArgs(cmd, args); + + ASSERT_EQUALS("", error); + ASSERT_EQUALS(4, args.size()); + ASSERT_EQUALS("gcc", args[0]); + ASSERT_EQUALS("-o", args[1]); + ASSERT_EQUALS("main", args[2]); + ASSERT_EQUALS("main.c", args[3]); + } + + void testCollectArgs2() const + { + std::vector args; + const std::string cmd = "gcc -o main \"directory with space\"/main.c"; + const std::string error = TestImporter::collectArgs(cmd, args); + + ASSERT_EQUALS("", error); + ASSERT_EQUALS(4, args.size()); + ASSERT_EQUALS("gcc", args[0]); + ASSERT_EQUALS("-o", args[1]); + ASSERT_EQUALS("main", args[2]); + ASSERT_EQUALS("directory with space/main.c", args[3]); + } + + void testCollectArgs3() const + { + std::vector args; + const std::string cmd = "gcc -o main directory\\ with\\ space/main.c"; + const std::string error = TestImporter::collectArgs(cmd, args); + + ASSERT_EQUALS("", error); + ASSERT_EQUALS(4, args.size()); + ASSERT_EQUALS("gcc", args[0]); + ASSERT_EQUALS("-o", args[1]); + ASSERT_EQUALS("main", args[2]); + ASSERT_EQUALS("directory with space/main.c", args[3]); + } + + void testCollectArgs4() const + { + std::vector args; + const std::string cmd = "gcc -o main \'directory with space\'/main.c"; + const std::string error = TestImporter::collectArgs(cmd, args); + + ASSERT_EQUALS("", error); + ASSERT_EQUALS(4, args.size()); + ASSERT_EQUALS("gcc", args[0]); + ASSERT_EQUALS("-o", args[1]); + ASSERT_EQUALS("main", args[2]); + ASSERT_EQUALS("directory with space/main.c", args[3]); + } + + void testCollectArgs5() const + { + std::vector args; + const std::string cmd = "gcc -o main directory_with_quote\\\"/main.c"; + const std::string error = TestImporter::collectArgs(cmd, args); + + ASSERT_EQUALS("", error); + ASSERT_EQUALS(4, args.size()); + ASSERT_EQUALS("gcc", args[0]); + ASSERT_EQUALS("-o", args[1]); + ASSERT_EQUALS("main", args[2]); + ASSERT_EQUALS("directory_with_quote\"/main.c", args[3]); + } + + void testCollectArgs6() const + { + std::vector args; + const std::string cmd = "gcc -o main windows\\\\path\\\\main.c"; + const std::string error = TestImporter::collectArgs(cmd, args); + + ASSERT_EQUALS("", error); + ASSERT_EQUALS(4, args.size()); + ASSERT_EQUALS("gcc", args[0]); + ASSERT_EQUALS("-o", args[1]); + ASSERT_EQUALS("main", args[2]); + ASSERT_EQUALS("windows\\path\\main.c", args[3]); + } + + void testCollectArgs7() const + { + std::vector args; + const std::string cmd = "gcc -o main \"non-terminated-quote/main.c"; + const std::string error = TestImporter::collectArgs(cmd, args); + + ASSERT_EQUALS("Missing closing quote in command string", error); + } + + void testVcxprojConditions() const + { + ASSERT(cppcheck::testing::evaluateVcxprojCondition("'$(Configuration)'=='Debug'", "Debug", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition("'$(Platform)'=='Win32'", "Debug", "Win32")); + ASSERT(!cppcheck::testing::evaluateVcxprojCondition("'$(Configuration)'=='Release'", "Debug", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" '$(Configuration)' == 'Debug' ", "Debug", "Win32")); + ASSERT(!cppcheck::testing::evaluateVcxprojCondition(" '$(Configuration)' != 'Debug' ", "Debug", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition("'$(Configuration)|$(Platform)' == 'Debug|Win32' ", "Debug", "Win32")); + ASSERT(!cppcheck::testing::evaluateVcxprojCondition("!('$(Configuration)|$(Platform)' == 'Debug|Win32' )", "Debug", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" '$(Configuration)' == 'Debug' And '$(Platform)' == 'Win32'", "Debug", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" '$(Configuration)' == 'Debug' Or '$(Platform)' == 'Win32'", "Release", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" $(Configuration.StartsWith('Debug'))", "Debug-AddressSanitizer", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" $(Configuration.EndsWith('AddressSanitizer'))", "Debug-AddressSanitizer", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" $(Configuration.Contains('Address'))", "Debug-AddressSanitizer", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" $(Configuration.Contains ( 'Address' ) )", "Debug-AddressSanitizer", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" $(Configuration.Contains('Address')) And '$(Platform)' == 'Win32'", "Debug-AddressSanitizer", "Win32")); + ASSERT(cppcheck::testing::evaluateVcxprojCondition(" ($(Configuration.Contains('Address')) ) And ( '$(Platform)' == 'Win32')", "Debug-AddressSanitizer", "Win32")); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("And", "", ""), std::runtime_error, "Invalid condition: 'And'"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("Or", "", ""), std::runtime_error, "Invalid condition: 'Or'"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("!", "", ""), std::runtime_error, "Invalid condition: '!'"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("'' == '' And ", "", ""), std::runtime_error, "Missing operator"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("('' == ''", "", ""), std::runtime_error, "'(' without closing ')'!"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("'' == '')", "", ""), std::runtime_error, "unmatched ')' in condition '' == '')"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("''", "", ""), std::runtime_error, "Invalid condition: ''''"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("'' == '", "", ""), std::runtime_error, "Can not tokenize condition"); + ASSERT_THROW_EQUALS(cppcheck::testing::evaluateVcxprojCondition("$(Configuration.Lower())", "", ""), std::runtime_error, "Missing operator"); + // invalid expression in => no error. We are ok with that as long as we don't crash + ASSERT(!cppcheck::testing::evaluateVcxprojCondition("' ' && ' '", "", "")); + } + // TODO: test fsParseCommand() - // TODO: test vcxproj conditions - /* - - - - - Debug - x64 - - - - - CPPCHECKLIB_IMPORT - - - - - - - */ }; REGISTER_TEST(TestImportProject) diff --git a/test/testincompletestatement.cpp b/test/testincompletestatement.cpp index 7a1fbdb2dab..bd94b52af0e 100644 --- a/test/testincompletestatement.cpp +++ b/test/testincompletestatement.cpp @@ -50,7 +50,7 @@ class TestIncompleteStatement : public TestFixture { ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); // Check for incomplete statements.. - CheckOther checkOther(&tokenizer, &settings1, this); + CheckOtherImpl checkOther(&tokenizer, &settings1, this); checkOther.checkIncompleteStatement(); } @@ -750,6 +750,14 @@ class TestIncompleteStatement : public TestFixture { " g();\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct S;\n" // #14664 + "S* a[1];\n" + "void f() {\n" + " a[0];\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:6]: (warning) Redundant code: Found unused array access. [constStatement]\n", + errout_str()); } void vardecl() { diff --git a/test/testinternal.cpp b/test/testinternal.cpp index 009129c5dc1..10431adcd38 100644 --- a/test/testinternal.cpp +++ b/test/testinternal.cpp @@ -56,8 +56,8 @@ class TestInternal : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check.. - runChecks(tokenizer, this); + CheckInternal check; + runChecks(check, tokenizer, this); } void simplePatternInTokenMatch() { diff --git a/test/testio.cpp b/test/testio.cpp index 788ff17ebbe..bc6e40034f6 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -109,11 +109,12 @@ class TestIO : public TestFixture { // Check.. if (options.onlyFormatStr) { - CheckIO checkIO(&tokenizer, &settings1, this); + CheckIOImpl checkIO(&tokenizer, &settings1, this); checkIO.checkWrongPrintfScanfArguments(); return; } - runChecks(tokenizer, this); + CheckIO check; + runChecks(check, tokenizer, this); } void coutCerrMisusage() { @@ -544,7 +545,29 @@ class TestIO : public TestFixture { " FILE *a = fopen(\"aa\", \"r\");\n" " while (fclose(a)) {}\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:3:5]: (error) Used file that is not opened. [useClosedFile]\n", "", errout_str()); + ASSERT_EQUALS("[test.cpp:3:12]: (warning) fclose() used as loop condition may skip loop body or double-close file handle. [fcloseInLoopCondition]\n", errout_str()); + + check("void foo() {\n" + " FILE *a = fopen(\"aa\", \"r\");\n" + " while (fclose(a)) {\n" + " break;\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout_str()); + + check("void foo() {\n" + " FILE *a = fopen(\"aa\", \"r\");\n" + " while (fclose(a)) {\n" + " a = fopen(\"aa\", \"r\");\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout_str()); + + check("void foo() {\n" + " FILE *a = fopen(\"aa\", \"r\");\n" + " do {} while (fclose(a));\n" + "}"); + ASSERT_EQUALS("[test.cpp:3:18]: (warning) fclose() used as loop condition may skip loop body or double-close file handle. [fcloseInLoopCondition]\n", errout_str()); // #6823 check("void foo() {\n" @@ -2186,6 +2209,12 @@ class TestIO : public TestFixture { " scanf(\"%i\", \"abc\" + 1);\n" "}\n"); ASSERT_EQUALS("[test.cpp:2]: (warning) %i in format string (no. 1) requires 'int *' but the argument type is 'const char *'.\n", errout_str()); + + check("struct S { unsigned char a[1]; };" // #14302 + "void f(S s) {\n" + " scanf(\"%hhu\", s.a);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void testPrintfArgument() { @@ -3365,6 +3394,20 @@ class TestIO : public TestFixture { "}"); ASSERT_EQUALS("", errout_str()); + check("enum E : uint8_t { E0 }; \n" // #7959 + "void f(E e) {\n" + " printf(\"%hhu\", e);\n" + "}"); + ASSERT_EQUALS("", errout_str()); + + check("enum E : uint8_t { E0 }; \n" + "void f(E e) {\n" + " printf(\"%lu\", e);\n" + "}"); + TODO_ASSERT_EQUALS("[test.cpp:3]: (warning) %lu in format string (no. 1) requires 'unsigned long' but the argument type is 'uint8_t'.\n", + "", + errout_str()); + check("void f() {\n" " printf(\"%lu\", sizeof(char));\n" "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64)); @@ -4794,6 +4837,13 @@ class TestIO : public TestFixture { " wscanf_s(L\"%4[^-]\", msStr1, _countof(msStr1));\n" "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W)); ASSERT_EQUALS("", errout_str()); + + check("void f(const char* c) {\n" + " const size_t N = 5;\n" + " char buf[N];\n" + " sscanf_s(c, \"%4[^.]\", buf, N);\n" + "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win64)); + ASSERT_EQUALS("", errout_str()); } void testQStringFormatArguments() { diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 1339e6868ac..265e31bf3c2 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -154,6 +154,7 @@ class TestLeakAutoVar : public TestFixture { TEST_CASE(ifelse27); TEST_CASE(ifelse28); // #11038 TEST_CASE(ifelse29); + TEST_CASE(ifelse30); // switch TEST_CASE(switch1); @@ -181,6 +182,7 @@ class TestLeakAutoVar : public TestFixture { TEST_CASE(return10); TEST_CASE(return11); // #13098 TEST_CASE(return12); // #12238 + TEST_CASE(return13); // General tests: variable type, allocation type, etc TEST_CASE(test1); @@ -224,23 +226,17 @@ class TestLeakAutoVar : public TestFixture { template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { const Settings& settings1 = options.s ? *options.s : settings; - - // Tokenize.. - SimpleTokenizer tokenizer(settings1, *this, options.cpp); - ASSERT_LOC(tokenizer.tokenize(code), file, line); - - // Check for leaks.. - runChecks(tokenizer, this); + check_(file, line, code, settings1, options.cpp); } template - void check_(const char* file, int line, const char (&code)[size], const Settings & s) { + void check_(const char* file, int line, const char (&code)[size], const Settings & s, bool cpp = true) { // Tokenize.. - SimpleTokenizer tokenizer(s, *this); + SimpleTokenizer tokenizer(s, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check for leaks.. - runChecks(tokenizer, this); + CheckLeakAutoVar check; + runChecks(check, tokenizer, this); } void assign1() { @@ -640,6 +636,14 @@ class TestLeakAutoVar : public TestFixture { " x = p != nullptr ? p : nullptr;\n" "}", dinit(CheckOptions, $.cpp = true)); ASSERT_EQUALS("", errout_str()); + + check("void f(const char* n) {\n" // #12724 + " FILE* fp = fopen(n, \"r\");\n" + " bool b = (fp == NULL);\n" + " if (b)\n" + " return;\n" + "}\n", dinit(CheckOptions, $.cpp = true)); + ASSERT_EQUALS("[test.cpp:6:1]: (error) Resource leak: fp [resourceLeak]\n", errout_str()); } void memcpy1() { // #11542 @@ -2381,6 +2385,22 @@ class TestLeakAutoVar : public TestFixture { ASSERT_EQUALS("", errout_str()); // don't crash } + void ifelse30() { + check("void f(void** pp) {\n" // #14709 + " void* p = malloc(8);\n" + " if ((void*)p == 0)\n" + " return;\n" + " *pp = p;\n" + "}\n" + "void g(void** pp) {\n" + " void* p = malloc(8);\n" + " if (static_cast(p) == 0)\n" + " return;\n" + " *pp = p;\n" + "}\n", dinit(CheckOptions, $.cpp = true)); + ASSERT_EQUALS("", errout_str()); + } + void switch1() { check("void f() {\n" " char *p = 0;\n" @@ -2838,6 +2858,22 @@ class TestLeakAutoVar : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void return13() { // #4638 + CheckOptions options; + options.cpp = true; + check("bool f() {\n" + " int* p = new int;\n" + " return p;\n" + "}\n" + "bool g() {\n" + " void* p = malloc(4);\n" + " return p;\n" + "}\n", options); + ASSERT_EQUALS("[test.cpp:3:5]: (error) Memory leak: p [memleak]\n" + "[test.cpp:7:5]: (error) Memory leak: p [memleak]\n", + errout_str()); + } + void test1() { check("void f(double*&p) {\n" // 3809 " p = malloc(0x100);\n" @@ -3224,14 +3260,14 @@ class TestLeakAutoVarRecursiveCountLimit : public TestFixture { #define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__) template - void checkP_(const char* file, int line, const char (&code)[size], bool cpp = false) { - SimpleTokenizer2 tokenizer(settings, *this, code, cpp?"test.cpp":"test.c"); + void checkP_(const char* file, int line, const char (&code)[size]) { + SimpleTokenizer2 tokenizer(settings, *this, code, "test.c"); // Tokenizer.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); - // Check for leaks.. - runChecks(tokenizer, this); + CheckLeakAutoVar check; + runChecks(check, tokenizer, this); } void run() override { @@ -3277,8 +3313,8 @@ class TestLeakAutoVarStrcpy : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check for leaks.. - runChecks(tokenizer, this); + CheckLeakAutoVar check; + runChecks(check, tokenizer, this); } void run() override { @@ -3382,8 +3418,8 @@ class TestLeakAutoVarWindows : public TestFixture { SimpleTokenizer tokenizer(settings, *this, false); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check for leaks.. - runChecks(tokenizer, this); + CheckLeakAutoVar check; + runChecks(check, tokenizer, this); } void run() override { @@ -3455,8 +3491,8 @@ class TestLeakAutoVarPosix : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check for leaks.. - runChecks(tokenizer, this); + CheckLeakAutoVar check; + runChecks(check, tokenizer, this); } void run() override { diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index 5ea3a2e7120..a531ac4cba9 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -1012,7 +1012,14 @@ class TestLibrary : public TestFixture { } } -#define LOADLIBERROR(xmldata, errorcode) loadLibError(xmldata, errorcode, __FILE__, __LINE__) +#define LOADLIBERROR(...) loadLibError(__FILE__, __LINE__, __VA_ARGS__) + template + void loadLibError(const char* file, unsigned line, const char (&xmldata)[size], Library::ErrorCode errorcode) const { + Library library; + Library::Error liberr; + assertEquals(file, line, true, LibraryHelper::loadxmldata(library, liberr, xmldata, size-1)); + assertEquals(file, line, true, errorcode == liberr.errorcode); + } void version() const { { @@ -1053,14 +1060,6 @@ class TestLibrary : public TestFixture { } } - template - void loadLibError(const char (&xmldata)[size], Library::ErrorCode errorcode, const char* file, unsigned line) const { - Library library; - Library::Error liberr; - assertEquals(file, line, true, LibraryHelper::loadxmldata(library, liberr, xmldata, size-1)); - assertEquals(file, line, true, errorcode == liberr.errorcode); - } - #define LOADLIB_ERROR_INVALID_RANGE(valid) LOADLIBERROR("\n" \ "\n" \ "\n" \ diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 6a0ba4c0871..8cbe5b50019 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -167,7 +167,7 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS("1", MathLib::calculate("0", "1", '^')); // Unknown action should throw exception - ASSERT_THROW_INTERNAL_EQUALS(MathLib::calculate("1","2",'j'),INTERNAL, "Unexpected action 'j' in MathLib::calculate(). Please report this to Cppcheck developers."); + ASSERT_THROW_INTERNAL_EQUALS(MathLib::calculate("1","2",'j'),INTERNAL, "Unexpected action 'j' in MathLib::calculate()."); } void calculate1() const { @@ -416,6 +416,8 @@ class TestMathLib : public TestFixture { TokenList::deleteTokens(tok); } + ASSERT_THROW_INTERNAL_EQUALS(MathLib::toBigNumber("''"), INTERNAL, "Internal Error. MathLib::toBigNumber: characterLiteralToLL('') => empty character literal"); + // TODO: test binary // TODO: test floating point @@ -588,6 +590,8 @@ class TestMathLib : public TestFixture { TokenList::deleteTokens(tok); } + ASSERT_THROW_INTERNAL_EQUALS(MathLib::toBigUNumber("''"), INTERNAL, "Internal Error. MathLib::toBigUNumber: characterLiteralToLL('') => empty character literal"); + // TODO: test binary // TODO: test floating point @@ -736,6 +740,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS("0.0", MathLib::toString(MathLib::toDoubleNumber("-0"))); ASSERT_EQUALS("0.0", MathLib::toString(MathLib::toDoubleNumber("-0."))); ASSERT_EQUALS("0.0", MathLib::toString(MathLib::toDoubleNumber("-0.0"))); + + ASSERT_THROW_INTERNAL_EQUALS(MathLib::toDoubleNumber("''"), INTERNAL, "Internal Error. MathLib::toDoubleNumber: characterLiteralToLL('') => empty character literal"); } void isint() const { diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index d93323c29ef..8982215d8e3 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,13 +39,12 @@ class TestMemleak : public TestFixture { #define functionReturnType(...) functionReturnType_(__FILE__, __LINE__, __VA_ARGS__) template - CheckMemoryLeak::AllocType functionReturnType_(const char* file, int line, const char (&code)[size]) { + CheckMemoryLeakImpl::AllocType functionReturnType_(const char* file, int line, const char (&code)[size]) { // Tokenize.. SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - const CheckMemoryLeak c(&tokenizer, this, &settingsDefault); - + const CheckMemoryLeakImpl c(&tokenizer, &settingsDefault, this); return (c.functionReturnType)(&tokenizer.getSymbolDatabase()->scopeList.front().functionList.front()); } @@ -53,19 +52,19 @@ class TestMemleak : public TestFixture { { const char code[] = "const char *foo()\n" "{ return 0; }"; - ASSERT_EQUALS(CheckMemoryLeak::No, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::No, functionReturnType(code)); } { const char code[] = "Fred *newFred()\n" "{ return new Fred; }"; - ASSERT_EQUALS(CheckMemoryLeak::New, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::New, functionReturnType(code)); } { const char code[] = "char *foo()\n" "{ return new char[100]; }"; - ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::NewArray, functionReturnType(code)); } { @@ -74,7 +73,7 @@ class TestMemleak : public TestFixture { " char *p = new char[100];\n" " return p;\n" "}"; - ASSERT_EQUALS(CheckMemoryLeak::NewArray, functionReturnType(code)); + ASSERT_EQUALS(CheckMemoryLeakImpl::NewArray, functionReturnType(code)); } } @@ -94,8 +93,8 @@ class TestMemleak : public TestFixture { // there is no allocation const Token *tok = Token::findsimplematch(tokenizer.tokens(), "ret ="); - const CheckMemoryLeak check(&tokenizer, nullptr, &settingsDefault); - ASSERT_EQUALS(CheckMemoryLeak::No, check.getAllocationType(tok->tokAt(2), 1)); + const CheckMemoryLeakImpl check(&tokenizer, &settingsDefault, nullptr); + ASSERT_EQUALS(CheckMemoryLeakImpl::No, check.getAllocationType(tok->tokAt(2), 1)); } }; @@ -120,7 +119,7 @@ class TestMemleakInFunction : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, this); + CheckMemoryLeakInFunctionImpl checkMemoryLeak(&tokenizer, &settings, this); checkMemoryLeak.checkReallocUsage(); } @@ -150,6 +149,7 @@ class TestMemleakInFunction : public TestFixture { TEST_CASE(realloc22); TEST_CASE(realloc23); TEST_CASE(realloc24); // #9228 + TEST_CASE(realloc25); } void realloc1() { @@ -418,6 +418,60 @@ class TestMemleakInFunction : public TestFixture { "}"); ASSERT_EQUALS("", errout_str()); } + + void realloc25() { + check("struct T {\n" + " char* ptr;\n" + " size_t len;\n" + "};\n" + "struct S {\n" + " struct T t;\n" + "};\n" + "void f(struct S* s, size_t len) {\n" + " char* p = s->t.ptr;\n" + " p = realloc(p, len);\n" + " if (p) {\n" + " s->t.ptr = p;\n" + " s->t.len = len;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct T {\n" + " char* ptr;\n" + " size_t len;\n" + "};\n" + "struct S {\n" + " struct T t[1];\n" + "};\n" + "void f(struct S* s, size_t len) {\n" + " char* p = s->t[0].ptr;\n" + " p = realloc(p, len);\n" + " if (p) {\n" + " s->t[0].ptr = p;\n" + " s->t[0].len = len;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct T {\n" // #14718 + " char* ptr;\n" + " size_t len;\n" + "};\n" + "struct S {\n" + " struct T t;\n" + "};\n" + "char* get(struct T t) { return t.ptr; };\n" + "void f(struct S* s, size_t len) {\n" + " char* p = get(s->t);\n" + " p = realloc(p, len);\n" + " if (p) {\n" + " s->t.ptr = p;\n" + " s->t.len = len;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } }; REGISTER_TEST(TestMemleakInFunction) @@ -447,7 +501,7 @@ class TestMemleakInClass : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakInClass checkMemoryLeak(&tokenizer, &settings, this); + CheckMemoryLeakInClassImpl checkMemoryLeak(&tokenizer, &settings, this); (checkMemoryLeak.check)(); } @@ -1652,7 +1706,7 @@ class TestMemleakStructMember : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakStructMember checkMemoryLeakStructMember(&tokenizer, &settings, this); + CheckMemoryLeakStructMemberImpl checkMemoryLeakStructMember(&tokenizer, &settings, this); (checkMemoryLeakStructMember.check)(); } @@ -1673,6 +1727,8 @@ class TestMemleakStructMember : public TestFixture { TEST_CASE(assign2); TEST_CASE(assign3); TEST_CASE(assign4); // #11019 + TEST_CASE(assign5); + TEST_CASE(assign6); // Failed allocation TEST_CASE(failedAllocation); @@ -1682,6 +1738,7 @@ class TestMemleakStructMember : public TestFixture { TEST_CASE(function3); // #3024: kernel list TEST_CASE(function4); // #3038: Deallocating in function TEST_CASE(function5); // #10381, #10382, #10158 + TEST_CASE(function6); // Handle if-else TEST_CASE(ifelse); @@ -1919,6 +1976,50 @@ class TestMemleakStructMember : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void assign5() { + check("struct S { int fd; };\n" + "void f() {\n" + " struct S* s = (struct S*)malloc(sizeof(struct S));\n" + " s->fd = open(\"abc\", O_RDWR | O_NOCTTY);\n" + " free(s);\n" + "}\n" + "void g() {\n" + " struct S* s = static_cast(malloc(sizeof(struct S)));\n" + " s->fd = open(\"abc\", O_RDWR | O_NOCTTY);\n" + " free(s);\n" + "}\n" + "void h() {\n" + " S* s = new S;\n" + " s->fd = open(\"abc\", O_RDWR | O_NOCTTY);\n" + " delete s;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5:5]: (error) Resource leak: s.fd [resourceLeak]\n" + "[test.cpp:10:5]: (error) Resource leak: s.fd [resourceLeak]\n" + "[test.cpp:16:1]: (error) Resource leak: s.fd [resourceLeak]\n", + errout_str()); + + check("struct S { int fd; };\n" // #13031 + "void f() {\n" + " struct S* s = malloc(sizeof(struct S));\n" + " s->fd = open(\"abc\", O_RDWR | O_NOCTTY);\n" + " if (s->fd < 0) {\n" + " free(s);\n" + " return NULL;\n" + " }\n" + " return s;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + + void assign6() { + check("struct S { S* p; };\n" // #14524 + "void f() {\n" + " S s;\n" + " s.p = static_cast(malloc(sizeof(S)));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5:1]: (error) Memory leak: s.p [memleak]\n", errout_str()); + } + void failedAllocation() { check("static struct ABC * foo()\n" "{\n" @@ -2018,7 +2119,33 @@ class TestMemleakStructMember : public TestFixture { " }\n" " return g(&a);\n" "}\n"); - TODO_ASSERT_EQUALS("", "[test.cpp:9:9]: (error) Memory leak: a.str [memleak]\n", errout_str()); + ASSERT_EQUALS("", errout_str()); + + check("struct S { int *p; };\n" + "S f(int i) {\n" + " S s;\n" + " switch(i) {\n" + " case 1:\n" + " s.p = new int;\n" + " break;\n" + " default: {\n" + " return {};\n" + " }\n" + " }\n" + " return s;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + + void function6() { + check("struct S { int* p; };\n" // #14706 + "void g(void*);\n" + "void f() {\n" + " S* s = new S();\n" + " s->p = new int();\n" + " g((void*)s);\n" + "}"); + ASSERT_EQUALS("", errout_str()); } void ifelse() { @@ -2261,7 +2388,7 @@ class TestMemleakNoVar : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // Check for memory leaks.. - CheckMemoryLeakNoVar checkMemoryLeakNoVar(&tokenizer, &settings, this); + CheckMemoryLeakNoVarImpl checkMemoryLeakNoVar(&tokenizer, &settings, this); (checkMemoryLeakNoVar.check)(); } @@ -2314,7 +2441,7 @@ class TestMemleakNoVar : public TestFixture { "void x() {\n" " set_error(strdup(p));\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Allocation with strdup, set_error doesn't release it.\n", "", errout_str()); + TODO_ASSERT_EQUALS("[test.cpp:5:15]: (error) Allocation with strdup, set_error doesn't release it. [leakNoVarFunctionCall]\n", "", errout_str()); check("void f()\n" "{\n" @@ -2466,6 +2593,15 @@ class TestMemleakNoVar : public TestFixture { " f(new U());\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct A {\n" // #14339 + " void g(int* p) { p_ = p; }\n" + " int *p_;\n" + "};\n" + "void f(A& a) {\n" + " a.g(new int);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void missingAssignment() { @@ -2707,6 +2843,18 @@ class TestMemleakNoVar : public TestFixture { " if (std::freopen(NULL, \"w+b\", fp2) == NULL) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void f() {\n" // #14172 + " if (malloc(4) == nullptr) {}\n" + " if (::malloc(4) == nullptr) {}\n" + " if (std::malloc(4) == nullptr) {}\n" + " if (::std::malloc(4) == nullptr) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:9]: (error) Return value of allocation function 'malloc' is not stored. [leakReturnValNotUsed]\n" + "[test.cpp:3:11]: (error) Return value of allocation function 'malloc' is not stored. [leakReturnValNotUsed]\n" + "[test.cpp:4:14]: (error) Return value of allocation function 'malloc' is not stored. [leakReturnValNotUsed]\n" + "[test.cpp:5:16]: (error) Return value of allocation function 'malloc' is not stored. [leakReturnValNotUsed]\n", + errout_str()); } void smartPointerFunctionParam() { diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 8f1adfc585d..3e9d4011500 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ class TestNullPointer : public TestFixture { private: const Settings settings = settingsBuilder().library("std.cfg").severity(Severity::warning).build(); + const Settings settings_i = settingsBuilder(settings).certainty(Certainty::inconclusive).build(); void run() override { mNewTemplate = true; @@ -183,20 +184,23 @@ class TestNullPointer : public TestFixture { { bool inconclusive = false; bool cpp = true; - Standards::cstd_t cstd = Standards::CLatest; }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { - const Settings settings1 = settingsBuilder(settings).certainty(Certainty::inconclusive, options.inconclusive).c(options.cstd).build(); + const Settings& settings1 = options.inconclusive ? settings_i : settings; + check_(file, line, code, settings1, options.cpp); + } + template + void check_(const char* file, int line, const char (&code)[size], const Settings& s, bool cpp = true) { // Tokenize.. - SimpleTokenizer tokenizer(settings1, *this, options.cpp); + SimpleTokenizer tokenizer(s, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check for null pointer dereferences.. - runChecks(tokenizer, this); + CheckNullPointer check; + runChecks(check, tokenizer, this); } #define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__) @@ -207,8 +211,8 @@ class TestNullPointer : public TestFixture { // Tokenizer.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); - // Check for null pointer dereferences.. - runChecks(tokenizer, this); + CheckNullPointer check; + runChecks(check, tokenizer, this); } @@ -995,6 +999,14 @@ class TestNullPointer : public TestFixture { "char f(S* s) { return s->p ? 'a' : s->p->c; }\n"); ASSERT_EQUALS("[test.cpp:2:24] -> [test.cpp:2:37]: (warning) Either the condition 's->p' is redundant or there is possible null pointer dereference: s->p. [nullPointerRedundantCheck]\n", errout_str()); + + check("int f(const int a[]) {\n" // #14544 + " int i = 0;\n" + " if (!a)\n" + " a = &i;\n" + " return *a;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void nullpointer5() { @@ -1330,7 +1342,8 @@ class TestNullPointer : public TestFixture { check(code); // C++ file => nullptr means NULL ASSERT_EQUALS("[test.cpp:4:11]: (error) Null pointer dereference: i [nullPointer]\n", errout_str()); - check(code, dinit(CheckOptions, $.cpp = false, $.cstd = Standards::C17)); // C17 file => nullptr does not mean NULL + const Settings s = settingsBuilder(settings).c(Standards::C17).build(); + check(code, s, false); // C17 file => nullptr does not mean NULL ASSERT_EQUALS("", errout_str()); check(code, dinit(CheckOptions, $.cpp = false)); @@ -2458,6 +2471,14 @@ class TestNullPointer : public TestFixture { " if (h(i) && *i == 1) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void f(int i) {\n" // #13797 + " int* p = nullptr;\n" + " if (!i) {\n" + " *p = 0;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:10]: (error) Null pointer dereference: p [nullPointer]\n", errout_str()); } void nullpointer78() // #7802 @@ -3473,8 +3494,7 @@ class TestNullPointer : public TestFixture { " printf(\"%s\", s);\n" "}"); ASSERT_EQUALS( - "[test.cpp:3:18]: (error) Null pointer dereference: s [nullPointer]\n" - "[test.cpp:3:18]: (error) Null pointer dereference [nullPointer]\n", + "[test.cpp:3:18]: (error) Null pointer dereference: s [nullPointer]\n", errout_str()); check("void f() {\n" @@ -3498,8 +3518,7 @@ class TestNullPointer : public TestFixture { " printf(\"%u%s\", 123, s);\n" "}"); ASSERT_EQUALS( - "[test.cpp:3:25]: (error) Null pointer dereference: s [nullPointer]\n" - "[test.cpp:3:25]: (error) Null pointer dereference [nullPointer]\n", + "[test.cpp:3:25]: (error) Null pointer dereference: s [nullPointer]\n", errout_str()); @@ -3544,16 +3563,14 @@ class TestNullPointer : public TestFixture { " sscanf(s, \"%s\", 0);\n" "}"); ASSERT_EQUALS( - "[test.cpp:2:21]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:2:21]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:2:21]: (error) Null pointer dereference [nullPointer]\n", errout_str()); check("void f() {\n" " scanf(\"%d\", 0);\n" "}"); ASSERT_EQUALS( - "[test.cpp:2:17]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:2:17]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:2:17]: (error) Null pointer dereference [nullPointer]\n", errout_str()); check("void f(char* foo) {\n" @@ -3574,9 +3591,7 @@ class TestNullPointer : public TestFixture { " sscanf(dummy, \"%d\", iVal);\n" "}"); ASSERT_EQUALS( - "[test.cpp:3:25]: (error) Null pointer dereference: iVal [nullPointer]\n" - "[test.cpp:3:25]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:3:25]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:3:25]: (error) Null pointer dereference: iVal [nullPointer]\n", errout_str()); check("void f(char *dummy) {\n" @@ -3595,8 +3610,7 @@ class TestNullPointer : public TestFixture { " sscanf(dummy, \"%*d%u\", 0);\n" "}"); ASSERT_EQUALS( - "[test.cpp:2:28]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:2:28]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:2:28]: (error) Null pointer dereference [nullPointer]\n", errout_str()); } @@ -3701,6 +3715,26 @@ class TestNullPointer : public TestFixture { " i++;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void f(const int* p) {\n" // #6710 + " for (int i = *p; i < 5; ++i) {}\n" + " if (p) {}\n" + "}\n" + "struct S { int a; };\n" + "void g(const S* s) {\n" + " for (int i = s->a; i < 5; ++i) {}\n" + " if (s) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:9] -> [test.cpp:2:19]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. [nullPointerRedundantCheck]\n" + "[test.cpp:8:9] -> [test.cpp:7:18]: (warning) Either the condition 's' is redundant or there is possible null pointer dereference: s. [nullPointerRedundantCheck]\n", + errout_str()); + + check("struct S { int a; };\n" // #6492 + "void h(const S* s) {\n" + " for (int i = s->a; s; ++i) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:24] -> [test.cpp:3:18]: (warning) Either the condition 's' is redundant or there is possible null pointer dereference: s. [nullPointerRedundantCheck]\n", + errout_str()); } void nullpointerDeadCode() { @@ -3742,6 +3776,15 @@ class TestNullPointer : public TestFixture { " return 1 ? 1 : *(int*)0 = 1;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check ("struct S {\n" // #13220 + " explicit S(int* p) : i(*p) {\n" + " if (p) {}\n" + " }\n" + " int i;\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:3:13] -> [test.cpp:2:29]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. [nullPointerRedundantCheck]\n", + errout_str()); } void nullpointerDelete() { @@ -3770,6 +3813,21 @@ class TestNullPointer : public TestFixture { " g(x);\n" "}"); ASSERT_EQUALS("", errout_str()); + + check("struct T {\n" // #14308 + " bool b{};\n" + " T* next{};\n" + "};\n" + "bool g(const T*& r) {\n" + " const T* t = r;\n" + " r = t->next;\n" + " return t->b;\n" + "}\n" + "void f(const T* tok) {\n" + " if (g(tok)) {}\n" + " if (tok) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void nullpointerExit() { @@ -3920,7 +3978,8 @@ class TestNullPointer : public TestFixture { " std::string s(p);\n" " return s;\n" "}\n", dinit(CheckOptions, $.inconclusive = true)); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:6:17]: (warning, inconclusive) Possible null pointer dereference: p [nullPointer]\n", + errout_str()); check("void f() {\n" // #11078 " const char* p = nullptr;\n" @@ -3935,6 +3994,15 @@ class TestNullPointer : public TestFixture { "void f() { std::string s = g(0L); }\n"); ASSERT_EQUALS("[test.cpp:2:29]: (error) Null pointer dereference: g(0L) [nullPointer]\n", errout_str()); + + check("const char* g() { return nullptr; }\n" // #14098 + "std::string f() {\n" + " std::string s{ g() };\n" + " return s + std::string(g());\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:21]: (error) Null pointer dereference: g() [nullPointer]\n" + "[test.cpp:4:29]: (error) Null pointer dereference: g() [nullPointer]\n", + errout_str()); } void nullpointerStdStream() { @@ -4283,8 +4351,7 @@ class TestNullPointer : public TestFixture { Library library; ASSERT(LibraryHelper::loadxmldata(library, xmldata, sizeof(xmldata))); - std::list null; - CheckNullPointer::parseFunctionCall(*xtok, null, library); + const std::list null = CheckNullPointerImpl::parseFunctionCall(*xtok, library); ASSERT_EQUALS(0U, null.size()); } @@ -4302,8 +4369,7 @@ class TestNullPointer : public TestFixture { Library library; ASSERT(LibraryHelper::loadxmldata(library, xmldata, sizeof(xmldata))); - std::list null; - CheckNullPointer::parseFunctionCall(*xtok, null, library); + const std::list null = CheckNullPointerImpl::parseFunctionCall(*xtok, library); ASSERT_EQUALS(1U, null.size()); ASSERT_EQUALS("a", null.front()->str()); } @@ -4617,18 +4683,18 @@ class TestNullPointer : public TestFixture { ASSERT_EQUALS("", errout_str()); } -#define ctu(code) ctu_(code, __FILE__, __LINE__) +#define ctu(...) ctu_(__FILE__, __LINE__, __VA_ARGS__) template - void ctu_(const char (&code)[size], const char* file, int line) { + void ctu_(const char* file, int line, const char (&code)[size]) { // Tokenize.. SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); CTU::FileInfo *ctu = CTU::getFileInfo(tokenizer); - // Check code.. + CheckNullPointer check; + Check& c = getCheck(check); std::list fileInfo; - Check& c = getCheck(); fileInfo.push_back(c.getFileInfo(tokenizer, settings, "")); c.analyseWholeProgram(*ctu, fileInfo, settings, *this); // TODO: check result while (!fileInfo.empty()) { @@ -4758,6 +4824,15 @@ class TestNullPointer : public TestFixture { "[test.cpp:5:20]: note: Assignment 'f=fopen(notexist,t)', assigned value is 0\n" "[test.cpp:6:8]: note: Calling function foo, 1st argument is null\n" "[test.cpp:2:13]: note: Dereferencing argument f that is null\n", errout_str()); + + ctu("void g(std::optional& o) {\n" // #14728 + " *o = 1;\n" + "}\n" + "void f() {\n" + " std::optional x = 0;\n" + " g(x);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } }; diff --git a/test/testoptions.cpp b/test/testoptions.cpp index 7c72b2de336..0dec04927e4 100644 --- a/test/testoptions.cpp +++ b/test/testoptions.cpp @@ -35,9 +35,8 @@ class TestOptions : public TestFixture { TEST_CASE(which_test); TEST_CASE(which_test_method); TEST_CASE(no_test_method); - TEST_CASE(not_quiet); + TEST_CASE(defaults); TEST_CASE(quiet); - TEST_CASE(not_help); TEST_CASE(help); TEST_CASE(help_long); TEST_CASE(multiple_testcases); @@ -45,54 +44,65 @@ class TestOptions : public TestFixture { TEST_CASE(invalid_switches); TEST_CASE(summary); TEST_CASE(dry_run); + TEST_CASE(exclude_tests); + TEST_CASE(timer_results); } void which_test() const { const char* argv[] = {"./test_runner", "TestClass"}; options args(getArrayLength(argv), argv); - ASSERT(std::set {"TestClass"} == args.which_test()); + const std::map> expected{ + { "TestClass", {} } + }; + ASSERT(expected == args.which_tests()); + ASSERT(args.errors().empty()); } void which_test_method() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod"}; options args(getArrayLength(argv), argv); - ASSERT(std::set {"TestClass::TestMethod"} == args.which_test()); + const std::map> expected{ + { "TestClass", {"TestMethod"} } + }; + ASSERT(expected == args.which_tests()); + ASSERT(args.errors().empty()); } void no_test_method() const { const char* argv[] = {"./test_runner"}; options args(getArrayLength(argv), argv); - ASSERT(std::set {""} == args.which_test()); + const std::map> expected{}; + ASSERT(expected == args.which_tests()); + ASSERT(args.errors().empty()); } - void not_quiet() const { - const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-v"}; + void defaults() const { + const char* argv[] = {"./test_runner", "TestClass::TestMethod"}; options args(getArrayLength(argv), argv); ASSERT_EQUALS(false, args.quiet()); + ASSERT_EQUALS(false, args.help()); + ASSERT_EQUALS(true, args.summary()); + ASSERT_EQUALS(false, args.dry_run()); + ASSERT_EQUALS(false, args.exclude_tests()); + ASSERT(args.errors().empty()); } - void quiet() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-q"}; options args(getArrayLength(argv), argv); ASSERT_EQUALS(true, args.quiet()); + ASSERT(args.errors().empty()); } - void not_help() const { - const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-v"}; - options args(getArrayLength(argv), argv); - ASSERT_EQUALS(false, args.help()); - } - - void help() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-h"}; options args(getArrayLength(argv), argv); ASSERT_EQUALS(true, args.help()); + ASSERT(args.errors().empty()); } @@ -100,40 +110,69 @@ class TestOptions : public TestFixture { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "--help"}; options args(getArrayLength(argv), argv); ASSERT_EQUALS(true, args.help()); + ASSERT(args.errors().empty()); } void multiple_testcases() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "TestClass::AnotherTestMethod"}; options args(getArrayLength(argv), argv); - std::set expected {"TestClass::TestMethod", "TestClass::AnotherTestMethod"}; - ASSERT(expected == args.which_test()); + const std::map> expected{ + { "TestClass", { "TestMethod", "AnotherTestMethod" } } + }; + ASSERT(expected == args.which_tests()); + ASSERT(args.errors().empty()); } void multiple_testcases_ignore_duplicates() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "TestClass"}; options args(getArrayLength(argv), argv); - std::set expected {"TestClass"}; - ASSERT(expected == args.which_test()); + const std::map> expected{ + { "TestClass", {} } + }; + ASSERT(expected == args.which_tests()); + ASSERT(args.errors().empty()); } void invalid_switches() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-a", "-v", "-q"}; options args(getArrayLength(argv), argv); - std::set expected {"TestClass::TestMethod"}; - ASSERT(expected == args.which_test()); + const std::map> expected { + { "TestClass", { "TestMethod" } } + }; + ASSERT(expected == args.which_tests()); ASSERT_EQUALS(true, args.quiet()); + ASSERT_EQUALS(2, args.errors().size()); + auto it = args.errors().cbegin(); + ASSERT_EQUALS("unknown option '-a'", *it); + ++it; + ASSERT_EQUALS("unknown option '-v'", *it); } void summary() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-n"}; options args(getArrayLength(argv), argv); ASSERT_EQUALS(false, args.summary()); + ASSERT(args.errors().empty()); } void dry_run() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-d"}; options args(getArrayLength(argv), argv); ASSERT_EQUALS(true, args.dry_run()); + ASSERT(args.errors().empty()); + } + + void exclude_tests() const { + const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-x"}; + options args(getArrayLength(argv), argv); + ASSERT_EQUALS(true, args.exclude_tests()); + ASSERT(args.errors().empty()); + } + + void timer_results() const { + const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-t"}; + options args(getArrayLength(argv), argv); + ASSERT(!!args.timer_results()); } }; diff --git a/test/testother.cpp b/test/testother.cpp index 8f21a7eedea..321657c668f 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -121,6 +121,9 @@ class TestOther : public TestFixture { TEST_CASE(varScope41); // #11845 TEST_CASE(varScope42); TEST_CASE(varScope43); + TEST_CASE(varScope44); + TEST_CASE(varScope45); + TEST_CASE(varScope46); TEST_CASE(oldStylePointerCast); TEST_CASE(intToPointerCast); @@ -195,6 +198,9 @@ class TestOther : public TestFixture { TEST_CASE(duplicateExpression16); // #10569 TEST_CASE(duplicateExpression17); // #12036 TEST_CASE(duplicateExpression18); + TEST_CASE(duplicateExpression19); + TEST_CASE(duplicateExpression20); + TEST_CASE(duplicateExpression21); TEST_CASE(duplicateExpressionLoop); TEST_CASE(duplicateValueTernary); TEST_CASE(duplicateValueTernarySizeof); // #13773 @@ -259,6 +265,7 @@ class TestOther : public TestFixture { TEST_CASE(testUnusedLabel); TEST_CASE(testUnusedLabelConfiguration); TEST_CASE(testUnusedLabelSwitchConfiguration); + TEST_CASE(testUnusedLabelPremiumMisra); TEST_CASE(testEvaluationOrder); TEST_CASE(testEvaluationOrderSelfAssignment); @@ -298,6 +305,8 @@ class TestOther : public TestFixture { TEST_CASE(moveForRange); TEST_CASE(moveTernary); TEST_CASE(movePointerAlias); + TEST_CASE(moveOutparam); + TEST_CASE(moveTryEmplace); TEST_CASE(funcArgNamesDifferent); TEST_CASE(funcArgOrderDifferent); @@ -337,7 +346,7 @@ class TestOther : public TestFixture { bool cpp = true; bool inconclusive = true; bool verbose = false; - Settings* settings = nullptr; + Settings* settings = nullptr; // TODO: split from this }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) @@ -350,10 +359,6 @@ class TestOther : public TestFixture { } else { settings = opt.settings; - settings->severity.enable(Severity::style); - settings->severity.enable(Severity::warning); - settings->severity.enable(Severity::portability); - settings->severity.enable(Severity::performance); } settings->certainty.setEnabled(Certainty::inconclusive, opt.inconclusive); settings->verbose = opt.verbose; @@ -362,8 +367,8 @@ class TestOther : public TestFixture { SimpleTokenizer tokenizer(*settings, *this, opt.cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check.. - runChecks(tokenizer, this); + CheckOther check; + runChecks(check, tokenizer, this); } struct CheckPOptions @@ -379,8 +384,8 @@ class TestOther : public TestFixture { // Tokenizer.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); - // Check.. - runChecks(tokenizer, this); + CheckOther check; + runChecks(check, tokenizer, this); } template @@ -1790,7 +1795,7 @@ class TestOther : public TestFixture { void varScope39() { check("struct S {\n" // #12405 - " void f(const std::string&) const;\n" + " void f(const std::string& s) const;\n" " const int* g(std::string&) const;\n" "};\n" "void h(int);\n" @@ -1946,6 +1951,100 @@ class TestOther : public TestFixture { ASSERT_EQUALS("[test.cpp:3:12]: (style) The scope of the variable 'x' can be reduced. [variableScope]\n", errout_str()); } + void varScope44() { // #14496 + check("char* f() {\n" + " char* p = nullptr;\n" + " {\n" + " p = strdup(\"abc\");\n" + " if (p) {\n" + " return p;\n" + " }\n" + " }\n" + " return nullptr;\n" + "}\n" + "char* g() {\n" + " char* q = NULL;\n" + " {\n" + " q = strdup(\"abc\");\n" + " if (q) {\n" + " return q;\n" + " }\n" + " }\n" + " return nullptr;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:11]: (style) The scope of the variable 'p' can be reduced. [variableScope]\n" + "[test.cpp:12:11]: (style) The scope of the variable 'q' can be reduced. [variableScope]\n", + errout_str()); + } + + void varScope45() { + check("void g(int x, int y) {\n" // #14497 + " int a = x, b = y;\n" + " if (a) {}\n" + " else {\n" + " if (b) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:16]: (style) The scope of the variable 'b' can be reduced. [variableScope]\n", errout_str()); + } + + void varScope46() { + check("void f() {\n" // #7091 + " int y1;\n" + " for (int i = 0; i < 3; ++i) {\n" + " for(int j = 0; j < 3; ++j) {\n" + " y1 = 2 * 1;\n" + " y1 += 1;\n" + " }\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:9]: (style) The scope of the variable 'y1' can be reduced. [variableScope]\n", + errout_str()); + + check("bool f() {\n" + "bool b = false;\n" + "do {\n" + " switch (g()) {\n" + " case 0:\n" + " b = true;\n" + " break;\n" + " case 1:\n" + " return b;\n" + " break;\n" + " default:\n" + " break;\n" + " }\n" + "}\n" + "while (true);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("void f() {\n" + " int y1 = 0;\n" + " for (int i = 0; i < 3; ++i) {\n" + " for(int j = 0; j < 3; ++j) {\n" + " y1 = y1 + 1;\n" + " dostuff(y1);\n" + " }\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("void f(int& r) {\n" // #14566 + " int i = 0;\n" + " while (g()) {\n" + " {\n" + " if (g()) {\n" + " i = 0;" + " std::swap(i, r);\n" + " }\n" + " }\n" + " }\n" + " use(i);" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + #define checkOldStylePointerCast(...) checkOldStylePointerCast_(__FILE__, __LINE__, __VA_ARGS__) template void checkOldStylePointerCast_(const char* file, int line, const char (&code)[size], Standards::cppstd_t std = Standards::CPPLatest) { @@ -1956,7 +2055,7 @@ class TestOther : public TestFixture { SimpleTokenizer tokenizerCpp(settings, *this); ASSERT_LOC(tokenizerCpp.tokenize(code), file, line); - CheckOther checkOtherCpp(&tokenizerCpp, &settings, this); + CheckOtherImpl checkOtherCpp(&tokenizerCpp, &settings, this); checkOtherCpp.warningOldStylePointerCast(); checkOtherCpp.warningDangerousTypeCast(); } @@ -2242,7 +2341,7 @@ class TestOther : public TestFixture { SimpleTokenizer tokenizerCpp(settings, *this); ASSERT_LOC(tokenizerCpp.tokenize(code), file, line); - CheckOther checkOtherCpp(&tokenizerCpp, &settings, this); + CheckOtherImpl checkOtherCpp(&tokenizerCpp, &settings, this); checkOtherCpp.warningIntToPointerCast(); } @@ -2281,7 +2380,7 @@ class TestOther : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - CheckOther checkOtherCpp(&tokenizer, &settings, this); + CheckOtherImpl checkOtherCpp(&tokenizer, &settings, this); checkOtherCpp.invalidPointerCast(); } @@ -2339,7 +2438,7 @@ class TestOther : public TestFixture { checkInvalidPointerCast("void test(float* data) {\n" " f.write((char*)data,sizeof(float));\n" "}", dinit(CheckInvalidPointerCastOptions, $.inconclusive = true)); // #3639 - ASSERT_EQUALS("[test.cpp:2:13]: (portability, inconclusive) Casting from float * to signed char * is not portable due to different binary data representations on different platforms. [invalidPointerCast]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:13]: (portability, inconclusive) Casting from float * to char * is not portable due to different binary data representations on different platforms. [invalidPointerCast]\n", errout_str()); checkInvalidPointerCast("long long* test(float* f) {\n" @@ -2627,6 +2726,14 @@ class TestOther : public TestFixture { check("void f(const std::array a[]) {}\n"); // #13524 ASSERT_EQUALS("", errout_str()); + check("struct S {\n" // #10733 + " std::vector v;\n" + " using F = void (*)();\n" + " void func(F f);\n" + "};\n" + "void S::func(S::F f) {}\n"); + ASSERT_EQUALS("", errout_str()); + /*const*/ Settings settingsWin64 = settingsBuilder().platform(Platform::Type::Win64).build(); check("using ui64 = unsigned __int64;\n" "ui64 Test(ui64 one, ui64 two) { return one + two; }\n", @@ -2656,7 +2763,9 @@ class TestOther : public TestFixture { check("void f(std::string str) {\n" " std::string s2 = str;\n" "}"); - ASSERT_EQUALS("[test.cpp:1:20]: (performance) Function parameter 'str' should be passed by const reference. [passedByValue]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:17]: (performance, inconclusive) Use const reference for 's2' to avoid unnecessary data copying. [redundantCopyLocalConst]\n" + "[test.cpp:1:20]: (performance) Function parameter 'str' should be passed by const reference. [passedByValue]\n", + errout_str()); check("void f(std::string str) {\n" " std::string& s2 = str;\n" @@ -2774,11 +2883,11 @@ class TestOther : public TestFixture { "};\n" "void f(X x) {}"; - /*const*/ Settings s32 = settingsBuilder(settings0).platform(Platform::Type::Unix32).build(); + /*const*/ Settings s32 = settingsBuilder(settings1).platform(Platform::Type::Unix32).build(); check(code, dinit(CheckOptions, $.settings = &s32)); ASSERT_EQUALS("[test.cpp:5:10]: (performance) Function parameter 'x' should be passed by const reference. [passedByValue]\n", errout_str()); - /*const*/ Settings s64 = settingsBuilder(settings0).platform(Platform::Type::Unix64).build(); + /*const*/ Settings s64 = settingsBuilder(settings1).platform(Platform::Type::Unix64).build(); check(code, dinit(CheckOptions, $.settings = &s64)); ASSERT_EQUALS("", errout_str()); } @@ -2802,6 +2911,9 @@ class TestOther : public TestFixture { ASSERT_EQUALS("", errout_str()); check("struct X { int a[5]; }; void f(const X v);"); + ASSERT_EQUALS("", errout_str()); + + check("struct X { int a[5]; }; void f(const X v) { (void) v; }"); ASSERT_EQUALS("[test.cpp:1:40]: (performance) Function parameter 'v' should be passed by const reference. [passedByValue]\n", errout_str()); check("extern \"C\" { struct X { int a[5]; }; void f(const X v); }"); @@ -3515,7 +3627,7 @@ class TestOther : public TestFixture { "class D\n" "{\n" "public:\n" - " explicit D(int&);\n" + " explicit D(int& i);\n" "\n" "private:\n" " C c;\n" @@ -3536,7 +3648,7 @@ class TestOther : public TestFixture { "class D\n" "{\n" "public:\n" - " explicit D(int&) noexcept;\n" + " explicit D(int& i) noexcept;\n" "\n" "private:\n" " C c;\n" @@ -3556,7 +3668,7 @@ class TestOther : public TestFixture { "class D\n" "{\n" "public:\n" - " explicit D(int&);\n" + " explicit D(int& i);\n" "\n" "private:\n" " C c;\n" @@ -3577,7 +3689,7 @@ class TestOther : public TestFixture { "class D\n" "{\n" "public:\n" - " explicit D(int&);\n" + " explicit D(int& i);\n" "\n" "private:\n" " C c;\n" @@ -3598,7 +3710,7 @@ class TestOther : public TestFixture { "class D\n" "{\n" "public:\n" - " explicit D(int&);\n" + " explicit D(int& i);\n" "\n" "private:\n" " C c;\n" @@ -3974,6 +4086,61 @@ class TestOther : public TestFixture { " return (void*)&s;\n" "}\n"); // don't crash ASSERT_EQUALS("", errout_str()); + + check("struct S { int i; };\n" // #14251 + "struct T { std::optional s; };\n" + "void f(T& t) {\n" + " t.s->i = 0;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct B {};\n" // #13877 + "struct D : B { int i; };\n" + "void f(B& b) {\n" + " static_cast(b).i = 0;\n" + "}\n" + "void g(B& b) {\n" + " std::cin >> static_cast(b).i;\n" + "}\n" + "int h(B& b) {\n" + " return static_cast(b).i;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:9:10]: (style) Parameter 'b' can be declared as reference to const [constParameterReference]\n", errout_str()); + + check("void f(int *p) {\n" // #14409 + " int*& pp{ p };\n" + " if (*pp) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("class C {\n" + "public:\n" + " explicit C(const std::string s);\n" + "private:\n" + " std::string _s;\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + + check("void f(int& r) {\n" // #9761 + " o1 = r;\n" + "}\n" + "boost::optional o2;\n" + "void g(int& r) {\n" + " o2 = r;\n" + "}\n" + "struct T {\n" + " int* p;\n" + " T& operator=(int& rhs) { p = &rhs; return *this; }\n" + "};\n" + "void h(T& t, int& r) {\n" + " t = r;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("void f(std::optional& o) {\n" + " *o = 1;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void constParameterCallback() { @@ -4015,6 +4182,16 @@ class TestOther : public TestFixture { " S s2{ cb };\n" "}\n"); ASSERT_EQUALS("[test.cpp:6:11] -> [test.cpp:2:21]: (performance) Function parameter 's' should be passed by const reference. However it seems that 'cb' is a callback function. [passedByValueCallback]\n", errout_str()); + + check("struct S {\n" // #14696 + " explicit S(std::string s = {}) {}\n" + "};\n" + "struct T {\n" + " explicit T(std::string* s = {}) {}\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:2:28]: (performance) Function parameter 's' should be passed by const reference. [passedByValue]\n" + "[test.cpp:5:29]: (style) Parameter 's' can be declared as pointer to const [constParameterPointer]\n", + errout_str()); } void constPointer() { @@ -4591,6 +4768,102 @@ class TestOther : public TestFixture { "}\n"); ASSERT_EQUALS("[test.cpp:4:15]: (style) Variable 'p' can be declared as pointer to const [constVariablePointer]\n", errout_str()); + + check("uintptr_t f(int* p) {\n" + " return (uintptr_t)p;\n" + "}\n" + "uintptr_t g(int* p) {\n" + " return static_cast(p);\n" + "}\n" + "U h(int* p) {\n" + " return (U)p;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:1:18]: (style) Parameter 'p' can be declared as pointer to const [constParameterPointer]\n" + "[test.cpp:4:18]: (style) Parameter 'p' can be declared as pointer to const [constParameterPointer]\n", + errout_str()); + + check("using fp_t = int (*)(int*);\n" // #14510 + "fp_t g_fp;\n" + "struct S { fp_t m_fp; };\n" + "void g(fp_t);\n" + "S f(S* s) {\n" + " g_fp = [](int* p) { return *p; };\n" + " s->m_fp = [](int* p) { return *p; };\n" + " g([](int* p) { return *p; });\n" + " auto x = [](int* p) { return *p; };\n" + " g(x);\n" + " return { [](int* p) { return *p; } };\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("void f() {\n" + " int i = 0;\n" + " auto x = [&]() { int* p = &i; if (*p) {} };\n" + " x();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:27]: (style) Variable 'p' can be declared as pointer to const [constVariablePointer]\n", errout_str()); + + check("int f() {\n" + " int i = 0;\n" + " return [](int* p) { return *p; }(&i);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:20]: (style) Parameter 'p' can be declared as pointer to const [constParameterPointer]\n", errout_str()); + + check("struct S {\n" // #14571 + " char* c;\n" + "};\n" + "struct T {\n" + " S s;\n" + "};\n" + "void f(std::string* p, T& t) {\n" + " S& r = t.s;\n" + " strcpy(r.c, p->c_str());\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:7:21]: (style) Parameter 'p' can be declared as pointer to const [constParameterPointer]\n", errout_str()); + + check("struct S {\n" // #14559 + " int gc() const;\n" + " int gnc();\n" + "};\n" + "int f1(S* s) {\n" + " return h(s ? s->gc() : 1);\n" + "}\n" + "int f2(S* s) {\n" + " return h(s ? s->gnc() : 1);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5:11]: (style) Parameter 's' can be declared as pointer to const [constParameterPointer]\n", errout_str()); + + check("using IntPtr = int *;\n" + "int* foo(IntPtr bar) {\n" + " return bar = 0;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct S { int x; };\n" // #14700 + "int f(S* s) {\n" + " return s->x ? 1 : 0;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:10]: (style) Parameter 's' can be declared as pointer to const [constParameterPointer]\n", errout_str()); + + check("struct S { int a[1][1]; };\n" // #14714 + "int f(S* s) {\n" + " return s->a[0][0] ? 1 : 0;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:10]: (style) Parameter 's' can be declared as pointer to const [constParameterPointer]\n", errout_str()); + + check("int f(int *p, int *q) {\n" // #14748 + " return p ? *p : *q;\n" + "}\n" + "void g(int *p, int *q) {\n" + " int& r = p ? *p : *q;\n" + " r = 0;\n" + "}\n" + "void h(int *p, int *q) {\n" + " i(p ? *p : *q);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:1:12]: (style) Parameter 'p' can be declared as pointer to const [constParameterPointer]\n" + "[test.cpp:1:20]: (style) Parameter 'q' can be declared as pointer to const [constParameterPointer]\n", + errout_str()); } void constArray() { @@ -5513,7 +5786,7 @@ class TestOther : public TestFixture { " \n" " \n" ""; - /*const*/ Settings settings = settingsBuilder().libraryxml(xmldata).build(); + /*const*/ Settings settings = settingsBuilder().libraryxml(xmldata).severity(Severity::style).build(); check("void foo() {\n" " exit(0);\n" @@ -6321,9 +6594,9 @@ class TestOther : public TestFixture { check("class Foo {\n" " int var;\n" - " void func(int var);\n" + " Foo(int var);\n" "};\n" - "void Foo::func(int var) {\n" + "Foo::Foo(int var) {\n" " this->var = var;\n" "}"); ASSERT_EQUALS("", errout_str()); @@ -6580,7 +6853,7 @@ class TestOther : public TestFixture { " AMethodObject(double, double, double);\n" "};\n" "struct S {\n" - " static void A(double, double, double);\n" + " static void A(double a1, double a2, double a3);\n" "};\n" "void S::A(double const a1, double const a2, double const a3) {\n" " AMethodObject(a1, a2, a3);\n" @@ -7100,6 +7373,15 @@ class TestOther : public TestFixture { " }\n" "}"); ASSERT_EQUALS("", errout_str()); + + check("void f(int i) {\n" + " if (1 == i) {\n" + " ;\n" + " } else {\n" + " ;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void duplicateBranch6() { @@ -7407,7 +7689,7 @@ class TestOther : public TestFixture { " \n" " \n" ""; - /*const*/ Settings settings = settingsBuilder().libraryxml(xmldata).build(); + /*const*/ Settings settings = settingsBuilder().libraryxml(xmldata).severity(Severity::style).build(); check("void foo() {\n" " if (x() || x()) {}\n" @@ -7511,7 +7793,7 @@ class TestOther : public TestFixture { "}"); ASSERT_EQUALS( "[test.cpp:2:22]: (style) Same expression on both sides of '&'. [duplicateExpression]\n" - "[test.cpp:2:29]: (style) Same expression on both sides of '&'. [duplicateExpression]\n", // duplicate + "[test.cpp:2:29]: (style) Same expression on both sides of '&'. [duplicateExpression]\n", errout_str()); } @@ -7817,7 +8099,7 @@ class TestOther : public TestFixture { "public:\n" " double getScale() const { return m_range * m_zoom; }\n" " void setZoom(double z) { m_zoom = z; }\n" - " void dostuff(int);\n" + " void dostuff(int x);\n" "private:\n" " double m_zoom;\n" " double m_range;\n" @@ -7968,6 +8250,49 @@ class TestOther : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void duplicateExpression19() { + checkP("const int i = 0;\n" + "void f() {\n" + " assert(i == 0);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + + void duplicateExpression20() { + check("enum { N = 1 };\n" // #14202 + "int f() { return N - 1; }"); + ASSERT_EQUALS("", errout_str()); + } + + void duplicateExpression21() { + check("struct S { int i; };\n" // #12795 + "struct T {\n" + " std::map m;\n" + " S* get(const std::string& s) { return m[s]; }\n" + " void modify() { for (const auto& e : m) e.second->i = 0; }\n" + "};\n" + "void f(T& t) {\n" + " const S* p = t.get(\"abc\");\n" + " const int o = p->i;\n" + " t.modify();\n" + " if (p->i == o) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct S { int i; };\n" + " struct T {\n" + " std::vector m;\n" + " void modify() { for (auto e : m) e->i = 0; }\n" + "};\n" + "void f(T& t) {\n" + " const S* p = t.m[0];\n" + " const int o = p->i;\n" + " t.modify();\n" + " if (p->i == o) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + void duplicateExpressionLoop() { check("void f() {\n" " int a = 1;\n" @@ -8101,7 +8426,7 @@ class TestOther : public TestFixture { const char code[] = "void foo(bool flag) {\n" " bar( (flag) ? ~0u : ~0ul);\n" "}"; - /*const*/ Settings settings = settings0; + /*const*/ Settings settings = settings1; settings.platform.sizeof_int = 4; settings.platform.int_bit = 32; @@ -8183,6 +8508,18 @@ class TestOther : public TestFixture { " return (x >= 0.0) ? 0.0 : -0.0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("struct A {};\n" // # 14300 + "struct B {};\n" + "void f(bool x) {\n" + " A* a = new A();\n" + " B* b = new B();\n" + " auto p = x ? static_cast(a) : static_cast(b);\n" + " (void)p;\n" + " delete a;\n" + " delete b;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void duplicateValueTernarySizeof() { // #13773 @@ -8667,8 +9004,7 @@ class TestOther : public TestFixture { " if (i == j) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n" - "[test.cpp:3:14] -> [test.cpp:4:14] -> [test.cpp:6:11]: (style) The comparison 'i == j' is always true because 'i' and 'j' represent the same value. [knownConditionTrueFalse]\n", + "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n", errout_str()); check("struct A { int x; int y; };" @@ -8680,8 +9016,7 @@ class TestOther : public TestFixture { " if (i == a.x) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n" - "[test.cpp:3:14] -> [test.cpp:6:11]: (style) The comparison 'i == a.x' is always true because 'i' and 'a.x' represent the same value. [knownConditionTrueFalse]\n", + "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n", errout_str()); check("struct A { int x; int y; };" @@ -8693,8 +9028,7 @@ class TestOther : public TestFixture { " if (j == a.x) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n" - "[test.cpp:4:14] -> [test.cpp:6:11]: (style) The comparison 'j == a.x' is always true because 'j' and 'a.x' represent the same value. [knownConditionTrueFalse]\n", + "[test.cpp:4:9] -> [test.cpp:3:9]: (style, inconclusive) Same expression used in consecutive assignments of 'i' and 'j'. [duplicateAssignExpression]\n", errout_str()); // Issue #8612 @@ -9103,6 +9437,24 @@ class TestOther : public TestFixture { " for (unsigned p = 0; p < (sizeof(a) / sizeof((a)[0])); ++p) {}\n" "}"); ASSERT_EQUALS("", errout_str()); + + check("void f(const unsigned char u) {\n" + " if (u > 0) {}\n" + " if (u < 0) {}\n" + " if (u >= 0) {}\n" + " if (u <= 0) {}\n" + " if (0 < u) {}\n" + " if (0 > u) {}\n" + " if (0 <= u) {}\n" + " if (0 >= u) {}\n" + "}"); + ASSERT_EQUALS("[test.cpp:3:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n" + "[test.cpp:4:11]: (style) Unsigned expression 'u' can't be negative so it is unnecessary to test it. [unsignedPositive]\n" + "[test.cpp:5:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n" + "[test.cpp:7:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n" + "[test.cpp:8:11]: (style) Unsigned expression 'u' can't be negative so it is unnecessary to test it. [unsignedPositive]\n" + "[test.cpp:9:11]: (style) Checking if unsigned expression 'u' is less than zero. [unsignedLessThanZero]\n", + errout_str()); } void checkSignOfPointer() { @@ -9744,9 +10096,7 @@ class TestOther : public TestFixture { " u.g();\n" " if (c == m->get()) {}\n" "}\n"); - TODO_ASSERT_EQUALS("", - "[test.cpp:16:33] -> [test.cpp:18:11]: (style) The comparison 'c == m->get()' is always true because 'c' and 'm->get()' represent the same value. [knownConditionTrueFalse]\n", - errout_str()); + ASSERT_EQUALS("", errout_str()); check("struct S {\n" // #12925 " const std::string & f() const { return str; }\n" @@ -9773,6 +10123,58 @@ class TestOther : public TestFixture { " if (s.empty()) {}\n" "}\n"); ASSERT_EQUALS("[test.cpp:6:16]: (performance, inconclusive) Use const reference for 's' to avoid unnecessary data copying. [redundantCopyLocalConst]\n", errout_str()); + + check("void f1(const std::string& s) {\n" + " std::string s1 = s;\n" + " (void)s1;\n" + "}\n" + "void f2() {\n" + " const std::string s;\n" + " std::string s1 = s;\n" + " (void)s1;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:17]: (performance, inconclusive) Use const reference for 's1' to avoid unnecessary data copying. [redundantCopyLocalConst]\n" + "[test.cpp:7:17]: (performance, inconclusive) Use const reference for 's1' to avoid unnecessary data copying. [redundantCopyLocalConst]\n", + errout_str()); + + check("struct S {\n" + " std::string m;\n" + " int f(const std::string& s);\n" + "};\n" + "int S::f(const std::string& s) {\n" + " std::string c = s;\n" + " m.clear();\n" + " return c.size();\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct S {\n" + " std::string m;\n" + " int f(std::string s);\n" + "};\n" + "int S::f(std::string s) {\n" + " s += m;\n" + " std::string c = s;\n" + " m.clear();\n" + " return c.size();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:7:17]: (performance, inconclusive) Use const reference for 'c' to avoid unnecessary data copying. [redundantCopyLocalConst]\n", + errout_str()); + + check("int f(const char* c) {\n" // #14530 + " std::string s = c;\n" + " return s.rfind('.');\n" + "}\n" + "struct M {\n" + " M(const std::array& a);\n" + " double m[3][3];\n" + " double trace() const;\n" + "};\n" + "double g(const std::array& a) {\n" + " M m = a;\n" + " return m.trace();\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void checkNegativeShift() { @@ -10357,7 +10759,7 @@ class TestOther : public TestFixture { // Member variable pointers check("void podMemPtrs() {\n" - " int POD::*memptr;\n" + " const int POD::*memptr;\n" " memptr = &POD::a;\n" " memptr = &POD::b;\n" " if (memptr)\n" @@ -10442,6 +10844,21 @@ class TestOther : public TestFixture { ASSERT_EQUALS( "[test.cpp:2:10]: (style) Variable 'a' can be declared as pointer to const [constVariablePointer]\n", errout_str()); + + check("std::string f() {\n" // #14534 + " std::string s = \"abc\";\n" + " s = \"def\";\n" + " return s;\n" + "}\n" + "const char* g() {\n" + " const char* p = \"abc\";\n" + " p = \"def\";\n" + " return p;\n" + "}"); + ASSERT_EQUALS( + "[test.cpp:2:19] -> [test.cpp:3:7]: (style) Redundant initialization for 's'. The initialized value is overwritten before it is read. [redundantInitialization]\n" + "[test.cpp:7:19] -> [test.cpp:8:7]: (style) Redundant initialization for 'p'. The initialized value is overwritten before it is read. [redundantInitialization]\n", + errout_str()); } void redundantVarAssignment_struct() { @@ -11025,6 +11442,15 @@ class TestOther : public TestFixture { " a = x;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("int f(int a, int b, int c) {\n" // #4491 + " int x = a + b;\n" + " if (c)\n" + " x = a + b;\n" + " return x;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:11] -> [test.cpp:4:9]: (style) Variable 'x' is assigned an expression that holds the same value. [redundantAssignment]\n", + errout_str()); } void varFuncNullUB() { // #4482 @@ -11035,6 +11461,12 @@ class TestOther : public TestFixture { check("void a(char *p, ...);\n" "void b() { a(NULL, 2); }"); ASSERT_EQUALS("", errout_str()); + + checkP("extern const int sentinel;\n" + "void a(int, ...);\n" + "#define b(x, ...) a((x), __VA_ARGS__, &sentinel)\n" + "void c() { b(1, NULL); }"); + ASSERT_EQUALS("", errout_str()); } void checkCastIntToCharAndBack() { // #160 @@ -11360,6 +11792,19 @@ class TestOther : public TestFixture { "void f(S s) {}\n"); ASSERT_EQUALS("", errout_str()); + check("struct T {\n" // #14667 + " U u1, u2;\n" + " union {\n" + " enum { E0, E1 } e;\n" + " U u3;\n" + " T i;\n" + " } x;\n" + "};\n" + "T f(T t) {\n" + " return t;\n" + "}"); + ASSERT_EQUALS("", errout_str()); // don't crash + Settings settingsUnix32 = settingsBuilder().platform(Platform::Type::Unix32).build(); check("struct S {\n" // #13850 " int i0 : 32;\n" @@ -11848,16 +12293,29 @@ class TestOther : public TestFixture { errout_str()); } + void testUnusedLabelPremiumMisra() { // #14467 - enable unusedLabel with --premium=misra-c-20xx flag + Settings s; + check("void f() {\n" + " label:\n" + "}", dinit(CheckOptions, $.settings = &s)); + ASSERT_EQUALS("", errout_str()); + s.premiumArgs = "--premium=misra-c-2012"; // <- activates unusedLabel checking + check("void f() {\n" + " label:\n" + "}", dinit(CheckOptions, $.settings = &s)); + ASSERT_EQUALS("[test.cpp:2:5]: (style) Label 'label' is not used. [unusedLabel]\n", errout_str()); + } + // TODO: only used in a single place #define checkCustomSettings(...) checkCustomSettings_(__FILE__, __LINE__, __VA_ARGS__) template - void checkCustomSettings_(const char* file, int line, const char (&code)[size], const Settings& settings) { + void checkCustomSettings_(const char* file, int line, const char (&code)[size], const Settings& settings, bool cpp = true) { // Tokenize.. - SimpleTokenizer tokenizer(settings, *this); + SimpleTokenizer tokenizer(settings, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check.. - runChecks(tokenizer, this); + CheckOther check; + runChecks(check, tokenizer, this); } void testEvaluationOrder() { @@ -11926,6 +12384,12 @@ class TestOther : public TestFixture { " i = i++ + 2;\n" "}", settings11); ASSERT_EQUALS("[test.cpp:2:11]: (error) Expression 'i+++2' depends on order of evaluation of side effects [unknownEvaluationOrder]\n", errout_str()); + + // #14431 + checkCustomSettings("int f(void) {\n" + " struct baz baz = {.bar = {.foo = {.foo = 1}}};\n" + "}\n", settings0, false); + ASSERT_EQUALS("", errout_str()); } void testEvaluationOrderSelfAssignment() { @@ -12289,6 +12753,24 @@ class TestOther : public TestFixture { " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:36]: (warning) Access of moved variable 'l'. [accessMoved]\n", errout_str()); + + check("struct S {\n" // #13179 + " operator bool() const { return !m.empty(); }\n" + " std::string m;\n" + "};\n" + "S get();\n" + "void set(S);\n" + "void f() {\n" + " while (S s = get()) {\n" + " set(std::move(s));\n" + " }\n" + "}\n" + "void g() {\n" + " while (S s{ get() }) {\n" + " set(std::move(s));\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void moveCallback() @@ -12389,6 +12871,38 @@ class TestOther : public TestFixture { ASSERT_EQUALS("[test.cpp:5:8]: (warning) Access of moved variable '.'. [accessMoved]\n", errout_str()); } + void moveOutparam() + { + check("void f(std::vector& v) {\n" // #11300 + " std::string l;\n" + " while (std::getline(std::cin, l)) {\n" + " if (!l.empty()) {\n" + " v.emplace_back(std::move(l));\n" + " }\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("void f(std::ifstream& fin, std::set& s) {\n" + " std::string line;\n" + " while (std::getline(fin, line)) {\n" + " s.emplace(std::move(line));\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + + void moveTryEmplace() + { + check("void f(std::map& m, std::string& s) {\n" // #12773 + " bool b = m.try_emplace(\"a\", std::move(s)).second;\n" + " if (!b) {\n" + " std::cout << s;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + } + void funcArgNamesDifferent() { check("void func1(int a, int b, int c);\n" "void func1(int a, int b, int c) { }\n" @@ -12413,6 +12927,31 @@ class TestOther : public TestFixture { "[test.cpp:9:20] -> [test.cpp:14:22]: (style, inconclusive) Function 'func4' argument 1 names different: declaration 'a' definition 'A'. [funcArgNamesDifferent]\n" "[test.cpp:9:31] -> [test.cpp:14:29]: (style, inconclusive) Function 'func4' argument 2 names different: declaration 'b' definition 'B'. [funcArgNamesDifferent]\n" "[test.cpp:9:42] -> [test.cpp:14:36]: (style, inconclusive) Function 'func4' argument 3 names different: declaration 'c' definition 'C'. [funcArgNamesDifferent]\n", errout_str()); + + check("using F1 = void (*)();\n" // #14633 + "void f(F1 a);\n" + "void f(F1 b) {}\n" + "typedef void (*F2)();\n" + "void g(F2 a);\n" + "void g(F2 b) {}\n" + "void h(void (*a)());\n" + "void h(void (*b)()) {}\n"); + ASSERT_EQUALS( + "[test.cpp:2:11] -> [test.cpp:3:11]: (style, inconclusive) Function 'f' argument 1 names different: declaration 'a' definition 'b'. [funcArgNamesDifferent]\n" + "[test.cpp:5:11] -> [test.cpp:6:11]: (style, inconclusive) Function 'g' argument 1 names different: declaration 'a' definition 'b'. [funcArgNamesDifferent]\n" + "[test.cpp:7:15] -> [test.cpp:8:15]: (style, inconclusive) Function 'h' argument 1 names different: declaration 'a' definition 'b'. [funcArgNamesDifferent]\n", + errout_str()); + + check("void f(int a);\n" // #14632 + "void f(int) {}\n" + "void g(int);\n" + "void g(int b) {}\n" + "void h(int);\n" + "void h(int) {}\n"); + ASSERT_EQUALS( + "[test.cpp:1:12]: (style, inconclusive) Function 'f' argument 1 names different: declaration 'a' definition ''. [funcArgNamesDifferentUnnamed]\n" + "[test.cpp:4:12]: (style, inconclusive) Function 'g' argument 1 names different: declaration '' definition 'b'. [funcArgNamesDifferentUnnamed]\n", + errout_str()); } void funcArgOrderDifferent() { @@ -12438,6 +12977,10 @@ class TestOther : public TestFixture { "[test.cpp:9:20] -> [test.cpp:14:22]: (warning) Function 'func2' argument order different: declaration 'a, b, c' definition 'c, b, a' [funcArgOrderDifferent]\n" "[test.cpp:10:20] -> [test.cpp:15:22]: (warning) Function 'func3' argument order different: declaration 'a, b, c' definition 'c, b, a' [funcArgOrderDifferent]\n" "[test.cpp:11:16] -> [test.cpp:16:22]: (warning) Function 'func4' argument order different: declaration ', b, c' definition 'c, b, a' [funcArgOrderDifferent]\n", errout_str()); + + check("void f(int N, const int a[N], const int b[N]);\n" // #14710 + "void f(int N, const int a[N], const int b[N]) {}\n"); + ASSERT_EQUALS("", errout_str()); } // #7846 - Syntax error when using C++11 braced-initializer in default argument @@ -12512,14 +13055,14 @@ class TestOther : public TestFixture { " int i{};\n" " void f() { int i; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:3:20]: (style) Local variable 'i' shadows outer variable [shadowVariable]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:3:20]: (style) Local variable 'i' shadows outer member [shadowMember]\n", errout_str()); check("struct S {\n" " int i{};\n" " std::vector v;\n" " void f() const { for (const int& i : v) {} }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:4:38]: (style) Local variable 'i' shadows outer variable [shadowVariable]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:9] -> [test.cpp:4:38]: (style) Local variable 'i' shadows outer member [shadowMember]\n", errout_str()); check("struct S {\n" // #10405 " F* f{};\n" @@ -12529,7 +13072,7 @@ class TestOther : public TestFixture { "void S::f() const {\n" " for (const F& f : fl) {}\n" "};\n"); - ASSERT_EQUALS("[test.cpp:2:8] -> [test.cpp:7:19]: (style) Local variable 'f' shadows outer variable [shadowVariable]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:8] -> [test.cpp:7:19]: (style) Local variable 'f' shadows outer member [shadowMember]\n", errout_str()); check("extern int a;\n" "int a;\n" @@ -12551,6 +13094,30 @@ class TestOther : public TestFixture { " friend int f() { int i = 5; return i; }\n" "};\n"); ASSERT_EQUALS("", errout_str()); + + check("int x;\n" + "void f(int x) {}\n"); + ASSERT_EQUALS("[test.cpp:1:5] -> [test.cpp:2:12]: (style) Argument 'x' shadows outer variable [shadowVariable]\n", errout_str()); + + check("void x() {}\n" + "void f(int x) {}\n"); + ASSERT_EQUALS("[test.cpp:1:6] -> [test.cpp:2:12]: (style) Argument 'x' shadows outer function [shadowFunction]\n", errout_str()); + + check("struct S { int v; void func(int v); };\n" + "void S::func(int v) { this->v = v; }\n"); + ASSERT_EQUALS("[test.cpp:1:16] -> [test.cpp:2:18]: (style) Argument 'v' shadows outer member [shadowMember]\n", errout_str()); + + check("struct S { int v; void func(void); };\n" + "void S::func() { int v = 0; }\n"); + ASSERT_EQUALS("[test.cpp:1:16] -> [test.cpp:2:22]: (style) Local variable 'v' shadows outer member [shadowMember]\n", errout_str()); + + check("struct S { int v; explicit S(int v); };\n" + "S::S(int v) : v(v) {}\n"); + ASSERT_EQUALS("", errout_str()); + + check("struct S { int v(); explicit S(int v); };\n" + "S::S(int v) : v(v) {}\n"); + ASSERT_EQUALS("", errout_str()); } void knownArgument() { @@ -12973,6 +13540,13 @@ class TestOther : public TestFixture { " if (j % c) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("void f() {\n" + " int i = 0;\n" + " i %= 1;\n" + " (void)i;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:7]: (style) Modulo of one is always equal to zero [moduloofone]\n", errout_str()); } void sameExpressionPointers() { @@ -13114,14 +13688,14 @@ class TestOther : public TestFixture { "}\n"); ASSERT_EQUALS("", errout_str()); - check("struct A { bool x; };\n" + check("struct A { bool x; };\n" // #14481 "bool f(A* a) {\n" " if (a) {\n" " return a->x;\n" " }\n" " return false;\n" "}\n"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:2:11]: (style) Parameter 'a' can be declared as pointer to const [constParameterPointer]\n", errout_str()); check("struct A { int* x; };\n" "bool f(A a) {\n" diff --git a/test/testpath.cpp b/test/testpath.cpp index 7c181e28afb..69ee91fa391 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,6 +57,7 @@ class TestPath : public TestFixture { TEST_CASE(getAbsolutePath); TEST_CASE(exists); TEST_CASE(fromNativeSeparators); + TEST_CASE(isRelative); } void removeQuotationMarks() const { @@ -202,6 +203,8 @@ class TestPath : public TestFixture { //ASSERT_EQUALS("", Path::join("S:/a", "S:/b")); //ASSERT_EQUALS("", Path::join("S:/a", "S:\\b")); //ASSERT_EQUALS("", Path::join("S:/a", "/b")); + + ASSERT_EQUALS("a/b/c", Path::join("a", "b", "c")); } void isDirectory() const { @@ -315,7 +318,7 @@ class TestPath : public TestFixture { ASSERT_EQUALS(Standards::Language::CPP, Path::identify("/mnt/c/foo/index.cpp", false)); ASSERT_EQUALS(Standards::Language::CPP, Path::identify("/mnt/c/foo/index.Cpp", false)); - // TODO: check for case-insenstive filesystem instead + // TODO: check for case-insensitive filesystem instead // In unix .C is considered C++ #if !defined(_WIN32) && !(defined(__APPLE__) && defined(__MACH__)) ASSERT_EQUALS(Standards::Language::CPP, Path::identify("index.C", false)); @@ -533,7 +536,7 @@ class TestPath : public TestFixture { #ifndef _WIN32 // the underlying realpath() call only returns something if the path actually exists - ASSERT_THROW_EQUALS_2(Path::getAbsoluteFilePath("testabspath2.txt"), std::runtime_error, "path 'testabspath2.txt' does not exist"); + ASSERT_THROW_EQUALS(Path::getAbsoluteFilePath("testabspath2.txt"), std::runtime_error, "path 'testabspath2.txt' does not exist"); #else ASSERT_EQUALS(Path::toNativeSeparators(Path::join(cwd, "testabspath2.txt")), Path::getAbsoluteFilePath("testabspath2.txt")); #endif @@ -572,7 +575,7 @@ class TestPath : public TestFixture { #endif #ifndef _WIN32 - ASSERT_THROW_EQUALS_2(Path::getAbsoluteFilePath("C:\\path\\files.txt"), std::runtime_error, "path 'C:\\path\\files.txt' does not exist"); + ASSERT_THROW_EQUALS(Path::getAbsoluteFilePath("C:\\path\\files.txt"), std::runtime_error, "path 'C:\\path\\files.txt' does not exist"); #endif // TODO: test UNC paths @@ -618,6 +621,33 @@ class TestPath : public TestFixture { ASSERT_EQUALS("//lib/file.c", Path::fromNativeSeparators("\\\\lib\\file.c")); ASSERT_EQUALS("./lib/file.c", Path::fromNativeSeparators(".\\lib\\file.c")); } + + void isRelative() const { + ASSERT_EQUALS(true, Path::isRelative("dir/file")); + ASSERT_EQUALS(true, Path::isRelative("dir\\file")); + + // TODO: is this expected? + ASSERT_EQUALS(true, Path::isRelative("file/")); + ASSERT_EQUALS(true, Path::isRelative("file\\")); + + ASSERT_EQUALS(false, Path::isRelative("file")); + +#ifdef _WIN32 + // this is a relative path on Windows + ASSERT_EQUALS(true, Path::isRelative("/dir/file")); +#else + ASSERT_EQUALS(false, Path::isRelative("/dir/file")); +#endif + +#ifdef _WIN32 + // TODO: this is not detected as absolute path in _WIN32 builds + ASSERT_EQUALS(false, Path::isRelative("c:\\dir\\file")); + ASSERT_EQUALS(false, Path::isRelative("c:/dir/file")); +#else + ASSERT_EQUALS(true, Path::isRelative("c:\\dir\\file")); + ASSERT_EQUALS(true, Path::isRelative("c:/dir/file")); +#endif + } }; REGISTER_TEST(TestPath) diff --git a/test/testpathmatch.cpp b/test/testpathmatch.cpp index 2be6a943845..7e721502a11 100644 --- a/test/testpathmatch.cpp +++ b/test/testpathmatch.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +28,11 @@ class TestPathMatch : public TestFixture { TestPathMatch() : TestFixture("TestPathMatch") {} private: + class PathMatchTest final : public PathMatch + { + friend class TestPathMatch; + }; + static constexpr auto unix = PathMatch::Syntax::unix; static constexpr auto windows = PathMatch::Syntax::windows; static constexpr auto ifreg = PathMatch::Filemode::regular; @@ -277,7 +282,7 @@ class TestPathMatch : public TestFixture { void pathiterator() const { /* See https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats * for information on Windows path syntax. */ - using PathIterator = PathMatch::PathIterator; + using PathIterator = PathMatchTest::PathIterator; ASSERT_EQUALS("/", PathIterator("/", nullptr, unix).read()); ASSERT_EQUALS("/", PathIterator("//", nullptr, unix).read()); ASSERT_EQUALS("/", PathIterator("/", "/", unix).read()); @@ -291,7 +296,7 @@ class TestPathMatch : public TestFixture { ASSERT_EQUALS("", PathIterator(nullptr, "", unix).read()); ASSERT_EQUALS("", PathIterator(nullptr, nullptr, unix).read()); ASSERT_EQUALS("c:", PathIterator("C:", nullptr, windows).read()); - /* C: without slash is a bit ambigous. It should probably not be considered a root because it's + /* C: without slash is a bit ambiguous. It should probably not be considered a root because it's * not fully qualified (it designates the current directory on the C drive), * so this test could be considered to be unspecified behavior. */ ASSERT_EQUALS("c:", PathIterator("C:", "../..", windows).read()); diff --git a/test/testplatform.cpp b/test/testplatform.cpp index 96fa960a5c3..ccb7d9b41a8 100644 --- a/test/testplatform.cpp +++ b/test/testplatform.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2024 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,11 +37,12 @@ class TestPlatform : public TestFixture { TEST_CASE(valid_config_win32w); TEST_CASE(valid_config_unix32); TEST_CASE(valid_config_win64); + // TODO: test native and unspecified TEST_CASE(valid_config_file_1); TEST_CASE(valid_config_file_2); - TEST_CASE(valid_config_file_3); TEST_CASE(valid_config_file_4); TEST_CASE(invalid_config_file_1); + TEST_CASE(invalid_config_file_2); TEST_CASE(empty_elements); TEST_CASE(default_platform); TEST_CASE(limitsDefines); @@ -50,7 +51,7 @@ class TestPlatform : public TestFixture { TEST_CASE(wrong_root_node); } - class PlatformTest : public Platform + class PlatformTest final : public Platform { friend class TestPlatform; }; @@ -85,7 +86,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(2, platform.sizeof_wchar_t); ASSERT_EQUALS(4, platform.sizeof_size_t); ASSERT_EQUALS(4, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -110,7 +111,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(4, platform.sizeof_wchar_t); ASSERT_EQUALS(8, platform.sizeof_size_t); ASSERT_EQUALS(8, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -138,7 +139,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(2, platform.sizeof_wchar_t); ASSERT_EQUALS(4, platform.sizeof_size_t); ASSERT_EQUALS(4, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -166,7 +167,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(4, platform.sizeof_wchar_t); ASSERT_EQUALS(4, platform.sizeof_size_t); ASSERT_EQUALS(4, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -194,7 +195,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(2, platform.sizeof_wchar_t); ASSERT_EQUALS(8, platform.sizeof_size_t); ASSERT_EQUALS(8, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -210,6 +211,7 @@ class TestPlatform : public TestFixture { // Similar to the avr8 platform file. constexpr char xmldata[] = "\n" "\n" + " false\n" " 8\n" " unsigned\n" " \n" @@ -254,6 +256,7 @@ class TestPlatform : public TestFixture { // char_bit > 8. constexpr char xmldata[] = "\n" "\n" + " true\n" " 20\n" " signed\n" " \n" @@ -273,7 +276,7 @@ class TestPlatform : public TestFixture { PlatformTest platform; ASSERT(readPlatform(platform, xmldata)); ASSERT_EQUALS(Platform::Type::File, platform.type); - ASSERT(!platform.isWindows()); + ASSERT(platform.isWindows()); ASSERT_EQUALS(20, platform.char_bit); ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(1, platform.sizeof_bool); @@ -293,11 +296,12 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(100, platform.long_long_bit); } - void valid_config_file_3() const { - // Valid platform configuration without any usable information. + void invalid_config_file_2() const { + // Invalid platform configuration without any usable information. // Similar like an empty file. constexpr char xmldata[] = "\n" "\n" + " true\n" " 8\n" " unsigned\n" " \n" @@ -324,6 +328,7 @@ class TestPlatform : public TestFixture { // set to 0. constexpr char xmldata[] = "\n" "\n" + " true\n" " 0\n" " z\n" " \n" @@ -343,7 +348,7 @@ class TestPlatform : public TestFixture { PlatformTest platform; ASSERT(readPlatform(platform, xmldata)); ASSERT_EQUALS(Platform::Type::File, platform.type); - ASSERT(!platform.isWindows()); + ASSERT(platform.isWindows()); ASSERT_EQUALS(0, platform.char_bit); ASSERT_EQUALS('z', platform.defaultSign); ASSERT_EQUALS(0, platform.sizeof_bool); @@ -367,6 +372,7 @@ class TestPlatform : public TestFixture { // Invalid XML file: mismatching elements "boolt" vs "bool". constexpr char xmldata[] = "\n" "\n" + " false\n" " 8\n" " unsigned\n" " \n" @@ -392,6 +398,7 @@ class TestPlatform : public TestFixture { // Similar like an empty file. constexpr char xmldata[] = "\n" "\n" + " \n" " \n" " \n" " \n" diff --git a/test/testpostfixoperator.cpp b/test/testpostfixoperator.cpp index 9e95fabc949..1d01217231a 100644 --- a/test/testpostfixoperator.cpp +++ b/test/testpostfixoperator.cpp @@ -38,8 +38,7 @@ class TestPostfixOperator : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check for postfix operators.. - CheckPostfixOperator checkPostfixOperator(&tokenizer, &settings, this); + CheckPostfixOperatorImpl checkPostfixOperator(&tokenizer, &settings, this); checkPostfixOperator.postfixOperator(); } diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index ada3a7e5c45..7e01f6f233b 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ // the code for a known configuration, it generates the code for each configuration. #include "errortypes.h" +#include "library.h" #include "path.h" #include "platform.h" #include "preprocessor.h" @@ -49,28 +50,20 @@ class TestPreprocessor : public TestFixture { TestPreprocessor() : TestFixture("TestPreprocessor") {} private: - class PreprocessorTest : public Preprocessor - { - friend class TestPreprocessor; - public: - PreprocessorTest(simplecpp::TokenList& tokens, const Settings& settings, ErrorLogger &errorLogger, Standards::Language lang) - : Preprocessor(tokens, settings, errorLogger, lang) - {} - }; - template std::string expandMacros(const char (&code)[size], ErrorLogger &errorLogger) const { simplecpp::OutputList outputList; std::vector files; simplecpp::TokenList tokens1 = simplecpp::TokenList(code, files, "file.cpp", &outputList); - PreprocessorTest p(tokens1, settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false)); - simplecpp::TokenList tokens2 = p.preprocess("", files, true); - p.reportOutput(outputList, true); + Preprocessor p(tokens1, settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false)); + ASSERT(p.loadFiles(files)); + simplecpp::TokenList tokens2 = p.preprocess("", files, outputList); + (void)p.reportOutput(outputList, true); return tokens2.stringify(); } template - static void preprocess(const char (&code)[size], std::vector &files, const std::string& file0, TokenList& tokenlist, const simplecpp::DUI& dui) + void preprocess(const char (&code)[size], std::vector &files, const std::string& file0, TokenList& tokenlist, const simplecpp::DUI& dui) { if (!files.empty()) throw std::runtime_error("file list not empty"); @@ -78,13 +71,15 @@ class TestPreprocessor : public TestFixture { if (tokenlist.front()) throw std::runtime_error("token list not empty"); - const simplecpp::TokenList tokens1(code, files, file0); + simplecpp::OutputList outputList; + const simplecpp::TokenList tokens1(code, files, file0, &outputList); // Preprocess.. simplecpp::TokenList tokens2(files); simplecpp::FileDataCache cache; - // TODO: provide and handle outputList - simplecpp::preprocess(tokens2, tokens1, files, cache, dui); + simplecpp::preprocess(tokens2, tokens1, files, cache, dui, &outputList); + Preprocessor preprocessor(tokens2, settingsDefault, *this, Standards::Language::C); + (void)preprocessor.reportOutput(outputList, true); // Tokenizer.. tokenlist.createTokens(std::move(tokens2)); @@ -126,19 +121,20 @@ class TestPreprocessor : public TestFixture { simplecpp::OutputList outputList; std::vector files; - simplecpp::TokenList tokens(code, size, files, Path::simplifyPath(filename), &outputList); + simplecpp::TokenList tokens({code, size}, files, Path::simplifyPath(filename), &outputList); + // TODO: we should be using the actual Preprocessor implementation - PreprocessorTest preprocessor(tokens, settings, errorlogger, Path::identify(tokens.getFiles()[0], false)); + Preprocessor preprocessor(tokens, settings, errorlogger, Path::identify(tokens.getFiles()[0], false)); + + // TODO: should be possible without a Preprocessor instance + if (preprocessor.reportOutput(outputList, true)) + return {}; + if (inlineSuppression) preprocessor.inlineSuppressions(*inlineSuppression); preprocessor.removeComments(); preprocessor.simplifyPragmaAsm(); - preprocessor.reportOutput(outputList, true); - - if (PreprocessorTest::hasErrors(outputList)) - return {}; - std::map cfgcode; if (cfgs.empty()) cfgs = preprocessor.getConfigs(); @@ -285,6 +281,7 @@ class TestPreprocessor : public TestFixture { // inline suppression, missingInclude/missingIncludeSystem TEST_CASE(inline_suppressions); + TEST_CASE(inline_suppressions_not_next_line); // remark comment TEST_CASE(remarkComment1); @@ -320,6 +317,17 @@ class TestPreprocessor : public TestFixture { TEST_CASE(getConfigs8); // #if A==1 => cfg: A=1 TEST_CASE(getConfigs10); // #5139 TEST_CASE(getConfigs11); // #9832 - include guards + TEST_CASE(getConfigs12); // #14222 + TEST_CASE(getConfigs13); // #14222 + TEST_CASE(getConfigs_gte); // #1059 + TEST_CASE(getConfigs_lte); // #1059 + TEST_CASE(getConfigs_gt); // #1059 + TEST_CASE(getConfigs_lt); // #1059 + TEST_CASE(getConfigs_eq_compound); // #1059 + TEST_CASE(getConfigs_gte_compound); // #1059 + TEST_CASE(getConfigs_lte_compound); // #1059 + TEST_CASE(getConfigs_gt_compound); // #1059 + TEST_CASE(getConfigs_lt_compound); // #1059 TEST_CASE(getConfigsError); TEST_CASE(getConfigsD1); @@ -332,6 +340,11 @@ class TestPreprocessor : public TestFixture { TEST_CASE(getConfigsU6); TEST_CASE(getConfigsU7); + TEST_CASE(getConfigsAndCodeIssue14317); + TEST_CASE(getConfigsMostGeneralConfigIssue14317); + + TEST_CASE(getConfigsInvalid); // #14732 + TEST_CASE(if_sizeof); TEST_CASE(invalid_ifs); // #5909 @@ -363,19 +376,25 @@ class TestPreprocessor : public TestFixture { TEST_CASE(standard); TEST_CASE(writeLocations); + + TEST_CASE(pragmaAsm); } template - std::string getConfigsStr(const char (&code)[size], const char *arg = nullptr) { + std::string getConfigsStr(const char (&code)[size], const char *arg = nullptr, const char *library = nullptr) { Settings settings; if (arg && std::strncmp(arg,"-D",2)==0) settings.userDefines = arg + 2; if (arg && std::strncmp(arg,"-U",2)==0) settings.userUndefs.insert(arg+2); + if (library) + ASSERT(settings.library.load("", library, false).errorcode == Library::ErrorCode::OK); std::vector files; - // TODO: this adds an empty filename - simplecpp::TokenList tokens(code,files); + simplecpp::OutputList outputList; + simplecpp::TokenList tokens(code,files,"test.c",&outputList); Preprocessor preprocessor(tokens, settings, *this, Standards::Language::C); // TODO: do we need to consider #file? + ASSERT(preprocessor.loadFiles(files)); + ASSERT(!preprocessor.reportOutput(outputList, true)); preprocessor.removeComments(); const std::set configs = preprocessor.getConfigs(); std::string ret; @@ -387,9 +406,9 @@ class TestPreprocessor : public TestFixture { template std::size_t getHash(const char (&code)[size]) { std::vector files; - // TODO: this adds an empty filename - simplecpp::TokenList tokens(code,files); + simplecpp::TokenList tokens(code,files,"test.c"); Preprocessor preprocessor(tokens, settingsDefault, *this, Standards::Language::C); // TODO: do we need to consider #file? + ASSERT(preprocessor.loadFiles(files)); preprocessor.removeComments(); return preprocessor.calculateHash(""); } @@ -427,7 +446,7 @@ class TestPreprocessor : public TestFixture { "#else\n" "#error abcd\n" "#endif\n"; - ASSERT_EQUALS("\nA\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nA=A\n", getConfigsStr(filedata)); } void error2() { @@ -446,7 +465,7 @@ class TestPreprocessor : public TestFixture { const auto settings = dinit(Settings, $.userDefines = "__cplusplus"); const char code[] = "#error hello world!\n"; (void)getcodeforcfg(settings, *this, code, "X", "test.c"); - ASSERT_EQUALS("[test.c:1:0]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[test.c:1:2]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str()); } // Ticket #2919 - wrong filename reported for #error @@ -456,7 +475,7 @@ class TestPreprocessor : public TestFixture { const auto settings = dinit(Settings, $.userDefines = "TEST"); const char code[] = "#file \"ab.h\"\n#error hello world!\n#endfile"; (void)getcodeforcfg(settings, *this, code, "TEST", "test.c"); - ASSERT_EQUALS("[ab.h:1:0]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[ab.h:1:2]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str()); } // After including a file @@ -464,7 +483,7 @@ class TestPreprocessor : public TestFixture { const auto settings = dinit(Settings, $.userDefines = "TEST"); const char code[] = "#file \"ab.h\"\n\n#endfile\n#error aaa"; (void)getcodeforcfg(settings, *this, code, "TEST", "test.c"); - ASSERT_EQUALS("[test.c:2:0]: (error) #error aaa [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[test.c:2:2]: (error) #error aaa [preprocessorErrorDirective]\n", errout_str()); } } @@ -487,7 +506,7 @@ class TestPreprocessor : public TestFixture { "#else\n" "#error 2\n" "#endif\n"; - ASSERT_EQUALS("\nA\nA;B\nB\n", getConfigsStr(filedata1)); + ASSERT_EQUALS("\nA=A\nA=A;B=B\nB=B\n", getConfigsStr(filedata1)); const char filedata2[] = "#ifndef A\n" "#error 1\n" @@ -519,7 +538,7 @@ class TestPreprocessor : public TestFixture { "#else\n" "#error \"2\"\n" "#endif\n"; - ASSERT_EQUALS("\nB\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nB=B\n", getConfigsStr(filedata)); } void error8() { @@ -532,7 +551,7 @@ class TestPreprocessor : public TestFixture { "#ifndef C\n" "#error aa\n" "#endif"; - ASSERT_EQUALS("A;B;C\nA;C\nC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("A=A;B=B;C\nA=A;C\nC\n", getConfigsStr(filedata)); } void setPlatformInfo() { @@ -573,7 +592,7 @@ class TestPreprocessor : public TestFixture { "#endfile\n" "#ifdef ABC\n" "#endif"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } void includeguard2() { @@ -584,7 +603,7 @@ class TestPreprocessor : public TestFixture { "\n" "#endif\n" "#endfile\n"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } @@ -603,7 +622,7 @@ class TestPreprocessor : public TestFixture { // Expected configurations: "" and "ABC" ASSERT_EQUALS(2, actual.size()); ASSERT_EQUALS("\n\n\nint main ( ) { }", actual.at("")); - ASSERT_EQUALS("\n#line 1 \"abc.h\"\nclass A { } ;\n#line 4 \"file.c\"\n int main ( ) { }", actual.at("ABC")); + ASSERT_EQUALS("\n#line 1 \"abc.h\"\nclass A { } ;\n#line 4 \"file.c\"\n int main ( ) { }", actual.at("ABC=ABC")); } void if0() { @@ -640,7 +659,7 @@ class TestPreprocessor : public TestFixture { "#else\n" "GHI\n" "#endif\n"; - ASSERT_EQUALS("\nDEF1\nDEF2\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nDEF1=DEF1\nDEF2=DEF2\n", getConfigsStr(filedata)); } } @@ -650,7 +669,7 @@ class TestPreprocessor : public TestFixture { "#else\n" " B\n" "#endif\n"; - TODO_ASSERT_EQUALS("\nLIBVER=101\n", "\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nLIBVER=101\n", getConfigsStr(filedata)); } void if_cond2() { @@ -660,7 +679,7 @@ class TestPreprocessor : public TestFixture { "#if defined(A) && defined(B)\n" "ab\n" "#endif\n"; - ASSERT_EQUALS("\nA\nA;B\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nA=A\nA=A;B=B\n", getConfigsStr(filedata)); if_cond2b(); if_cond2c(); @@ -677,7 +696,7 @@ class TestPreprocessor : public TestFixture { "#else\n" "a\n" "#endif\n"; - TODO_ASSERT_EQUALS("\nA;B\n", "\nA\nB\n", getConfigsStr(filedata)); + TODO_ASSERT_EQUALS("\nA;B=B\n", "\nA\nB=B\n", getConfigsStr(filedata)); } void if_cond2c() { @@ -691,7 +710,7 @@ class TestPreprocessor : public TestFixture { "#else\n" "a\n" "#endif\n"; - TODO_ASSERT_EQUALS("\nA\nA;B\n", "\nA\nB\n", getConfigsStr(filedata)); + TODO_ASSERT_EQUALS("\nA\nA;B=B\n", "\nA\nB=B\n", getConfigsStr(filedata)); } void if_cond2d() { @@ -710,7 +729,7 @@ class TestPreprocessor : public TestFixture { "!b\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nA\nA;B\nB\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nA\nA;B=B\nB=B\n", getConfigsStr(filedata)); } void if_cond2e() { @@ -729,7 +748,7 @@ class TestPreprocessor : public TestFixture { "abc\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nA\nA;B;C\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nA=A\nA=A;B=B;C=C\n", getConfigsStr(filedata)); } void if_cond4() { @@ -750,7 +769,7 @@ class TestPreprocessor : public TestFixture { "#endif\n" "}\n" "#endif\n"; - ASSERT_EQUALS("\nA\nA;B\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nA\nA;B=B\n", getConfigsStr(filedata)); } { @@ -785,20 +804,20 @@ class TestPreprocessor : public TestFixture { "#if defined(B) && defined(A)\n" "ef\n" "#endif\n"; - ASSERT_EQUALS("\nA;B\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nA=A;B=B\n", getConfigsStr(filedata)); } void if_cond6() { const char filedata[] = "\n" "#if defined(A) && defined(B))\n" "#endif\n"; - ASSERT_EQUALS("\nA;B\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nA=A;B=B\n", getConfigsStr(filedata)); } void if_cond8() { const char filedata[] = "#if defined(A) + defined(B) + defined(C) != 1\n" "#endif\n"; - TODO_ASSERT_EQUALS("\nA\n", "\nA;B;C\n", getConfigsStr(filedata)); + TODO_ASSERT_EQUALS("\nA=A\n", "\nA=A;B=B;C=C\n", getConfigsStr(filedata)); } @@ -857,7 +876,7 @@ class TestPreprocessor : public TestFixture { const char filedata[] = "#if defined(DEF_10) || defined(DEF_11)\n" "a1;\n" "#endif\n"; - ASSERT_EQUALS("\nDEF_10;DEF_11\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nDEF_10=DEF_10;DEF_11=DEF_11\n", getConfigsStr(filedata)); } void if_or_2() { @@ -1521,7 +1540,7 @@ class TestPreprocessor : public TestFixture { ASSERT_EQUALS(2, actual.size()); const std::string expected("void f ( ) {\n\n\n}"); ASSERT_EQUALS(expected, actual.at("")); - ASSERT_EQUALS(expected, actual.at("A")); + ASSERT_EQUALS(expected, actual.at("A=A")); } void handle_error() { @@ -1538,7 +1557,7 @@ class TestPreprocessor : public TestFixture { const std::map actual = getcode(settings0, *this, filedata); ASSERT_EQUALS(0, actual.size()); - ASSERT_EQUALS("[file.c:2:0]: (error) No pair for character ('). Can't process file. File is either invalid or unicode, which is currently not supported. [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.c:2:14]: (error) No pair for character ('). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str()); } } @@ -1553,7 +1572,7 @@ class TestPreprocessor : public TestFixture { const std::string actual(expandMacros(filedata, *this)); ASSERT_EQUALS("", actual); - ASSERT_EQUALS("[file.cpp:3:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.cpp:3:1]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str()); } { @@ -1566,7 +1585,7 @@ class TestPreprocessor : public TestFixture { const std::string actual(expandMacros(filedata, *this)); ASSERT_EQUALS("", actual); - ASSERT_EQUALS("[abc.h:2:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[abc.h:2:1]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str()); } { @@ -1579,7 +1598,7 @@ class TestPreprocessor : public TestFixture { const std::string actual(expandMacros(filedata, *this)); ASSERT_EQUALS("", actual); - ASSERT_EQUALS("[file.cpp:2:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.cpp:2:1]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str()); } { @@ -1591,7 +1610,7 @@ class TestPreprocessor : public TestFixture { const std::string actual(expandMacros(filedata, *this)); ASSERT_EQUALS("", actual); - ASSERT_EQUALS("[file.cpp:2:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.cpp:2:11]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str()); } { @@ -1607,7 +1626,7 @@ class TestPreprocessor : public TestFixture { // expand macros.. (void)expandMacros(filedata, *this); - ASSERT_EQUALS("[file.cpp:7:0]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.cpp:7:12]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str()); } } @@ -1641,7 +1660,7 @@ class TestPreprocessor : public TestFixture { // Compare results.. ASSERT_EQUALS(2, actual.size()); ASSERT_EQUALS("\n\n\n\n\n$20", actual.at("")); - ASSERT_EQUALS("\n\n\n\n\n$10", actual.at("A")); + ASSERT_EQUALS("\n\n\n\n\n$10", actual.at("A=A")); ASSERT_EQUALS("", errout_str()); } @@ -1660,7 +1679,7 @@ class TestPreprocessor : public TestFixture { // Compare results.. ASSERT_EQUALS(1, actual.size()); ASSERT_EQUALS("", actual.at("")); - ASSERT_EQUALS("[file.c:6:0]: (error) failed to expand 'BC', Wrong number of parameters for macro 'BC'. [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.c:6:3]: (error) failed to expand 'BC', Wrong number of parameters for macro 'BC'. [syntaxError]\n", errout_str()); } void newline_in_macro() { @@ -1693,7 +1712,7 @@ class TestPreprocessor : public TestFixture { // Compare results.. ASSERT_EQUALS(2, actual.size()); ASSERT_EQUALS("", actual.at("")); - ASSERT_EQUALS("\nA\n\n\nA", actual.at("ABC")); + ASSERT_EQUALS("\nA\n\n\nA", actual.at("ABC=ABC")); } void define_if1() { @@ -1934,9 +1953,9 @@ class TestPreprocessor : public TestFixture { // Compare results.. ASSERT_EQUALS(4, actual.size()); ASSERT(actual.find("") != actual.end()); - ASSERT(actual.find("BAR") != actual.end()); - ASSERT(actual.find("FOO") != actual.end()); - ASSERT(actual.find("BAR;FOO") != actual.end()); + ASSERT(actual.find("BAR=BAR") != actual.end()); + ASSERT(actual.find("FOO=FOO") != actual.end()); + ASSERT(actual.find("BAR=BAR;FOO=FOO") != actual.end()); } @@ -1970,25 +1989,25 @@ class TestPreprocessor : public TestFixture { // cases should be fixed whenever this other bug is fixed ASSERT_EQUALS(2U, actual.size()); - ASSERT_EQUALS_MSG(true, (actual.find("A") != actual.end()), "A is expected to be checked but it was not checked"); + ASSERT_EQUALS_MSG(true, (actual.find("A=A") != actual.end()), "A is expected to be checked but it was not checked"); - ASSERT_EQUALS_MSG(true, (actual.find("A;A;B") == actual.end()), "A;A;B is expected to NOT be checked but it was checked"); + ASSERT_EQUALS_MSG(true, (actual.find("A=A;A=A;B=B") == actual.end()), "A;A;B is expected to NOT be checked but it was checked"); } void invalid_define_1() { (void)getcode(settings0, *this, "#define =\n"); - ASSERT_EQUALS("[file.c:1:0]: (error) Failed to parse #define [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.c:1:2]: (error) Failed to parse #define, bad macro syntax [syntaxError]\n", errout_str()); } void invalid_define_2() { // #4036 (void)getcode(settings0, *this, "#define () {(int f(x) }\n"); - ASSERT_EQUALS("[file.c:1:0]: (error) Failed to parse #define [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[file.c:1:2]: (error) Failed to parse #define, bad macro syntax [syntaxError]\n", errout_str()); } void inline_suppressions() { - /*const*/ Settings settings; - settings.inlineSuppressions = true; - settings.checks.enable(Checks::missingInclude); + const auto settings = dinit(Settings, + $.inlineSuppressions = true, + $.checks.enable (Checks::missingInclude)); const char code[] = "// cppcheck-suppress missingInclude\n" "#include \"missing.h\"\n" @@ -2019,6 +2038,38 @@ class TestPreprocessor : public TestFixture { ignore_errout(); // we are not interested in the output } + void inline_suppressions_not_next_line() { + const auto settings = dinit(Settings, + $.inlineSuppressions = true, + $.checks.enable (Checks::missingInclude)); + + const char code[] = "// cppcheck-suppress missingInclude\n" + "// some other comment\n" + "#include \"missing.h\"\n" + "// cppcheck-suppress missingIncludeSystem\n" + "\n" // Empty line + "#include \n"; + SuppressionList inlineSuppr; + (void)getcodeforcfg(settings, *this, code, "", "test.c", &inlineSuppr); + + auto suppressions = inlineSuppr.getSuppressions(); + ASSERT_EQUALS(2, suppressions.size()); + + auto suppr = suppressions.front(); + suppressions.pop_front(); + ASSERT_EQUALS("missingInclude", suppr.errorId); + ASSERT_EQUALS("test.c", suppr.fileName); + ASSERT_EQUALS(3, suppr.lineNumber); + + suppr = suppressions.front(); + suppressions.pop_front(); + ASSERT_EQUALS("missingIncludeSystem", suppr.errorId); + ASSERT_EQUALS("test.c", suppr.fileName); + ASSERT_EQUALS(6, suppr.lineNumber); + + ignore_errout(); + } + void remarkComment1() { const char code[] = "// REMARK: assignment with 1\n" "x=1;\n"; @@ -2128,7 +2179,7 @@ class TestPreprocessor : public TestFixture { const char code[] = "#elif (){\n"; const std::string actual = getcodeforcfg(settings0, *this, code, "TEST", "test.c"); ASSERT_EQUALS("", actual); - ASSERT_EQUALS("[test.c:1:0]: (error) #elif without #if [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[test.c:1:2]: (error) #elif without #if [syntaxError]\n", errout_str()); } void getConfigs1() { @@ -2138,7 +2189,7 @@ class TestPreprocessor : public TestFixture { " qwerty\n" "#endif \n"; - ASSERT_EQUALS("\nWIN32\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nWIN32=WIN32\n", getConfigsStr(filedata)); } void getConfigs2() { @@ -2159,7 +2210,7 @@ class TestPreprocessor : public TestFixture { "c\n" "#endif\n"; - ASSERT_EQUALS("\nABC\nABC;DEF\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\nABC=ABC;DEF=DEF\n", getConfigsStr(filedata)); } void getConfigs4() { @@ -2169,7 +2220,7 @@ class TestPreprocessor : public TestFixture { "#ifdef ABC\n" "A\n" "#endif\n"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } void getConfigs5() { @@ -2181,7 +2232,7 @@ class TestPreprocessor : public TestFixture { "C\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nABC\nDEF\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\nDEF=DEF\n", getConfigsStr(filedata)); } void getConfigs7() { @@ -2191,7 +2242,7 @@ class TestPreprocessor : public TestFixture { "B\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } void getConfigs7a() { @@ -2211,7 +2262,7 @@ class TestPreprocessor : public TestFixture { "B\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } void getConfigs7c() { @@ -2221,7 +2272,7 @@ class TestPreprocessor : public TestFixture { "B\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } void getConfigs7d() { @@ -2231,7 +2282,7 @@ class TestPreprocessor : public TestFixture { "B\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } void getConfigs7e() { @@ -2244,7 +2295,7 @@ class TestPreprocessor : public TestFixture { "#endif\n" "#endfile\n" "#endif\n"; - ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nABC=ABC\n", getConfigsStr(filedata)); } void getConfigs8() { @@ -2273,6 +2324,275 @@ class TestPreprocessor : public TestFixture { ASSERT_EQUALS("\n", getConfigsStr(filedata)); } + void getConfigs12() { // #14222 + const char filedata[] = "#ifdef INT8_MAX\n" + "INT8_MAX\n" + "#endif\n"; + ASSERT_EQUALS("\n", getConfigsStr(filedata, nullptr, "std.cfg")); + } + + void getConfigs13() { // #14222 + const char filedata[] = "#ifdef __builtin_bswap16\n" + "__builtin_bswap16(x);\n" + "#endif\n"; + ASSERT_EQUALS("\n", getConfigsStr(filedata, nullptr, "gnu.cfg")); + } + + void getConfigs_gte() { // #1059 + { + const char filedata[] = "#if A >= 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A >= 201112L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A >= 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483647\n", getConfigsStr(filedata)); + } + } + + void getConfigs_lte() { // #1059 + { + const char filedata[] = "#if A <= 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A <= 201112L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A <= 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483647\n", getConfigsStr(filedata)); + } + } + + void getConfigs_gt() { // #1059 + { + const char filedata[] = "#if A > 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1U\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1UL\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1Z\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 0x1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 01\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 0b1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 1t\n" + "1\n" + "#endif\n"; + ASSERT_THROW_INTERNAL_EQUALS(getConfigsStr(filedata), INTERNAL, "Internal Error. MathLib::toBigNumber: input was not completely consumed: 1t"); + } + { + const char filedata[] = "#if A > 1.0\n" + "1\n" + "#endif\n"; + TODO_ASSERT_THROW(getConfigsStr(filedata), InternalError); // floating point literals are not allowed + } + { + const char filedata[] = "#if A > 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483648\n", getConfigsStr(filedata)); + } + } + + void getConfigs_lt() { // #1059 + { + const char filedata[] = "#if A < 1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1L\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1U\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1UL\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1Z\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 0x1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 01\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 0b1\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 1t\n" + "1\n" + "#endif\n"; + ASSERT_THROW_INTERNAL_EQUALS(getConfigsStr(filedata), INTERNAL, "Internal Error. MathLib::toBigNumber: input was not completely consumed: 1t"); + } + { + const char filedata[] = "#if A < 1.0\n" + "1\n" + "#endif\n"; + TODO_ASSERT_THROW(getConfigsStr(filedata), InternalError); // floating point literals are not allowed + } + { + const char filedata[] = "#if A < 12147483647\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=12147483646\n", getConfigsStr(filedata)); + } + } + + void getConfigs_eq_compound() { // #1059 + { + const char filedata[] = "#if A == 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A == 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L;B=B\n", getConfigsStr(filedata)); + } + } + + void getConfigs_gte_compound() { // #1059 + { + const char filedata[] = "#if A >= 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A >= 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L;B=B\n", getConfigsStr(filedata)); + } + } + + void getConfigs_lte_compound() { // #1059 + { + const char filedata[] = "#if A <= 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=1;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A <= 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201112L;B=B\n", getConfigsStr(filedata)); + } + } + + void getConfigs_gt_compound() { // #1059 + { + const char filedata[] = "#if A > 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=2;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A > 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201113;B=B\n", getConfigsStr(filedata)); + } + } + + void getConfigs_lt_compound() { // #1059 + { + const char filedata[] = "#if A < 1 && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=0;B=B\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if A < 201112L && defined(B)\n" + "1\n" + "#endif\n"; + ASSERT_EQUALS("\nA=201111;B=B\n", getConfigsStr(filedata)); + } + } + void getConfigsError() { const char filedata1[] = "#ifndef X\n" "#error \"!X\"\n" @@ -2284,7 +2604,7 @@ class TestPreprocessor : public TestFixture { "#error \"!Y\"\n" "#endif\n" "#endif\n"; - ASSERT_EQUALS("\nX;Y\nY\n", getConfigsStr(filedata2)); + ASSERT_EQUALS("\nX=X;Y\nY\n", getConfigsStr(filedata2)); } void getConfigsD1() { @@ -2294,14 +2614,14 @@ class TestPreprocessor : public TestFixture { "#endif\n" "#endif\n"; ASSERT_EQUALS("\n", getConfigsStr(filedata, "-DX")); - ASSERT_EQUALS("\nX\nY\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nX=X\nY=Y\n", getConfigsStr(filedata)); } void getConfigsU1() { const char filedata[] = "#ifdef X\n" "#endif\n"; ASSERT_EQUALS("\n", getConfigsStr(filedata, "-UX")); - ASSERT_EQUALS("\nX\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nX=X\n", getConfigsStr(filedata)); } void getConfigsU2() { @@ -2325,8 +2645,8 @@ class TestPreprocessor : public TestFixture { const char filedata[] = "#if defined(X) || defined(Y) || defined(Z)\n" "#else\n" "#endif\n"; - ASSERT_EQUALS("\nY;Z\n", getConfigsStr(filedata, "-UX")); - ASSERT_EQUALS("\nX;Y;Z\n", getConfigsStr(filedata)); + ASSERT_EQUALS("\nY=Y;Z=Z\n", getConfigsStr(filedata, "-UX")); + ASSERT_EQUALS("\nX=X;Y=Y;Z=Z\n", getConfigsStr(filedata)); } void getConfigsU5() { @@ -2350,6 +2670,80 @@ class TestPreprocessor : public TestFixture { ASSERT_EQUALS("\nY\n", getConfigsStr(code, "-DX")); } + void getConfigsAndCodeIssue14317() { + const char filedata[] = "bool test() {\n" + "return\n" + "#if defined(isless)\n" + "0 != isless(1.0, 2.0)\n" + "#else\n" + "0\n" + "#endif\n" + ";\n" + "}\n"; + // Test getConfigsStr() + ASSERT_EQUALS("\nisless=isless\n", getConfigsStr(filedata)); + + // Test getcode() + // Preprocess => actual result.. + const std::map actual = getcode(settings0, *this, filedata); + + // Expected configurations: "" and "ABC" + ASSERT_EQUALS(2, actual.size()); + ASSERT_EQUALS("bool test ( ) {\nreturn\n\n\n\n0\n\n;\n}", actual.at("")); + ASSERT_EQUALS("bool test ( ) {\nreturn\n\n0 != $isless ( 1.0 , 2.0 )\n\n\n\n;\n}", actual.at("isless=isless")); + } + + void getConfigsMostGeneralConfigIssue14317() { + // Verifies that the most general X (out of X=X and X) and Y=Y is returned + // For Z: First Z=Z is added to ret, then the ifndef else branch replaces Z=Z with the more general Z + const char filedata[] = "#ifdef X\n" + "print(X);\n" + "#endif\n" + "#if X\n" + "print(X+1);\n" + "#endif\n" + "#if defined(Y)\n" + "print(Y);\n" + "#endif\n" + "#ifdef Z\n" + "print(Z);\n" + "#endif\n" + "#ifndef Z\n" + "print(Z+1);\n" + "#else\n" + "print(Z+2);\n" + "#endif\n"; + // Test getConfigsStr() + ASSERT_EQUALS("\nX\nY=Y\nZ\n", getConfigsStr(filedata)); + } + + void getConfigsInvalid() { // #14732 + { + const char filedata[] = "#if<"; + ASSERT_EQUALS("\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if>"; + ASSERT_EQUALS("\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if=="; + ASSERT_EQUALS("\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if<="; + ASSERT_EQUALS("\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if>="; + ASSERT_EQUALS("\n", getConfigsStr(filedata)); + } + { + const char filedata[] = "#if!"; + ASSERT_EQUALS("\n", getConfigsStr(filedata)); + } + } + void if_sizeof() { // #4071 const char code[] = "#if sizeof(unsigned short) == 2\n" "Fred & Wilma\n" @@ -2377,8 +2771,8 @@ class TestPreprocessor : public TestFixture { // Preprocess => don't crash.. (void)getcode(settings0, *this, filedata); ASSERT_EQUALS( - "[file.c:1:0]: (error) Syntax error in #ifdef [preprocessorErrorDirective]\n" - "[file.c:1:0]: (error) Syntax error in #ifdef [preprocessorErrorDirective]\n", errout_str()); + "[file.c:1:2]: (error) Syntax error in #ifdef [syntaxError]\n" + "[file.c:1:2]: (error) Syntax error in #ifdef [syntaxError]\n", errout_str()); } void garbage() { @@ -2394,15 +2788,16 @@ class TestPreprocessor : public TestFixture { const auto settings = dinit(Settings, $.userDefines = "foo"); const char code[] = "#error hello world!\n"; (void)getcodeforcfg(settings, *this, code, "X", "./././test.c"); - ASSERT_EQUALS("[test.c:1:0]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[test.c:1:2]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str()); } // test for existing local include void testMissingInclude() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", ""); @@ -2415,24 +2810,26 @@ class TestPreprocessor : public TestFixture { // test for missing local include void testMissingInclude2() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); const char code[] = "#include \"header.h\""; (void)getcodeforcfg(settings, *this, code, "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: \"header.h\" not found. [missingInclude]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: \"header.h\" not found. [missingInclude]\n", errout_str()); } // test for missing local include - no include path given void testMissingInclude3() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", "", "inc"); @@ -2440,16 +2837,17 @@ class TestPreprocessor : public TestFixture { const char code[] = "#include \"header.h\""; (void)getcodeforcfg(settings, *this, code, "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: \"header.h\" not found. [missingInclude]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: \"header.h\" not found. [missingInclude]\n", errout_str()); } // test for existing local include - include path provided void testMissingInclude4() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.includePaths.emplace_back("inc"); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.includePaths.emplace_back ("inc"), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", "", "inc"); @@ -2462,11 +2860,12 @@ class TestPreprocessor : public TestFixture { // test for existing local include - absolute path void testMissingInclude5() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.includePaths.emplace_back("inc"); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.includePaths.emplace_back ("inc"), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", "", Path::getCurrentPath()); @@ -2479,10 +2878,11 @@ class TestPreprocessor : public TestFixture { // test for missing local include - absolute path void testMissingInclude6() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); const std::string header = Path::join(Path::getCurrentPath(), "header.h"); @@ -2490,15 +2890,16 @@ class TestPreprocessor : public TestFixture { std::string code("#include \"" + header + "\""); (void)getcodeforcfg(settings, *this, code.data(), code.size(), "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: \"" + header + "\" not found. [missingInclude]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: \"" + header + "\" not found. [missingInclude]\n", errout_str()); } // test for missing system include - system includes are not searched for in relative path void testMissingSystemInclude() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", ""); @@ -2506,47 +2907,50 @@ class TestPreprocessor : public TestFixture { const char code[] = "#include "; (void)getcodeforcfg(settings, *this, code, "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n", errout_str()); } // test for missing system include void testMissingSystemInclude2() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); const char code[] = "#include "; (void)getcodeforcfg(settings, *this, code, "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n", errout_str()); } // test for existing system include in system include path void testMissingSystemInclude3() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple", // has no effect + $.includePaths.emplace_back ("system") + ); setTemplateFormat("simple"); - settings.includePaths.emplace_back("system"); ScopedFile header("header.h", "", "system"); const char code[] = "#include "; - (void)getcodeforcfg(settings0, *this, code, "", "test.c"); + (void)getcodeforcfg(settings, *this, code, "", "test.c"); ASSERT_EQUALS("", errout_str()); } // test for existing system include - absolute path void testMissingSystemInclude4() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.includePaths.emplace_back("inc"); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.includePaths.emplace_back ("inc"); + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", "", Path::getCurrentPath()); @@ -2559,10 +2963,11 @@ class TestPreprocessor : public TestFixture { // test for missing system include - absolute path void testMissingSystemInclude5() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); const std::string header = Path::join(Path::getCurrentPath(), "header.h"); @@ -2570,15 +2975,17 @@ class TestPreprocessor : public TestFixture { std::string code("#include <" + header + ">"); (void)getcodeforcfg(settings, *this, code.data(), code.size(), "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: <" + header + "> not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: <" + header + "> not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n", errout_str()); } // test for missing local and system include void testMissingIncludeMixed() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", ""); @@ -2590,17 +2997,18 @@ class TestPreprocessor : public TestFixture { "#include \"header2.h\""; (void)getcodeforcfg(settings, *this, code, "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: \"missing.h\" not found. [missingInclude]\n" - "test.c:2:0: information: Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n" - "test.c:3:0: information: Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: \"missing.h\" not found. [missingInclude]\n" + "test.c:2:2: information: Include file: not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n" + "test.c:3:2: information: Include file: not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n", errout_str()); } void testMissingIncludeCheckConfig() { - /*const*/ Settings settings; - settings.clearIncludeCache = true; - settings.checks.enable(Checks::missingInclude); - settings.includePaths.emplace_back("system"); - settings.templateFormat = "simple"; // has no effect + const auto settings = dinit(Settings, + $.clearIncludeCache = true, + $.checks.enable (Checks::missingInclude), + $.includePaths.emplace_back ("system"); + $.templateFormat = "simple" // has no effect + ); setTemplateFormat("simple"); ScopedFile header("header.h", ""); @@ -2626,12 +3034,12 @@ class TestPreprocessor : public TestFixture { "#include <" + missing4 + ">\n"); (void)getcodeforcfg(settings, *this, code.data(), code.size(), "", "test.c"); - ASSERT_EQUALS("test.c:1:0: information: Include file: \"missing.h\" not found. [missingInclude]\n" - "test.c:2:0: information: Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n" - "test.c:3:0: information: Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n" - "test.c:6:0: information: Include file: \"header4.h\" not found. [missingInclude]\n" - "test.c:9:0: information: Include file: \"" + missing3 + "\" not found. [missingInclude]\n" - "test.c:11:0: information: Include file: <" + missing4 + "> not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]\n", errout_str()); + ASSERT_EQUALS("test.c:1:2: information: Include file: \"missing.h\" not found. [missingInclude]\n" + "test.c:2:2: information: Include file: not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n" + "test.c:3:2: information: Include file: not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n" + "test.c:6:2: information: Include file: \"header4.h\" not found. [missingInclude]\n" + "test.c:9:2: information: Include file: \"" + missing3 + "\" not found. [missingInclude]\n" + "test.c:11:2: information: Include file: <" + missing4 + "> not found. Please note: Standard library headers do not need to be provided to get proper results. [missingIncludeSystem]\n", errout_str()); } void hasInclude() { @@ -2640,7 +3048,7 @@ class TestPreprocessor : public TestFixture { settings.standards.setStd("c++11"); ASSERT_EQUALS("", getcodeforcfg(settings, *this, code, "", "test.cpp")); - ASSERT_EQUALS("[test.cpp:1:0]: (error) failed to evaluate #if condition, undefined function-like macro invocation: __has_include( ... ) [preprocessorErrorDirective]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:1:2]: (error) failed to evaluate #if condition, undefined function-like macro invocation: __has_include( ... ) [syntaxError]\n", errout_str()); // TODO: use individual ID settings.standards.setStd("c++17"); ASSERT_EQUALS("", getcodeforcfg(settings, *this, code, "", "test.cpp")); @@ -2676,7 +3084,7 @@ class TestPreprocessor : public TestFixture { ASSERT(getHash(code2) != getHash(code3)); } - void standard() const { + void standard() { const char code[] = "int a;"; // TODO: this bypasses the standard determined from the settings - the parameter should not be exposed @@ -2718,7 +3126,8 @@ class TestPreprocessor : public TestFixture { dui.std = "gnu77"; std::vector files; TokenList tokenlist{settingsDefault, Standards::Language::CPP}; - preprocess(code, files, "test.cpp", tokenlist, dui); + // TODO: can this happen from application code? if yes we need to turn it into a proper error + ASSERT_THROW_EQUALS(preprocess(code, files, "test.cpp", tokenlist, dui), std::runtime_error, "unexpected simplecpp::Output type 9"); ASSERT(!tokenlist.front()); // nothing is tokenized when an unknown standard is provided } } @@ -2741,6 +3150,12 @@ class TestPreprocessor : public TestFixture { "} ;", processed); } + + void pragmaAsm() + { + const char code[] = "#pragma asm"; + ASSERT_THROW_INTERNAL(getcodeforcfg(settingsDefault, *this, code, "", "test.cpp"), InternalError::SYNTAX); + } }; REGISTER_TEST(TestPreprocessor) diff --git a/test/testprocessexecutor.cpp b/test/testprocessexecutor.cpp index c0c19ae2b1f..87b03d915f8 100644 --- a/test/testprocessexecutor.cpp +++ b/test/testprocessexecutor.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,8 +16,11 @@ * along with this program. If not, see . */ -#include "filesettings.h" +#include "config.h" #include "fixture.h" + +#ifdef HAS_THREADING_MODEL_FORK +#include "filesettings.h" #include "helpers.h" #include "processexecutor.h" #include "redirect.h" @@ -33,13 +36,22 @@ #include #include #include +#endif // HAS_THREADING_MODEL_FORK class TestProcessExecutorBase : public TestFixture { public: - TestProcessExecutorBase(const char * const name, bool useFS) : TestFixture(name), useFS(useFS) {} + TestProcessExecutorBase(const char * const name, bool useFS) + : TestFixture(name) +#ifdef HAS_THREADING_MODEL_FORK + , useFS(useFS) +#endif // HAS_THREADING_MODEL_FORK + { + (void)useFS; + } private: - /*const*/ Settings settings = settingsBuilder().library("std.cfg").build(); +#ifdef HAS_THREADING_MODEL_FORK + /*const*/ Settings settings; bool useFS; std::string fprefix() const @@ -52,7 +64,7 @@ class TestProcessExecutorBase : public TestFixture { struct CheckOptions { bool quiet = true; - SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; + Settings::ShowTime showtime = Settings::ShowTime::NONE; const char* plistOutput = nullptr; std::vector filesList; }; @@ -92,6 +104,9 @@ class TestProcessExecutorBase : public TestFixture { s.plistOutput = opt.plistOutput; s.templateFormat = "{callstack}: ({severity}) {inconclusive:inconclusive: }{message}"; Suppressions supprs; + std::unique_ptr timerResults; + if (s.showtime != Settings::ShowTime::NONE) + timerResults.reset(new TimerResults); // NOLINTNEXTLINE(performance-unnecessary-value-param) auto executeFn = [](std::string,std::vector,std::string,std::string&){ @@ -107,13 +122,14 @@ class TestProcessExecutorBase : public TestFixture { if (useFS) filelist.clear(); - ProcessExecutor executor(filelist, fileSettings, s, supprs, *this, executeFn); + ProcessExecutor executor(filelist, fileSettings, s, supprs, *this, timerResults.get(), executeFn); ASSERT_EQUALS(result, executor.check()); } +#endif // HAS_THREADING_MODEL_FORK void run() override { -#if !defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) mNewTemplate = true; +#ifdef HAS_THREADING_MODEL_FORK TEST_CASE(deadlock_with_many_errors); TEST_CASE(many_threads); TEST_CASE(many_threads_showtime); @@ -124,15 +140,14 @@ class TestProcessExecutorBase : public TestFixture { TEST_CASE(one_error_less_files); TEST_CASE(one_error_several_files); TEST_CASE(showtime_top5_file); - TEST_CASE(showtime_top5_summary); TEST_CASE(showtime_file); - TEST_CASE(showtime_summary); TEST_CASE(showtime_file_total); TEST_CASE(suppress_error_library); TEST_CASE(unique_errors); -#endif // !WIN32 +#endif // HAS_THREADING_MODEL_FORK } +#ifdef HAS_THREADING_MODEL_FORK void deadlock_with_many_errors() { std::ostringstream oss; oss << "void f()\n" @@ -164,7 +179,7 @@ class TestProcessExecutorBase : public TestFixture { "void f()\n" "{\n" " (void)(*((int*)0));\n" - "}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY)); + "}", dinit(CheckOptions, $.showtime = Settings::ShowTime::SUMMARY)); // we are not interested in the results - so just consume them ignore_errout(); } @@ -233,25 +248,10 @@ class TestProcessExecutorBase : public TestFixture { check(2, 2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE)); - // for each file: top5 results + overall + empty line - const std::string output_s = GET_REDIRECT_OUTPUT; - // for each file: top5 results + overall + empty line - TODO_ASSERT_EQUALS(static_cast(5 + 1 + 1) * 2, 0, cppcheck::count_all_of(output_s, '\n')); - } - - void showtime_top5_summary() { - REDIRECT; - check(2, 2, 0, - "int main() {}", - dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY)); + $.showtime = Settings::ShowTime::TOP5_FILE)); const std::string output_s = GET_REDIRECT_OUTPUT; - // once: top5 results + overall + empty line - TODO_ASSERT_EQUALS(5 + 1 + 1, 2, cppcheck::count_all_of(output_s, '\n')); - // should only report the top5 once - ASSERT(output_s.find("1 result(s)") == std::string::npos); - TODO_ASSERT(output_s.find("2 result(s)") != std::string::npos); + // for each file: top5 results + check time + TODO_ASSERT_EQUALS(static_cast(5 + 1) * 2, 0, cppcheck::count_all_of(output_s, '\n')); } void showtime_file() { @@ -259,29 +259,17 @@ class TestProcessExecutorBase : public TestFixture { check(2, 2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_FILE)); + $.showtime = Settings::ShowTime::FILE)); const std::string output_s = GET_REDIRECT_OUTPUT; TODO_ASSERT_EQUALS(2, 0, cppcheck::count_all_of(output_s, "Overall time:")); } - void showtime_summary() { - REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized - check(2, 2, 0, - "int main() {}", - dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY)); - const std::string output_s = GET_REDIRECT_OUTPUT; - // should only report the actual summary once - ASSERT(output_s.find("1 result(s)") == std::string::npos); - TODO_ASSERT(output_s.find("2 result(s)") != std::string::npos); - } - void showtime_file_total() { REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized check(2, 2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL)); + $.showtime = Settings::ShowTime::FILE_TOTAL)); const std::string output_s = GET_REDIRECT_OUTPUT; TODO_ASSERT(output_s.find("Check time: " + fprefix() + "_1.c: ") != std::string::npos); TODO_ASSERT(output_s.find("Check time: " + fprefix() + "_2.c: ") != std::string::npos); @@ -315,6 +303,7 @@ class TestProcessExecutorBase : public TestFixture { } // TODO: test whole program analysis +#endif // HAS_THREADING_MODEL_FORK }; class TestProcessExecutorFiles : public TestProcessExecutorBase { diff --git a/test/testprogrammemory.cpp b/test/testprogrammemory.cpp index 1dc1cb1d909..688efa0075b 100644 --- a/test/testprogrammemory.cpp +++ b/test/testprogrammemory.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2024 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -98,8 +98,8 @@ class TestProgramMemory : public TestFixture { void at() const { ProgramMemory pm; - ASSERT_THROW_EQUALS_2(pm.at(123), std::out_of_range, "ProgramMemory::at"); - ASSERT_THROW_EQUALS_2(utils::as_const(pm).at(123), std::out_of_range, "ProgramMemory::at"); + ASSERT_THROW_EQUALS(pm.at(123), std::out_of_range, "ProgramMemory::at"); + ASSERT_THROW_EQUALS(utils::as_const(pm).at(123), std::out_of_range, "ProgramMemory::at"); } }; diff --git a/test/testregex.cpp b/test/testregex.cpp index 5003d31c0f3..4b6b2781cc8 100644 --- a/test/testregex.cpp +++ b/test/testregex.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2024 Cppcheck team. + * Copyright (C) 2007-2025 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,11 +26,13 @@ #include #include -class TestRegEx : public TestFixture { +class TestRegExBase : public TestFixture { public: - TestRegEx() : TestFixture("TestRegEx") {} + TestRegExBase(const char * const name, Regex::Engine engine) : TestFixture(name), mEngine(engine) {} private: + Regex::Engine mEngine; + void run() override { TEST_CASE(match); TEST_CASE(nomatch); @@ -44,7 +46,7 @@ class TestRegEx : public TestFixture { #define assertRegex(...) assertRegex_(__FILE__, __LINE__, __VA_ARGS__) std::shared_ptr assertRegex_(const char* file, int line, std::string pattern, const std::string& exp_err = "") const { std::string regex_err; - auto r = Regex::create(std::move(pattern), regex_err); + auto r = Regex::create(std::move(pattern), mEngine, regex_err); if (exp_err.empty()) ASSERT_LOC(!!r.get(), file, line); else @@ -80,7 +82,11 @@ class TestRegEx : public TestFixture { } void compileError() const { - (void)assertRegex("[", "pcre_compile failed: missing terminating ] for character class"); + std::string exp; + if (mEngine == Regex::Engine::Pcre) + exp = "missing terminating ] for character class"; + + (void)assertRegex("[", exp); } void copy() const { @@ -190,6 +196,11 @@ class TestRegEx : public TestFixture { #undef assertRegex }; -REGISTER_TEST(TestRegEx) +class TestRegExPcre : public TestRegExBase { +public: + TestRegExPcre() : TestRegExBase("TestRegExPcre", Regex::Engine::Pcre) {} +}; + +REGISTER_TEST(TestRegExPcre) #endif // HAVE_RULES diff --git a/test/testrunner.vcxproj b/test/testrunner.vcxproj index 6acc2a937b1..1c5230c5535 100755 --- a/test/testrunner.vcxproj +++ b/test/testrunner.vcxproj @@ -53,6 +53,7 @@ + @@ -207,7 +208,7 @@ true ProgramDatabase Disabled - CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level4 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 @@ -236,7 +237,7 @@ true ProgramDatabase Disabled - CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level4 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 @@ -264,7 +265,7 @@ ..\cli;..\frontend;..\lib;..\externals;..\externals\picojson;..\externals\simplecpp;..\externals\tinyxml2;$(BoostInclude);%(AdditionalIncludeDirectories) false MaxSpeed - CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);NDEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);NDEBUG;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDLL Level4 AnySuitable @@ -304,7 +305,7 @@ ..\cli;..\frontend;..\lib;..\externals;..\externals\picojson;..\externals\simplecpp;..\externals\tinyxml2;$(BoostInclude);%(AdditionalIncludeDirectories) false MaxSpeed - CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);NDEBUG;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + CPPCHECKLIB_IMPORT;SIMPLECPP_IMPORT;$(HaveBoost);NDEBUG;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDLL Level4 AnySuitable diff --git a/test/testsarifreport.cpp b/test/testsarifreport.cpp index 76fe64fe20f..e9fc56d736d 100644 --- a/test/testsarifreport.cpp +++ b/test/testsarifreport.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,12 +20,14 @@ #include "errorlogger.h" #include "errortypes.h" #include "fixture.h" -#include "helpers.h" #include +#include #include #include +#include "json.h" + class TestSarifReport : public TestFixture { public: @@ -98,6 +100,10 @@ class TestSarifReport : public TestFixture ASSERT_EQUALS("2.1.0", root.at("version").get()); ASSERT(root.at("$schema").get().find("sarif-schema-2.1.0") != std::string::npos); + // From SARIF specification (https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790730): + // Although the order in which properties appear in a JSON object value is not semantically significant, the version property SHOULD appear first. + ASSERT_EQUALS("{\n \"version\": \"2.1.0\"", sarif.substr(0,22)); + const picojson::array& runs = root.at("runs").get(); ASSERT_EQUALS(1U, runs.size()); diff --git a/test/testsettings.cpp b/test/testsettings.cpp index b2dbb7db001..ddd11de3273 100644 --- a/test/testsettings.cpp +++ b/test/testsettings.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,6 +34,14 @@ class TestSettings : public TestFixture { TEST_CASE(loadCppcheckCfgSafety); TEST_CASE(getNameAndVersion); TEST_CASE(checkLevelDefault); + + TEST_CASE(getMaxConfigsDefault); + TEST_CASE(getMaxConfigsOpt); + TEST_CASE(getMaxConfigsForce); + TEST_CASE(getMaxConfigsOptAndForce); + TEST_CASE(getMaxConfigsDefines); + TEST_CASE(getMaxConfigsDefinesAndOpt); + TEST_CASE(getMaxConfigsOptAndProject); } void simpleEnableGroup() const { @@ -228,6 +236,21 @@ class TestSettings : public TestFixture { R"({"suppressions": [1]}\n)"); ASSERT_EQUALS("'suppressions' array entry is not a string", Settings::loadCppcheckCfg(s, supprs)); } + { + Settings s; + Suppressions supprs; + ScopedFile file("cppcheck.cfg", + R"({"manualUrl": "https://docs.notcppcheck.com/manual.pdf"})"); + ASSERT_EQUALS("", Settings::loadCppcheckCfg(s, supprs)); + ASSERT_EQUALS("https://docs.notcppcheck.com/manual.pdf", s.manualUrl); + } + { + Settings s; + Suppressions supprs; + ScopedFile file("cppcheck.cfg", + R"({"manualUrl": 0}\n)"); + ASSERT_EQUALS("'manualUrl' is not a string", Settings::loadCppcheckCfg(s, supprs)); + } // TODO: test with FILESDIR } @@ -287,6 +310,52 @@ class TestSettings : public TestFixture { ASSERT_EQUALS(true, s.vfOptions.doConditionExpressionAnalysis); ASSERT_EQUALS(-1, s.vfOptions.maxForwardBranches); } + + void getMaxConfigsDefault() const { + Settings s; + ASSERT_EQUALS(12, s.getMaxConfigs()); + } + + void getMaxConfigsOpt() const { + Settings s; + s.maxConfigsOption = 1; + ASSERT_EQUALS(1, s.getMaxConfigs()); + } + + void getMaxConfigsForce() const { + Settings s; + s.force = true; + ASSERT(s.getMaxConfigs() > 1000); + } + + void getMaxConfigsOptAndForce() const { + Settings s; + s.maxConfigsOption = 1; + s.force = true; + ASSERT(s.getMaxConfigs() > 1000); + } + + void getMaxConfigsDefines() const { + Settings s; + s.userDefines = "X=1"; + ASSERT_EQUALS(1, s.getMaxConfigs()); + } + + void getMaxConfigsDefinesAndOpt() const { + Settings s; + s.userDefines = "X=1"; + s.maxConfigsOption = 3; + ASSERT_EQUALS(3, s.getMaxConfigs()); + } + + void getMaxConfigsOptAndProject() const { + Settings s; + s.maxConfigsOption = 3; + s.maxConfigsProject = 1; + ASSERT_EQUALS(3, s.getMaxConfigs()); + s.maxConfigsProject = 10; + ASSERT_EQUALS(3, s.getMaxConfigs()); + } }; REGISTER_TEST(TestSettings) diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index a17646854e9..b28bc503869 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +32,8 @@ #include #include +class ErrorLogger; + class TestSimplifyTemplate : public TestFixture { public: TestSimplifyTemplate() : TestFixture("TestSimplifyTemplate") {} @@ -222,6 +224,8 @@ class TestSimplifyTemplate : public TestFixture { TEST_CASE(template180); TEST_CASE(template181); TEST_CASE(template182); // #13770 + TEST_CASE(template183); + TEST_CASE(template184); TEST_CASE(template_specialization_1); // #7868 - template specialization template struct S> {..}; TEST_CASE(template_specialization_2); // #7868 - template specialization template struct S> {..}; TEST_CASE(template_specialization_3); @@ -319,6 +323,20 @@ class TestSimplifyTemplate : public TestFixture { TEST_CASE(dumpTemplateArgFrom); } + class TemplateSimplifierTest final : public TemplateSimplifier + { + friend class TestSimplifyTemplate; + }; + + class TokenizerTest final : public Tokenizer + { + friend class TestSimplifyTemplate; + public: + TokenizerTest(TokenList tokenList, ErrorLogger &errorLogger) + : Tokenizer(std::move(tokenList), errorLogger) + {} + }; + struct CheckOptions { bool debugwarnings = false; @@ -4662,6 +4680,51 @@ class TestSimplifyTemplate : public TestFixture { ASSERT_EQUALS(exp, tok(code)); } + void template183() { // #11498 + const char code[] = "template \n" + "struct S {\n" + " void f();\n" + " using X = decltype(&S::f);\n" + "private:\n" + " X x;\n" + "};\n" + "S s;\n"; + const char exp[] = "struct S ; " + "S s ; " + "struct S { " + "void f ( ) ; " + "private: " + "decltype ( & S :: f ) x ; " + "} ;"; + ASSERT_EQUALS(exp, tok(code)); + } + + void template184() { + const char code[] = "template \n" + "T g(T x) {\n" + " return x;\n" + "}\n" + "template <>\n" + "float g(float x) {\n" + " return x + 1.0f;\n" + "}\n" + "void f(int i) {\n" + " g(i);\n" + " g(1.0f);\n" + "}\n"; + const char exp[] = "float g ( float x ) ; " + "template < typename T > " + "T g ( T x ) { return x ; } " + "float g ( float x ) {" + " return x + 1.0f ; " + "} " + "void f ( int i ) {" + " g ( i ) ;" + " g ( 1.0f ) ; " + "}"; + ASSERT_EQUALS(exp, tok(code)); // TODO: instantiate g(int) + } + void template_specialization_1() { // #7868 - template specialization template struct S> {..}; const char code[] = "template struct C {};\n" "template struct S {a};\n" @@ -5461,7 +5524,7 @@ class TestSimplifyTemplate : public TestFixture { tokenlist.appendFileIfNew("test.cpp"); if (!tokenlist.createTokensFromString(data)) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); @@ -5531,7 +5594,7 @@ class TestSimplifyTemplate : public TestFixture { tokenlist.appendFileIfNew("test.cpp"); if (!tokenlist.createTokensFromString(data)) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); @@ -5602,7 +5665,7 @@ class TestSimplifyTemplate : public TestFixture { TokenList tokenlist{settings, Standards::Language::CPP}; if (!TokenListHelper::createTokensFromString(tokenlist, data, "test.cpp")) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); @@ -5633,12 +5696,12 @@ class TestSimplifyTemplate : public TestFixture { if (!TokenListHelper::createTokensFromString(tokenlist, data, "test.cpp")) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); std::vector typeParametersInDeclaration; - TemplateSimplifier::getTemplateParametersInDeclaration(tokenizer.tokens()->tokAt(2), typeParametersInDeclaration); + TemplateSimplifierTest::getTemplateParametersInDeclaration(tokenizer.tokens()->tokAt(2), typeParametersInDeclaration); if (params.size() != typeParametersInDeclaration.size()) return false; @@ -5938,7 +6001,7 @@ class TestSimplifyTemplate : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); - return (TemplateSimplifier::instantiateMatch)(tokenizer.tokens(), numberOfArguments, false, patternAfter); + return (TemplateSimplifierTest::instantiateMatch)(tokenizer.tokens(), numberOfArguments, false, patternAfter); } void instantiateMatchTest() { @@ -6356,7 +6419,7 @@ class TestSimplifyTemplate : public TestFixture { "class E<1,3> { " "template < int ... I > " "int f ( int n , std :: integer_sequence < int , I ... > ) { " - "return ( ( ( I == n ) ? : 0 ) + ... ) ; " + "return ( ( ( I == n ) ? ( 1 , 3 ) : 0 ) + ... ) ; " // TODO the simplification is not quite correct "} " "} ;"; ASSERT_EQUALS(expected, tok(code)); @@ -6374,6 +6437,18 @@ class TestSimplifyTemplate : public TestFixture { "A a ; " "struct A { } ;"; ASSERT_EQUALS(expected2, tok(code2)); + + const char code3[] = "template \n" // #14477 + " int f() {\n" + " return (0 | ... | (1, 2, 4));\n" + "}\n" + "int main() {\n" + " return f<1, 2, 4>();\n" + "}\n"; + const char expected3[] = "int f<1,2,4> ( ) ; " + "int main ( ) { return f<1,2,4> ( ) ; } " + "int f<1,2,4> ( ) { return ( 0 | ... | ( 1 , 2 , 4 ) ) ; }"; + ASSERT_EQUALS(expected3, tok(code3)); } void template_variable_1() { diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index f55b1e83fc7..88d1a4b2725 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -208,7 +208,7 @@ class TestSimplifyTokens : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); // result.. - return tokenizer.tokens()->stringifyList(true); + return tokenizer.tokens()->stringifyList(true, false, true, true, true); } @@ -2207,6 +2207,7 @@ class TestSimplifyTokens : public TestFixture { "for ( i = 0 ; ( i < sz ) && ( sz > 3 ) ; ++ i ) { }\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeAndStringifyOptions, $.cpp = false))); + ignore_errout(); } void simplifyKnownVariables49() { // #3691 diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 3ffa4290341..342cda59dc8 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,8 @@ #include #include +class ErrorLogger; + class TestSimplifyTypedef : public TestFixture { public: TestSimplifyTypedef() : TestFixture("TestSimplifyTypedef") {} @@ -227,6 +229,8 @@ class TestSimplifyTypedef : public TestFixture { TEST_CASE(simplifyTypedef156); TEST_CASE(simplifyTypedef157); TEST_CASE(simplifyTypedef158); + TEST_CASE(simplifyTypedef159); + TEST_CASE(simplifyTypedef160); TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -246,7 +250,8 @@ class TestSimplifyTypedef : public TestFixture { TEST_CASE(simplifyTypedefMacro); - TEST_CASE(simplifyTypedefOriginalName); + TEST_CASE(simplifyTypedefOriginalName1); + TEST_CASE(simplifyTypedefOriginalName2); TEST_CASE(simplifyTypedefTokenColumn1); TEST_CASE(simplifyTypedefTokenColumn2); @@ -255,8 +260,18 @@ class TestSimplifyTypedef : public TestFixture { TEST_CASE(typedefInfo1); TEST_CASE(typedefInfo2); TEST_CASE(typedefInfo3); + TEST_CASE(typedefInfo4); } + class TokenizerTest final : public Tokenizer + { + friend class TestSimplifyTypedef; + public: + TokenizerTest(TokenList tokenList, ErrorLogger &errorLogger) + : Tokenizer(std::move(tokenList), errorLogger) + {} + }; + struct TokOptions { bool simplify = true; @@ -280,7 +295,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::CPP}; if (!tokenlist.createTokensFromString(data)) return ""; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); @@ -315,7 +330,7 @@ class TestSimplifyTypedef : public TestFixture { if (!TokenListHelper::createTokensFromString(tokenlist, data, "file.c")) return ""; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); try { @@ -331,7 +346,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; if (!TokenListHelper::createTokensFromString(tokenlist, code, "file.c")) return {}; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); try { @@ -1275,7 +1290,7 @@ class TestSimplifyTypedef : public TestFixture { "LPCSTR ccp;"; const char expected[] = - "; char c ; " + "char c ; " "char * cp ; " "const char * ccp ;"; @@ -3670,7 +3685,7 @@ class TestSimplifyTypedef : public TestFixture { "Y y;\n" "Yp yp;\n" "Ya ya;\n"; - exp = "long y ; long * yp ; long ya [ 3 ] ;"; + exp = "; long y ; long * yp ; long ya [ 3 ] ;"; ASSERT_EQUALS(exp, tok(code)); } @@ -3791,6 +3806,42 @@ class TestSimplifyTypedef : public TestFixture { TODO_ASSERT_EQUALS(exp, cur, tok(code)); } + void simplifyTypedef159() { + const char code[] = "typedef void (*const func_t)();\n" // #14387 + "func_t g() { return nullptr; }\n"; + const char exp[] = "void * const g ( ) { return nullptr ; }"; + ASSERT_EQUALS(exp, tok(code)); + } + + void simplifyTypedef160() { + const char code[] = "struct S1 {};\n" + "typedef struct S1 S2;\n" + "namespace N {\n" + " struct B {\n" + " explicit B(int& i);\n" + " };\n" + " struct S2 : B {\n" + " explicit S2(int& i) : B(i) {}\n" + " };\n" + "}\n"; + const char exp[] = "struct S1 { } ; " // #12623 + "namespace N { " + "struct B { " + "explicit B ( int & i ) ; } ; " + "struct S2 : B { " + "explicit S2 ( int & i ) : B ( i ) { } " + "} ; " + "}"; + ASSERT_EQUALS(exp, tok(code)); + + const char code2[] = "typedef stuct T* T;\n" // #14669 + "struct T {\n" + " T p;\n" + "};\n"; + const char exp2[] = "struct T { stuct T * p ; } ;"; + ASSERT_EQUALS(exp2, simplifyTypedefC(code2)); + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n" @@ -4435,7 +4486,7 @@ class TestSimplifyTypedef : public TestFixture { simplifyTypedefP(code)); } - void simplifyTypedefOriginalName() { + void simplifyTypedefOriginalName1() { const char code[] = "typedef unsigned char uint8_t;" "typedef float (*rFunctionPointer_fp)(uint8_t, uint8_t);" "typedef enum eEnumDef {" @@ -4457,7 +4508,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; ASSERT(TokenListHelper::createTokensFromString(tokenlist, code, "file.c")); - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); @@ -4486,11 +4537,31 @@ class TestSimplifyTypedef : public TestFixture { // Search for the simplified short token and check its original Name, start from front to get the variable in the struct token = Token::findsimplematch(tokenizer.list.front(), "short", tokenizer.list.back()); ASSERT_EQUALS("int16_t", token->originalName()); - // Search for the simplified * token -> function pointer gets "(*" tokens infront of it + // Search for the simplified * token -> function pointer gets "(*" tokens in front of it token = Token::findsimplematch(endOfTypeDef, "*", tokenizer.list.back()); ASSERT_EQUALS("rFunctionPointer_fp", token->originalName()); } + void simplifyTypedefOriginalName2() { + const char code[] = "typedef unsigned short uint16;\n" + "typedef uint16 A;\n" + "A a;"; + TokenList tokenlist{ settings1, Standards::Language::C }; + ASSERT(TokenListHelper::createTokensFromString(tokenlist, code, "file.c")); + TokenizerTest tokenizer(std::move(tokenlist), *this); + tokenizer.createLinks(); + tokenizer.simplifyTypedef(); + + try { + tokenizer.validate(); + } + catch (const InternalError&) { + ASSERT_EQUALS_MSG(false, true, "Validation of Tokenizer failed"); + } + const Token* token = Token::findsimplematch(tokenizer.list.front(), "short"); + ASSERT_EQUALS("A", token->originalName()); + } + void simplifyTypedefTokenColumn1() { // #13155 const char code[] = "void foo(void) {\n" " typedef signed int MY_INT;\n" @@ -4499,7 +4570,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; ASSERT(TokenListHelper::createTokensFromString(tokenlist, code, "file.c")); - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); @@ -4517,7 +4588,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; ASSERT(TokenListHelper::createTokensFromString(tokenlist, code, "file.c")); - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); @@ -4544,7 +4615,7 @@ class TestSimplifyTypedef : public TestFixture { void typedefInfo1() { const std::string xml = dumpTypedefInfo("typedef int A;\nA x;"); ASSERT_EQUALS(" \n" - " \n" + " \n" " \n", xml); } @@ -4556,7 +4627,7 @@ class TestSimplifyTypedef : public TestFixture { " typedef fp16 ( *pfp16 ) ( void );\n" "}\n"); ASSERT_EQUALS(" \n" - " \n" + " \n" " \n" " \n" " \n" @@ -4568,8 +4639,8 @@ class TestSimplifyTypedef : public TestFixture { " \n" " \n" " \n" - " \n" - " \n" + " \n" + " \n" " \n" " \n" " \n" @@ -4598,6 +4669,17 @@ class TestSimplifyTypedef : public TestFixture { "}\n"); ASSERT_EQUALS("",xml); } + + void typedefInfo4() { + const std::string xml = dumpTypedefInfo("typedef struct coord {\n" + " uint16_t x;\n" + " uint16_t y;\n" + "} coord;\n" + "coord c;"); + ASSERT_EQUALS(" \n" + " \n" + " \n", xml); + } }; REGISTER_TEST(TestSimplifyTypedef) diff --git a/test/testsimplifyusing.cpp b/test/testsimplifyusing.cpp index fa067f822ce..7359613510f 100644 --- a/test/testsimplifyusing.cpp +++ b/test/testsimplifyusing.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #include "helpers.h" #include "platform.h" #include "settings.h" +#include "standards.h" #include "token.h" #include "utils.h" @@ -73,6 +74,9 @@ class TestSimplifyUsing : public TestFixture { TEST_CASE(simplifyUsing34); TEST_CASE(simplifyUsing35); TEST_CASE(simplifyUsing36); + TEST_CASE(simplifyUsing37); + TEST_CASE(simplifyUsing38); + TEST_CASE(simplifyUsing39); TEST_CASE(simplifyUsing8970); TEST_CASE(simplifyUsing8971); @@ -104,12 +108,14 @@ class TestSimplifyUsing : public TestFixture { Platform::Type type = Platform::Type::Native; bool debugwarnings = true; bool preprocess = false; + Standards::cppstd_t cppstd = Standards::CPPLatest; }; #define tok(...) tok_(__FILE__, __LINE__, __VA_ARGS__) template std::string tok_(const char* file, int line, const char (&code)[size], const TokOptions& options = make_default_obj()) { - const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive).debugwarnings(options.debugwarnings).platform(options.type).build(); + const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive).debugwarnings(options.debugwarnings) + .platform(options.type).cpp(options.cppstd).build(); if (options.preprocess) { SimpleTokenizer2 tokenizer(settings, *this, code, "test.cpp"); @@ -882,6 +888,57 @@ class TestSimplifyUsing : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void simplifyUsing37() { + const char code1[] = "using fp1_t = int(*)(int);\n" + "using fp2_t = int(* const)(int);\n" + "fp1_t fp1;\n" + "fp2_t fp2;\n"; + const char expected1[] = "int ( * fp1 ) ( int ) ; int ( * const fp2 ) ( int ) ;"; + ASSERT_EQUALS(expected1, tok(code1)); + ASSERT_EQUALS("", errout_str()); + + const char code2[] = "using f_t = int(int);\n" + "f_t* fp1;\n" + "f_t* const fp2;\n"; + const char expected2[] = "int ( * fp1 ) ( int ) ; int ( * const fp2 ) ( int ) ;"; + ASSERT_EQUALS(expected2, tok(code2)); + ASSERT_EQUALS("", errout_str()); + + const char code3[] = "using FP = std::string (*)();\n" // #14421 + "using FPC = std::string (*const)();\n" + "FP fp;\n" + "FPC fpc{};\n"; + const char expected3[] = "std :: string ( * fp ) ( ) ; std :: string ( * const fpc ) ( ) { } ;"; + ASSERT_EQUALS(expected3, tok(code3)); + ASSERT_EQUALS("", errout_str()); + + const char code4[] = "using F = void(*)(char);\n" // #14429 + "F f(int);\n"; + const char expected4[] = "void * f ( char ) ;"; + ASSERT_EQUALS(expected4, tok(code4)); + ASSERT_EQUALS("", errout_str()); + } + + void simplifyUsing38() { + const char code[] = "using std::begin;\n" // #14424 + "using std::end;\n" + "Unknown begin;\n" + "int end;\n"; + const char expected[] = "Unknown begin ; int end ;"; + ASSERT_EQUALS(expected, tok(code)); + ASSERT_EQUALS("", errout_str()); + } + + void simplifyUsing39() { + const char code[] = "using std::wstring;\n" // #14578 + "wstring ws;"; + const char expected[] = "std :: wstring ws ;"; + ASSERT_EQUALS(expected, tok(code)); + ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS(expected, tok(code, dinit(TokOptions, $.cppstd = Standards::CPP03))); + ASSERT_EQUALS("", errout_str()); + } + void simplifyUsing8970() { const char code[] = "using V = std::vector;\n" "struct A {\n" diff --git a/test/testsingleexecutor.cpp b/test/testsingleexecutor.cpp index 4f0665ff12e..d3f42868a4d 100644 --- a/test/testsingleexecutor.cpp +++ b/test/testsingleexecutor.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ class TestSingleExecutorBase : public TestFixture { TestSingleExecutorBase(const char * const name, bool useFS) : TestFixture(name), useFS(useFS) {} private: - /*const*/ Settings settings = settingsBuilder().library("std.cfg").build(); + /*const*/ Settings settings; bool useFS; std::string fprefix() const @@ -61,7 +61,7 @@ class TestSingleExecutorBase : public TestFixture { struct CheckOptions { bool quiet = true; - SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; + Settings::ShowTime showtime = Settings::ShowTime::NONE; const char* plistOutput = nullptr; std::vector filesList; }; @@ -97,9 +97,12 @@ class TestSingleExecutorBase : public TestFixture { s.templateFormat = "{callstack}: ({severity}) {inconclusive:inconclusive: }{message}"; // TODO: remove when we only longer rely on toString() in unique message handling? Suppressions supprs; + std::unique_ptr timerResults; + if (s.showtime != Settings::ShowTime::NONE) + timerResults.reset(new TimerResults); // NOLINTNEXTLINE(performance-unnecessary-value-param) - CppCheck cppcheck(s, supprs, *this, true, [](std::string,std::vector,std::string,std::string&){ + CppCheck cppcheck(s, supprs, *this, timerResults.get(), true, [](std::string,std::vector,std::string,std::string&){ return EXIT_SUCCESS; }); @@ -112,7 +115,7 @@ class TestSingleExecutorBase : public TestFixture { if (useFS) filelist.clear(); - SingleExecutor executor(cppcheck, filelist, fileSettings, s, supprs, *this); + SingleExecutor executor(cppcheck, filelist, fileSettings, s, supprs, *this, timerResults.get()); ASSERT_EQUALS(result, executor.check()); } @@ -127,9 +130,7 @@ class TestSingleExecutorBase : public TestFixture { TEST_CASE(one_error_less_files); TEST_CASE(one_error_several_files); TEST_CASE(showtime_top5_file); - TEST_CASE(showtime_top5_summary); TEST_CASE(showtime_file); - TEST_CASE(showtime_summary); TEST_CASE(showtime_file_total); TEST_CASE(suppress_error_library); TEST_CASE(unique_errors); @@ -166,7 +167,7 @@ class TestSingleExecutorBase : public TestFixture { "void f()\n" "{\n" " (void)(*((int*)0));\n" - "}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY)); + "}", dinit(CheckOptions, $.showtime = Settings::ShowTime::SUMMARY)); // we are not interested in the results - so just consume them ignore_errout(); } @@ -240,24 +241,10 @@ class TestSingleExecutorBase : public TestFixture { check(2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE)); + $.showtime = Settings::ShowTime::TOP5_FILE)); const std::string output_s = GET_REDIRECT_OUTPUT; - // for each file: top5 results + overall + empty line - ASSERT_EQUALS((5 + 1 + 1) * 2LL, cppcheck::count_all_of(output_s, '\n')); - } - - void showtime_top5_summary() { - REDIRECT; - check(2, 0, - "int main() {}", - dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY)); - const std::string output_s = GET_REDIRECT_OUTPUT; - // once: top5 results + overall + empty line - ASSERT_EQUALS(5 + 1 + 1, cppcheck::count_all_of(output_s, '\n')); - // should only report the top5 once - ASSERT(output_s.find("1 result(s)") == std::string::npos); - ASSERT(output_s.find("2 result(s)") != std::string::npos); + // for each file: top5 results + check time + ASSERT_EQUALS((5 + 1) * 2LL, cppcheck::count_all_of(output_s, '\n')); } void showtime_file() { @@ -265,21 +252,9 @@ class TestSingleExecutorBase : public TestFixture { check(2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_FILE)); - const std::string output_s = GET_REDIRECT_OUTPUT; - ASSERT_EQUALS(2, cppcheck::count_all_of(output_s, "Overall time:")); - } - - void showtime_summary() { - REDIRECT; - check(2, 0, - "int main() {}", - dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY)); + $.showtime = Settings::ShowTime::FILE)); const std::string output_s = GET_REDIRECT_OUTPUT; - // should only report the actual summary once - ASSERT(output_s.find("1 result(s)") == std::string::npos); - ASSERT(output_s.find("2 result(s)") != std::string::npos); + ASSERT_EQUALS(0, cppcheck::count_all_of(output_s, "Overall time:")); } void showtime_file_total() { @@ -287,7 +262,7 @@ class TestSingleExecutorBase : public TestFixture { check(2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL)); + $.showtime = Settings::ShowTime::FILE_TOTAL)); const std::string output_s = GET_REDIRECT_OUTPUT; ASSERT(output_s.find("Check time: " + fprefix() + "_" + zpad3(1) + ".c: ") != std::string::npos); ASSERT(output_s.find("Check time: " + fprefix() + "_" + zpad3(2) + ".c: ") != std::string::npos); diff --git a/test/testsizeof.cpp b/test/testsizeof.cpp index ad8aa3192af..fca8cb7ed7a 100644 --- a/test/testsizeof.cpp +++ b/test/testsizeof.cpp @@ -54,8 +54,8 @@ class TestSizeof : public TestFixture { SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check... - runChecks(tokenizer, this); + CheckSizeof check; + runChecks(check, tokenizer, this); } #define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__) @@ -66,8 +66,8 @@ class TestSizeof : public TestFixture { // Tokenize.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); - // Check... - runChecks(tokenizer, this); + CheckSizeof check; + runChecks(check, tokenizer, this); } void sizeofsizeof() { @@ -722,6 +722,12 @@ class TestSizeof : public TestFixture { " return AtomName;\n" "}"); ASSERT_EQUALS("", errout_str()); + + check("void* f(size_t n) {\n" // #11754 + " char* p = malloc(n * sizeof(void*));\n" + " return p;\n" + "}"); + ASSERT_EQUALS("", errout_str()); } void checkPointerSizeofStruct() { diff --git a/test/teststl.cpp b/test/teststl.cpp index 6714222cca8..18549e08f9f 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -183,20 +183,24 @@ class TestStl : public TestFixture { struct CheckOptions { bool inconclusive = false; - const Settings* s = nullptr; }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { - const Settings* s = options.s ? options.s : (options.inconclusive ? &settings_i : &settings); + const Settings& s = options.inconclusive ? settings_i : settings; - // Tokenize.. - SimpleTokenizer tokenizer(*s, *this); + check_(file, line, code, s); + } + + template + void check_(const char* file, int line, const char (&code)[size], const Settings& s) { + SimpleTokenizer tokenizer(s, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - runChecks(tokenizer, this); + CheckStl check; + runChecks(check, tokenizer, this); } // TODO: get rid of this @@ -206,18 +210,19 @@ class TestStl : public TestFixture { ASSERT_LOC(tokenizer.tokenize(code), file, line); - runChecks(tokenizer, this); + CheckStl check; + runChecks(check, tokenizer, this); } -#define checkNormal(code) checkNormal_(code, __FILE__, __LINE__) +#define checkNormal(...) checkNormal_(__FILE__, __LINE__, __VA_ARGS__) template - void checkNormal_(const char (&code)[size], const char* file, int line) { + void checkNormal_(const char* file, int line, const char (&code)[size]) { // Tokenize.. SimpleTokenizer tokenizer(settings, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); - // Check.. - runChecks(tokenizer, this); + CheckStl check; + runChecks(check, tokenizer, this); } void outOfBounds() { @@ -942,6 +947,59 @@ class TestStl : public TestFixture { " (void)v[0];\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + checkNormal("int f(const std::vector& v) {\n" // #8983 + " return v[2];\n" + "}\n" + "int g() {\n" + " return f({});\n" + "}\n" + "int h() {\n" + " return f({ 1, 2 });\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:13]: error: Out of bounds access in 'v[2]', if 'v' size is 2 and '2' is 2 [containerOutOfBounds]\n" + "[test.cpp:2:13]: error: Out of bounds access in expression 'v[2]' because 'v' is empty. [containerOutOfBounds]\n", + errout_str()); + + checkNormal("int f(int x, const std::vector& v) {\n" + " return x + v[0];\n" + "}\n" + "int g() {\n" + " return f(1, {});\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:17]: error: Out of bounds access in expression 'v[0]' because 'v' is empty. [containerOutOfBounds]\n", + errout_str()); + + checkNormal("bool f(const std::string_view s) { return s[500] == 'x'; }\n" // #12046 + "bool g() { return f(\" \"); }\n"); + ASSERT_EQUALS("[test.cpp:1:44]: error: Out of bounds access in 's[500]', if 's' size is 1 and '500' is 500 [containerOutOfBounds]\n", + errout_str()); + + checkNormal("int main() {\n" // #14342 + " const int a[] = { 1, 2, 3 };\n" + " std::span x{ a };\n" + " return x[3];\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:13]: error: Out of bounds access in 'x[3]', if 'x' size is 1 and '3' is 3 [containerOutOfBounds]\n", + errout_str()); + + checkNormal("int main() {\n" + " const char a[] = \"abc\";\n" + " std::string_view x{ a };\n" + " return x[5];\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:13]: error: Out of bounds access in 'x[5]', if 'x' size is 4 and '5' is 5 [containerOutOfBounds]\n", + errout_str()); + + checkNormal("int f(const std::string& v) {\n" + " return v[2];\n" + "}\n" + "int main() {\n" + " std::string_view x{ \"a\" };\n" + " return f(std::string(x));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:13]: error: Out of bounds access in 'v[2]', if 'v' size is 1 and '2' is 2 [containerOutOfBounds]\n", + errout_str()); } void outOfBoundsSymbolic() @@ -954,6 +1012,12 @@ class TestStl : public TestFixture { ASSERT_EQUALS( "[test.cpp:2:12] -> [test.cpp:4:21]: (warning) Either the condition 'col>textline.size()' is redundant or 'col' can have the value textline.size(). Expression 'textline[col]' causes access out of bounds. [containerOutOfBounds]\n", errout_str()); + + check("void f(const std::vector& v) {\n" // #12742 + " for (unsigned i = 0; i < v.size();)\n" + " (void)v[i++];\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void outOfBoundsIndexExpression() { @@ -2643,7 +2707,7 @@ class TestStl : public TestFixture { check("void f() {\n" " const char a[][5] = { \"1\", \"true\", \"on\", \"yes\" };\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("", errout_str()); } @@ -2660,7 +2724,7 @@ class TestStl : public TestFixture { "}\n" "void g(const std::vector& w) {\n" " f(-1, w);\n" - "}\n", dinit(CheckOptions, $.s = &s)); + "}\n", s); ASSERT_EQUALS("[test.cpp:5:9]: warning: Array index -1 is out of bounds. [negativeContainerIndex]\n" "[test.cpp:8:8]: note: Calling function 'f', 1st argument '-1' value is -1\n" "[test.cpp:3:9]: note: Assuming condition is false\n" @@ -3786,7 +3850,7 @@ class TestStl : public TestFixture { "{\n" " if (x.size() == 0) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:7:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3798,7 +3862,7 @@ class TestStl : public TestFixture { "{\n" " if (x.size() == 0) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3810,7 +3874,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (x.size() == 0) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3822,7 +3886,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (0 == x.size()) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3834,7 +3898,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (x.size() != 0) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3846,7 +3910,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (0 != x.size()) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3858,7 +3922,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (x.size() > 0) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3870,7 +3934,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (0 < x.size()) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:13]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3882,7 +3946,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (x.size() >= 1) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3894,7 +3958,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (x.size() < 1) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3906,7 +3970,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (1 <= x.size()) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3918,7 +3982,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (1 > x.size()) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:13]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3930,7 +3994,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (x.size()) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:9]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3942,7 +4006,7 @@ class TestStl : public TestFixture { " std::list x;\n" " if (!x.size()) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:10]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3961,7 +4025,7 @@ class TestStl : public TestFixture { " std::list x;\n" " fun(!x.size());\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:10]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -3973,7 +4037,7 @@ class TestStl : public TestFixture { " std::list x;\n" " fun(a && x.size());\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS("[test.cpp:4:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", errout_str()); check(code); ASSERT_EQUALS("", errout_str()); @@ -4010,7 +4074,7 @@ class TestStl : public TestFixture { "{\n" " if (f.x.size() == 0) {}\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS( "[test.cpp:10:11]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n" "[test.cpp:10:11]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", // duplicate @@ -4033,7 +4097,7 @@ class TestStl : public TestFixture { "int main() {\n" " if (zzz->x.size() > 0) { }\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS( "[test.cpp:10:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n" "[test.cpp:10:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", // duplicate @@ -4052,7 +4116,7 @@ class TestStl : public TestFixture { " Zzz * zzz;\n" " if (zzz->x.size() > 0) { }\n" "}"; - check(code, dinit(CheckOptions, $.s = &settingsCpp03)); + check(code, settingsCpp03); ASSERT_EQUALS( "[test.cpp:10:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n" "[test.cpp:10:14]: (performance) Possible inefficient checking for 'x' emptiness. [stlSize]\n", // duplicate @@ -4565,6 +4629,14 @@ class TestStl : public TestFixture { "[test.cpp:14:10]: (performance) Passing the result of c_str() to a stream is slow and redundant. [stlcstrStream]\n", errout_str()); + check("void f(const std::string& s) {\n" + " std::cout << s.c_str();\n" + " std::cerr << s.c_str();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:15]: (performance) Passing the result of c_str() to a stream is slow and redundant. [stlcstrStream]\n" + "[test.cpp:3:15]: (performance) Passing the result of c_str() to a stream is slow and redundant. [stlcstrStream]\n", + errout_str()); + check("struct S { std::string str; };\n" "struct T { S s; };\n" "struct U { T t[1]; };\n" @@ -4610,6 +4682,52 @@ class TestStl : public TestFixture { " return s->x.c_str();\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("std::string f(const std::string& s) {\n" // #14533 + " auto x = std::string(\"abc\") + s.c_str();\n" + " auto y = s.c_str() + std::string(\"def\");\n" + " return x + y;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:33]: (performance) Concatenating the result of c_str() and a std::string is slow and redundant. [stlcstrConcat]\n" + "[test.cpp:3:24]: (performance) Concatenating the result of c_str() and a std::string is slow and redundant. [stlcstrConcat]\n", + errout_str()); + + check("std::string get();\n" + "std::string f(const std::string& s) {\n" + " return get() + s.c_str();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:18]: (performance) Concatenating the result of c_str() and a std::string is slow and redundant. [stlcstrConcat]\n", + errout_str()); + + check("std::string get();\n" // #14536 + " std::string f(const std::string& s) {\n" + " return s + get().c_str();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:14]: (performance) Concatenating the result of c_str() and a std::string is slow and redundant. [stlcstrConcat]\n", + errout_str()); + + check("std::string get();\n" + "std::string f(std::string & s) {\n" + " s = get().c_str();\n" + " std::string s2{ get().c_str() };\n" + " return s2;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:5]: (performance) Assigning the result of c_str() to a std::string is slow and redundant. [stlcstrAssignment]\n" + "[test.cpp:4:17]: (performance) Constructing a std::string from the result of c_str() is slow and redundant. [stlcstrConstructor]\n", + errout_str()); + + check("void f() {\n" + " std::string s;\n" + " auto a = + s.c_str();\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("std::string f(const std::string& a) {\n" // #14600 + " std::string b(a.c_str() + 1 + 2);\n" + " return b;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:17]: (performance) Constructing a std::string from the result of c_str() is slow and redundant. [stlcstrConstructor]\n", + errout_str()); } void uselessCalls() { @@ -4717,6 +4835,12 @@ class TestStl : public TestFixture { "[test.cpp:3:5]: (warning) Return value of std::remove_if() ignored. Elements remain in container. [uselessCallsRemove]\n" "[test.cpp:4:5]: (warning) Return value of std::unique() ignored. Elements remain in container. [uselessCallsRemove]\n", errout_str()); + check("void f(std::string& s) {\n" // #14764 + " auto it{ std::remove(s.begin(), s.end(), 'a') };\n" + " s.erase(it, s.end());\n" + "}"); + ASSERT_EQUALS("", errout_str()); + // #4431 - fp check("bool f() {\n" " return x ? true : (y.empty());\n" @@ -5223,6 +5347,13 @@ class TestStl : public TestFixture { " return it;\n" "}\n", dinit(CheckOptions, $.inconclusive = true)); ASSERT_EQUALS("[test.cpp:18:5]: (error, inconclusive) Invalid iterator 'it' used. [eraseDereference]\n", errout_str()); + + check("int f(const std::vector& v) {\n" // #11895 + " auto it = v.end();\n" + " std::advance(it, -2);\n" + " return *it;\n" + "}\n", dinit(CheckOptions, $.inconclusive = true)); + ASSERT_EQUALS("", errout_str()); } void loopAlgoElementAssign() { @@ -6806,13 +6937,13 @@ class TestStl : public TestFixture { " }\n" "}\n"; s.standards.cpp = Standards::CPP11; - check(code, dinit(CheckOptions, $.s = &s)); + check(code, s); ASSERT_EQUALS("", errout_str()); s.standards.cpp = Standards::CPP14; - check(code, dinit(CheckOptions, $.s = &s)); + check(code, s); ASSERT_EQUALS("", errout_str()); s.standards.cpp = Standards::CPP17; - check(code, dinit(CheckOptions, $.s = &s)); + check(code, s); ASSERT_EQUALS("[test.cpp:3:18]: (performance) Searching before insertion is not necessary. [stlFindInsert]\n", errout_str()); } @@ -6827,7 +6958,7 @@ class TestStl : public TestFixture { " if(x.find(5) == x.end())\n" " x[5] = data;\n" " }\n" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("", errout_str()); s.standards.cpp = Standards::CPP11; @@ -6839,7 +6970,7 @@ class TestStl : public TestFixture { " if(x.find(5) == x.end())\n" " x[5] = data;\n" " }\n" - "}", dinit(CheckOptions, $.s = &s)); + "}", s); ASSERT_EQUALS("[test.cpp:7:17]: (performance) Searching before insertion is not necessary. Instead of 'x[5]=data' consider using 'x.emplace(5, data);'. [stlFindInsert]\n", errout_str()); check("void foo() {\n" @@ -6850,7 +6981,7 @@ class TestStl : public TestFixture { " if(x.find(5) == x.end())\n" " x[5] = data;\n" " }\n" - "}"); + "}"); // TODO: use s? ASSERT_EQUALS("[test.cpp:7:17]: (performance) Searching before insertion is not necessary. Instead of 'x[5]=data' consider using 'x.try_emplace(5, data);'. [stlFindInsert]\n", errout_str()); } } diff --git a/test/teststring.cpp b/test/teststring.cpp index 051aa870788..e0e401256e2 100644 --- a/test/teststring.cpp +++ b/test/teststring.cpp @@ -74,8 +74,8 @@ class TestString : public TestFixture { // Tokenize.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); - // Check char variable usage.. - runChecks(tokenizer, this); + CheckString check; + runChecks(check, tokenizer, this); } void stringLiteralWrite() { diff --git a/test/testsuppressions.cpp b/test/testsuppressions.cpp index eabfbe7b9e2..49d46149c90 100644 --- a/test/testsuppressions.cpp +++ b/test/testsuppressions.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +#include "addoninfo.h" +#include "config.h" #include "cppcheck.h" #include "cppcheckexecutor.h" #include "errorlogger.h" @@ -30,8 +32,8 @@ #include "suppressions.h" #include "threadexecutor.h" -#include #include +#include #include #include #include @@ -46,10 +48,17 @@ class TestSuppressions : public TestFixture { private: + class CppCheckExecutorTest final : public CppCheckExecutor + { + friend class TestSuppressions; + }; + const std::string templateFormat{"{callstack}: ({severity}) {inconclusive:inconclusive: }{message}"}; void run() override { mNewTemplate = true; + TEST_CASE(parseLine); + TEST_CASE(parseLineInvalid); TEST_CASE(suppressionsBadId1); TEST_CASE(suppressionsDosFormat); // Ticket #1836 TEST_CASE(suppressionsFileNameWithColon); // Ticket #1919 - filename includes colon @@ -58,12 +67,14 @@ class TestSuppressions : public TestFixture { TEST_CASE(suppressionsFileNameWithExtraPath); TEST_CASE(suppressionsSettingsFiles); TEST_CASE(suppressionsSettingsFS); +#ifdef HAS_THREADING_MODEL_THREAD TEST_CASE(suppressionsSettingsThreadsFiles); TEST_CASE(suppressionsSettingsThreadsFS); -#if !defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +#endif // HAS_THREADING_MODEL_THREAD +#ifdef HAS_THREADING_MODEL_FORK TEST_CASE(suppressionsSettingsProcessesFiles); TEST_CASE(suppressionsSettingsProcessesFS); -#endif +#endif // HAS_THREADING_MODEL_FORK TEST_CASE(suppressionsMultiFileFiles); TEST_CASE(suppressionsMultiFileFS); TEST_CASE(suppressionsPathSeparator); @@ -88,8 +99,8 @@ class TestSuppressions : public TestFixture { TEST_CASE(suppressingSyntaxErrorsFS); // #7076 TEST_CASE(suppressingSyntaxErrorsInlineFiles); // #5917 TEST_CASE(suppressingSyntaxErrorsInlineFS); // #5917 - TEST_CASE(suppressingSyntaxErrorsWhileFileReadFiles); // PR #1333 - TEST_CASE(suppressingSyntaxErrorsWhileFileReadFS); // PR #1333 + TEST_CASE(suppressingSimplecppErrorsWhileFileReadFiles); // PR #1333 + TEST_CASE(suppressingSimplecppErrorsWhileFileReadFS); // PR #1333 TEST_CASE(symbol); TEST_CASE(unusedFunctionFiles); @@ -113,6 +124,85 @@ class TestSuppressions : public TestFixture { TEST_CASE(suppressionFromErrorMessage); TEST_CASE(suppressionWildcard); + + TEST_CASE(polyspaceParseRange); + TEST_CASE(polyspaceParseIds); + + TEST_CASE(polyspaceMisraC2012); + TEST_CASE(polyspacePremiumMisraC2012); + TEST_CASE(polyspaceMisraC2023); + TEST_CASE(polyspaceMisraCpp2008); + TEST_CASE(polyspaceMisraCpp2023); + TEST_CASE(polyspaceCertC); + TEST_CASE(polyspaceCertCpp); + TEST_CASE(polyspaceAutosar); + TEST_CASE(polyspaceIgnored); + TEST_CASE(polyspaceMultiple1); + TEST_CASE(polyspaceMultiple2); + TEST_CASE(polyspaceMultiple3); + TEST_CASE(polyspaceRange); + TEST_CASE(polyspaceBlock); + TEST_CASE(polyspaceExtraComments); + } + + + void parseLine() const { + ASSERT_EQUALS("bad", SuppressionList::parseLine("bad").toString()); + ASSERT_EQUALS("bad:test.c", SuppressionList::parseLine("bad:test.c").toString()); + ASSERT_EQUALS("bad:test.c:1", SuppressionList::parseLine("bad:test.c:1").toString()); + + // symbol + ASSERT_EQUALS("bad\nsymbol=x", SuppressionList::parseLine("bad\nsymbol=x").toString()); + ASSERT_EQUALS("bad:test.c\nsymbol=x", SuppressionList::parseLine("bad:test.c\nsymbol=x").toString()); + ASSERT_EQUALS("bad:test.c:1\nsymbol=x", SuppressionList::parseLine("bad:test.c:1\nsymbol=x").toString()); + + // empty symbol + ASSERT_EQUALS("bad", SuppressionList::parseLine("bad\nsymbol=").toString()); + ASSERT_EQUALS("bad:test.c", SuppressionList::parseLine("bad:test.c\nsymbol=").toString()); + ASSERT_EQUALS("bad:test.c:1", SuppressionList::parseLine("bad:test.c:1\nsymbol=").toString()); + + // polyspace + ASSERT_EQUALS("bad\npolyspace=1", SuppressionList::parseLine("bad\npolyspace=1").toString()); + ASSERT_EQUALS("bad:test.c\npolyspace=1", SuppressionList::parseLine("bad:test.c\npolyspace=1").toString()); + ASSERT_EQUALS("bad:test.c:1\npolyspace=1", SuppressionList::parseLine("bad:test.c:1\npolyspace=1").toString()); + + // symbol + polyspace + ASSERT_EQUALS("bad\nsymbol=x\npolyspace=1", SuppressionList::parseLine("bad\nsymbol=x\npolyspace=1").toString()); + ASSERT_EQUALS("bad:test.c\nsymbol=x\npolyspace=1", SuppressionList::parseLine("bad:test.c\nsymbol=x\npolyspace=1").toString()); + ASSERT_EQUALS("bad:test.c:1\nsymbol=x\npolyspace=1", SuppressionList::parseLine("bad:test.c:1\nsymbol=x\npolyspace=1").toString()); + + // polyspace + symbol + ASSERT_EQUALS("bad\nsymbol=x\npolyspace=1", SuppressionList::parseLine("bad\npolyspace=1\nsymbol=x").toString()); + ASSERT_EQUALS("bad:test.c\nsymbol=x\npolyspace=1", SuppressionList::parseLine("bad:test.c\npolyspace=1\nsymbol=x").toString()); + ASSERT_EQUALS("bad:test.c:1\nsymbol=x\npolyspace=1", SuppressionList::parseLine("bad:test.c:1\npolyspace=1\nsymbol=x").toString()); + } + + void parseLineInvalid() const { + // missing filename + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:"), std::runtime_error, "filename is missing"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:\n"), std::runtime_error, "filename is missing"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:\n1.c"), std::runtime_error, "filename is missing"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:#1.c"), std::runtime_error, "filename is missing"); // TODO: looks like a valid filename + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id://1.c"), std::runtime_error, "filename is missing"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id::"), std::runtime_error, "filename is missing"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id::1"), std::runtime_error, "filename is missing"); + + // missing/invalid line + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:\n"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:\n1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:#1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))"); // TODO: looks like a valid filename + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c://1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:zero"), std::runtime_error, "invalid line number (converting 'zero' to integer failed - not an integer (invalid_argument))"); + + // invalid extras + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:1\n"), std::runtime_error, "unexpected extra ''"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:1\nsym=x"), std::runtime_error, "unexpected extra 'sym=x'"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:1\nsymbol:x"), std::runtime_error, "unexpected extra 'symbol:x'"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:1\npolyspace=0"), std::runtime_error, "unexpected extra 'polyspace=0'"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:1\npolyspace:1"), std::runtime_error, "unexpected extra 'polyspace:1'"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id\n:"), std::runtime_error, "unexpected extra ':'"); + ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c\n:"), std::runtime_error, "unexpected extra ':'"); } void suppressionsBadId1() const { @@ -283,17 +373,18 @@ class TestSuppressions : public TestFixture { if (useFS) filelist.clear(); - CppCheck cppCheck(settings, supprs, *this, true, nullptr); - SingleExecutor executor(cppCheck, filelist, fileSettings, settings, supprs, *this); + CppCheck cppCheck(settings, supprs, *this, nullptr, true, nullptr); + SingleExecutor executor(cppCheck, filelist, fileSettings, settings, supprs, *this, nullptr); unsigned int exitCode = executor.check(); - const bool err = CppCheckExecutor::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); + const bool err = CppCheckExecutorTest::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); if (err && exitCode == 0) exitCode = 1; return exitCode; } +#ifdef HAS_THREADING_MODEL_THREAD unsigned int checkSuppressionThreadsFiles(const char code[], const std::string &suppression = "") { return _checkSuppressionThreads(code, false, suppression); } @@ -311,12 +402,12 @@ class TestSuppressions : public TestFixture { fileSettings.emplace_back("test.cpp", Standards::Language::CPP, strlen(code)); } - /*const*/ auto settings = dinit(Settings, - $.jobs = 2, - $.quiet = true, - $.inlineSuppressions = true); - settings.severity.enable(Severity::information); - settings.templateFormat = templateFormat; + const auto settings = dinit(Settings, + $.jobs = 2, + $.quiet = true, + $.inlineSuppressions = true, + $.severity.enable (Severity::information), + $.templateFormat = templateFormat); Suppressions supprs; if (!suppression.empty()) { @@ -332,17 +423,18 @@ class TestSuppressions : public TestFixture { if (useFS) filelist.clear(); - ThreadExecutor executor(filelist, fileSettings, settings, supprs, *this, CppCheckExecutor::executeCommand); + ThreadExecutor executor(filelist, fileSettings, settings, supprs, *this, nullptr, CppCheckExecutorTest::executeCommand); unsigned int exitCode = executor.check(); - const bool err = CppCheckExecutor::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); + const bool err = CppCheckExecutorTest::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); if (err && exitCode == 0) exitCode = 1; return exitCode; } +#endif // HAS_THREADING_MODEL_THREAD -#if !defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +#ifdef HAS_THREADING_MODEL_FORK unsigned int checkSuppressionProcessesFiles(const char code[], const std::string &suppression = "") { return _checkSuppressionProcesses(code, false, suppression); } @@ -381,18 +473,17 @@ class TestSuppressions : public TestFixture { if (useFS) filelist.clear(); - ProcessExecutor executor(filelist, fileSettings, settings, supprs, *this, CppCheckExecutor::executeCommand); + ProcessExecutor executor(filelist, fileSettings, settings, supprs, *this, nullptr, CppCheckExecutorTest::executeCommand); unsigned int exitCode = executor.check(); - const bool err = CppCheckExecutor::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); + const bool err = CppCheckExecutorTest::reportUnmatchedSuppressions(settings, supprs.nomsg, filelist, fileSettings, *this); if (err && exitCode == 0) exitCode = 1; return exitCode; } -#endif +#endif // HAS_THREADING_MODEL_FORK - // TODO: check all results void runChecks(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // check to make sure the appropriate errors are present ASSERT_EQUALS(1, (this->*check)("void f() {\n" @@ -426,7 +517,7 @@ class TestSuppressions : public TestFixture { " a++;\n" "}\n", "")); - ASSERT_EQUALS("[test.cpp:2:0]: (error) File suppression should be at the top of the file [preprocessorErrorDirective]\n" + ASSERT_EQUALS("[test.cpp:2:5]: (error) File suppression should be at the top of the file [invalidSuppression]\n" "[test.cpp:4:5]: (error) Uninitialized variable: a [uninitvar]\n", errout_str()); ASSERT_EQUALS(1, (this->*check)("void f() {\n" @@ -435,7 +526,7 @@ class TestSuppressions : public TestFixture { "}\n" "// cppcheck-suppress-file uninitvar\n", "")); - ASSERT_EQUALS("[test.cpp:5:0]: (error) File suppression should be at the top of the file [preprocessorErrorDirective]\n" + ASSERT_EQUALS("[test.cpp:5:1]: (error) File suppression should be at the top of the file [invalidSuppression]\n" "[test.cpp:3:5]: (error) Uninitialized variable: a [uninitvar]\n", errout_str()); ASSERT_EQUALS(0, (this->*check)("// cppcheck-suppress-file uninitvar\n" @@ -487,7 +578,7 @@ class TestSuppressions : public TestFixture { " b++;\n" "}\n", "")); - ASSERT_EQUALS("[test.cpp:1:0]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:1:1]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); // suppress uninitvar for this file only ASSERT_EQUALS(0, (this->*check)("void f() {\n" @@ -503,7 +594,7 @@ class TestSuppressions : public TestFixture { " b++;\n" "}\n", "uninitvar:test.cpp")); - ASSERT_EQUALS("[test.cpp]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:0:0]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); // suppress all for this file only ASSERT_EQUALS(0, (this->*check)("void f() {\n" @@ -519,7 +610,7 @@ class TestSuppressions : public TestFixture { " b++;\n" "}\n", "*:test.cpp")); - ASSERT_EQUALS("[test.cpp]: (information) Unmatched suppression: * [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:0:0]: (information) Unmatched suppression: * [unmatchedSuppression]\n", errout_str()); // suppress uninitvar for this file and line ASSERT_EQUALS(0, (this->*check)("void f() {\n" @@ -665,7 +756,7 @@ class TestSuppressions : public TestFixture { " b++;\n" "}\n", "")); - ASSERT_EQUALS("[test.cpp:4:0]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:5]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); // suppress block inline checks ASSERT_EQUALS(0, (this->*check)("void f() {\n" @@ -687,7 +778,7 @@ class TestSuppressions : public TestFixture { " b++;\n" "}\n", "")); - ASSERT_EQUALS("[test.cpp:2:0]: (error) Suppress Begin: No matching end [preprocessorErrorDirective]\n" + ASSERT_EQUALS("[test.cpp:2:5]: (error) Suppress Begin: No matching end [invalidSuppression]\n" "[test.cpp:4:5]: (error) Uninitialized variable: a [uninitvar]\n" "[test.cpp:6:5]: (error) Uninitialized variable: b [uninitvar]\n", errout_str()); @@ -699,10 +790,57 @@ class TestSuppressions : public TestFixture { " // cppcheck-suppress-end uninitvar\n" "}\n", "")); - ASSERT_EQUALS("[test.cpp:6:0]: (error) Suppress End: No matching begin [preprocessorErrorDirective]\n" + ASSERT_EQUALS("[test.cpp:6:5]: (error) Suppress End: No matching begin [invalidSuppression]\n" "[test.cpp:3:5]: (error) Uninitialized variable: a [uninitvar]\n" "[test.cpp:5:5]: (error) Uninitialized variable: b [uninitvar]\n", errout_str()); + ASSERT_EQUALS(1, (this->*check)("// cppcheck-suppress: id\n" + "// cppcheck-suppress-unknown id\n" + "// cppcheck-suppress-begin-unknown id\n" + "// cppcheck-suppress-begin id4\n" + "void f() {}\n" + "// cppcheck-suppress-end-unknown id4\n", + "")); + ASSERT_EQUALS("[test.cpp:1:1]: (error) unknown suppression type 'cppcheck-suppress:' [invalidSuppression]\n" + "[test.cpp:2:1]: (error) unknown suppression type 'cppcheck-suppress-unknown' [invalidSuppression]\n" + "[test.cpp:3:1]: (error) unknown suppression type 'cppcheck-suppress-begin-unknown' [invalidSuppression]\n" + "[test.cpp:6:1]: (error) unknown suppression type 'cppcheck-suppress-end-unknown' [invalidSuppression]\n" + "[test.cpp:4:1]: (error) Suppress Begin: No matching end [invalidSuppression]\n", errout_str()); + + ASSERT_EQUALS(1, (this->*check)("// cppcheck-suppress-file\n" + "// cppcheck-suppress\n" + "// cppcheck-suppress \n" + "// cppcheck-suppress\t\n" + "// cppcheck-suppress []\n" // TODO + "// cppcheck-suppress-macro\n" + "// cppcheck-suppress-begin\n" + "// cppcheck-suppress-begin id0\n" + "void f() {}\n" + "// cppcheck-suppress-end\n", + "")); + ASSERT_EQUALS("[test.cpp:1:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:2:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:3:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:4:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:6:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:7:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:10:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:8:1]: (error) Suppress Begin: No matching end [invalidSuppression]\n", errout_str()); + + ASSERT_EQUALS(1, (this->*check)("// cppcheck-suppress:\n" + "// cppcheck-suppress-unknown\n" + "// cppcheck-suppress-begin-unknown\n" + "// cppcheck-suppress-begin\n" + "void f() {}\n" + "// cppcheck-suppress-end-unknown\n", + "")); + // TODO: actually these are all invalid types + ASSERT_EQUALS("[test.cpp:1:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:2:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:3:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:4:1]: (error) suppression without error ID [invalidSuppression]\n" + "[test.cpp:6:1]: (error) suppression without error ID [invalidSuppression]\n", errout_str()); + ASSERT_EQUALS(1, (this->*check)("void f() {\n" " int a;\n" " // cppcheck-suppress-begin uninitvar\n" @@ -801,7 +939,7 @@ class TestSuppressions : public TestFixture { " // cppcheck-suppress-end [uninitvar, syntaxError]\n" "}\n", "")); - ASSERT_EQUALS("[test.cpp:2:0]: (information) Unmatched suppression: syntaxError [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:5]: (information) Unmatched suppression: syntaxError [unmatchedSuppression]\n", errout_str()); ASSERT_EQUALS(1, (this->*check)("// cppcheck-suppress-begin [uninitvar, syntaxError]\n" "void f() {\n" @@ -816,7 +954,7 @@ class TestSuppressions : public TestFixture { "}\n" "// cppcheck-suppress-end [uninitvar, syntaxError]\n", "")); - ASSERT_EQUALS("[test.cpp:1:0]: (information) Unmatched suppression: syntaxError [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:1:1]: (information) Unmatched suppression: syntaxError [unmatchedSuppression]\n", errout_str()); ASSERT_EQUALS(1, (this->*check)("// cppcheck-suppress-begin [uninitvar, syntaxError]\n" "void f() {\n" @@ -831,7 +969,7 @@ class TestSuppressions : public TestFixture { "}\n" "// cppcheck-suppress-end [uninitvar, syntaxError]", "")); - ASSERT_EQUALS("[test.cpp:1:0]: (information) Unmatched suppression: syntaxError [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:1:1]: (information) Unmatched suppression: syntaxError [unmatchedSuppression]\n", errout_str()); // test of multiple suppression types ASSERT_EQUALS(0, (this->*check)("// cppcheck-suppress-file uninitvar\n" @@ -881,7 +1019,7 @@ class TestSuppressions : public TestFixture { " a++;\n" "}\n", "")); - ASSERT_EQUALS("[test.cpp:4:0]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:4:5]: (information) Unmatched suppression: uninitvar [unmatchedSuppression]\n", errout_str()); // #5746 - exitcode ASSERT_EQUALS(1U, @@ -898,18 +1036,19 @@ class TestSuppressions : public TestFixture { "uninitvar")); ASSERT_EQUALS("", errout_str()); - // cppcheck-suppress-macro + // TODO: check result (this->*check)("// cppcheck-suppress-macro zerodiv\n" "#define DIV(A,B) A/B\n" "a = DIV(10,0);\n", ""); ASSERT_EQUALS("", errout_str()); + // TODO: check result (this->*check)("// cppcheck-suppress-macro abc\n" "#define DIV(A,B) A/B\n" "a = DIV(10,1);\n", ""); - ASSERT_EQUALS("[test.cpp:2:0]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:1]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); } void suppressionsSettingsFiles() { @@ -920,6 +1059,7 @@ class TestSuppressions : public TestFixture { runChecks(&TestSuppressions::checkSuppressionFS); } +#ifdef HAS_THREADING_MODEL_THREAD void suppressionsSettingsThreadsFiles() { runChecks(&TestSuppressions::checkSuppressionThreadsFiles); } @@ -927,8 +1067,9 @@ class TestSuppressions : public TestFixture { void suppressionsSettingsThreadsFS() { runChecks(&TestSuppressions::checkSuppressionThreadsFS); } +#endif // HAS_THREADING_MODEL_THREAD -#if !defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +#ifdef HAS_THREADING_MODEL_FORK void suppressionsSettingsProcessesFiles() { runChecks(&TestSuppressions::checkSuppressionProcessesFiles); } @@ -936,7 +1077,7 @@ class TestSuppressions : public TestFixture { void suppressionsSettingsProcessesFS() { runChecks(&TestSuppressions::checkSuppressionProcessesFS); } -#endif +#endif // HAS_THREADING_MODEL_FORK void suppressionsMultiFileInternal(unsigned int (TestSuppressions::*check)(std::map &f, const std::string &)) { std::map files; @@ -1256,10 +1397,10 @@ class TestSuppressions : public TestFixture { Suppressions supprs; ASSERT_EQUALS("", supprs.nomsg.addSuppressionLine("uninitvar")); - CppCheck cppCheck(settings, supprs, *this, false, nullptr); // <- do not "use global suppressions". pretend this is a thread that just checks a file. + CppCheck cppCheck(settings, supprs, *this, nullptr, false, nullptr); // <- do not "use global suppressions". pretend this is a thread that just checks a file. const char code[] = "int f() { int a; return a; }"; - ASSERT_EQUALS(0, cppCheck.checkBuffer(FileWithDetails("test.c", Standards::Language::C, 0), reinterpret_cast(code), sizeof(code))); // <- no unsuppressed error is seen + ASSERT_EQUALS(0, cppCheck.checkBuffer(FileWithDetails("test.c", Standards::Language::C, 0),code, sizeof(code))); // <- no unsuppressed error is seen ASSERT_EQUALS("[test.c:1:25]: (error) Uninitialized variable: a [uninitvar]\n", errout_str()); // <- report error so ThreadExecutor can suppress it and make sure the global suppression is matched. } @@ -1298,8 +1439,8 @@ class TestSuppressions : public TestFixture { " // cppcheck-suppress unusedStructMember\n" " int y;\n" "};"; - CppCheck cppCheck(settings, supprs, *this, true, nullptr); - ASSERT_EQUALS(0, cppCheck.checkBuffer(FileWithDetails("/somewhere/test.cpp", Standards::Language::CPP, 0), reinterpret_cast(code), sizeof(code))); + CppCheck cppCheck(settings, supprs, *this, nullptr, true, nullptr); + ASSERT_EQUALS(0, cppCheck.checkBuffer(FileWithDetails("/somewhere/test.cpp", Standards::Language::CPP, 0), code, sizeof(code))); ASSERT_EQUALS("",errout_str()); } @@ -1341,7 +1482,7 @@ class TestSuppressions : public TestFixture { suppressingSyntaxErrorsInlineInternal(&TestSuppressions::checkSuppressionFS); } - void suppressingSyntaxErrorsWhileFileReadInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // syntaxError while file read should be suppressible (PR #1333) + void suppressingSimplecppErrorsWhileFileReadInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // syntaxError while file read should be suppressible (PR #1333) const char code[] = "CONST (genType, KS_CONST) genService[KS_CFG_NR_OF_NVM_BLOCKS] =\n" "{\n" "[!VAR \"BC\" = \"$BC + 1\"!][!//\n" @@ -1359,12 +1500,12 @@ class TestSuppressions : public TestFixture { ASSERT_EQUALS("", errout_str()); } - void suppressingSyntaxErrorsWhileFileReadFiles() { - suppressingSyntaxErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles); + void suppressingSimplecppErrorsWhileFileReadFiles() { + suppressingSimplecppErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles); } - void suppressingSyntaxErrorsWhileFileReadFS() { - suppressingSyntaxErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles); + void suppressingSimplecppErrorsWhileFileReadFS() { + suppressingSimplecppErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles); } // TODO: this tests an internal function - should it be private? @@ -1481,7 +1622,7 @@ class TestSuppressions : public TestFixture { // No unmatched suppression { SuppressionList suppressions; - ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS(false, CppCheckExecutorTest::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); ASSERT_EQUALS("", errout_str()); } @@ -1490,7 +1631,7 @@ class TestSuppressions : public TestFixture { SuppressionList suppressions; addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); addCheckedSuppression(suppressions, {"unmatchedSuppression", "*", SuppressionList::Suppression::NO_LINE}); - ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS(false, CppCheckExecutorTest::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); ASSERT_EQUALS("", errout_str()); } @@ -1499,7 +1640,7 @@ class TestSuppressions : public TestFixture { SuppressionList suppressions; addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); addCheckedSuppression(suppressions, {"unmatchedSuppression", "", SuppressionList::Suppression::NO_LINE}); - ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS(false, CppCheckExecutorTest::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); ASSERT_EQUALS("", errout_str()); } @@ -1508,7 +1649,7 @@ class TestSuppressions : public TestFixture { SuppressionList suppressions; addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); addCheckedSuppression(suppressions, {"unmatchedSuppression", "a.c", SuppressionList::Suppression::NO_LINE}); - ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS(false, CppCheckExecutorTest::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); ASSERT_EQUALS("", errout_str()); } @@ -1517,7 +1658,7 @@ class TestSuppressions : public TestFixture { SuppressionList suppressions; addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); addCheckedSuppression(suppressions, {"unmatchedSuppression", "a.c", 10U}); - ASSERT_EQUALS(false, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS(false, CppCheckExecutorTest::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); ASSERT_EQUALS("", errout_str()); } @@ -1526,7 +1667,7 @@ class TestSuppressions : public TestFixture { SuppressionList suppressions; addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); addCheckedSuppression(suppressions, {"unmatchedSuppression", "b.c", SuppressionList::Suppression::NO_LINE}); - ASSERT_EQUALS(true, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS(true, CppCheckExecutorTest::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); ASSERT_EQUALS("[a.c:10:0]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); } @@ -1535,7 +1676,7 @@ class TestSuppressions : public TestFixture { SuppressionList suppressions; addCheckedSuppression(suppressions, {"abc", "a.c", 10U}); addCheckedSuppression(suppressions, {"unmatchedSuppression", "a.c", 1U}); - ASSERT_EQUALS(true, CppCheckExecutor::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); + ASSERT_EQUALS(true, CppCheckExecutorTest::reportUnmatchedSuppressions(settingsDefault, suppressions, files, fs, *this)); ASSERT_EQUALS("[a.c:10:0]: (information) Unmatched suppression: abc [unmatchedSuppression]\n", errout_str()); } } @@ -1733,7 +1874,7 @@ class TestSuppressions : public TestFixture { SuppressionList::Suppression s; s.errorId = "unitvar"; s.symbolName = "sym"; - ASSERT_EQUALS("unitvar:sym", s.toString()); + ASSERT_EQUALS("unitvar\nsymbol=sym", s.toString()); } } @@ -1842,6 +1983,261 @@ class TestSuppressions : public TestFixture { ASSERT(!suppressions.getUnmatchedGlobalSuppressions().empty()); } } + + static std::string polyspaceParseIdsResults(const std::string& comment, std::string::size_type pos) { + std::string ret; + for (const auto& fr: polyspace::Parser::parseFamilyRules(comment,pos)) { + if (!fr.second.empty()) + ret += ',' + fr.first + ':' + fr.second; + } + return ret.empty() ? ret : ret.substr(1); + } + + void polyspaceParseRange() const { + std::string::size_type pos; + + // Happy case + pos = 0; + ASSERT_EQUALS(12, polyspace::Parser::parseRange(" +12 ",pos)); + ASSERT_EQUALS(4U, pos); + + // Invalid range => pos will point at the token + pos = 0; + ASSERT_EQUALS(0, polyspace::Parser::parseRange(" ",pos)); + ASSERT_EQUALS(std::string::npos, pos); + + pos = 0; + ASSERT_EQUALS(0, polyspace::Parser::parseRange(" test ",pos)); + ASSERT_EQUALS(1U, pos); + + pos = 0; + ASSERT_EQUALS(0, polyspace::Parser::parseRange(" +",pos)); + ASSERT_EQUALS(1U, pos); + + pos = 0; + ASSERT_EQUALS(0, polyspace::Parser::parseRange(" +12",pos)); + ASSERT_EQUALS(1U, pos); + + pos = 0; + ASSERT_EQUALS(0, polyspace::Parser::parseRange(" +A ",pos)); + ASSERT_EQUALS(1U, pos); + } + + void polyspaceParseIds() const { + ASSERT_EQUALS("test:12", polyspaceParseIdsResults("abc test:12",3)); + ASSERT_EQUALS("test:12", polyspaceParseIdsResults("abc test:12 [12]",3)); + ASSERT_EQUALS("test:12", polyspaceParseIdsResults("abc test:12 */",3)); + ASSERT_EQUALS("test:1*", polyspaceParseIdsResults("abc test:1* */",3)); + ASSERT_EQUALS("test:*", polyspaceParseIdsResults("// abc test:*",6)); + // -_. + ASSERT_EQUALS("test:1-2.3", polyspaceParseIdsResults("abc test:1-2.3",3)); + ASSERT_EQUALS("t-e_s.t:12", polyspaceParseIdsResults("abc t-e_s.t : 12",3)); + // multiple ids + ASSERT_EQUALS("d:1,d:2", polyspaceParseIdsResults("abc d:1,2",3)); + ASSERT_EQUALS("d:1,d:2,e:3,e:4,f:6", polyspaceParseIdsResults("abc d:1,2 e: 3 , 4 f : 6 ",3)); + } + + struct PolyspaceComment { + std::string text; + int line; + + PolyspaceComment(const std::string &&text, int line) + : text(text) + , line(line) + {} + }; + + struct PolyspaceParseResult { + std::string errorId; + int lineNumber; + std::string extraComment; + SuppressionList::Type type = SuppressionList::Type::unique; + int lineBegin = SuppressionList::Suppression::NO_LINE; + int lineEnd = SuppressionList::Suppression::NO_LINE; + + PolyspaceParseResult(const std::string &&errorId, + int lineNumber, + const std::string &&extraComment = "", + SuppressionList::Type type = SuppressionList::Type::unique, + int lineBegin = SuppressionList::Suppression::NO_LINE, + int lineEnd = SuppressionList::Suppression::NO_LINE) + : errorId(errorId) + , lineNumber(lineNumber) + , extraComment(extraComment) + , type(type) + , lineBegin(lineBegin) + , lineEnd(lineEnd) + {} + }; + + void testPolyspaceSuppression(const std::string& addon, + const std::string& premiumArgs, + const PolyspaceComment& comment, + std::initializer_list results) const + { + SuppressionList list; + Settings settings; + if (!addon.empty()) { + AddonInfo info; + info.name = addon; + settings.addonInfos.push_back(info); + } + settings.premiumArgs = premiumArgs; + polyspace::Parser parser(settings); + + const std::string fileName = "file.c"; + const auto supprs = parser.parse(comment.text, comment.line, fileName); + + ASSERT_EQUALS(results.size(), supprs.size()); + + auto supprIt = supprs.cbegin(); + const auto *resultIt = results.begin(); + + for (; supprIt != supprs.cend(); supprIt++, resultIt++) { + ASSERT(supprIt->isPolyspace); + ASSERT(supprIt->isInline); + ASSERT_EQUALS(fileName, supprIt->fileName); + ASSERT_EQUALS(resultIt->errorId, supprIt->errorId); + ASSERT_EQUALS(resultIt->extraComment, supprIt->extraComment); + ASSERT_EQUALS_ENUM(resultIt->type, supprIt->type); + ASSERT_EQUALS(resultIt->lineNumber, supprIt->lineNumber); + ASSERT_EQUALS(resultIt->lineBegin, supprIt->lineBegin); + ASSERT_EQUALS(resultIt->lineEnd, supprIt->lineEnd); + } + } + + void polyspaceMisraC2012() const { + testPolyspaceSuppression( + "misra", "", + { "/* polyspace MISRA2012 : 2.7 */", 1 }, + { { "misra-c2012-2.7", 1 } } + ); + } + + void polyspacePremiumMisraC2012() const { + testPolyspaceSuppression( + "", "--misra-c-2012", + { "/* polyspace MISRA2012 : 2.7 */", 1 }, + { { "premium-misra-c-2012-2.7", 1 } } + ); + } + + void polyspaceMisraC2023() const { + testPolyspaceSuppression( + "", "--misra-c-2023", + { "// polyspace MISRA-C-2023 : *", 2 }, + { { "premium-misra-c-2023-*", 2 } } + ); + } + + void polyspaceMisraCpp2008() const { + testPolyspaceSuppression( + "", "--misra-cpp-2008", + { "// polyspace MISRA-CPP : 7-1-1", 1 }, + { { "premium-misra-cpp-2008-7-1-1", 1 } } + ); + } + + void polyspaceMisraCpp2023() const { + testPolyspaceSuppression( + "", "--misra-cpp-2023", + { "// polyspace MISRA-CPP-2023 : 4.6.1", 1 }, + { { "premium-misra-cpp-2023-4.6.1", 1 } } + ); + } + + void polyspaceCertC() const { + testPolyspaceSuppression( + "", "--cert-c", + { "// polyspace CERT-C : PRE30", 1 }, + { { "premium-cert-c-PRE30", 1 } } + ); + } + + void polyspaceCertCpp() const { + testPolyspaceSuppression( + "", "--cert-cpp", + { "// polyspace CERT-CPP : CTR51", 1 }, + { { "premium-cert-cpp-CTR51", 1 } } + ); + } + + void polyspaceAutosar() const { + testPolyspaceSuppression( + "", "--autosar", + { "// polyspace AUTOSAR-CPP14 : a2-10-1", 1 }, + { { "premium-autosar-a2-10-1", 1 } } + ); + } + + void polyspaceIgnored() const { + testPolyspaceSuppression( + "", "", + { "// polyspace DEFECT : INT_OVFL AUTOSAR-CPP14 : a2-10-1", 1 }, + {} + ); + } + + void polyspaceMultiple1() const { + testPolyspaceSuppression( + "", "--misra-c-2012", + { "/* polyspace MISRA2012 : 2.7, 9.1 */", 1 }, + { { "premium-misra-c-2012-2.7", 1 }, + { "premium-misra-c-2012-9.1", 1 } } + ); + } + + void polyspaceMultiple2() const { + testPolyspaceSuppression( + "", "--misra-c-2012 --misra-cpp-2008", + { "/* polyspace MISRA2012 : 2.7 MISRA-CPP : 7-1-1 */", 1 }, + { { "premium-misra-c-2012-2.7", 1 }, + { "premium-misra-cpp-2008-7-1-1", 1 } } + ); + } + + void polyspaceMultiple3() const { + testPolyspaceSuppression( + "", "--misra-c-2012 --misra-cpp-2008", + { "/* polyspace MISRA2012 : 2.7 [Justified:Low] \"comment 1\" polyspace MISRA-CPP : 7-1-1 \"comment 2\"*/", 1 }, + { { "premium-misra-c-2012-2.7", 1, "comment 1" }, + { "premium-misra-cpp-2008-7-1-1", 1, "comment 2" }, } + ); + } + + void polyspaceRange() const { + testPolyspaceSuppression( + "", "--misra-c-2012", + { "/* polyspace +3 MISRA2012 : 2.7 */", 1 }, + { { "premium-misra-c-2012-2.7", 1, "", SuppressionList::Type::block, 1, 4 } } + ); + } + + void polyspaceBlock() const { + testPolyspaceSuppression( + "", "--misra-c-2012", + { "/* polyspace-begin MISRA2012 : 2.7 */", 1 }, + { { "premium-misra-c-2012-2.7", 1, "", SuppressionList::Type::blockBegin } } + ); + + testPolyspaceSuppression( + "", "--misra-c-2012", + { "/* polyspace-end MISRA2012 : 2.7 */", 1 }, + { { "premium-misra-c-2012-2.7", 1, "", SuppressionList::Type::blockEnd } } + ); + + } + + void polyspaceExtraComments() const { + testPolyspaceSuppression( + "", "--misra-c-2012 --misra-cpp-2008", + { "/* polyspace MISRA2012 : 2.7 MISRA-CPP : 7-1-1 \"comment 1\" polyspace MISRA2012 : 8.1, 8.3 \"comment 2\" */", 1 }, + { { "premium-misra-c-2012-2.7", 1, "comment 1" }, + { "premium-misra-cpp-2008-7-1-1", 1, "comment 1" }, + { "premium-misra-c-2012-8.1", 1, "comment 2" }, + { "premium-misra-c-2012-8.3", 1, "comment 2" }, } + ); + } }; REGISTER_TEST(TestSuppressions) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 9e7eed4ebdd..e981c8ea546 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -442,6 +441,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(createSymbolDatabaseFindAllScopes8); // #12761 TEST_CASE(createSymbolDatabaseFindAllScopes9); TEST_CASE(createSymbolDatabaseFindAllScopes10); + TEST_CASE(createSymbolDatabaseFindAllScopes11); TEST_CASE(createSymbolDatabaseIncompleteVars); @@ -464,6 +464,9 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(enum17); TEST_CASE(enum18); TEST_CASE(enum19); + TEST_CASE(enum20); // #14419 + + TEST_CASE(struct1); TEST_CASE(sizeOfType); @@ -535,6 +538,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(findFunction59); TEST_CASE(findFunction60); TEST_CASE(findFunction61); + TEST_CASE(findFunction62); // #14272 - pointer passed to function is const TEST_CASE(findFunctionRef1); TEST_CASE(findFunctionRef2); // #13328 TEST_CASE(findFunctionContainer); @@ -582,6 +586,8 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(valueType2); TEST_CASE(valueType3); TEST_CASE(valueTypeThis); + TEST_CASE(valueTypeChar); + TEST_CASE(valueTypeRValueReference); TEST_CASE(variadic1); // #7453 TEST_CASE(variadic2); // #7649 @@ -626,6 +632,8 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(stdintFunction); TEST_CASE(userDefinedLiteral); + + TEST_CASE(dumpValueNegative); // #14735 - dumping negative impossible value for unsigned expression } void array() { @@ -1868,11 +1876,11 @@ class TestSymbolDatabase : public TestFixture { // TODO: we should provide our own error message #ifdef _MSC_VER - ASSERT_THROW_EQUALS_2(db->getVariableFromVarId(3), std::out_of_range, "invalid vector subscript"); + ASSERT_THROW_EQUALS(db->getVariableFromVarId(3), std::out_of_range, "invalid vector subscript"); #elif !defined(_LIBCPP_VERSION) - ASSERT_THROW_EQUALS_2(db->getVariableFromVarId(3), std::out_of_range, "vector::_M_range_check: __n (which is 3) >= this->size() (which is 3)"); + ASSERT_THROW_EQUALS(db->getVariableFromVarId(3), std::out_of_range, "vector::_M_range_check: __n (which is 3) >= this->size() (which is 3)"); #else - ASSERT_THROW_EQUALS_2(db->getVariableFromVarId(3), std::out_of_range, "vector"); + ASSERT_THROW_EQUALS(db->getVariableFromVarId(3), std::out_of_range, "vector"); #endif } @@ -3671,8 +3679,7 @@ class TestSymbolDatabase : public TestFixture { } void symboldatabase36() { // ticket #4892 - check("void struct ( ) { if ( 1 ) } int main ( ) { }"); - ASSERT_EQUALS("", errout_str()); + ASSERT_THROW_INTERNAL(check("void struct ( ) { if ( 1 ) } int main ( ) { }"), SYNTAX); } void symboldatabase37() { @@ -6107,6 +6114,24 @@ class TestSymbolDatabase : public TestFixture { } } + void createSymbolDatabaseFindAllScopes11() // #13685 + { + GET_SYMBOL_DB("int f() {\n" + " int x;\n" + " if (!({ int *p = &x; *p = 1; 1; }))\n" + " return 0;\n" + " return x;\n" + "}\n"); + ASSERT(db && db->scopeList.size() == 4); + + auto it = db->scopeList.begin(); + std::advance(it, 3); + const Scope& compoundScope = *it; + ASSERT_EQUALS_ENUM(ScopeType::eUnconditional, compoundScope.type); + ASSERT_EQUALS_ENUM(ScopeType::eFunction, compoundScope.nestedIn->type); + ASSERT_EQUALS("f", compoundScope.nestedIn->className); + } + void createSymbolDatabaseIncompleteVars() { { @@ -6858,6 +6883,59 @@ class TestSymbolDatabase : public TestFixture { } } + void enum20() { // #14419 + { + GET_SYMBOL_DB("enum class myclass : uint8_t { A = 0U };\n"); + const Token *A = Token::findsimplematch(tokenizer.tokens(), "A"); + ASSERT(A && A->valueType() && A->valueType()->isEnum()); + ASSERT_EQUALS_ENUM(ValueType::CHAR, A->valueType()->type); + ASSERT_EQUALS_ENUM(ValueType::UNSIGNED, A->valueType()->sign); + } + { + GET_SYMBOL_DB("enum myclass : uint8_t { A = 0U };\n"); + const Token *A = Token::findsimplematch(tokenizer.tokens(), "A"); + ASSERT(A && A->valueType() && A->valueType()->isEnum()); + ASSERT_EQUALS_ENUM(ValueType::CHAR, A->valueType()->type); + ASSERT_EQUALS_ENUM(ValueType::UNSIGNED, A->valueType()->sign); + } + } + + void struct1() { + GET_SYMBOL_DB_C("struct deer {\n" + " uint16_t a;\n" + " uint16_t b;\n" + "};\n" + "void herd ( void ) {\n" + " struct deer {\n" + " uint16_t a;\n" + " };\n" + "}"); + + ASSERT_EQUALS("", errout_str()); + ASSERT(db); + + const Token* deer = Token::findsimplematch(tokenizer.tokens(), "deer {"); + ASSERT(deer); + ASSERT(deer->type()); + ASSERT(deer->type()->classScope); + const Token* tok = deer->next(); + ASSERT(tok->scope()); + ASSERT_EQUALS_ENUM(ScopeType::eStruct, tok->scope()->type); + ASSERT_EQUALS(tok, tok->scope()->bodyStart); + ASSERT_EQUALS(tok->scope(), deer->type()->classScope); + + const Token* secondDeer = Token::findsimplematch(tok, "deer {"); + ASSERT(secondDeer); + ASSERT(secondDeer != deer); + ASSERT(secondDeer->type()); + ASSERT(secondDeer->type()->classScope); + tok = secondDeer->next(); + ASSERT(tok->scope()); + ASSERT_EQUALS_ENUM(ScopeType::eStruct, tok->scope()->type); + ASSERT_EQUALS(tok, tok->scope()->bodyStart); + ASSERT_EQUALS(tok->scope(), secondDeer->type()->classScope); + } + void sizeOfType() { // #7615 - crash in Symboldatabase::sizeOfType() GET_SYMBOL_DB("enum e;\n" @@ -7740,20 +7818,12 @@ class TestSymbolDatabase : public TestFixture { f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v7 ) ) ;"); ASSERT(f); ASSERT(f->function()); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS(10, f->function()->tokenDef->linenr()); - } else { - ASSERT_EQUALS(5, f->function()->tokenDef->linenr()); - } + ASSERT_EQUALS(10, f->function()->tokenDef->linenr()); f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v8 ) ) ;"); ASSERT(f); ASSERT(f->function()); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS(5, f->function()->tokenDef->linenr()); - } else { - ASSERT_EQUALS(11, f->function()->tokenDef->linenr()); - } + ASSERT_EQUALS(11, f->function()->tokenDef->linenr()); f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v9 ) ) ;"); ASSERT(f); @@ -8694,6 +8764,22 @@ class TestSymbolDatabase : public TestFixture { ASSERT(fun && !fun->function()); } + void findFunction62() { // #14272 + GET_SYMBOL_DB("class Token {\n" + " std::string stringifyList(const Token* end, bool attributes = true) const;\n" + " std::string stringifyList(bool varid = false) const;\n" + "};\n" + "\n" + "void foo(const Token * const tokIf) {\n" + " tokIf->stringifyList(tokIf);\n" + "}\n"); + const Token* functionCall = Token::findsimplematch(tokenizer.tokens(), "stringifyList ( tokIf )"); + ASSERT(functionCall); + ASSERT(functionCall->function()); + ASSERT(functionCall->function()->token); + ASSERT_EQUALS(2, functionCall->function()->token->linenr()); + } + void findFunctionRef1() { GET_SYMBOL_DB("struct X {\n" " const std::vector getInts() const & { return mInts; }\n" @@ -9886,6 +9972,18 @@ class TestSymbolDatabase : public TestFixture { ASSERT(tok && tok->valueType()); ASSERT_EQUALS("iterator(std :: vector <)", tok->valueType()->str()); } + { + GET_SYMBOL_DB("struct S { std::vector v[1][1]; };\n" + "void f(S& s) {\n" + " auto it = std::begin(s.v[0][0]);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + const Token* tok = tokenizer.tokens(); + tok = Token::findsimplematch(tok, "auto"); + ASSERT(tok && tok->valueType()); + ASSERT_EQUALS("iterator(std :: vector <)", tok->valueType()->str()); + } { GET_SYMBOL_DB("void f(std::vector::iterator beg, std::vector::iterator end) {\n" " auto it = std::find(beg, end, 0);\n" @@ -10073,6 +10171,17 @@ class TestSymbolDatabase : public TestFixture { ASSERT_EQUALS("const C *", typeOf("class C { void foo() const; }; void C::foo() const { *this = 0; }", "this")); } + void valueTypeChar() { + Settings s = settings2; + s.platform.defaultSign = 's'; + ASSERT_EQUALS("char", typeOf("char c; c = 'x';", "c =", true, &s)); + ASSERT_EQUALS("char", typeOf("char buf[10]; buf[0] = 'x';", "[ 0 ]", true, &s)); + } + + void valueTypeRValueReference() { + TODO_ASSERT_EQUALS("", "bool", typeOf("void f(std::string&& s = {})", "&&")); + } + void variadic1() { // #7453 { GET_SYMBOL_DB("CBase* create(const char *c1, ...);\n" @@ -11337,6 +11446,18 @@ class TestSymbolDatabase : public TestFixture { ASSERT(!x->varId()); ASSERT(!x->variable()); } + + void dumpValueNegative() { // #14735 + GET_SYMBOL_DB("void f(unsigned int x) { a = x; }"); + const Token* x = Token::findsimplematch(tokenizer.tokens(), "x ;"); + ASSERT(x != nullptr); + std::ostringstream out; + x->printValueFlow({"test.cpp"}, true, out); + const std::string dump = out.str(); + const std::string expected = ""; + // dump should contain expected string, otherwise print the dump string + ASSERT_EQUALS(expected, dump.find(expected) == std::string::npos ? dump : expected); + } }; REGISTER_TEST(TestSymbolDatabase) diff --git a/test/testthreadexecutor.cpp b/test/testthreadexecutor.cpp index ad260727d01..ddd65c316b2 100644 --- a/test/testthreadexecutor.cpp +++ b/test/testthreadexecutor.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,8 +16,11 @@ * along with this program. If not, see . */ -#include "filesettings.h" +#include "config.h" #include "fixture.h" + +#ifdef HAS_THREADING_MODEL_THREAD +#include "filesettings.h" #include "helpers.h" #include "redirect.h" #include "settings.h" @@ -33,13 +36,22 @@ #include #include #include +#endif // HAS_THREADING_MODEL_THREAD class TestThreadExecutorBase : public TestFixture { public: - TestThreadExecutorBase(const char * const name, bool useFS) : TestFixture(name), useFS(useFS) {} + TestThreadExecutorBase(const char * const name, bool useFS) + : TestFixture(name) +#ifdef HAS_THREADING_MODEL_THREAD + , useFS(useFS) +#endif // HAS_THREADING_MODEL_THREAD + { + (void)useFS; + } private: - /*const*/ Settings settings = settingsBuilder().library("std.cfg").build(); +#ifdef HAS_THREADING_MODEL_THREAD + /*const*/ Settings settings; bool useFS; std::string fprefix() const @@ -52,7 +64,7 @@ class TestThreadExecutorBase : public TestFixture { struct CheckOptions { bool quiet = true; - SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; + Settings::ShowTime showtime = Settings::ShowTime::NONE; const char* plistOutput = nullptr; std::vector filesList; }; @@ -93,6 +105,9 @@ class TestThreadExecutorBase : public TestFixture { s.templateFormat = "{callstack}: ({severity}) {inconclusive:inconclusive: }{message}"; // TODO: remove when we only longer rely on toString() in unique message handling? Suppressions supprs; + std::unique_ptr timerResults; + if (s.showtime != Settings::ShowTime::NONE) + timerResults.reset(new TimerResults); // NOLINTNEXTLINE(performance-unnecessary-value-param) auto executeFn = [](std::string,std::vector,std::string,std::string&){ @@ -108,12 +123,14 @@ class TestThreadExecutorBase : public TestFixture { if (useFS) filelist.clear(); - ThreadExecutor executor(filelist, fileSettings, s, supprs, *this, executeFn); + ThreadExecutor executor(filelist, fileSettings, s, supprs, *this, timerResults.get(), executeFn); ASSERT_EQUALS(result, executor.check()); } +#endif // HAS_THREADING_MODEL_THREAD void run() override { mNewTemplate = true; +#ifdef HAS_THREADING_MODEL_THREAD TEST_CASE(deadlock_with_many_errors); TEST_CASE(many_threads); TEST_CASE(many_threads_showtime); @@ -124,14 +141,14 @@ class TestThreadExecutorBase : public TestFixture { TEST_CASE(one_error_less_files); TEST_CASE(one_error_several_files); TEST_CASE(showtime_top5_file); - TEST_CASE(showtime_top5_summary); TEST_CASE(showtime_file); - TEST_CASE(showtime_summary); TEST_CASE(showtime_file_total); TEST_CASE(suppress_error_library); TEST_CASE(unique_errors); +#endif // HAS_THREADING_MODEL_THREAD } +#ifdef HAS_THREADING_MODEL_THREAD void deadlock_with_many_errors() { std::ostringstream oss; oss << "void f()\n" @@ -163,7 +180,7 @@ class TestThreadExecutorBase : public TestFixture { "void f()\n" "{\n" " (void)(*((int*)0));\n" - "}", dinit(CheckOptions, $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY)); + "}", dinit(CheckOptions, $.showtime = Settings::ShowTime::SUMMARY)); // we are not interested in the results - so just consume them ignore_errout(); } @@ -232,25 +249,10 @@ class TestThreadExecutorBase : public TestFixture { check(2, 2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE)); - // for each file: top5 results + overall + empty line - const std::string output_s = GET_REDIRECT_OUTPUT; - // for each file: top5 results + overall + empty line - ASSERT_EQUALS((5 + 1 + 1) * 2LL, cppcheck::count_all_of(output_s, '\n')); - } - - void showtime_top5_summary() { - REDIRECT; - check(2, 2, 0, - "int main() {}", - dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY)); + $.showtime = Settings::ShowTime::TOP5_FILE)); const std::string output_s = GET_REDIRECT_OUTPUT; - // once: top5 results + overall + empty line - ASSERT_EQUALS(5 + 1 + 1, cppcheck::count_all_of(output_s, '\n')); - // should only report the top5 once - ASSERT(output_s.find("1 result(s)") == std::string::npos); - ASSERT(output_s.find("2 result(s)") != std::string::npos); + // for each file: top5 results + check time + ASSERT_EQUALS((5 + 1) * 2LL, cppcheck::count_all_of(output_s, '\n')); } void showtime_file() { @@ -258,21 +260,9 @@ class TestThreadExecutorBase : public TestFixture { check(2, 2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_FILE)); - const std::string output_s = GET_REDIRECT_OUTPUT; - ASSERT_EQUALS(2, cppcheck::count_all_of(output_s, "Overall time:")); - } - - void showtime_summary() { - REDIRECT; // should not cause TSAN failures as the showtime logging is synchronized - check(2, 2, 0, - "int main() {}", - dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY)); + $.showtime = Settings::ShowTime::FILE)); const std::string output_s = GET_REDIRECT_OUTPUT; - // should only report the actual summary once - ASSERT(output_s.find("1 result(s)") == std::string::npos); - ASSERT(output_s.find("2 result(s)") != std::string::npos); + ASSERT_EQUALS(0, cppcheck::count_all_of(output_s, "Overall time:")); } void showtime_file_total() { @@ -280,7 +270,7 @@ class TestThreadExecutorBase : public TestFixture { check(2, 2, 0, "int main() {}", dinit(CheckOptions, - $.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL)); + $.showtime = Settings::ShowTime::FILE_TOTAL)); const std::string output_s = GET_REDIRECT_OUTPUT; ASSERT(output_s.find("Check time: " + fprefix() + "_1.c: ") != std::string::npos); ASSERT(output_s.find("Check time: " + fprefix() + "_2.c: ") != std::string::npos); @@ -314,6 +304,7 @@ class TestThreadExecutorBase : public TestFixture { } // TODO: test whole program analysis +#endif // HAS_THREADING_MODEL_THREAD }; class TestThreadExecutorFiles : public TestThreadExecutorBase { diff --git a/test/testtimer.cpp b/test/testtimer.cpp index 00b3b810bbc..4d5c1c2700c 100644 --- a/test/testtimer.cpp +++ b/test/testtimer.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,28 +17,53 @@ */ #include "fixture.h" +#include "redirect.h" #include "timer.h" -#include -#include +#include class TestTimer : public TestFixture { public: TestTimer() : TestFixture("TestTimer") {} private: - void run() override { TEST_CASE(result); } - void result() const { - TimerResultsData t1; - t1.mClocks = ~static_cast(0); - ASSERT(t1.seconds() > 100.0); + void result() { + REDIRECT; + + TimerResults t1; + t1.addResults("call1", std::chrono::milliseconds{1230}); + t1.addResults("call2", std::chrono::milliseconds{1234}); + t1.addResults("call1", std::chrono::milliseconds{1235}); + t1.addResults("call1", std::chrono::milliseconds{1239}); + + const auto results = t1.getResults(); + ASSERT_EQUALS(2, results.size()); + + auto it = results.find("call1"); + ASSERT(it != results.cend()); + ASSERT_EQUALS(3, it->second.size()); + ASSERT_EQUALS(1230, it->second[0].count()); + ASSERT_EQUALS(1235, it->second[1].count()); + ASSERT_EQUALS(1239, it->second[2].count()); + + it = results.find("call2"); + ASSERT(it != results.cend()); + ASSERT_EQUALS(1, it->second.size()); + ASSERT_EQUALS(1234, it->second[0].count()); + + t1.showResults(); + ASSERT_EQUALS("call1: 3.704s (avg. 1.23467s / min 1.23s / max 1.239s - 3 result(s))\n" + "call2: 1.234s (avg. 1.234s / min 1.234s / max 1.234s - 1 result(s))\n", GET_REDIRECT_OUTPUT); + + t1.showResults(1); + ASSERT_EQUALS("call1: 3.704s (avg. 1.23467s / min 1.23s / max 1.239s - 3 result(s))\n", GET_REDIRECT_OUTPUT); - t1.mClocks = CLOCKS_PER_SEC * 5 / 2; - ASSERT(std::fabs(t1.seconds()-2.5) < 0.01); + t1.showResults(1, false); + ASSERT_EQUALS("call1: 3.704s\n", GET_REDIRECT_OUTPUT); } }; diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 1a94e092ac9..83a514eb963 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,6 +36,11 @@ class TestToken : public TestFixture { TestToken() : TestFixture("TestToken") {} private: + class TokenTest final : public Token + { + friend class TestToken; + }; + const TokenList list{settingsDefault, Standards::Language::C}; std::vector arithmeticalOps; @@ -59,6 +64,7 @@ class TestToken : public TestFixture { TEST_CASE(multiCompare3); // false positive for %or% on code using "|=" TEST_CASE(multiCompare4); TEST_CASE(multiCompare5); + TEST_CASE(multiCompare6); TEST_CASE(charTypes); TEST_CASE(stringTypes); TEST_CASE(getStrLength); @@ -165,15 +171,15 @@ class TestToken : public TestFixture { auto tokensFrontBack = std::make_shared(); Token one(list, std::move(tokensFrontBack)); one.str("one"); - ASSERT_EQUALS(1, Token::multiCompare(&one, "one|two", 0)); + ASSERT_EQUALS(1, TokenTest::multiCompare(&one, "one|two", 0)); } { auto tokensFrontBack = std::make_shared(); Token two(list, std::move(tokensFrontBack)); two.str("two"); - ASSERT_EQUALS(1, Token::multiCompare(&two, "one|two", 0)); - ASSERT_EQUALS(1, Token::multiCompare(&two, "verybig|two|", 0)); + ASSERT_EQUALS(1, TokenTest::multiCompare(&two, "one|two", 0)); + ASSERT_EQUALS(1, TokenTest::multiCompare(&two, "verybig|two|", 0)); } // Test for empty string found @@ -181,45 +187,45 @@ class TestToken : public TestFixture { auto tokensFrontBack = std::make_shared(); Token notfound(list, std::move(tokensFrontBack)); notfound.str("notfound"); - ASSERT_EQUALS(0, Token::multiCompare(¬found, "one|two|", 0)); + ASSERT_EQUALS(0, TokenTest::multiCompare(¬found, "one|two|", 0)); // Test for not found - ASSERT_EQUALS(-1, Token::multiCompare(¬found, "one|two", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(¬found, "one|two", 0)); } { auto tokensFrontBack = std::make_shared(); Token s(list, std::move(tokensFrontBack)); s.str("s"); - ASSERT_EQUALS(-1, Token::multiCompare(&s, "verybig|two", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(&s, "verybig|two", 0)); } { auto tokensFrontBack = std::make_shared(); Token ne(list, std::move(tokensFrontBack)); ne.str("ne"); - ASSERT_EQUALS(-1, Token::multiCompare(&ne, "one|two", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(&ne, "one|two", 0)); } { auto tokensFrontBack = std::make_shared(); Token a(list, std::move(tokensFrontBack)); a.str("a"); - ASSERT_EQUALS(-1, Token::multiCompare(&a, "abc|def", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(&a, "abc|def", 0)); } { auto tokensFrontBack = std::make_shared(); Token abcd(list, std::move(tokensFrontBack)); abcd.str("abcd"); - ASSERT_EQUALS(-1, Token::multiCompare(&abcd, "abc|def", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(&abcd, "abc|def", 0)); } { auto tokensFrontBack = std::make_shared(); Token def(list, std::move(tokensFrontBack)); def.str("default"); - ASSERT_EQUALS(-1, Token::multiCompare(&def, "abc|def", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(&def, "abc|def", 0)); } // %op% @@ -227,15 +233,15 @@ class TestToken : public TestFixture { auto tokensFrontBack = std::make_shared(); Token plus(list, std::move(tokensFrontBack)); plus.str("+"); - ASSERT_EQUALS(1, Token::multiCompare(&plus, "one|%op%", 0)); - ASSERT_EQUALS(1, Token::multiCompare(&plus, "%op%|two", 0)); + ASSERT_EQUALS(1, TokenTest::multiCompare(&plus, "one|%op%", 0)); + ASSERT_EQUALS(1, TokenTest::multiCompare(&plus, "%op%|two", 0)); } { auto tokensFrontBack = std::make_shared(); Token x(list, std::move(tokensFrontBack)); x.str("x"); - ASSERT_EQUALS(-1, Token::multiCompare(&x, "one|%op%", 0)); - ASSERT_EQUALS(-1, Token::multiCompare(&x, "%op%|two", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(&x, "one|%op%", 0)); + ASSERT_EQUALS(-1, TokenTest::multiCompare(&x, "%op%|two", 0)); } } @@ -314,7 +320,18 @@ class TestToken : public TestFixture { auto tokensFrontBack = std::make_shared(); Token tok(list, std::move(tokensFrontBack)); tok.str("||"); - ASSERT_EQUALS(true, Token::multiCompare(&tok, "+|%or%|%oror%", 0) >= 0); + ASSERT_EQUALS(true, TokenTest::multiCompare(&tok, "+|%or%|%oror%", 0) >= 0); + } + + void multiCompare6() const { + { + const SimpleTokenList stl("x %= y;"); + ASSERT_EQUALS(true, Token::Match(stl.front(), "%name% %= %name%")); + } + { + const SimpleTokenList stl("x += y;"); + ASSERT_EQUALS(false, Token::Match(stl.front(), "%name% %= %name%")); + } } void charTypes() const { @@ -705,7 +722,7 @@ class TestToken : public TestFixture { ASSERT(var.tokenize("int a ; int b ;")); // Varid == 0 should throw exception - ASSERT_THROW_INTERNAL_EQUALS((void)Token::Match(var.tokens(), "%type% %varid% ; %type% %name%", 0),INTERNAL,"Internal error. Token::Match called with varid 0. Please report this to Cppcheck developers"); + ASSERT_THROW_INTERNAL_EQUALS((void)Token::Match(var.tokens(), "%type% %varid% ; %type% %name%", 0),INTERNAL,"Internal error. Token::Match called with varid 0."); ASSERT_EQUALS(true, Token::Match(var.tokens(), "%type% %varid% ; %type% %name%", 1)); ASSERT_EQUALS(true, Token::Match(var.tokens(), "%type% %name% ; %type% %varid%", 2)); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 17ab380bb49..5f4d59503e2 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -1,6 +1,6 @@ /* * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2025 Cppcheck team. + * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,14 +39,24 @@ #include +class ErrorLogger; + class TestTokenizer : public TestFixture { public: TestTokenizer() : TestFixture("TestTokenizer") {} private: - const Settings settings0 = settingsBuilder().library("qt.cfg").build(); - const Settings settings1 = settingsBuilder().library("qt.cfg").library("std.cfg").build(); - const Settings settings_windows = settingsBuilder().library("windows.cfg").build(); + const Settings settings1 = settingsBuilder().library("std.cfg").debugwarnings().build(); + const Settings settings2 = settingsBuilder(settings1).cpp(Standards::CPP11).c(Standards::C11).build(); + const Settings settings2_win32a = settingsBuilder(settings2).platform(Platform::Type::Win32A).build(); + const Settings settings2_win32w = settingsBuilder(settings2).platform(Platform::Type::Win32W).build(); + const Settings settings2_win64 = settingsBuilder(settings2).platform(Platform::Type::Win64).build(); + const Settings settings2_unix32 = settingsBuilder(settings2).platform(Platform::Type::Unix32).build(); + const Settings settings2_unix64 = settingsBuilder(settings2).platform(Platform::Type::Unix64).build(); + const Settings settings3 = settingsBuilder().c(Standards::C89).cpp(Standards::CPP03).build(); + const Settings settings_windows = settingsBuilder().library("windows.cfg").debugwarnings().cpp(Standards::CPP11).build(); + const Settings settings_win32a = settingsBuilder(settings_windows).platform(Platform::Type::Win32A).build(); + const Settings settings_win32w = settingsBuilder(settings_windows).platform(Platform::Type::Win32W).build(); void run() override { mNewTemplate = true; @@ -180,6 +190,8 @@ class TestTokenizer : public TestFixture { TEST_CASE(removeParentheses26); // Ticket #8875 a[0](0) TEST_CASE(removeParentheses27); TEST_CASE(removeParentheses28); // #12164 - don't remove parentheses in '(expr1) ? (expr2) : (expr3);' + TEST_CASE(removeParantheses29); // #13735 + TEST_CASE(removeParentheses30); TEST_CASE(tokenize_double); TEST_CASE(tokenize_strings); @@ -274,9 +286,14 @@ class TestTokenizer : public TestFixture { TEST_CASE(functionAttributeListAfter); TEST_CASE(functionAttributeListAfter2); TEST_CASE(cppMaybeUnusedBefore); - TEST_CASE(cppMaybeUnusedAfter); + TEST_CASE(cppMaybeUnusedAfter1); + TEST_CASE(cppMaybeUnusedAfter2); TEST_CASE(cppMaybeUnusedStructuredBinding); + TEST_CASE(attributeAlignasBefore); + TEST_CASE(attributeAlignasAfter); + TEST_CASE(simplifyAlignedStorage); + TEST_CASE(splitTemplateRightAngleBrackets); TEST_CASE(cpp03template1); @@ -418,6 +435,11 @@ class TestTokenizer : public TestFixture { TEST_CASE(astdesignatedinit); TEST_CASE(astrvaluedecl); TEST_CASE(astorkeyword); + TEST_CASE(astenumdecl); + TEST_CASE(astcompound); + TEST_CASE(astfuncdecl); + TEST_CASE(astarrayinit); + TEST_CASE(astbracedinit); TEST_CASE(startOfExecutableScope); @@ -457,6 +479,7 @@ class TestTokenizer : public TestFixture { TEST_CASE(cppKeywordInCSource); TEST_CASE(cppcast); + TEST_CASE(ccast); TEST_CASE(checkHeader1); @@ -504,30 +527,42 @@ class TestTokenizer : public TestFixture { TEST_CASE(dumpFallthrough); TEST_CASE(simplifyRedundantParentheses); + + TEST_CASE(simplifyEnum1); + + TEST_CASE(simplifyEnum2); } + class TokenizerTest final : public Tokenizer + { + friend class TestTokenizer; + public: + TokenizerTest(TokenList tokenList, ErrorLogger &errorLogger) + : Tokenizer(std::move(tokenList), errorLogger) + {} + }; + + struct TokenizeOptions + { + bool expand = true; + bool cpp = true; + }; + #define tokenizeAndStringify(...) tokenizeAndStringify_(__FILE__, __LINE__, __VA_ARGS__) - // TODO: use options template - std::string tokenizeAndStringify_(const char* file, int linenr, const char (&code)[size], bool expand = true, Platform::Type platform = Platform::Type::Native, - bool cpp = true, Standards::cppstd_t cppstd = Standards::CPP11, Standards::cstd_t cstd = Standards::C11) { - const Settings settings = settingsBuilder(settings1).debugwarnings().cpp(cppstd).c(cstd).platform(platform).build(); - + std::string tokenizeAndStringify_(const char* file, int linenr, const char (&code)[size], const TokenizeOptions& opt = make_default_obj{}) { // tokenize.. - SimpleTokenizer tokenizer(settings, *this, cpp); + SimpleTokenizer tokenizer(settings2, *this, opt.cpp); ASSERT_LOC(tokenizer.tokenize(code), file, linenr); if (tokenizer.tokens()) - return tokenizer.tokens()->stringifyList(false, expand, false, true, false, nullptr, nullptr); + return tokenizer.tokens()->stringifyList(false, opt.expand, false, true, false, nullptr, nullptr); return ""; } // TODO: get rid of this std::string tokenizeAndStringify_(const char* file, int linenr, const std::string& code) { - const Settings settings = settingsBuilder(settings1).debugwarnings().cpp(Standards::CPP11).c(Standards::C11).build(); - - // tokenize.. - SimpleTokenizer tokenizer(settings, *this); + SimpleTokenizer tokenizer(settings2, *this); ASSERT_LOC(tokenizer.tokenize(code), file, linenr); if (tokenizer.tokens()) @@ -535,36 +570,20 @@ class TestTokenizer : public TestFixture { return ""; } -#define tokenizeAndStringifyWindows(...) tokenizeAndStringifyWindows_(__FILE__, __LINE__, __VA_ARGS__) template - std::string tokenizeAndStringifyWindows_(const char* file, int linenr, const char (&code)[size], bool expand = true, Platform::Type platform = Platform::Type::Native, bool cpp = true, bool cpp11 = true) { - const Settings settings = settingsBuilder(settings_windows).debugwarnings().cpp(cpp11 ? Standards::CPP11 : Standards::CPP03).platform(platform).build(); - - // tokenize.. - SimpleTokenizer tokenizer(settings, *this, cpp); - ASSERT_LOC(tokenizer.tokenize(code), file, linenr); - - if (tokenizer.tokens()) - return tokenizer.tokens()->stringifyList(false, expand, false, true, false, nullptr, nullptr); - return ""; - } - - template - std::string tokenizeAndStringify_(const char* file, int line, const char (&code)[size], const Settings &settings, bool cpp = true) { + std::string tokenizeAndStringify_(const char* file, int line, const char (&code)[size], const Settings &settings, bool cpp = true, bool expand = true) { // tokenize.. SimpleTokenizer tokenizer(settings, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); if (!tokenizer.tokens()) return ""; - return tokenizer.tokens()->stringifyList(false, true, false, true, false, nullptr, nullptr); + return tokenizer.tokens()->stringifyList(false, expand, false, true, false, nullptr, nullptr); } #define tokenizeDebugListing(...) tokenizeDebugListing_(__FILE__, __LINE__, __VA_ARGS__) template std::string tokenizeDebugListing_(const char* file, int line, const char (&code)[size], bool cpp = true) { - const Settings settings = settingsBuilder(settings0).c(Standards::C89).cpp(Standards::CPP03).build(); - - SimpleTokenizer tokenizer(settings, *this, cpp); + SimpleTokenizer tokenizer(settings3, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); // result.. @@ -582,6 +601,8 @@ class TestTokenizer : public TestFixture { std::vector files; simplecpp::TokenList tokens1(code, files, filename, &outputList); Preprocessor preprocessor(tokens1, settings, *this, Path::identify(tokens1.getFiles()[0], false)); + (void)preprocessor.reportOutput(outputList, true); + ASSERT(preprocessor.loadFiles(files)); std::list directives = preprocessor.createDirectives(); TokenList tokenlist{settings, Path::identify(filename, false)}; @@ -915,10 +936,10 @@ class TestTokenizer : public TestFixture { void validate() { // C++ code in C file - ASSERT_THROW_INTERNAL(tokenizeAndStringify(";using namespace std;",false,Platform::Type::Native,false), SYNTAX); - ASSERT_THROW_INTERNAL(tokenizeAndStringify(";std::map m;",false,Platform::Type::Native,false), SYNTAX); - ASSERT_THROW_INTERNAL(tokenizeAndStringify(";template class X { };",false,Platform::Type::Native,false), SYNTAX); - ASSERT_THROW_INTERNAL(tokenizeAndStringify("int X() {};",false,Platform::Type::Native,false), SYNTAX); + ASSERT_THROW_INTERNAL(tokenizeAndStringify(";using namespace std;",dinit(TokenizeOptions, $.expand = false, $.cpp = false)), SYNTAX); + ASSERT_THROW_INTERNAL(tokenizeAndStringify(";std::map m;",dinit(TokenizeOptions, $.expand = false, $.cpp = false)), SYNTAX); + ASSERT_THROW_INTERNAL(tokenizeAndStringify(";template class X { };",dinit(TokenizeOptions, $.expand = false, $.cpp = false)), SYNTAX); + ASSERT_THROW_INTERNAL(tokenizeAndStringify("int X() {};",dinit(TokenizeOptions, $.expand = false, $.cpp = false)), SYNTAX); { TokenList tokenlist{settings1, Standards::Language::C}; // headers are treated as C files const char code[] = "void foo(int i) { reinterpret_cast(i) };"; @@ -1716,7 +1737,7 @@ class TestTokenizer : public TestFixture { { const char code[] = "extern \"C\" int foo();"; // tokenize.. - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); @@ -1725,7 +1746,7 @@ class TestTokenizer : public TestFixture { { const char code[] = "extern \"C\" { int foo(); }"; // tokenize.. - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); @@ -1734,7 +1755,7 @@ class TestTokenizer : public TestFixture { { const char code[] = "extern \"C++\" int foo();"; // tokenize.. - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); @@ -1743,7 +1764,7 @@ class TestTokenizer : public TestFixture { { const char code[] = "extern \"C++\" { int foo(); }"; // tokenize.. - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); @@ -2002,7 +2023,7 @@ class TestTokenizer : public TestFixture { const char code[] = "struct foo {\n" " void operator delete(void *obj, size_t sz);\n" "}\n"; - const std::string actual(tokenizeAndStringify(code, true, Platform::Type::Win32A)); + const std::string actual(tokenizeAndStringify(code, settings2_win32a)); const char expected[] = "struct foo {\n" "void operatordelete ( void * obj , unsigned long sz ) ;\n" @@ -2156,6 +2177,31 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } + void removeParantheses29() { // Ticket #13735 + static char code[] = "double foo(void)\n" + "{\n" + "return (modf)(12.3, NULL);\n" + "}"; + static const char exp[] = "double foo ( )\n" + "{\n" + "return modf ( 12.3 , NULL ) ;\n" + "}"; + ASSERT_EQUALS(exp, tokenizeAndStringify(code)); + } + + void removeParentheses30() { + static char code[] = "void f (Node *node) {\n" + " if (node->data && (node->provider)->free)\n" + " (node->provider)->free (node);\n" + "}\n"; + static const char exp[] = "void f ( Node * node ) {\n" + "if ( node . data && ( node . provider ) . free ) {\n" + "node . provider . free ( node ) ; }\n" + "}"; + ASSERT_EQUALS(exp, tokenizeAndStringify(code)); + (void) errout_str(); + } + void tokenize_double() { const char code[] = "void f() {\n" " double a = 4.2;\n" @@ -2513,8 +2559,9 @@ class TestTokenizer : public TestFixture { } void vardecl14() { + const Settings s = settingsBuilder(settings1).cpp(Standards::CPP03).build(); const char code[] = "::std::tr1::shared_ptr pNum1, pNum2;\n"; - ASSERT_EQUALS(":: std :: tr1 :: shared_ptr < int > pNum1 ; :: std :: tr1 :: shared_ptr < int > pNum2 ;", tokenizeAndStringify(code, false, Platform::Type::Native, true, Standards::CPP03)); + ASSERT_EQUALS(":: std :: tr1 :: shared_ptr < int > pNum1 ; :: std :: tr1 :: shared_ptr < int > pNum2 ;", tokenizeAndStringify(code, s, true, false)); } void vardecl15() { @@ -2724,7 +2771,7 @@ class TestTokenizer : public TestFixture { void vardecl26() { // #5907 const char code[] = "extern int *new, obj, player;"; const char expected[] = "extern int * new ; extern int obj ; extern int player ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Type::Native, false)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); ASSERT_EQUALS(expected, tokenizeAndStringify(code)); ASSERT_EQUALS("[test.cpp:1:13]: (debug) Scope::checkVariable found variable 'new' with varid 0. [varid0]\n", errout_str()); } @@ -2736,7 +2783,7 @@ class TestTokenizer : public TestFixture { " return 0;\n" " return 0;\n" "}"; - (void)tokenizeAndStringify(code, /*expand=*/ true, Platform::Type::Native, false); + (void)tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false)); } void vardecl28() { @@ -2748,7 +2795,7 @@ class TestTokenizer : public TestFixture { "const unsigned short x ; x = 1 ;\n" "return x ;\n" "}", - tokenizeAndStringify(code, /*expand=*/ true, Platform::Type::Native, false)); + tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } void vardecl29() { // #9282 @@ -2772,9 +2819,9 @@ class TestTokenizer : public TestFixture { void vardecl30() { const char code[] = "struct D {} const d;"; ASSERT_EQUALS("struct D { } ; struct D const d ;", - tokenizeAndStringify(code, true, Platform::Type::Native, true)); + tokenizeAndStringify(code)); ASSERT_EQUALS("struct D { } ; struct D const d ;", - tokenizeAndStringify(code, true, Platform::Type::Native, false)); + tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } void vardecl31() { @@ -2792,21 +2839,21 @@ class TestTokenizer : public TestFixture { void vardecl32() { { const char code[] = "static enum { E } f() { return E; }"; - ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 f ( ) { return E ; }", tokenizeAndStringify(code, true, Platform::Type::Native, false)); + ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 f ( ) { return E ; }", tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } } void vardecl33() { { const char code[] = "static enum { E } *f() { return NULL; }"; - ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 * f ( ) { return NULL ; }", tokenizeAndStringify(code, true, Platform::Type::Native, false)); + ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 * f ( ) { return NULL ; }", tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } } void vardecl34() { { const char code[] = "static enum { E } const *f() { return NULL; }"; - ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 const * f ( ) { return NULL ; }", tokenizeAndStringify(code, true, Platform::Type::Native, false)); + ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 const * f ( ) { return NULL ; }", tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } } @@ -2873,15 +2920,15 @@ class TestTokenizer : public TestFixture { } void implicitIntConst() { - ASSERT_EQUALS("const int x ;", tokenizeAndStringify("const x;", true, Platform::Type::Native, false)); - ASSERT_EQUALS("const int * x ;", tokenizeAndStringify("const *x;", true, Platform::Type::Native, false)); - ASSERT_EQUALS("const int * f ( ) ;", tokenizeAndStringify("const *f();", true, Platform::Type::Native, false)); + ASSERT_EQUALS("const int x ;", tokenizeAndStringify("const x;", dinit(TokenizeOptions, $.cpp = false))); + ASSERT_EQUALS("const int * x ;", tokenizeAndStringify("const *x;", dinit(TokenizeOptions, $.cpp = false))); + ASSERT_EQUALS("const int * f ( ) ;", tokenizeAndStringify("const *f();", dinit(TokenizeOptions, $.cpp = false))); } void implicitIntExtern() { - ASSERT_EQUALS("extern int x ;", tokenizeAndStringify("extern x;", true, Platform::Type::Native, false)); - ASSERT_EQUALS("extern int * x ;", tokenizeAndStringify("extern *x;", true, Platform::Type::Native, false)); - ASSERT_EQUALS("const int * f ( ) ;", tokenizeAndStringify("const *f();", true, Platform::Type::Native, false)); + ASSERT_EQUALS("extern int x ;", tokenizeAndStringify("extern x;", dinit(TokenizeOptions, $.cpp = false))); + ASSERT_EQUALS("extern int * x ;", tokenizeAndStringify("extern *x;", dinit(TokenizeOptions, $.cpp = false))); + ASSERT_EQUALS("const int * f ( ) ;", tokenizeAndStringify("const *f();", dinit(TokenizeOptions, $.cpp = false))); } /** @@ -3115,27 +3162,27 @@ class TestTokenizer : public TestFixture { { const char code[] = "float complex x;"; const char expected[] = "_Complex float x ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Native, false)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } { const char code[] = "complex float x;"; const char expected[] = "_Complex float x ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Native, false)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } { const char code[] = "complex long double x;"; const char expected[] = "_Complex long double x ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Native, false)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } { const char code[] = "long double complex x;"; const char expected[] = "_Complex long double x ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Native, false)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } { const char code[] = "double complex;"; const char expected[] = "double complex ;"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Native, false)); + ASSERT_EQUALS(expected, tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } } @@ -3144,7 +3191,7 @@ class TestTokenizer : public TestFixture { const char code[] = "class A{\n" " void f() {}\n" "};"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); // A body {} @@ -3167,7 +3214,7 @@ class TestTokenizer : public TestFixture { " char a[10];\n" " char *b ; b = new char[a[0]];\n" "};"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); // a[10] @@ -3189,7 +3236,7 @@ class TestTokenizer : public TestFixture { const char code[] = "void f(){\n" " foo(g());\n" "};"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); // foo( @@ -3207,7 +3254,7 @@ class TestTokenizer : public TestFixture { const char code[] = "bool foo(C a, bar>& f, int b) {\n" " return(af);\n" "}"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); // template< @@ -3233,7 +3280,7 @@ class TestTokenizer : public TestFixture { const char code[] = "void foo() {\n" " return static_cast(a);\n" "}"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3248,7 +3295,7 @@ class TestTokenizer : public TestFixture { const char code[] = "void foo() {\n" " nvwa<(x > y)> ERROR_nnn;\n" "}"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3262,7 +3309,7 @@ class TestTokenizer : public TestFixture { { // #4860 const char code[] = "class A : public B {};"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3276,7 +3323,7 @@ class TestTokenizer : public TestFixture { { // #4860 const char code[] = "Bar>>>::set(1, 2, 3);"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3291,7 +3338,7 @@ class TestTokenizer : public TestFixture { { // #5627 const char code[] = "new Foo[10];"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3305,7 +3352,7 @@ class TestTokenizer : public TestFixture { { // #6242 const char code[] = "func = integral_;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3318,7 +3365,7 @@ class TestTokenizer : public TestFixture { { // if (a < b || c > d) { } const char code[] = "{ if (a < b || c > d); }"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3328,7 +3375,7 @@ class TestTokenizer : public TestFixture { { // bool f = a < b || c > d const char code[] = "bool f = a < b || c > d;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3338,7 +3385,7 @@ class TestTokenizer : public TestFixture { { // template const char code[] = "a < b || c > d;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3348,7 +3395,7 @@ class TestTokenizer : public TestFixture { { // if (a < ... > d) { } const char code[] = "{ if (a < b || c == 3 || d > e); }"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3358,7 +3405,7 @@ class TestTokenizer : public TestFixture { { // template const char code[] = "a d;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(7)); @@ -3367,7 +3414,7 @@ class TestTokenizer : public TestFixture { { // template const char code[] = "a d;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(7)); @@ -3375,7 +3422,7 @@ class TestTokenizer : public TestFixture { { const char code[] = "template < f = b || c > struct S;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(7)); @@ -3384,7 +3431,7 @@ class TestTokenizer : public TestFixture { { const char code[] = "struct A : B {};"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(4) == tok->tokAt(8)); @@ -3393,7 +3440,7 @@ class TestTokenizer : public TestFixture { { const char code[] = "Data;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(4)); @@ -3403,7 +3450,7 @@ class TestTokenizer : public TestFixture { { // #6601 const char code[] = "template struct FuncType : FuncType { };"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = tokenizer.tokens(); @@ -3421,7 +3468,7 @@ class TestTokenizer : public TestFixture { { // #7158 const char code[] = "enum { value = boost::mpl::at_c };"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok = Token::findsimplematch(tokenizer.tokens(), "<"); ASSERT_EQUALS(true, tok->link() == tok->tokAt(4)); @@ -3433,7 +3480,7 @@ class TestTokenizer : public TestFixture { const char code[] = "template \n" "struct CheckedDivOp< T, U, typename std::enable_if::value || std::is_floating_point::value>::type> {\n" "};\n"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "struct")->tokAt(2); const Token *tok2 = Token::findsimplematch(tokenizer.tokens(), "{")->previous(); @@ -3444,7 +3491,7 @@ class TestTokenizer : public TestFixture { { // #7975 const char code[] = "template X copy() {};\n"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "< Y"); const Token *tok2 = Token::findsimplematch(tok1, "> copy"); @@ -3455,7 +3502,7 @@ class TestTokenizer : public TestFixture { { // #8006 const char code[] = "C && a = b;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok1 = tokenizer.tokens()->next(); const Token *tok2 = tok1->tokAt(2); @@ -3466,7 +3513,7 @@ class TestTokenizer : public TestFixture { { // #8115 const char code[] = "void Test(C && c);"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "<"); const Token *tok2 = tok1->tokAt(2); @@ -3477,7 +3524,7 @@ class TestTokenizer : public TestFixture { // #8654 const char code[] = "template struct A {}; " "template struct foo : A... {};"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *A = Token::findsimplematch(tokenizer.tokens(), "A <"); ASSERT_EQUALS(true, A->linkAt(1) == A->tokAt(3)); @@ -3486,7 +3533,7 @@ class TestTokenizer : public TestFixture { // #8851 const char code[] = "template::type>" "void basic_json() {}"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT_EQUALS(true, Token::simpleMatch(tokenizer.tokens()->linkAt(1), "> void")); } @@ -3494,7 +3541,7 @@ class TestTokenizer : public TestFixture { { // #9094 - template usage or comparison? const char code[] = "a = f(x%x<--a==x>x);"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr == Token::findsimplematch(tokenizer.tokens(), "<")->link()); } @@ -3504,7 +3551,7 @@ class TestTokenizer : public TestFixture { const char code[] = "using std::same_as;\n" "template T>\n" "void f();"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "template <"); const Token *tok2 = Token ::findsimplematch(tokenizer.tokens(), "same_as <"); @@ -3515,7 +3562,7 @@ class TestTokenizer : public TestFixture { { // #9131 - template usage or comparison? const char code[] = "using std::list; list l;"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "<")->link()); } @@ -3526,7 +3573,7 @@ class TestTokenizer : public TestFixture { "{\n" " for (set::iterator i = sources.begin(); i != sources.end(); ++i) {}\n" "}"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "<")->link()); } @@ -3537,7 +3584,7 @@ class TestTokenizer : public TestFixture { " a<> b;\n" " b.a<>::c();\n" "}\n"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> ::")->link()); } @@ -3548,7 +3595,7 @@ class TestTokenizer : public TestFixture { "template struct c {\n" " void d() { a[0]; }\n" "};\n"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> [")->link()); } @@ -3560,7 +3607,7 @@ class TestTokenizer : public TestFixture { "template using f = c;\n" "template > struct g {};\n" "template using baz = g;\n"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> ;")->link()); } @@ -3574,7 +3621,7 @@ class TestTokenizer : public TestFixture { "template using c = a;\n" "template c e;\n" "auto f = -e<1> == 0;\n"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> ==")->link()); } @@ -3592,7 +3639,7 @@ class TestTokenizer : public TestFixture { "constexpr void b::operator()(c &&) const {\n" " i<3>.f([] {});\n" "}\n"; - SimpleTokenizer tokenizer(settings0, *this); + SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> . f (")->link()); } @@ -3600,7 +3647,7 @@ class TestTokenizer : public TestFixture { { // #10491 const char code[] = "template