diff --git a/.astylerc b/.astylerc deleted file mode 100755 index 450a57322f0..00000000000 --- a/.astylerc +++ /dev/null @@ -1,20 +0,0 @@ -############################################################## -# Documentation is available from # -# http://astyle.sourceforge.net/astyle.html # -############################################################## - -### Options ### ---pad-header ---unpad-paren ---suffix=none ---convert-tabs ---attach-inlines ---attach-classes ---attach-namespaces - -### Settings ### ---style=kr ---indent=spaces=4 ---indent-namespaces ---lineend=linux ---min-conditional-indent=0 diff --git a/.clang-tidy b/.clang-tidy index 37a4ae0a275..62047bd3966 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,79 @@ --- -Checks: '*,-abseil-*,-altera-*,-android-*,-cert-*,-cppcoreguidelines-*,-fuchsia-*,-google-*,-hicpp-*,-linuxkernel-*,-llvm-*,-llvmlibc-*,-mpi-*,-objc-*,-openmp-*,-zircon-*,-readability-braces-around-statements,-readability-magic-numbers,-bugprone-macro-parentheses,-readability-isolate-declaration,-readability-function-size,-modernize-use-trailing-return-type,-readability-implicit-bool-conversion,-readability-uppercase-literal-suffix,-modernize-use-auto,-readability-else-after-return,-modernize-use-default-member-init,-readability-named-parameter,-readability-redundant-member-init,-performance-faster-string-find,-modernize-avoid-c-arrays,-modernize-use-equals-default,-readability-container-size-empty,-readability-simplify-boolean-expr,-modernize-use-override,-modernize-pass-by-value,-bugprone-branch-clone,-bugprone-narrowing-conversions,-modernize-raw-string-literal,-readability-convert-member-functions-to-static,-modernize-loop-convert,-misc-unused-using-decls,-modernize-use-emplace,-readability-const-return-type,-performance-unnecessary-value-param,-modernize-return-braced-init-list,-performance-inefficient-string-concatenation,-performance-for-range-copy,-misc-throw-by-value-catch-by-reference,-readability-avoid-const-params-in-decls,-readability-non-const-parameter,-misc-non-private-member-variables-in-classes,-bugprone-suspicious-string-compare,-readability-misleading-indentation,-clang-analyzer-*,-bugprone-signed-char-misuse,-readability-make-member-function-const,-misc-no-recursion,-readability-use-anyofallof,-performance-no-automatic-move,-bugprone-suspicious-include,-modernize-replace-random-shuffle,-readability-function-cognitive-complexity,-readability-redundant-access-specifiers,-modernize-use-equals-delete,-performance-noexcept-move-constructor,-concurrency-mt-unsafe' +Checks: > + *, + -abseil-*, + -altera-*, + -android-*, + -boost-*, + -cert-*, + -cppcoreguidelines-*, + -darwin-*, + -fuchsia-*, + -google-*, + -hicpp-*, + -linuxkernel-*, + -llvm-*, + -llvmlibc-*, + -mpi-*, + -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-easily-swappable-parameters, + -bugprone-empty-catch, + -bugprone-macro-parentheses, + -bugprone-narrowing-conversions, + -bugprone-signed-char-misuse, + -bugprone-switch-missing-default-case, + -bugprone-unchecked-optional-access, + -clang-analyzer-*, + -concurrency-mt-unsafe, + -misc-const-correctness, + -misc-no-recursion, + -misc-non-private-member-variables-in-classes, + -misc-throw-by-value-catch-by-reference, + -misc-use-anonymous-namespace, + -modernize-avoid-c-arrays, + -modernize-deprecated-ios-base-aliases, + -misc-include-cleaner, + -misc-unused-using-decls, + -modernize-loop-convert, + -modernize-macro-to-enum, + -modernize-raw-string-literal, + -modernize-replace-auto-ptr, + -modernize-return-braced-init-list, + -modernize-type-traits, + -modernize-use-designated-initializers, + -modernize-use-nodiscard, + -modernize-use-trailing-return-type, + -performance-avoid-endl, + -performance-inefficient-string-concatenation, + -performance-no-automatic-move, + -portability-simd-intrinsics, + -portability-std-allocator-const, + -readability-avoid-nested-conditional-operator, + -readability-braces-around-statements, + -readability-container-data-pointer, + -readability-enum-initial-value, + -readability-function-cognitive-complexity, + -readability-function-size, + -readability-identifier-length, + -readability-identifier-naming, + -readability-implicit-bool-conversion, + -readability-isolate-declaration, + -readability-magic-numbers, + -readability-suspicious-call-argument, + -readability-uppercase-literal-suffix WarningsAsErrors: '*' +HeaderFilterRegex: '(cli|gui|frontend|lib|oss-fuzz|test|triage)\/[a-z_]+\.h' +ExcludeHeaderFilterRegex: 'ui_.*.h' CheckOptions: - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic - value: '1' \ No newline at end of file + value: '1' + - key: readability-simplify-boolean-expr.SimplifyDeMorgan + value: '0' diff --git a/.codacy.yml b/.codacy.yml index 855f04b6e54..dcfec8e5c10 100644 --- a/.codacy.yml +++ b/.codacy.yml @@ -4,7 +4,5 @@ exclude_paths: - htmlreport/example.cc - samples/**/bad.c - samples/**/bad.cpp - - test/test.cxx - test/cfg/*.c - test/cfg/*.cpp - - test/synthetic/*.c diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..ed782473718 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +## standard default enconding +* text=auto + +## UNIX specific files +*.sh text eol=lf + +## Windows specific files +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +*.vcxproj text eol=crlf +*.vcxproj.filters text eol=crlf +*.sln text eol=crlf +*.wixproj text eol=crlf +*.wxi text eol=crlf +*.wxs text eol=crlf + +## Binary resources +*.pdf binary \ No newline at end of file diff --git a/.github/workflows/CI-cygwin.yml b/.github/workflows/CI-cygwin.yml index 71617f00792..93a77d70c33 100644 --- a/.github/workflows/CI-cygwin.yml +++ b/.github/workflows/CI-cygwin.yml @@ -1,41 +1,61 @@ -# Some convenient links: -# - https://github.com/actions/virtual-environments/blob/master/images/win/Windows2019-Readme.md -# - +# 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: CI-cygwin -on: [push,pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read defaults: run: shell: cmd jobs: + # TODO: add CMake build build_cygwin: strategy: matrix: - os: [windows-2019] - arch: [x64, x86] - fail-fast: true + # only use the latest windows-* as the installed toolchain is identical + os: [windows-2025] + platform: [x86_64] + include: + - platform: 'x86_64' + packages: | + gcc-g++ + python3 + fail-fast: false runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Set up Cygwin - uses: egor-tensin/setup-cygwin@v3 + uses: cygwin/cygwin-install-action@master with: - platform: ${{ matrix.arch }} + platform: ${{ matrix.platform }} + packages: ${{ matrix.packages }} - - name: Build cppcheck + # Cygwin will always link the binaries even if they already exist. The linking is also extremely slow. So just run the "check" target which includes all the binaries. + - name: Build all and run test run: | - C:\tools\cygwin\bin\bash.exe -l -c cd %GITHUB_WORKSPACE% && make -j2 + C:\cygwin\bin\bash.exe -l -c cd %GITHUB_WORKSPACE% && make VERBOSE=1 -j%NUMBER_OF_PROCESSORS% check - - name: Build test + - name: Extra test for misra run: | - C:\tools\cygwin\bin\bash.exe -l -c cd %GITHUB_WORKSPACE% && make -j2 testrunner + cd %GITHUB_WORKSPACE%\addons\test + ..\..\cppcheck.exe --dump -DDUMMY --suppress=uninitvar --inline-suppr misra\misra-test.c --std=c89 --platform=unix64 + python3 ..\misra.py -verify misra\misra-test.c.dump + ..\..\cppcheck.exe --addon=misra --enable=style --inline-suppr --enable=information --error-exitcode=1 misra\misra-ctu-1-test.c misra\misra-ctu-2-test.c - - name: Run test - run: | - C:\tools\cygwin\bin\bash.exe -l -c cd %GITHUB_WORKSPACE% && make -j2 check diff --git a/.github/workflows/CI-mingw.yml b/.github/workflows/CI-mingw.yml new file mode 100644 index 00000000000..a8c27b17224 --- /dev/null +++ b/.github/workflows/CI-mingw.yml @@ -0,0 +1,79 @@ +# 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: CI-mingw + +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read + +defaults: + run: + shell: msys2 {0} + +jobs: + # TODO: add CMake build + build_mingw: + strategy: + matrix: + # only use the latest windows-* as the installed toolchain is identical + os: [windows-2025] + fail-fast: false + + runs-on: ${{ matrix.os }} + + timeout-minutes: 19 # max + 3*std of the last 7K runs + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Set up MSYS2 + uses: msys2/setup-msys2@v2 + with: + release: false # use pre-installed + # TODO: install mingw-w64-x86_64-make and use mingw32.make instead - currently fails with "Windows Subsystem for Linux has no installed distributions." + install: >- + mingw-w64-x86_64-lld + mingw-w64-x86_64-ccache + make + mingw-w64-x86_64-gcc + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }} + + # TODO: bail out on warning + - name: Build cppcheck + run: | + export PATH="/mingw64/lib/ccache/bin:$PATH" + # set RDYNAMIC to work around broken MinGW detection + make VERBOSE=1 RDYNAMIC=-lshlwapi -j$(nproc) cppcheck + env: + LDFLAGS: -fuse-ld=lld # use lld for faster linking + + - name: Build test + run: | + export PATH="/mingw64/lib/ccache/bin:$PATH" + # set RDYNAMIC to work around broken MinGW detection + make VERBOSE=1 RDYNAMIC=-lshlwapi -j$(nproc) testrunner + env: + LDFLAGS: -fuse-ld=lld # use lld for faster linking + + - name: Run test + run: | + export PATH="/mingw64/lib/ccache/bin:$PATH" + # set RDYNAMIC to work around broken MinGW detection + make VERBOSE=1 RDYNAMIC=-lshlwapi -j$(nproc) check + env: + LDFLAGS: -fuse-ld=lld # use lld for faster linking diff --git a/.github/workflows/CI-unixish-docker.yml b/.github/workflows/CI-unixish-docker.yml index 9c74ad08acf..f8a74b4d8f7 100644 --- a/.github/workflows/CI-unixish-docker.yml +++ b/.github/workflows/CI-unixish-docker.yml @@ -2,73 +2,134 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: CI-unixish-docker -on: [push, pull_request] - +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read + jobs: - build: + build_cmake: strategy: matrix: - image: ["centos:7", "ubuntu:14.04", "ubuntu:16.04", "ubuntu:21.04"] + image: ["ubuntu:24.04", "ubuntu:24.10"] + include: + - build_gui: false + - image: "ubuntu:24.04" + build_gui: true + - image: "ubuntu:24.10" + build_gui: true fail-fast: false # Prefer quick result - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 + + # TODO: is this actually applied to the guest? + env: + # TODO: figure out why there are cache misses with PCH enabled + CCACHE_SLOPPINESS: pch_defines,time_macros container: image: ${{ matrix.image }} steps: - - uses: actions/checkout@v2 - - - name: Install missing software on CentOS 7 - if: matrix.image == 'centos:7' - run: | - yum install -y cmake gcc-c++ make - yum install -y pcre-devel + - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Install missing software on ubuntu - if: matrix.image != 'centos:7' + if: contains(matrix.image, 'ubuntu') run: | apt-get update - apt-get install -y cmake g++ make python libxml2-utils - apt-get install -y libpcre3-dev + apt-get install -y cmake g++ make libxml2-utils libpcre3-dev - # tests require CMake 3.4 - - name: Test CMake build (no tests) - if: matrix.image != 'ubuntu:21.04' + - name: Install missing software (gui) on latest ubuntu + if: matrix.build_gui run: | - mkdir cmake.output - cd cmake.output - cmake -G "Unix Makefiles" -DHAVE_RULES=On .. - make -j$(nproc) - cd .. + apt-get install -y qt6-base-dev qt6-charts-dev qt6-tools-dev + + # needs to be called after the package installation since + # - it doesn't call "apt-get update" + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ matrix.image }} - - name: Test CMake build - if: matrix.image == 'ubuntu:21.04' + - name: CMake build + if: ${{ !matrix.build_gui }} run: | mkdir cmake.output cd cmake.output - cmake -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On .. - make -j$(nproc) check - cd .. + cmake -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. + cmake --build . -- -j$(nproc) + + - name: CMake build (with GUI) + if: matrix.build_gui + 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_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build cmake.output -- -j$(nproc) + + - name: Run CMake test + run: | + cmake --build cmake.output --target check -- -j$(nproc) + + build_make: + + strategy: + matrix: + image: ["ubuntu:24.04", "ubuntu:24.10"] + fail-fast: false # Prefer quick result + + runs-on: ubuntu-22.04 + + container: + image: ${{ matrix.image }} + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install missing software on ubuntu + if: contains(matrix.image, 'ubuntu') + run: | + apt-get update + apt-get install -y g++ make python3 libxml2-utils libpcre3-dev + + # needs to be called after the package installation since + # - it doesn't call "apt-get update" + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ matrix.image }} - name: Build cppcheck run: | - make clean - make -j$(nproc) HAVE_RULES=yes + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) HAVE_RULES=yes CXXFLAGS="-w" - name: Build test run: | - make -j$(nproc) testrunner HAVE_RULES=yes + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) testrunner HAVE_RULES=yes CXXFLAGS="-w" - name: Run test run: | make -j$(nproc) check HAVE_RULES=yes + # requires python3 - name: Run extra tests run: | - tools/generate_and_run_more_tests.sh + test/scripts/generate_and_run_more_tests.sh + # requires which - name: Validate run: | make -j$(nproc) checkCWEEntries validateXML diff --git a/.github/workflows/CI-unixish.yml b/.github/workflows/CI-unixish.yml index b92457164bd..9b720b95b4a 100644 --- a/.github/workflows/CI-unixish.yml +++ b/.github/workflows/CI-unixish.yml @@ -2,115 +2,443 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: CI-unixish -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: - build: + build_cmake_tinyxml2: strategy: matrix: - os: [ubuntu-18.04, ubuntu-20.04, macos-10.15] + os: [ubuntu-22.04, macos-13, macos-15] 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@v2 + - uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Set up Python 3.9 - uses: actions/setup-python@v2 + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 with: - python-version: 3.9 + key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }} - - name: Install missing software on ubuntu 18.04 - if: matrix.os == 'ubuntu-18.04' + - name: Install missing software on ubuntu + if: contains(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install libxml2-utils - sudo apt-get install z3 libz3-dev - cp externals/z3_version_old.h externals/z3_version.h + sudo apt-get install libxml2-utils libtinyxml2-dev + # 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 tinyxml2 pcre - - name: Install missing software on ubuntu 20.04 - if: matrix.os == 'ubuntu-20.04' + - 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_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_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) + run: | + cmake --build cmake.output.tinyxml2 --target check -- -j$(nproc) + + build_cmake: + + strategy: + matrix: + os: [ubuntu-22.04, macos-13, macos-15] + 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 }} + + # TODO: move latest compiler to separate step + # TODO: bail out on warnings with latest GCC + - name: Set up GCC + uses: egor-tensin/setup-gcc@v1 + if: false # matrix.os == 'ubuntu-22.04' + with: + version: 13 + platform: x64 + + - name: Select compiler + if: false # matrix.os == 'ubuntu-22.04' + run: | + echo "CXX=g++-13" >> $GITHUB_ENV + + - name: Install missing software on ubuntu + if: contains(matrix.os, 'ubuntu') run: | sudo apt-get update sudo apt-get install libxml2-utils - sudo apt-get install z3 libz3-dev + # 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: | - brew install coreutils z3 - cp externals/z3_version_old.h externals/z3_version.h + # pcre was removed from runner images in November 2022 + brew install coreutils qt@6 pcre - - name: Install missing Python packages - run: | - python -m pip install pip --upgrade - python -m pip install pytest - - - name: Install Qt + - name: Run CMake on ubuntu (with GUI) if: contains(matrix.os, 'ubuntu') - uses: jurplel/install-qt-action@v2 + run: | + cmake -S . -B cmake.output -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install + + - name: Run CMake on macos (with GUI) + if: contains(matrix.os, 'macos') + run: | + cmake -S . -B cmake.output -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DBUILD_TRIAGE=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=cppcheck-cmake-install -DQt6_DIR=$(brew --prefix qt@6)/lib/cmake/Qt6 + + - name: Run CMake build + run: | + cmake --build cmake.output -- -j$(nproc) + + - name: Run CMake test + run: | + cmake --build cmake.output --target check -- -j$(nproc) + + - name: Run CTest + run: | + pushd cmake.output + ctest --output-on-failure -j$(nproc) + + - name: Run CMake install + run: | + cmake --build cmake.output --target install + + build_uchar: + + strategy: + matrix: + os: [ubuntu-22.04, macos-13, macos-15] + fail-fast: false # Prefer quick result + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 with: - modules: 'qtcharts' + persist-credentials: false - - name: Test CMake build + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }} + + # coreutils contains "nproc" + - name: Install missing software on macos + if: contains(matrix.os, 'macos') run: | - mkdir cmake.output - cd cmake.output - cmake -G "Unix Makefiles" -DUSE_Z3=On -DHAVE_RULES=On -DBUILD_TESTS=On .. - make -j$(nproc) check - cd .. + brew install coreutils - - name: Build and test with Unsigned char + - name: Build with Unsigned char run: | - make clean + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" make -j$(nproc) CXXFLAGS=-funsigned-char testrunner + + - name: Test with Unsigned char + run: | ./testrunner TestSymbolDatabase + build_mathlib: + + strategy: + matrix: + os: [ubuntu-22.04, macos-13, macos-15] + fail-fast: false # Prefer quick result + + runs-on: ${{ matrix.os }} + + 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 }} + + # coreutils contains "nproc" + - name: Install missing software on macos + if: contains(matrix.os, 'macos') + run: | + brew install coreutils + + - name: Build with TEST_MATHLIB_VALUE + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) CPPFLAGS=-DTEST_MATHLIB_VALUE all + + - name: Test with TEST_MATHLIB_VALUE + run: | + make -j$(nproc) CPPFLAGS=-DTEST_MATHLIB_VALUE check + + check_nonneg: + + strategy: + matrix: + os: [ubuntu-22.04, macos-13, macos-15] + fail-fast: false # Prefer quick result + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + # coreutils contains "g++" (default is "c++") and "nproc" + - name: Install missing software on macos + if: contains(matrix.os, 'macos') + run: | + brew install coreutils + - name: Check syntax with NONNEG run: | ls lib/*.cpp | xargs -n 1 -P $(nproc) g++ -fsyntax-only -std=c++0x -Ilib -Iexternals -Iexternals/picojson -Iexternals/simplecpp -Iexternals/tinyxml2 -DNONNEG + build_cmake_boost: + + strategy: + matrix: + os: [macos-13, macos-15] # non-macos platforms are already built with Boost in other contexts + 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 }} + + - name: Run CMake on macOS (force Boost) + 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 + exit 1 + else + exit 0 + fi + + # coreutils contains "nproc" + - name: Install missing software on macOS + run: | + brew install coreutils boost + + - name: Run CMake on macOS (force Boost) + run: | + cmake -S . -B cmake.output.boost-force -G "Unix Makefiles" -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 + if grep -q '\-DHAVE_BOOST' ./cmake.output.boost-no/compile_commands.json; then + exit 1 + else + exit 0 + fi + + - 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_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: + + strategy: + matrix: + os: [ubuntu-22.04, macos-13, macos-15] + include: + - xdist_n: auto + # FIXME: test_color_tty fails with xdist + - os: macos-13 + xdist_n: '1' + fail-fast: false # Prefer quick result + + runs-on: ${{ matrix.os }} + + 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: Install missing software on ubuntu + if: contains(matrix.os, 'ubuntu') + run: | + sudo apt-get update + sudo apt-get install libxml2-utils + + # packages for strict cfg checks + - name: Install missing software on ubuntu 22.04 (cfg) + if: matrix.os == 'ubuntu-22.04' + run: | + sudo apt-get install libcairo2-dev libcurl4-openssl-dev liblua5.3-dev libssl-dev libsqlite3-dev libcppunit-dev libsigc++-2.0-dev libgtk-3-dev libboost-all-dev libselinux-dev libwxgtk3.0-gtk3-dev xmlstarlet qtbase5-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 pcre gnu-sed + + - name: Install missing Python packages on ubuntu + if: contains(matrix.os, 'ubuntu') + 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 + + # we need to use -break-system-packages --user because the common approaches do not work. + # using pip works but it appears to install the packages into a different Python installation so they are not found later on. + # using python3 -m pip without the additional flags fails since the packages are being managed by a different tool (brew) and that lacks some of the packages. + # using pipx also does not work. + - name: Install missing Python packages on macos + if: contains(matrix.os, 'macos') + run: | + python3 -m pip install --break-system-packages --user pip --upgrade + python3 -m pip install --break-system-packages --user pytest + python3 -m pip install --break-system-packages --user pytest-timeout + python3 -m pip install --break-system-packages --user pytest-xdist + python3 -m pip install --break-system-packages --user psutil + - name: Build cppcheck run: | - make clean - make -j$(nproc) USE_Z3=yes HAVE_RULES=yes + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) HAVE_RULES=yes - name: Build test run: | - make -j$(nproc) testrunner USE_Z3=yes HAVE_RULES=yes + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) testrunner HAVE_RULES=yes - name: Run test run: | - make -j$(nproc) check USE_Z3=yes HAVE_RULES=yes + make -j$(nproc) check HAVE_RULES=yes - # the script uses sed parameters not supported by MacOS + # requires "gnu-sed" installed on macos - name: Run extra tests - if: contains(matrix.os, 'ubuntu') run: | - tools/generate_and_run_more_tests.sh + test/scripts/generate_and_run_more_tests.sh - name: Run test/cli run: | - cd test/cli - pytest test-*.py - cd ../../.. + python3 -m pytest -Werror --strict-markers -vv -n ${{ matrix.xdist_n }} test/cli + + # TODO: use the step below instead + # do not use pushd in this step since we go below the working directory + - name: Run test/cli (symlink) + run: | + cd .. ln -s cppcheck 'cpp check' cd 'cpp check/test/cli' - pytest test-*.py + python3 -m pytest -Werror --strict-markers -vv -n ${{ matrix.xdist_n }} + + # FIXME: proj2_test.py fails because of the relative path cleanups in ImportProject::setRelativePaths() + # It fails because the application path used as base path has its symlink resolved by getcwd(). + - name: Run test/cli (symlink) + if: false + run: | + ln -s . 'cpp check' + python3 -m pytest -Werror --strict-markers -vv -n ${{ matrix.xdist_n }} 'cpp check/test/cli' + + - name: Run test/cli (-j2) + run: | + python3 -m pytest -Werror --strict-markers -vv -n ${{ matrix.xdist_n }} test/cli + env: + TEST_CPPCHECK_INJECT_J: 2 + + - name: Run test/cli (--clang) + if: false + run: | + python3 -m pytest -Werror --strict-markers -vv -n ${{ matrix.xdist_n }} test/cli + env: + TEST_CPPCHECK_INJECT_CLANG: clang + + - name: Run test/cli (--cppcheck-build-dir) + run: | + python3 -m pytest -Werror --strict-markers -vv -n ${{ matrix.xdist_n }} test/cli + env: + TEST_CPPCHECK_INJECT_BUILDDIR: injected - # fails on macos since some includes (e.g. sys/epoll.h) are not available - name: Run cfg tests - if: contains(matrix.os, 'ubuntu') + if: matrix.os != 'ubuntu-22.04' run: | make -j$(nproc) checkcfg - # it seems macos has no "wc" command - - name: Run showtimetop5 tests - if: contains(matrix.os, 'ubuntu') + - name: Run cfg tests (strict) + if: matrix.os == 'ubuntu-22.04' run: | - ./tools/test_showtimetop5.sh + make -j$(nproc) checkcfg + env: + STRICT: 1 - name: Run --dump test run: | @@ -121,62 +449,164 @@ jobs: run: | make -j$(nproc) checkCWEEntries validateXML - - name: Test addons + - name: Test install run: | - ./cppcheck --addon=threadsafety addons/test/threadsafety - ./cppcheck --addon=threadsafety --std=c++03 addons/test/threadsafety + # this is only to test the "install" target - since we did not build with FILESDIR it would not work as intended + make DESTDIR=cppcheck-make-install FILESDIR=/share/Cppcheck install + rm -rf cppcheck-make-install - - name: Build GUI on ubuntu - if: contains(matrix.os, 'ubuntu') + - name: Test Signalhandler run: | - pushd gui - qmake HAVE_QCHART=yes - make -j$(nproc) + cmake -S . -B build.cmake.signal -G "Unix Makefiles" -DBUILD_TESTS=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* . + python3 -m pytest -Werror --strict-markers -vv test/signal/test-signalhandler.py + rm test-signalhandler - - name: Run GUI tests on ubuntu + # no unix backtrace support on MacOs + - name: Test Stacktrace if: contains(matrix.os, 'ubuntu') run: | - pushd gui/test/projectfile - qmake - make -j$(nproc) - ./test-projectfile - popd - pushd gui/test/cppchecklibrarydata - qmake - make -j$(nproc) - ./test-cppchecklibrarydata - - - name: Generate Qt help file on ubuntu - if: contains(matrix.os, 'ubuntu') + cmake -S . -B build.cmake.stack -G "Unix Makefiles" -DBUILD_TESTS=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* . + python3 -m pytest -Werror --strict-markers -vv test/signal/test-stacktrace.py + rm test-stacktrace + + # TODO: move to scriptcheck.yml so these are tested with all Python versions? + - name: Test addons run: | - pushd gui/help - qhelpgenerator online-help.qhcp -o online-help.qhc + set -x + ./cppcheck --error-exitcode=1 --inline-suppr --addon=threadsafety addons/test/threadsafety + ./cppcheck --error-exitcode=1 --inline-suppr --addon=threadsafety --std=c++03 addons/test/threadsafety + ./cppcheck --error-exitcode=1 --inline-suppr --addon=misra addons/test/misra/crash*.c + ./cppcheck --error-exitcode=1 --inline-suppr --addon=misra --enable=information addons/test/misra/config*.c - # Run self check after "Build GUI" to include generated headers in analysis - - name: Self check - if: matrix.os == 'ubuntu-20.04' + ./cppcheck --addon=misra --enable=style --inline-suppr --enable=information --error-exitcode=1 addons/test/misra/misra-ctu-*-test.c + pushd addons/test + # We'll force C89 standard to enable an additional verification for + # rules 5.4 and 5.5 which have standard-dependent options. + ../../cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra/misra-test.c --std=c89 --platform=unix64 + python3 ../misra.py -verify misra/misra-test.c.dump + # Test slight MISRA differences in C11 standard + ../../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 + # TODO: do we need to verify something here? + ../../cppcheck --dump -DDUMMY --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra/misra-test.h + ../../cppcheck --dump misra/misra-test.cpp + python3 ../misra.py -verify misra/misra-test.cpp.dump + python3 ../misra.py --rule-texts=misra/misra2012_rules_dummy_ascii.txt -verify misra/misra-test.cpp.dump + python3 ../misra.py --rule-texts=misra/misra2012_rules_dummy_utf8.txt -verify misra/misra-test.cpp.dump + python3 ../misra.py --rule-texts=misra/misra2012_rules_dummy_windows1250.txt -verify misra/misra-test.cpp.dump + ../../cppcheck --addon=misra --enable=style --platform=avr8 --error-exitcode=1 misra/misra-test-avr8.c + ../../cppcheck --dump misc-test.cpp + python3 ../misc.py -verify misc-test.cpp.dump + ../../cppcheck --dump naming_test.c + python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump + ../../cppcheck --dump naming_test.cpp + python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump + + # TODO: run with "-n auto" when misra_test.py can be run in parallel + - name: test addons (Python) + if: matrix.os != 'ubuntu-22.04' + run: | + python3 -m pytest -Werror --strict-markers -vv -n 1 addons/test + env: + PYTHONPATH: ./addons + + # TODO: run with "-n auto" when misra_test.py can be run in parallel + # we cannot specify -Werror since xml/etree/ElementTree.py in Python 3.10 contains an unclosed file + - name: test addons (Python) + if: matrix.os == 'ubuntu-22.04' + run: | + python3 -m pytest --strict-markers -vv -n 1 addons/test + env: + PYTHONPATH: ./addons + + - name: Build democlient + if: matrix.os == 'ubuntu-22.04' + run: | + 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: Show all ignored files + if: false # TODO: currently lists all the contents of ignored folders - we only need what actually matched + run: | + git ls-files --others --ignored --exclude-standard + + - name: Check for changed and unversioned files + run: | + # TODO: how to do this with a single command? + git status --ignored=no + git status --ignored=no | grep -q 'working tree clean' + + selfcheck: + needs: build # wait for all tests to be successful first + + runs-on: ubuntu-22.04 # run on the latest image only + + 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: Install missing software on ubuntu + run: | + sudo apt-get update + # 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 + sudo apt-get install libboost-container-dev + + - name: Self check (build) run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" # compile with verification and ast matchers - make clean - make -j$(nproc) -s CPPFLAGS="-DCHECK_INTERNAL" CXXFLAGS="-g -O2" MATCHCOMPILER=yes VERIFY=1 + make -j$(nproc) -s CPPFLAGS="-DCHECK_INTERNAL" CXXFLAGS="-g -O2 -w -DHAVE_BOOST" MATCHCOMPILER=yes VERIFY=1 + + - name: CMake + run: | + cmake -S . -B cmake.output -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DUSE_QT6=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: | + # make sure auto-generated GUI files exist + make -C cmake.output autogen + make -C cmake.output gui-build-deps triage-build-ui-deps + + - 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 --exception-handling --debug-warnings --check-level=exhaustive" + cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2" + 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 -q -j$(nproc) --std=c++11 --template=selfcheck --cppcheck-build-dir=b1 -D__CPPCHECK__ --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib --addon=naming.json -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli --inconclusive --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings cli lib + ./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 -q -j$(nproc) --std=c++11 --template=selfcheck --cppcheck-build-dir=b2 -D__CPPCHECK__ -DQT_VERSION=0x050000 --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=qt --addon=naming.json -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings gui/*.cpp + ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b2 -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=68 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui || ec=1 # self check test and tools - ./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli -Igui --inconclusive --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings test/*.cpp tools - - - name: Build triage on ubuntu - if: matrix.os == 'ubuntu-20.04' - run: | - pushd tools/triage - qmake - make -j$(nproc) - - - name: Build Fuzzer - if: matrix.os == 'ubuntu-20.04' - run: | - pushd oss-fuzz - make -j$(nproc) CXX=clang++ CXXFLAGS="-fsanitize=address" fuzz-client translate + ./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 -DQ_MOC_OUTPUT_REVISION=68 -DQT_CHARTS_LIB --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage || ec=1 + exit $ec diff --git a/.github/workflows/CI-windows.yml b/.github/workflows/CI-windows.yml index 67816efc6fe..3cf7d66a8fc 100644 --- a/.github/workflows/CI-windows.yml +++ b/.github/workflows/CI-windows.yml @@ -1,129 +1,273 @@ -# Some convenient links: -# - https://github.com/actions/virtual-environments/blob/master/images/win/Windows2019-Readme.md -# - +# 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: CI-windows -on: [push,pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read defaults: run: shell: cmd - + +# TODO: choose/add a step to bail out on compiler warnings (maybe even the release build) + jobs: + build_qt: + strategy: + matrix: + os: [windows-2022, windows-2025] + qt_ver: [6.9.1] + 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: Install Qt ${{ matrix.qt_ver }} + uses: jurplel/install-qt-action@v4 + with: + version: ${{ matrix.qt_ver }} + modules: 'qtcharts' + setup-python: 'false' + cache: true + aqtversion: '==3.1.*' # TODO: remove when aqtinstall 3.2.2 is available + + - name: Run CMake + 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 || exit /b !errorlevel! + + - name: Build GUI release + run: | + cmake --build build --target cppcheck-gui --config Release || exit /b !errorlevel! + + - name: Deploy GUI + run: | + windeployqt build\bin\Release || exit /b !errorlevel! + del build\bin\Release\cppcheck-gui.ilk || exit /b !errorlevel! + del build\bin\Release\cppcheck-gui.pdb || exit /b !errorlevel! + + # TODO: run GUI tests + + - name: Run CMake install + run: | + cmake --build build --target install + build: strategy: matrix: - # windows 2016 should default to VS 2017. Not supported by setup-msbuild - os: [windows-2019] - arch: [x64, x86] + os: [windows-2022, windows-2025] + config: [debug, release] fail-fast: false runs-on: ${{ matrix.os }} + env: + # see https://www.pcre.org/original/changelog.txt + PCRE_VERSION: 8.45 + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Set up Python 3.9 - uses: actions/setup-python@v2 + - name: Set up Python 3.13 + if: matrix.config == 'release' + uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: '3.13' + check-latest: true - - name: Setup msbuild.exe - uses: microsoft/setup-msbuild@v1.0.2 + - name: Set up Visual Studio environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Cache PCRE + id: cache-pcre + uses: actions/cache@v4 + with: + path: | + externals\pcre.h + externals\pcre.lib + externals\pcre64.lib + key: pcre-${{ env.PCRE_VERSION }}-x64-bin-win + + - name: Download PCRE + if: steps.cache-pcre.outputs.cache-hit != 'true' + run: | + curl -fsSL https://github.com/pfultz2/pcre/archive/refs/tags/%PCRE_VERSION%.zip -o pcre-%PCRE_VERSION%.zip || exit /b !errorlevel! - name: Install PCRE + if: steps.cache-pcre.outputs.cache-hit != 'true' run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }} || exit /b !errorlevel! - curl -fsSL https://ftp.pcre.org/pub/pcre/pcre-%PCRE_VERSION%.zip -o pcre-%PCRE_VERSION%.zip || exit /b !errorlevel! + @echo on 7z x pcre-%PCRE_VERSION%.zip || exit /b !errorlevel! cd pcre-%PCRE_VERSION% || exit /b !errorlevel! - cmake . -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DPCRE_BUILD_PCRECPP=Off -DPCRE_BUILD_TESTS=Off -DPCRE_BUILD_PCREGREP=Off || exit /b !errorlevel! + git apply --ignore-space-change ..\externals\pcre.patch || exit /b !errorlevel! + cmake . -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DPCRE_BUILD_PCRECPP=Off -DPCRE_BUILD_TESTS=Off -DPCRE_BUILD_PCREGREP=Off -DCMAKE_POLICY_VERSION_MINIMUM=3.5 || exit /b !errorlevel! nmake || exit /b !errorlevel! copy pcre.h ..\externals || exit /b !errorlevel! - if "${{ matrix.arch }}" == "x86" ( - copy pcre.lib ..\externals\pcre.lib || exit /b !errorlevel! - ) else ( - copy pcre.lib ..\externals\pcre64.lib || exit /b !errorlevel! - ) + copy pcre.lib ..\externals\pcre64.lib || exit /b !errorlevel! env: - # see https://www.pcre.org/original/changelog.txt - PCRE_VERSION: 8.44 CL: /MP - - name: Install Z3 library - run: | - curl -fsSL https://github.com/Z3Prover/z3/releases/download/z3-%Z3_VERSION%/z3-%Z3_VERSION%-${{ matrix.arch }}-win.zip -o z3-%Z3_VERSION%-win.zip || exit /b !errorlevel! - 7z x z3-%Z3_VERSION%-win.zip -oexternals -r -y || exit /b !errorlevel! - move externals\z3-%Z3_VERSION%-${{ matrix.arch }}-win externals\z3 || exit /b !errorlevel! - env: - # see https://github.com/Z3Prover/z3/releases: - Z3_VERSION: 4.8.10 - - # no 32-bit Qt available - - name: Install Qt - if: matrix.arch == 'x64' - uses: jurplel/install-qt-action@v2 - with: - modules: 'qtcharts' - - name: Install missing Python packages + if: matrix.config == 'release' run: | - python -m pip install pip --upgrade - python -m pip install pytest - python -m pip install pytest-custom_exit_code + python -m pip install pip --upgrade || exit /b !errorlevel! + python -m pip install pytest || exit /b !errorlevel! + python -m pip install pytest-custom_exit_code || exit /b !errorlevel! + python -m pip install pytest-timeout || exit /b !errorlevel! + python -m pip install pytest-xdist || exit /b !errorlevel! + python -m pip install psutil || exit /b !errorlevel! + + # TODO: build with CMake - - name: Build GUI release - if: matrix.arch == 'x64' - run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }} || exit /b !errorlevel! - cd gui || exit /b !errorlevel! - qmake HAVE_QCHART=yes || exit /b !errorlevel! - nmake release || exit /b !errorlevel! - env: - CL: /MP - - - name: Deploy GUI - if: matrix.arch == 'x64' - run: | - windeployqt Build\gui || exit /b !errorlevel! - del Build\gui\cppcheck-gui.ilk || exit /b !errorlevel! - del Build\gui\cppcheck-gui.pdb || exit /b !errorlevel! - - name: Build CLI debug configuration using MSBuild + if: matrix.config == 'debug' run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }} || exit /b !errorlevel! - set ARCH=${{ matrix.arch }} - if "${{ matrix.arch }}" == "x86" ( - set ARCH=Win32 - ) - msbuild -m cppcheck.sln /p:Configuration=Debug-PCRE;Platform=%ARCH% -maxcpucount || exit /b !errorlevel! + :: cmake --build build --target check --config Debug || exit /b !errorlevel! + msbuild -m cppcheck.sln /p:Configuration=Debug-PCRE;Platform=x64 -maxcpucount || exit /b !errorlevel! + env: + _CL_: /WX - name: Run Debug test + if: matrix.config == 'debug' run: .\bin\debug\testrunner.exe || exit /b !errorlevel! - name: Build CLI release configuration using MSBuild + if: matrix.config == 'release' run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.arch }} || exit /b !errorlevel! - set ARCH=${{ matrix.arch }} - if "${{ matrix.arch }}" == "x86" ( - set ARCH=Win32 - ) - msbuild -m cppcheck.sln /p:Configuration=Release-PCRE;Platform=%ARCH% -maxcpucount || exit /b !errorlevel! + :: cmake --build build --target check --config Release || exit /b !errorlevel! + msbuild -m cppcheck.sln /p:Configuration=Release-PCRE;Platform=x64 -maxcpucount || exit /b !errorlevel! + env: + _CL_: /WX - name: Run Release test + if: matrix.config == 'release' run: .\bin\testrunner.exe || exit /b !errorlevel! - - name: Run test/cli + - name: Prepare test/cli + if: matrix.config == 'release' run: | :: since FILESDIR is not set copy the binary to the root so the addons are found + :: copy .\build\bin\Release\cppcheck.exe .\cppcheck.exe || exit /b !errorlevel! copy .\bin\cppcheck.exe .\cppcheck.exe || exit /b !errorlevel! copy .\bin\cppcheck-core.dll .\cppcheck-core.dll || exit /b !errorlevel! - cd test/cli || exit /b !errorlevel! - python -m pytest --suppress-no-test-exit-code test-clang-import.py || exit /b !errorlevel! - python -m pytest test-helloworld.py || exit /b !errorlevel! - python -m pytest test-inline-suppress.py || exit /b !errorlevel! - python -m pytest test-more-projects.py || exit /b !errorlevel! - python -m pytest test-proj2.py || exit /b !errorlevel! - python -m pytest test-suppress-syntaxError.py || exit /b !errorlevel! + + - name: Run test/cli + if: matrix.config == 'release' + run: | + python -m pytest -Werror --strict-markers -vv -n auto test/cli || exit /b !errorlevel! + + - name: Run test/cli (-j2) + if: matrix.config == 'release' + run: | + python -m pytest -Werror --strict-markers -vv -n auto test/cli || exit /b !errorlevel! + env: + TEST_CPPCHECK_INJECT_J: 2 + + # TODO: install clang + - name: Run test/cli (--clang) + if: false # matrix.config == 'release' + run: | + python -m pytest -Werror --strict-markers -vv -n auto test/cli || exit /b !errorlevel! + env: + TEST_CPPCHECK_INJECT_CLANG: clang + + - name: Run test/cli (--cppcheck-build-dir) + if: matrix.config == 'release' + run: | + python -m pytest -Werror --strict-markers -vv -n auto test/cli || exit /b !errorlevel! + env: + TEST_CPPCHECK_INJECT_BUILDDIR: injected + + # TODO: test with Release configuration? + - name: Test SEH wrapper + if: matrix.config == 'release' + run: | + cmake -S . -B build.cmake.seh -DBUILD_TESTS=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! + python3 -m pytest -Werror --strict-markers -vv test/seh/test-sehwrapper.py || exit /b !errorlevel! + del test-sehwrapper.exe || exit /b !errorlevel! + + - name: Test addons + if: matrix.config == 'release' + run: | + echo on + .\cppcheck --addon=threadsafety addons\test\threadsafety || exit /b !errorlevel! + .\cppcheck --addon=threadsafety --std=c++03 addons\test\threadsafety || exit /b !errorlevel! + .\cppcheck --addon=misra --enable=style --inline-suppr --enable=information --error-exitcode=1 addons\test\misra\misra-ctu-*-test.c || exit /b !errorlevel! + cd addons\test + rem We'll force C89 standard to enable an additional verification for + rem rules 5.4 and 5.5 which have standard-dependent options. + ..\..\cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra\misra-test.c --std=c89 --platform=unix64 || exit /b !errorlevel! + python3 ..\misra.py -verify misra\misra-test.c.dump || exit /b !errorlevel! + rem Test slight MISRA differences in C11 standard + ..\..\cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra\misra-test-c11.c --std=c11 --platform=unix64 || exit /b !errorlevel! + python3 ..\misra.py -verify misra\misra-test-c11.c.dump || exit /b !errorlevel! + rem TODO: do we need to verify something here? + ..\..\cppcheck --dump -DDUMMY --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra\misra-test.h || exit /b !errorlevel! + ..\..\cppcheck --dump misra\misra-test.cpp || exit /b !errorlevel! + python3 ..\misra.py -verify misra\misra-test.cpp.dump || exit /b !errorlevel! + python3 ..\misra.py --rule-texts=misra\misra2012_rules_dummy_ascii.txt -verify misra\misra-test.cpp.dump || exit /b !errorlevel! + python3 ..\misra.py --rule-texts=misra\misra2012_rules_dummy_utf8.txt -verify misra\misra-test.cpp.dump || exit /b !errorlevel! + python3 ..\misra.py --rule-texts=misra\misra2012_rules_dummy_windows1250.txt -verify misra\misra-test.cpp.dump || exit /b !errorlevel! + ..\..\cppcheck --addon=misra --enable=style --platform=avr8 --error-exitcode=1 misra\misra-test-avr8.c || exit /b !errorlevel! + ..\..\cppcheck --dump misc-test.cpp || exit /b !errorlevel! + python3 ..\misc.py -verify misc-test.cpp.dump || exit /b !errorlevel! + ..\..\cppcheck --dump naming_test.c || exit /b !errorlevel! + rem TODO: fix this - does not fail on Linux + rem python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump || exit /b !errorlevel! + ..\..\cppcheck --dump naming_test.cpp || exit /b !errorlevel! + python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump || exit /b !errorlevel! + + # TODO: run with "-n auto" when misra_test.py can be run in parallel + - name: test addons (Python) + if: matrix.config == 'release' + run: | + python -m pytest -Werror --strict-markers -vv -n 1 addons/test || exit /b !errorlevel! + env: + PYTHONPATH: ./addons + + - name: Check Windows test syntax + if: matrix.config == 'debug' + run: | + cd test\cfg + cl.exe windows.cpp -DUNICODE=1 -D_UNICODE=1 /Zs || exit /b !errorlevel! + cl.exe mfc.cpp /EHsc /Zs || exit /b !errorlevel! + + - name: Show all ignored files + if: false # TODO: currently lists all the contents of ignored folders - we only need what actually matched + run: | + git ls-files --others --ignored --exclude-standard || exit /b !errorlevel! + + - name: Check for changed and unversioned files + run: | + :: TODO: how to do this with a single command? + git status --ignored=no + :: TODO: make this work + :: git status --ignored=no | grep -q 'working tree clean' diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml index e56c4e0d344..f2c4f2cdd1b 100644 --- a/.github/workflows/asan.yml +++ b/.github/workflows/asan.yml @@ -2,42 +2,154 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: address sanitizer -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: + QT_VERSION: 6.9.1 ASAN_OPTIONS: detect_stack_use_after_return=1 + # TODO: figure out why there are cache misses with PCH enabled + CCACHE_SLOPPINESS: pch_defines,time_macros steps: - - uses: actions/checkout@v2 + - 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 3.13 + uses: actions/setup-python@v5 + with: + python-version: '3.13' + check-latest: true - name: Install missing software on ubuntu run: | sudo apt-get update - sudo apt-get install libz3-4 libz3-dev + 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 20 + + - 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: Build - run: make -j$(nproc) cppcheck testrunner USE_Z3=yes HAVE_RULES=yes MATCHCOMPILER=yes VERIFY=1 + # TODO: disable all warnings + - name: CMake + run: | + cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DUSE_QT6=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_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache env: - CC: clang - CXX: clang++ - CXXFLAGS: "-fsanitize=address -O1 -g3 -DCPPCHK_GLIBCXX_DEBUG" - CPPFLAGS: "-DCHECK_INTERNAL" + CC: clang-20 + CXX: clang++-20 + + - 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: ./testrunner + run: ./cmake.output/bin/testrunner - - name: Self check + - name: Run cfg tests run: | - ./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli --inconclusive --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings cli lib - ./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ -DQT_VERSION=0x050000 --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=qt -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings gui/*.cpp - ./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli -Igui --inconclusive --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings test/*.cpp tools + cmake --build cmake.output --target checkcfg -- -j $(nproc) -# This takes too long time right now -# - name: Bughunting lib -# run: ./cppcheck -D__CPPCHECK__ --bug-hunting -j$(nproc) lib + - name: Run CTest + 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 + + - 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 --exception-handling --debug-warnings --check-level=exhaustive" + cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2" + 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 -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui/*.cpp || 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 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage/*.cpp || ec=1 + exit $ec diff --git a/.github/workflows/buildman.yml b/.github/workflows/buildman.yml index cf2b5c2afcc..b0b399dd851 100644 --- a/.github/workflows/buildman.yml +++ b/.github/workflows/buildman.yml @@ -1,25 +1,65 @@ +# 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: Build manual -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: convert_via_pandoc: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + persist-credentials: false - run: | mkdir output - - uses: docker://pandoc/latex:2.9 + - uses: docker://pandoc/latex:3.6.3 with: args: --output=output/manual.html man/manual.md - - - uses: docker://pandoc/latex:2.9 + + - uses: docker://pandoc/latex:3.6.3 with: - args: --output=output/manual.pdf man/manual.md - - - uses: actions/upload-artifact@v2 + args: --output=output/manual.pdf man/manual.md + + - uses: docker://pandoc/latex:3.6.3 + with: + args: --output=output/manual-premium.pdf man/manual-premium.md + + - uses: actions/upload-artifact@v4 with: name: output path: output + + manpage: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install missing software on ubuntu + run: | + sudo apt-get update + sudo apt-get install -y xsltproc docbook-xsl + + - name: build manpage + run: | + make man + + - uses: actions/upload-artifact@v4 + with: + name: cppcheck.1 + path: cppcheck.1 diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml new file mode 100644 index 00000000000..7b462c688f0 --- /dev/null +++ b/.github/workflows/cifuzz.yml @@ -0,0 +1,34 @@ +# 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: CIFuzz + +on: [pull_request] + +permissions: + contents: read + +jobs: + Fuzzing: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'danmar' }} + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'cppcheck' + dry-run: false + language: c++ + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'cppcheck' + fuzz-seconds: 300 + dry-run: false + language: c++ + - name: Upload Crash + uses: actions/upload-artifact@v4 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index e767d63bca4..e9c486cc4f4 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -2,47 +2,92 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: clang-tidy -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + schedule: + - cron: '0 0 * * 0' + workflow_dispatch: + +permissions: + contents: read jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 - container: - image: "ubuntu:21.04" + env: + QT_VERSION: 6.9.1 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Install missing software run: | - apt-get update - apt-get install -y cmake g++ make - apt-get install -y z3 libz3-dev - apt-get install -y libpcre3-dev - apt-get install -y software-properties-common - add-apt-repository universe - apt-get update - apt-get install -y clang-tidy-12 - - # uses "sudo" internally which is not available on docker by default - #- name: Install Qt - # uses: jurplel/install-qt-action@v2 - # with: - # modules: 'qtcharts' + sudo apt-get update + sudo apt-get install -y cmake make + sudo apt-get install -y libpcre3-dev + sudo apt-get install -y libgl-dev # fixes missing dependency for Qt in CMake + + - 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 20 + sudo apt-get install -y clang-tidy-20 + + - name: Install Qt ${{ env.QT_VERSION }} + uses: jurplel/install-qt-action@v4 + with: + version: ${{ env.QT_VERSION }} + modules: 'qtcharts' + setup-python: 'false' + install-deps: false + cache: true + + - name: Verify clang-tidy configuration + run: | + clang-tidy-20 --verify-config - name: Prepare CMake run: | - mkdir cmake.output - cd cmake.output - # cannot include GUI since we need to generate the ui_*.h files first - cmake -G "Unix Makefiles" -DUSE_Z3=On -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off .. - cd .. + 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 -DCPPCHK_GLIBCXX_DEBUG=Off -DWARNINGS_ARE_ERRORS=On + env: + CC: clang-20 + CXX: clang++-20 - - name: Clang-Tidy + - name: Prepare CMake dependencies run: | + # make sure the auto-generated GUI sources exist + make -C cmake.output autogen # make sure the precompiled headers exist - make -C cmake.output lib/CMakeFiles/lib_objs.dir/cmake_pch.hxx.cxx - make -C cmake.output test/CMakeFiles/testrunner.dir/cmake_pch.hxx.cxx + make -C cmake.output/cli cmake_pch.hxx.pch + make -C cmake.output/gui cmake_pch.hxx.pch + make -C cmake.output/lib cmake_pch.hxx.pch + make -C cmake.output/test cmake_pch.hxx.pch + + - name: Clang-Tidy + if: ${{ github.event.schedule == '' && github.event_name != 'workflow_dispatch' }} + run: | cmake --build cmake.output --target run-clang-tidy 2> /dev/null + + - name: Clang Static Analyzer + if: ${{ github.event.schedule != '' || github.event_name == 'workflow_dispatch' }} + run: | + cmake --build cmake.output --target run-clang-tidy-csa 2> /dev/null + + - uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: Compilation Database + path: ./cmake.output/compile_commands.json diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1734626ef15..185ebe139c6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,11 +1,26 @@ +# 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: "CodeQL" -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: analyze: name: Analyze - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 + permissions: + security-events: write strategy: fail-fast: false @@ -18,27 +33,20 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Install missing software on ubuntu - run: | - sudo apt-get update - sudo apt-get install libxml2-utils - sudo apt-get install libz3-dev libz3-4 - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - setup-python-dependencies: false - - run: | - make -j$(nproc) USE_Z3=yes HAVE_RULES=yes cppcheck + - name: Build cppcheck + if: matrix.language == 'cpp' + run: | + make -j$(nproc) HAVE_RULES=yes cppcheck - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 120db3e9fd1..3c0c8e1d1df 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -2,48 +2,69 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: Coverage -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - 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 libxml2-utils - sudo apt-get install libz3-dev libz3-4 - sudo apt-get install lcov - sudo apt-get install libcppunit-dev + sudo apt-get install libxml2-utils lcov + + - name: Install missing Python packages on ubuntu + run: | python -m pip install pip --upgrade python -m pip install lcov_cobertura - name: Compile instrumented run: | - make -j$(nproc) test CXXFLAGS="-g -fprofile-arcs -ftest-coverage" USE_Z3=yes HAVE_RULES=yes - - - name: Generate coverage report + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) all CXXFLAGS="-g -fprofile-arcs -ftest-coverage" HAVE_RULES=yes + + - name: Run instrumented tests run: | - rm -rf coverage_report ./testrunner test/cfg/runtests.sh + + - name: Generate coverage report + run: | gcov lib/*.cpp -o lib/ lcov --directory ./ --capture --output-file lcov_tmp.info -b ./ lcov --extract lcov_tmp.info "$(pwd)/*" --output-file lcov.info genhtml lcov.info -o coverage_report --frame --legend --demangle-cpp - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: Coverage results path: coverage_report - - uses: codecov/codecov-action@v1.2.1 + - uses: codecov/codecov-action@v4 with: - # token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos + token: ${{ secrets.CODECOV_TOKEN }} # file: ./coverage.xml # optional flags: unittests # optional name: ${{ github.repository }} # optional diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml new file mode 100644 index 00000000000..3c07b61d7c7 --- /dev/null +++ b/.github/workflows/coverity.yml @@ -0,0 +1,41 @@ +# 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: Coverity + +on: + schedule: + - cron: "0 0 * * *" + +permissions: + contents: read + +jobs: + scan: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'danmar' }} + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Install missing software on ubuntu + run: | + sudo apt-get update + sudo apt-get install qtbase5-dev qttools5-dev libqt5charts5-dev libboost-container-dev + - name: Download Coverity build tool + run: | + wget -c -N https://scan.coverity.com/download/linux64 --post-data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=cppcheck" -O coverity_tool.tar.gz + mkdir coverity_tool + tar xzf coverity_tool.tar.gz --strip 1 -C coverity_tool + - name: Build with Coverity build tool + run: | + export PATH=`pwd`/coverity_tool/bin:$PATH + cov-build --dir cov-int make CPPCHK_GLIBCXX_DEBUG= + - name: Submit build result to Coverity Scan + run: | + tar czvf cov.tar.gz cov-int + curl --form token=${{ secrets.COVERITY_SCAN_TOKEN }} \ + --form email=daniel.marjamaki@gmail.com \ + --form file=@cov.tar.gz \ + --form version="Commit $GITHUB_SHA" \ + --form description="Development" \ + https://scan.coverity.com/builds?project=cppcheck diff --git a/.github/workflows/cppcheck-premium.yml b/.github/workflows/cppcheck-premium.yml new file mode 100644 index 00000000000..87aa920193e --- /dev/null +++ b/.github/workflows/cppcheck-premium.yml @@ -0,0 +1,82 @@ +# 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: cppcheck-premium + +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + workflow_dispatch: + inputs: + premium_version: + description: 'Cppcheck Premium version' + +permissions: + contents: read + security-events: write + +jobs: + + build: + runs-on: ubuntu-24.04 # run on the latest image only + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Download cppcheckpremium release + if: false + run: | + premium_version=${{ inputs.premium_version }} + if [ -z $premium_version ]; then + premium_version=24.11.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 + wget https://files.cppchecksolutions.com/$premium_version/ubuntu-24.04/cppcheckpremium-$premium_version-amd64.tar.gz -O cppcheckpremium.tar.gz + fi + tar xzf cppcheckpremium.tar.gz + mv cppcheckpremium-$premium_version cppcheckpremium + + - name: Download cppcheckpremium devdrop + run: | + wget https://files.cppchecksolutions.com/devdrop/cppcheckpremium-devdrop-20250713-amd64.tar.gz -O cppcheckpremium.tar.gz + tar xzvf cppcheckpremium.tar.gz + mv cppcheckpremium-devdrop-20250713 cppcheckpremium + # Overwrite cppcheck binary + make -j$(nproc) CXXFLAGS=-O2 MATCHCOMPILER=yes + cp cppcheck cppcheckpremium/ + + - name: Generate a license file + run: | + echo cppcheck > cppcheck.lic + echo 251231 >> cppcheck.lic + echo 80000 >> cppcheck.lic + echo 4f8dc8e7c8bb288f >> cppcheck.lic + echo path:lib >> cppcheck.lic + + - name: Check + run: | + cppcheckpremium/premiumaddon --check-loc-license cppcheck.lic > cppcheck-premium-loc + cppcheckpremium/cppcheck --premium=safety-off -j$(nproc) -D__GNUC__ -D__CPPCHECK__ --suppressions-list=cppcheckpremium-suppressions --platform=unix64 --enable=style --premium=misra-c++-2023 --premium=cert-c++-2016 --inline-suppr lib --error-exitcode=0 --output-format=sarif 2> results.sarif + + - name: Cat results + run: | + #sed -i 's|"security-severity":.*||' results.sarif + cat results.sarif + + - uses: actions/upload-artifact@v4 + with: + name: results + path: results.sarif + + - name: Upload report + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif + category: cppcheckpremium diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 00000000000..8ad9408a376 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,55 @@ +# 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: format + +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-22.04 + + env: + UNCRUSTIFY_VERSION: 0.80.1 + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Cache uncrustify + uses: actions/cache@v4 + id: cache-uncrustify + with: + path: | + ~/uncrustify + key: ${{ runner.os }}-uncrustify-${{ env.UNCRUSTIFY_VERSION }} + + - name: build uncrustify + if: steps.cache-uncrustify.outputs.cache-hit != 'true' + run: | + set -x + wget https://github.com/uncrustify/uncrustify/archive/refs/tags/uncrustify-${{ env.UNCRUSTIFY_VERSION }}.tar.gz + tar xzvf uncrustify-${{ env.UNCRUSTIFY_VERSION }}.tar.gz + cd uncrustify-uncrustify-${{ env.UNCRUSTIFY_VERSION }} + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release + cmake --build build -- -j$(nproc) -s + mkdir ~/uncrustify + cp build/uncrustify ~/uncrustify/ + + - name: Uncrustify check + run: | + ~/uncrustify/uncrustify -c .uncrustify.cfg -l CPP --no-backup --replace */*.cpp */*.h + git diff + git diff | diff - /dev/null &> /dev/null diff --git a/.github/workflows/irc.yml b/.github/workflows/irc.yml deleted file mode 100644 index 5d7e71f5abf..00000000000 --- a/.github/workflows/irc.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: "IRC Push Notification" -on: [pull_request, create] - -jobs: - test: - if: github.repository == 'danmar/cppcheck' - runs-on: ubuntu-20.04 - steps: - - name: irc pull request - uses: rectalogic/notify-irc@v1 - if: github.event_name == 'pull_request' - with: - channel: "#cppcheck" - nickname: cppcheck-github-notifier - message: | - ${{ github.actor }} opened PR ${{ github.event.html_url }} - - name: irc tag created - uses: rectalogic/notify-irc@v1 - if: github.event_name == 'create' && github.event.ref_type == 'tag' - with: - channel: "#cppcheck" - nickname: cppcheck-github-notifier - message: | - ${{ github.actor }} tagged ${{ github.repository }} ${{ github.event.ref }} diff --git a/.github/workflows/iwyu.yml b/.github/workflows/iwyu.yml new file mode 100644 index 00000000000..65e5ca5f9f1 --- /dev/null +++ b/.github/workflows/iwyu.yml @@ -0,0 +1,270 @@ +# 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: include-what-you-use + +on: + schedule: + - cron: '0 0 * * 0' + workflow_dispatch: + +permissions: + contents: read + +jobs: + iwyu: + + strategy: + matrix: + # "opensuse/tumbleweed:latest" / "fedora:latest" / "debian:unstable" / "archlinux:latest" + include: + - os: ubuntu-22.04 + image: "fedora:latest" + 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 + 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' }} + + container: + image: ${{ matrix.image }} + + env: + QT_VERSION: 6.9.1 + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install missing software on debian/ubuntu + if: contains(matrix.image, 'debian') + run: | + apt-get update + apt-get install -y cmake clang make libpcre3-dev + apt-get install -y libgl-dev # fixes missing dependency for Qt in CMake + apt-get install -y iwyu + + - name: Install missing software on archlinux + if: contains(matrix.image, 'archlinux') + run: | + set -x + pacman -Sy + pacman -S cmake make clang pcre --noconfirm + pacman -S libglvnd --noconfirm # fixes missing dependency for Qt in CMake + pacman-key --init + pacman-key --recv-key 3056513887B78AEB --keyserver keyserver.ubuntu.com + pacman-key --lsign-key 3056513887B78AEB + pacman -U 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst' 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst' --noconfirm + echo "[chaotic-aur]" >> /etc/pacman.conf + echo "Include = /etc/pacman.d/chaotic-mirrorlist" >> /etc/pacman.conf + pacman -Sy + pacman -S include-what-you-use --noconfirm + ln -s iwyu-tool /usr/sbin/iwyu_tool + + - name: Install missing software on Fedora + if: contains(matrix.image, 'fedora') + run: | + dnf install -y cmake clang pcre-devel + 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 + dnf install -y python3-devel # fixes building of wheels for jurplel/install-qt-action + dnf install -y cairo-devel gtk3-devel libcurl-devel lua-devel openssl-devel python3-devel sqlite-devel boost-devel cppunit-devel libsigc++20-devel # for strict cfg checks + dnf install -y iwyu + ln -s iwyu_tool.py /usr/bin/iwyu_tool + + - name: Install missing software on Fedora (libc++) + if: contains(matrix.image, 'fedora') && matrix.stdlib == 'libc++' + run: | + dnf install -y libcxx-devel + + - name: Install missing software on OpenSUSE + if: contains(matrix.image, 'opensuse') + run: | + zypper install -y cmake clang pcre-devel + zypper install -y include-what-you-use-tools + ln -s iwyu_tool.py /usr/bin/iwyu_tool + + # coreutils contains "nproc" + - name: Install missing software on macOS + if: contains(matrix.os, 'macos') + run: | + brew install include-what-you-use pcre coreutils + ln -s 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 + - name: Install Qt ${{ env.QT_VERSION }} + uses: jurplel/install-qt-action@v4 + with: + version: ${{ env.QT_VERSION }} + modules: 'qtcharts' + setup-python: 'false' + install-deps: false + cache: true + + - name: Generate macOS mappings + if: contains(matrix.os, 'macos') + run: | + set -x + + wget https://raw.githubusercontent.com/include-what-you-use/include-what-you-use/master/mapgen/iwyu-mapgen-apple-libc.py + python3 iwyu-mapgen-apple-libc.py $(xcrun --show-sdk-path)/usr/include > macos.imp + + - name: Prepare CMake + run: | + # TODO: why does it build dmake in the next step? + 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 -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++ + + # Fails on Debian: + # /__w/cppcheck/Qt/6.7.0/gcc_64/libexec/rcc: error while loading shared libraries: libglib-2.0.so.0: cannot open shared object file: No such file or directory + - name: Prepare CMake dependencies + run: | + # make sure the auto-generated GUI sources exist + make -C cmake.output autogen + # make sure the precompiled headers exist + #make -C cmake.output/cli cmake_pch.hxx.pch + #make -C cmake.output/gui cmake_pch.hxx.pch + #make -C cmake.output/lib cmake_pch.hxx.pch + #make -C cmake.output/test cmake_pch.hxx.pch + # make sure the auto-generated GUI dependencies exist + make -C cmake.output gui-build-deps + make -C cmake.output triage-build-ui-deps + + - 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 + + # TODO: run with all configurations + - name: test/cfg + if: matrix.stdlib == 'libstdc++' + run: | + # TODO: redirect to log + ./test/cfg/runtests.sh + env: + IWYU: include-what-you-use + IWYU_CLANG_INC: ${{ matrix.clang_inc }} + + - uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: Compilation Database (include-what-you-use - ${{ matrix.os }} ${{ matrix.stdlib }}) + path: ./cmake.output/compile_commands.json + + - uses: actions/upload-artifact@v4 + if: ${{ contains(matrix.os, 'macos') && (success() || failure()) }} + with: + name: macOS Mappings + path: | + ./iwyu-mapgen-apple-libc.py + ./macos.imp + + - uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: Logs (include-what-you-use - ${{ matrix.os }} ${{ matrix.stdlib }}) + path: ./*.log + + clang-include-cleaner: + + strategy: + matrix: + stdlib: [libstdc++, libc++] + include: + - stdlib: libstdc++ + use_libcxx: Off + - stdlib: libc++ + use_libcxx: On + fail-fast: false + + runs-on: ubuntu-22.04 + if: ${{ github.repository_owner == 'danmar' }} + + env: + QT_VERSION: 6.9.1 + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install missing software + run: | + sudo apt-get update + sudo apt-get install -y cmake make libpcre3-dev + sudo apt-get install -y libgl-dev # missing dependency for using Qt in CMake + + - 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 20 + sudo apt-get install -y clang-tools-20 + + - name: Install libc++ + if: matrix.stdlib == 'libc++' + run: | + sudo apt-get install -y libc++-20-dev + + - name: Install Qt ${{ env.QT_VERSION }} + uses: jurplel/install-qt-action@v4 + with: + version: ${{ env.QT_VERSION }} + modules: 'qtcharts' + setup-python: 'false' + install-deps: false + cache: true + + - name: Prepare CMake + run: | + # TODO: why does it build dmake in the next step? + 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 -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCPPCHK_GLIBCXX_DEBUG=Off -DUSE_MATCHCOMPILER=Off -DEXTERNALS_AS_SYSTEM=On -DUSE_LIBCXX=${{ matrix.use_libcxx }} + env: + CC: clang-20 + CXX: clang++-20 + + - name: Prepare CMake dependencies + run: | + # make sure the auto-generated GUI sources exist + make -C cmake.output autogen + # make sure the precompiled headers exist + #make -C cmake.output/cli cmake_pch.hxx.pch + #make -C cmake.output/gui cmake_pch.hxx.pch + #make -C cmake.output/lib cmake_pch.hxx.pch + #make -C cmake.output/test cmake_pch.hxx.pch + # make sure the auto-generated GUI dependencies exist + make -C cmake.output gui-build-deps + + - 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-20 --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() + with: + name: Compilation Database (clang-include-cleaner - ${{ matrix.stdlib }}) + path: ./cmake.output/compile_commands.json + + - uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: Logs (clang-include-cleaner - ${{ matrix.stdlib }}) + path: ./*.log diff --git a/.github/workflows/release-windows.yml b/.github/workflows/release-windows.yml index c22ba17bef3..afc6643e268 100644 --- a/.github/workflows/release-windows.yml +++ b/.github/workflows/release-windows.yml @@ -1,7 +1,5 @@ -# Some convenient links: -# - https://github.com/actions/virtual-environments/blob/master/images/win/Windows2019-Readme.md -# - +# 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: release-windows on: @@ -12,6 +10,9 @@ on: - cron: '0 0 * * *' workflow_dispatch: +permissions: + contents: read + defaults: run: shell: cmd @@ -20,87 +21,177 @@ jobs: build: - runs-on: windows-2019 + runs-on: windows-2025 + if: ${{ github.repository_owner == 'danmar' }} + + env: + # see https://www.pcre.org/original/changelog.txt + PCRE_VERSION: 8.45 + QT_VERSION: 6.9.1 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Setup msbuild.exe - uses: microsoft/setup-msbuild@v1.0.2 + - name: Set up Visual Studio environment + uses: ilammy/msvc-dev-cmd@v1 - - name: Install PCRE - run: | - curl -fsSL https://ftp.pcre.org/pub/pcre/pcre-8.44.zip -o pcre-8.44.zip - 7z x pcre-8.44.zip - cd pcre-8.44 - cmake . -G "Visual Studio 16 2019" -A x64 - msbuild -m PCRE.sln /p:Configuration=Release /p:Platform=x64 - dir - dir Release - dir x64 - dir x64\Release - copy pcre.h ..\externals - copy Release\pcre.lib ..\externals\pcre64.lib - - - name: Install Z3 library + - name: Download PCRE run: | - curl -fsSL https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-win.zip -o z3-4.8.7-win.zip - 7z x z3-4.8.7-win.zip -oexternals -r -y - move externals\z3-4.8.7-x64-win externals\z3 + curl -fsSL https://github.com/pfultz2/pcre/archive/refs/tags/%PCRE_VERSION%.zip -o pcre-%PCRE_VERSION%.zip || exit /b !errorlevel! - - name: Install Qt - uses: jurplel/install-qt-action@v2 + - name: Install PCRE + run: | + @echo on + 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 || exit /b !errorlevel! + msbuild -m PCRE.sln -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! + + # 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 }} + uses: jurplel/install-qt-action@v4 with: - version: '5.15.2' - modules: 'qtcharts qthelp' - mirror: 'http://mirrors.ocf.berkeley.edu/qt/' + 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 - - name: Create .qm + # 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 -DUSE_QT6=On -DWITH_QCHART=On -DBUILD_ONLINE_HELP=On || exit /b !errorlevel! + cmake --build build --target cppcheck-gui --config Release || exit /b !errorlevel! + + # TODO: package PDBs + - name: Deploy app run: | - cd gui - lupdate gui.pro - lrelease gui.pro -removeidentical + windeployqt build\bin\Release || exit /b !errorlevel! + del build\bin\Release\cppcheck-gui.ilk || exit /b !errorlevel! + del build\bin\Release\cppcheck-gui.pdb || exit /b !errorlevel! + + - uses: actions/upload-artifact@v4 + with: + name: deploy + path: build\bin\Release - name: Matchcompiler - run: python tools\matchcompiler.py --write-dir lib + run: python tools\matchcompiler.py --write-dir lib || exit /b !errorlevel! - - name: Build x64 release GUI + # TODO: build with multiple threads + # TODO: build with boost enabled + - name: Build CLI x64 release configuration using MSBuild + run: msbuild -m cppcheck.sln -t:cli -p:Configuration=Release-PCRE -p:Platform=x64 || exit /b !errorlevel! + + - uses: actions/upload-artifact@v4 + with: + name: bin + path: bin + + - name: Install missing Python packages run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - cd gui - qmake HAVE_QCHART=yes - nmake release - env: - CL: /MP + pip install -U pyinstaller || exit /b !errorlevel! - - name: Deploy app + # TODO: include in installer? + - name: Compile misra.py executable run: | - windeployqt Build\gui - del Build\gui\cppcheck-gui.ilk - del Build\gui\cppcheck-gui.pdb + cd addons || exit /b !errorlevel! + pyinstaller --hidden-import xml --hidden-import xml.etree --hidden-import xml.etree.ElementTree misra.py || exit /b !errorlevel! + del *.spec || exit /b !errorlevel! - - name: Build CLI x64 release configuration using MSBuild - run: msbuild -m cppcheck.sln /t:cli /p:Configuration=Release-PCRE /p:Platform=x64 + # TODO: include in installer? + - name: Compile cppcheck-htmlreport executable + run: | + cd htmlreport || exit /b !errorlevel! + pyinstaller cppcheck-htmlreport || exit /b !errorlevel! + del *.spec || exit /b !errorlevel! + + # TODO: test the compiled Python files + + - name: Collect files + run: | + @echo on + move build\bin\Release win_installer\files || exit /b !errorlevel! + copy AUTHORS win_installer\files\authors.txt || exit /b !errorlevel! + copy win_installer\GPLv3.txt win_installer\files\ || exit /b !errorlevel! + copy externals\picojson\LICENSE win_installer\files\picojson-license.txt || exit /b !errorlevel! + copy externals\simplecpp\LICENSE win_installer\files\simplecpp-license.txt || exit /b !errorlevel! + copy externals\tinyxml2\LICENSE win_installer\files\tinyxml2-license.txt || exit /b !errorlevel! + copy addons\dist\misra\*.* win_installer\files\addons || exit /b !errorlevel! + copy bin\cppcheck.exe win_installer\files || exit /b !errorlevel! + copy bin\cppcheck-core.dll win_installer\files || exit /b !errorlevel! + :: mkdir win_installer\files\help || exit /b !errorlevel! + xcopy /s gui\help win_installer\files\help || exit /b !errorlevel! + copy gui\help\online-help.qhc win_installer\files\ || exit /b !errorlevel! + copy gui\help\online-help.qch win_installer\files\ || exit /b !errorlevel! + del win_installer\files\cfg\*.rng || exit /b !errorlevel! + del win_installer\files\platforms\*.rng || exit /b !errorlevel! + del win_installer\files\translations\*.qm || exit /b !errorlevel! + move build\gui\*.qm win_installer\files\translations || exit /b !errorlevel! + copy htmlreport\dist\cppcheck-htmlreport\*.* win_installer\files || exit /b !errorlevel! + :: copy libcrypto-3-x64.dll and libssl-3-x64.dll + copy %RUNNER_WORKSPACE%\Qt\Tools\OpenSSLv3\Win_x64\bin\lib*.dll win_installer\files || exit /b !errorlevel! + + - uses: actions/upload-artifact@v4 + with: + name: collect + path: win_installer\files - name: Build Installer run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - mkdir bin - xcopy /S Build\gui bin - cd win_installer - REM Read ProductVersion + cd win_installer || exit /b !errorlevel! + :: Read ProductVersion for /f "tokens=4 delims= " %%a in ('find "ProductVersion" productInfo.wxi') do set PRODUCTVER=%%a - REM Remove double quotes + :: Remove double quotes set PRODUCTVER=%PRODUCTVER:"=% - echo ProductVersion=%PRODUCTVER% - msbuild -m cppcheck.wixproj /p:Platform=x64,ProductVersion=%PRODUCTVER%.${{ github.run_number }} + @echo ProductVersion="%PRODUCTVER%" || exit /b !errorlevel! + msbuild -m cppcheck.wixproj -p:Platform=x64,ProductVersion=%PRODUCTVER%.${{ github.run_number }} || exit /b !errorlevel! - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: installer path: win_installer/Build/ - - uses: actions/upload-artifact@v2 + - name: Clean up deploy + run: | + @echo on + :: del win_installer\files\addons\*.dll || exit /b !errorlevel! + del win_installer\files\addons\*.doxyfile || exit /b !errorlevel! + del win_installer\files\addons\*.md || exit /b !errorlevel! + :: del win_installer\files\addons\*.pyd || exit /b !errorlevel! + :: del win_installer\files\addons\base_library.zip || exit /b !errorlevel! + rmdir /s /q win_installer\files\addons\test || exit /b !errorlevel! + rmdir /s /q win_installer\files\addons\doc || exit /b !errorlevel! + :: rmdir /s /q win_installer\files\bearer || exit /b !errorlevel! + rmdir /s /q win_installer\files\generic || exit /b !errorlevel! + rmdir /s /q win_installer\files\help || exit /b !errorlevel! + rmdir /s /q win_installer\files\iconengines || exit /b !errorlevel! + rmdir /s /q win_installer\files\imageformats || exit /b !errorlevel! + rmdir /s /q win_installer\files\networkinformation || exit /b !errorlevel! + :: rmdir /s /q win_installer\files\printsupport || exit /b !errorlevel! + rmdir /s /q win_installer\files\sqldrivers || exit /b !errorlevel! + rmdir /s /q win_installer\files\tls || exit /b !errorlevel! + ren win_installer\files\translations lang || exit /b !errorlevel! + del win_installer\files\d3dcompiler_47.dll || exit /b !errorlevel! + del win_installer\files\dxcompiler.dll || exit /b !errorlevel! + del win_installer\files\dxil.dll || exit /b !errorlevel! + del win_installer\files\dmake.exe || exit /b !errorlevel! + del win_installer\files\dmake.pdb || exit /b !errorlevel! + :: del win_installer\files\libEGL.dll || exit /b !errorlevel! + :: del win_installer\files\libGLESv2.dll || exit /b !errorlevel! + del win_installer\files\opengl32sw.dll || exit /b !errorlevel! + del win_installer\files\Qt6Svg.dll || exit /b !errorlevel! + del win_installer\files\vc_redist.x64.exe || exit /b !errorlevel! + + - uses: actions/upload-artifact@v4 with: - name: deploy - path: Build\gui + name: portable + path: win_installer\files diff --git a/.github/workflows/scriptcheck.yml b/.github/workflows/scriptcheck.yml index 5e1ab6df757..3394604d155 100644 --- a/.github/workflows/scriptcheck.yml +++ b/.github/workflows/scriptcheck.yml @@ -2,81 +2,129 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: scriptcheck -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ runner.os }} + + - name: Cache Cppcheck + uses: actions/cache@v4 + with: + path: cppcheck + key: ${{ runner.os }}-scriptcheck-cppcheck-${{ github.sha }} + + - name: build cppcheck + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + make -j$(nproc) -s CXXFLAGS="-w" + strip -s ./cppcheck + + scriptcheck: + + needs: build + runs-on: ubuntu-22.04 strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] + python-version: [3.7, 3.8, 3.9, '3.10', '3.11', '3.12', '3.13'] + include: + - python-version: '3.13' + python-latest: true + fail-fast: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + persist-credentials: false + + # TODO: bailout on error + - name: Restore Cppcheck + uses: actions/cache@v4 + with: + path: cppcheck + key: ${{ runner.os }}-scriptcheck-cppcheck-${{ github.sha }} - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + check-latest: true - name: Install missing software on ubuntu run: | sudo apt-get update sudo apt-get install tidy libxml2-utils - - name: Install missing software on ubuntu (Python 2) - if: matrix.python-version == '2.7' - run: | - python -m pip install pip --upgrade - python -m pip install pytest - python -m pip install pygments - - name: Install missing software on ubuntu (Python 3) - if: matrix.python-version != '2.7' run: | + # shellcheck cannot be installed via pip + # ERROR: Could not find a version that satisfies the requirement shellcheck (from versions: none) + # ERROR: No matching distribution found for shellcheck sudo apt-get install shellcheck python -m pip install pip --upgrade python -m pip install natsort python -m pip install pexpect - python -m pip install pylint + python -m pip install 'pylint<=3.3.0' python -m pip install unittest2 python -m pip install pytest + python -m pip install pytest-xdist python -m pip install pygments python -m pip install requests python -m pip install psutil + python -m pip install setuptools - name: run Shellcheck - if: matrix.python-version == '3.9' + if: matrix.python-latest run: | find . -name "*.sh" | xargs shellcheck --exclude SC2002,SC2013,SC2034,SC2035,SC2043,SC2046,SC2086,SC2089,SC2090,SC2129,SC2211,SC2231 - name: run pylint - if: matrix.python-version == '3.9' + if: matrix.python-latest run: | - pylint --rcfile=pylintrc_travis addons/*.py - pylint --rcfile=pylintrc_travis htmlreport/cppcheck-htmlreport - pylint --rcfile=pylintrc_travis htmlreport/*.py - pylint --rcfile=pylintrc_travis tools/*.py + shopt -s globstar + pylint --jobs $(nproc) --py-version 3.7 addons/**/*.py htmlreport/cppcheck-htmlreport htmlreport/**/*.py test/**/*.py tools/**/*.py - name: check .json files - if: matrix.python-version == '3.9' + if: matrix.python-latest run: | find . -name '*.json' | xargs -n 1 python -m json.tool > /dev/null - name: Validate - if: matrix.python-version == '3.9' + if: matrix.python-latest run: | make -j$(nproc) validateCFG validatePlatforms validateRules - name: check python syntax - if: matrix.python-version != '2.7' run: | - python -m py_compile addons/*.py + shopt -s globstar + python -m py_compile addons/**/*.py python -m py_compile htmlreport/cppcheck-htmlreport - python -m py_compile htmlreport/*.py - python -m py_compile tools/*.py + python -m py_compile htmlreport/**/*.py + python -m py_compile test/**/*.py + python -m py_compile tools/**/*.py - name: compile addons run: | @@ -84,27 +132,91 @@ jobs: - name: test matchcompiler run: | - python tools/test_matchcompiler.py + python test/tools/test_matchcompiler.py + env: + PYTHONPATH: ./tools - - name: build cppcheck + # TODO: run with "-n auto" when misra_test.py can be run in parallel + # we cannot specify -Werror since xml/etree/ElementTree.py in Python 3.9/3.10 contains an unclosed file + - name: test addons + if: matrix.python-version == '3.9' || matrix.python-version == '3.10' run: | - make -j$(nproc) -s + python -m pytest --strict-markers -vv -n 1 addons/test + env: + PYTHONPATH: ./addons + # TODO: run with "-n auto" when misra_test.py can be run in parallel - name: test addons + if: matrix.python-version != '3.9' && matrix.python-version != '3.10' run: | - python -m pytest addons/test/test-*.py + python -m pytest -Werror --strict-markers -vv -n 1 addons/test env: PYTHONPATH: ./addons - - name: test htmlreport + - name: test htmlreport (standalone) run: | - htmlreport/test_htmlreport.py - cd htmlreport - ./check.sh + test/tools/htmlreport/test_htmlreport.py + test/tools/htmlreport/check.sh - - name: dmake - if: matrix.python-version == '3.9' + - name: test htmlreport (pip) run: | - make -j$(nproc) run-dmake - git diff --exit-code + python -m venv venv + source venv/bin/activate + python -m pip install -U pip + pip install ./htmlreport/ + which cppcheck-htmlreport + PIP_PACKAGE_TEST=1 test/tools/htmlreport/test_htmlreport.py + # TODO: does not test the pip binary + test/tools/htmlreport/check.sh + + - name: test reduce + run: | + python -m pytest -Werror --strict-markers -vv test/tools/reduce_test.py + env: + PYTHONPATH: ./tools + + - name: test donate_cpu_lib + run: | + python -m pytest -Werror --strict-markers -vv test/tools/donate_cpu_lib_test.py + env: + PYTHONPATH: ./tools + + - name: test donate_cpu_server + run: | + python -m pytest -Werror --strict-markers -vv test/tools/donate_cpu_server_test.py + # TODO: why is this file generated? also should be in a temporary folder if possible + rm -f test/tools/donate-cpu-server.log + env: + PYTHONPATH: ./tools + + - name: Show all ignored files + if: false # TODO: currently lists all the contents of ignored folders - we only need what actually matched + run: | + git ls-files --others --ignored --exclude-standard + + - name: Check for changed and unversioned files + run: | + # TODO: how to do this with a single command? + git status --ignored=no + git status --ignored=no | grep -q 'working tree clean' + dmake: + strategy: + matrix: + os: [ubuntu-22.04, macos-13, macos-15, windows-2025] + fail-fast: false + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: run dmake + run: | + make -j3 CXXFLAGS="-w" run-dmake + + - name: check diff + run: | + git diff --exit-code diff --git a/.github/workflows/selfcheck.yml b/.github/workflows/selfcheck.yml new file mode 100644 index 00000000000..69aab78db07 --- /dev/null +++ b/.github/workflows/selfcheck.yml @@ -0,0 +1,189 @@ +# 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: selfcheck + +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-22.04 + + env: + QT_VERSION: 6.9.1 + + 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 + run: | + sudo apt-get update + sudo apt-get install clang-14 + sudo apt-get install libboost-container-dev + sudo apt-get install valgrind + sudo apt-get install -y libgl-dev # fixes missing dependency for Qt in CMake + + - name: Install Qt ${{ env.QT_VERSION }} + uses: jurplel/install-qt-action@v4 + with: + version: ${{ env.QT_VERSION }} + modules: 'qtcharts' + setup-python: 'false' + install-deps: false + cache: true + + # TODO: cache this - perform same build as for the other self check + - name: Self check (build) + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + # valgrind cannot handle DWARF 5 yet so force version 4 + # work around performance regression with -inline-deferral + make -j$(nproc) -s CXXFLAGS="-O2 -w -DHAVE_BOOST -gdwarf-4 -mllvm -inline-deferral" MATCHCOMPILER=yes + env: + CC: clang-14 + CXX: clang++-14 + + # 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 + + - name: Generate dependencies + run: | + # make sure auto-generated GUI files exist + make -C cmake.output autogen + # make sure the precompiled headers exist + make -C cmake.output lib/CMakeFiles/cppcheck-core.dir/cmake_pch.hxx.cxx + make -C cmake.output test/CMakeFiles/testrunner.dir/cmake_pch.hxx.cxx + # 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 + env: + DISABLE_VALUEFLOW: 1 + UNUSEDFUNCTION_ONLY: 1 + # unusedFunction - end + + # the following steps are duplicated from above since setting up the build node in a parallel step takes longer than the actual steps + + # 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 + + - name: Generate dependencies (no test) + run: | + # make sure auto-generated GUI files exist + make -C cmake.output.notest autogen + # make sure the precompiled headers exist + make -C cmake.output.notest lib/CMakeFiles/cppcheck-core.dir/cmake_pch.hxx.cxx + # 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 + env: + DISABLE_VALUEFLOW: 1 + UNUSEDFUNCTION_ONLY: 1 + # unusedFunction notest - end + + # 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 + + - 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 + env: + DISABLE_VALUEFLOW: 1 + UNUSEDFUNCTION_ONLY: 1 + # unusedFunction notest nogui - end + + # 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 + + - name: Generate dependencies (no test / no cli) + run: | + # make sure auto-generated GUI files exist + make -C cmake.output.notest_nocli autogen + # make sure the precompiled headers exist + make -C cmake.output.notest_nocli lib/CMakeFiles/cppcheck-core.dir/cmake_pch.hxx.cxx + # 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 + env: + DISABLE_VALUEFLOW: 1 + UNUSEDFUNCTION_ONLY: 1 + # unusedFunction notest nocli - end + + - name: Fetch corpus + run: | + wget https://github.com/danmar/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 -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + + - name: Generate dependencies (corpus) + run: | + # make sure auto-generated GUI files exist + make -C cmake.output.corpus autogen + # make sure the precompiled headers exist + make -C cmake.output.corpus lib/CMakeFiles/lib_objs.dir/cmake_pch.hxx.cxx + # 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) + cat callgrind.log + callgrind_annotate --auto=no > callgrind.annotated.log + head -50 callgrind.annotated.log + env: + DISABLE_VALUEFLOW: 1 + + - uses: actions/upload-artifact@v4 + with: + name: Callgrind Output + path: ./callgrind.* diff --git a/.github/workflows/tsan.yml b/.github/workflows/tsan.yml new file mode 100644 index 00000000000..4347e5e1b98 --- /dev/null +++ b/.github/workflows/tsan.yml @@ -0,0 +1,158 @@ +# 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.9.1 + 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 3.13 + uses: actions/setup-python@v5 + with: + python-version: '3.13' + 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 20 + + - 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 -DUSE_QT6=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_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + env: + CC: clang-20 + CXX: clang++-20 + + - 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 --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" + 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 -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui/*.cpp || 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 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage/*.cpp || ec=1 + exit $ec diff --git a/.github/workflows/ubsan.yml b/.github/workflows/ubsan.yml index f50ef22c7b3..11dc26a8ec3 100644 --- a/.github/workflows/ubsan.yml +++ b/.github/workflows/ubsan.yml @@ -2,42 +2,151 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: undefined behaviour sanitizers -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: - UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1 + QT_VERSION: 6.9.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 steps: - - uses: actions/checkout@v2 + - 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 3.13 + uses: actions/setup-python@v5 + with: + python-version: '3.13' + check-latest: true - name: Install missing software on ubuntu run: | sudo apt-get update - sudo apt-get install libz3-4 libz3-dev + 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 20 + + - 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: Build - run: make -j$(nproc) cppcheck testrunner USE_Z3=yes HAVE_RULES=yes MATCHCOMPILER=yes VERIFY=1 + # TODO: disable warnings + - name: CMake + run: | + cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DUSE_QT6=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_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache env: - CC: clang - CXX: clang++ - CXXFLAGS: "-fsanitize=undefined -fsanitize=nullability -fno-sanitize=signed-integer-overflow -O1 -g3 -DCPPCHK_GLIBCXX_DEBUG" - CPPFLAGS: "-DCHECK_INTERNAL" + CC: clang-20 + CXX: clang++-20 + + - 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: ./testrunner + run: ./cmake.output/bin/testrunner - - name: Self check + - name: Run cfg tests run: | - ./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli --inconclusive --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings cli lib - ./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ -DQT_VERSION=0x050000 --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=qt -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings gui/*.cpp - ./cppcheck -q -j$(nproc) --std=c++11 --template=selfcheck -D__CPPCHECK__ --error-exitcode=1 --inline-suppr --suppressions-list=.travis_suppressions --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2/ -Icli -Igui --inconclusive --enable=style,performance,portability,warning,internal --exception-handling --debug-warnings test/*.cpp tools + cmake --build cmake.output --target checkcfg -- -j $(nproc) -# This takes too long time right now -# - name: Bughunting lib -# run: ./cppcheck -D__CPPCHECK__ --bug-hunting -j$(nproc) lib + - name: Run CTest + 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 + + - 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 + 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: 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 + 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 --exception-handling --debug-warnings --check-level=exhaustive" + cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2" + 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 -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui/*.cpp || 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 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage/*.cpp || ec=1 + exit $ec diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml index 5f9bb5b978d..7fd16382802 100644 --- a/.github/workflows/valgrind.yml +++ b/.github/workflows/valgrind.yml @@ -2,51 +2,64 @@ # Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners name: valgrind -on: [push, pull_request] +on: + push: + branches: + - 'main' + - 'releases/**' + - '2.*' + tags: + - '2.*' + pull_request: + +permissions: + contents: read jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 - - - name: Prepare - run: | - sudo apt-get update - sudo apt-get install debian-goodies ubuntu-dbgsym-keyring - # the key expired and the ubuntu-dbgsym-keyring package does not yet include the latest one - see https://bugs.launchpad.net/ubuntu/+source/ubuntu-keyring/+bug/1920640 - wget -O - http://ddebs.ubuntu.com/dbgsym-release-key.asc | sudo apt-key add - + - uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Add debug repos on ubuntu - run: | - echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/ddebs.list - echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/ddebs.list - echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/ddebs.list + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ github.workflow }}-${{ runner.os }} - name: Install missing software run: | sudo apt-get update sudo apt-get install libxml2-utils sudo apt-get install valgrind - sudo apt-get install libz3-dev libz3-4 libz3-4-dbgsym - sudo apt-get install libc6-dbg-amd64-cross + sudo apt-get install libboost-container-dev + sudo apt-get install debuginfod - name: Build cppcheck run: | - CXXFLAGS="-O1 -g" make -j$(nproc) USE_Z3=yes HAVE_RULES=yes MATCHCOMPILER=yes + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + CXXFLAGS="-O1 -g -w -DHAVE_BOOST" make -j$(nproc) HAVE_RULES=yes MATCHCOMPILER=yes - name: Build test run: | - CXXFLAGS="-O1 -g" make -j$(nproc) testrunner USE_Z3=yes HAVE_RULES=yes MATCHCOMPILER=yes + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + CXXFLAGS="-O1 -g -w -DHAVE_BOOST" make -j$(nproc) testrunner HAVE_RULES=yes MATCHCOMPILER=yes - name: Run valgrind run: | - 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=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 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 + #env: + # DEBUGINFOD_URLS: https://debuginfod.ubuntu.com - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 + if: success() || failure() with: name: Logs path: ./*.log diff --git a/.gitignore b/.gitignore index 19f081c3e49..9a2c61ded12 100644 --- a/.gitignore +++ b/.gitignore @@ -2,24 +2,27 @@ *.gcno *.o *.pyc -cppcheck -cppcheck.exe +/cppcheck +/cppcheck.exe cppcheck-core.dll -dmake -dmake.exe +/dmake +/dmake.exe reduce reduce.exe tags -testrunner -testrunner.exe +/testrunner +/testrunner.exe tools/daca2*.html -tools/dmake tools/errmsg tools/extracttests +.DS_Store # dump files generated by Cppcheck *.*.dump +# CTU info files generated by Cppcheck +*.*.ctu-info + # VS generated files *.aps *.idb @@ -31,55 +34,30 @@ tools/extracttests *.sdf *.suo *.user -.vs/ +/.vs/ +UpgradeLog*.htm # VS build folders bin/ Build/ BuildTmp/ -cli/temp/ +/cli/temp/ ipch/ -lib/temp/ -test/temp/ +/lib/temp/ +/test/temp/ # XCode build folders and files *.mode[0-9]v[0-9] *.pbxuser build/ -# GUI build folders -gui/debug/ -gui/release/ -gui/temp/ - # Other (generated) GUI files -gui/*.qm -gui/cppcheck-gui -gui/cppcheck-gui.exe -gui/gui.sln -gui/gui.vcproj -gui/Makefile -gui/Makefile.debug -gui/Makefile.release -gui/qrc_gui.cpp -gui/test/Makefile -gui/test/*/Makefile -gui/test/*/*/Makefile -gui/test/benchmark/simple/benchmark-simple -gui/test/filelist/test-filelist -gui/test/projectfile/test-projectfile -gui/test/translationhandler/test-translationhandler -gui/test/xmlreport/test-xmlreport -gui/test/xmlreportv1/test-xmlreportv1 -gui/test/xmlreportv2/test-xmlreportv2 +/gui/help/online-help.qch +/gui/help/online-help.qhc # Doxygen output folder doxyoutput/ -# qmake generated -htmlreport/.tox/ -htmlreport/MANIFEST - # Backup files and stuff from patches *.rej *~ @@ -88,7 +66,7 @@ htmlreport/MANIFEST *.kdev4 # Common cmake build directories -build* +build**/ # Temporal files *.swp @@ -99,25 +77,53 @@ prime parts stage *.snap -snap/.snapcraft +/snap/.snapcraft # Manual folder -man/manual.log -man/manual.tex -man/*.pdf -man/*.html +/man/manual.log +/man/manual.tex +/man/*.pdf +/man/*.html # CLion -.idea +/.idea /.metadata/ -cmake-* +/cmake-build-* +/.run # clang tooling temporary files -.clangd/ -compile_commands.json - -# qmake -/gui/.qmake.stash +/.clangd/ +/.cache/ +/compile_commands.json #vs code -.vscode +/.vscode + +# fuzzing output +/oss-fuzz/corpus +/oss-fuzz/corpus_ +/oss-fuzz/samples + +# Python +/.venv/ +/venv/ +**/*.egg-info/ + +# cppcheck-htmlreport auto files +/htmlreport/cppcheck_htmlreport/run.py + +# GDB configuration +.gdbinit + +# pyinstaller output +/addons/dist +/addons/misra.spec +/htmlreport/cppcheck-htmlreport.spec +/htmlreport/dist + +# ccache folder in CI +/.ccache + +# PCRE Windows files +/externals/pcre.h +/externals/pcre64.lib diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 00000000000..9b14fa2d00e --- /dev/null +++ b/.pylintrc @@ -0,0 +1,66 @@ +[MESSAGES CONTROL] +disable= + # W start + redefined-builtin, + broad-exception-caught, + fixme, + bare-except, + redefined-outer-name, + attribute-defined-outside-init, + unspecified-encoding, + global-statement, + protected-access, + broad-exception-raised, + subprocess-popen-preexec-fn, + logging-not-lazy, + unknown-option-value, + unused-wildcard-import, + wildcard-import, + unused-argument, + pointless-string-statement, + arguments-renamed, + duplicate-string-formatting-argument, + # C start + consider-using-f-string, + invalid-name, + line-too-long, + missing-module-docstring, + missing-function-docstring, + import-outside-toplevel, + missing-class-docstring, + superfluous-parens, + too-many-lines, + trailing-newlines, + missing-final-newline, + use-implicit-booleaness-not-len, + wrong-import-order, + use-implicit-booleaness-not-comparison, + consider-using-enumerate, + unnecessary-lambda-assignment, + consider-using-dict-items, + consider-iterating-dictionary, + # R start + duplicate-code, + consider-using-with, + too-many-statements, + too-many-branches, + too-many-locals, + too-many-arguments, + too-few-public-methods, + too-many-return-statements, + consider-using-in, + too-many-nested-blocks, + too-many-public-methods, + chained-comparison, + too-many-instance-attributes, + too-many-boolean-expressions, + use-a-generator, + too-many-positional-arguments +[REPORTS] +reports=no +[TYPECHECK] +# See https://stackoverflow.com/questions/10300082/how-to-prevent-python-pylint-complaining-about-socket-class-sendall-method +ignored-classes=SQLObject,_socketobject +[MASTER] +init-hook='import sys; sys.path.append("./addons")' +suggestion-mode=yes diff --git a/.selfcheck_suppressions b/.selfcheck_suppressions new file mode 100644 index 00000000000..6a00f33655f --- /dev/null +++ b/.selfcheck_suppressions @@ -0,0 +1,38 @@ +missingIncludeSystem + +# temporary suppressions - fix the warnings! +simplifyUsing:lib/valueptr.h +varid0:gui/projectfile.cpp +naming-privateMemberVariable:gui/test/cppchecklibrarydata/testcppchecklibrarydata.h +symbolDatabaseWarning:*/moc_*.cpp +simplifyUsing:*/moc_*.cpp + +# warnings in Qt generated code we cannot fix +funcArgNamesDifferent:*/moc_*.cpp +naming-varname:*/ui_*.h +functionStatic:*/ui_fileview.h + +# --debug-warnings suppressions +valueFlowBailout +valueFlowBailoutIncompleteVar +autoNoType +# ticket 11631 +templateInstantiation:test/testutils.cpp + +naming-varname:externals/simplecpp/simplecpp.h +naming-privateMemberVariable:externals/simplecpp/simplecpp.h + +valueFlowMaxIterations:externals/tinyxml2/tinyxml2.cpp + +# TODO: these warnings need to be addressed upstream +uninitMemberVar:externals/tinyxml2/tinyxml2.h +noExplicitConstructor:externals/tinyxml2/tinyxml2.h +missingOverride:externals/tinyxml2/tinyxml2.h +invalidPrintfArgType_sint:externals/tinyxml2/tinyxml2.h +naming-privateMemberVariable:externals/tinyxml2/tinyxml2.h +functionStatic:externals/tinyxml2/tinyxml2.cpp +invalidPrintfArgType_uint:externals/tinyxml2/tinyxml2.cpp +funcArgNamesDifferent:externals/tinyxml2/tinyxml2.cpp +nullPointerRedundantCheck:externals/tinyxml2/tinyxml2.cpp +knownConditionTrueFalse:externals/tinyxml2/tinyxml2.cpp +useStlAlgorithm:externals/simplecpp/simplecpp.cpp diff --git a/.selfcheck_unused_suppressions b/.selfcheck_unused_suppressions new file mode 100644 index 00000000000..ce685d8ab10 --- /dev/null +++ b/.selfcheck_unused_suppressions @@ -0,0 +1,8 @@ +# 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/.travis.yml b/.travis.yml deleted file mode 100644 index d22cfc4af01..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,129 +0,0 @@ -language: cpp -dist: xenial - -compiler: - - gcc - - clang - -env: - global: - - ORIGINAL_CXXFLAGS="-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 -D_GLIBCXX_DEBUG -g" -# unfortunately we need this to stay within 50min timelimit given by travis. - - CXXFLAGS="${ORIGINAL_CXXFLAGS} -O2 -march=native -Wstrict-aliasing=2 -Werror=strict-aliasing" - - CPPCHECK=${TRAVIS_BUILD_DIR}/cppcheck - matrix: - - CXXFLAGS="${CXXFLAGS} -DCHECK_INTERNAL" - - CXXFLAGS="${CXXFLAGS} -DCHECK_INTERNAL" MAKEFLAGS="HAVE_RULES=yes" MATCHCOMPILER=yes VERIFY=1 - -before_install: -# install needed deps - - travis_retry sudo apt-get update -qq - - travis_retry sudo apt-get install -qq python3-pip libxml2-utils libpcre3 gdb unzip wx-common xmlstarlet python3-dev liblua5.3-dev libcurl3 libcairo2-dev libsigc++-2.0-dev tidy libopencv-dev libz3-dev -# Python 2 modules - - travis_retry python2 -m pip install --user pytest==4.6.4 - - travis_retry python2 -m pip install --user unittest2 - - travis_retry python2 -m pip install --user pexpect # imported by tools/ci.py - - travis_retry python2 -m pip install --user pygments -# Python 3 modules - - travis_retry python3 -m pip install --user setuptools --upgrade - - travis_retry python3 -m pip install --user pytest - - travis_retry python3 -m pip install --user unittest2 - - travis_retry python3 -m pip install --user pexpect # imported by tools/ci.py - - travis_retry python3 -m pip install --user requests # imported by tools/pr.py - - travis_retry python3 -m pip install --user pygments - - travis_retry python3 -m pip install --user natsort - - cp externals/z3_version_old.h externals/z3_version.h # because travis z3 version is old - -matrix: -# do notify immediately about it when a job of a build fails. - fast_finish: true -# defined extra jobs that run besides what is configured in the build matrix - include: - -# check a lot of stuff that only needs to be checked in a single configuration - - name: "misc" - compiler: clang - script: - - make -j$(nproc) -s -# check if DESTDIR works TODO: actually execute this - - mkdir install_test - - echo $CXXFLAGS - - make -s DESTDIR=install_test FILESDIR=/usr/share/cppcheck install -# rm everything - - git clean -dfx -# check what happens if we want to install it to some other dir, - - echo $CXXFLAGS - - make -s MATCHCOMPILER=yes FILESDIR=/usr/share/cppcheck -j$(nproc) - - sudo make MATCHCOMPILER=yes FILESDIR=/usr/share/cppcheck install -# check if it actually works: - - /usr/bin/cppcheck -j$(nproc) ./cli -# check addons/misc.py - - cd addons/test - - ${CPPCHECK} --dump misc-test.cpp - - python3 ../misc.py -verify misc-test.cpp.dump - - cd ../../ -# check addons/cert.py - - cd addons/test - - ${CPPCHECK} --dump cert-test.c - - python3 ../cert.py -verify cert-test.c.dump - - ${CPPCHECK} --dump cert-test.cpp - - python3 ../cert.py -verify cert-test.cpp.dump - - cd ../../ -# check addons/misra.py - - cd addons/test - # We'll force C89 standard to enable an additional verification for - # rules 5.4 and 5.5 which have standard-dependent options. - - ${CPPCHECK} --dump --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra/misra-test.c - - ${CPPCHECK} --dump --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra/misra-test.h - - python3 ../misra.py -verify misra/misra-test.c.dump - - ${CPPCHECK} --dump misra/misra-test.cpp - - python3 ../misra.py -verify misra/misra-test.cpp.dump - - python ../misra.py --rule-texts=misra/misra2012_rules_dummy_ascii.txt -verify misra/misra-test.cpp.dump - - python3 ../misra.py --rule-texts=misra/misra2012_rules_dummy_ascii.txt -verify misra/misra-test.cpp.dump - - python ../misra.py --rule-texts=misra/misra2012_rules_dummy_utf8.txt -verify misra/misra-test.cpp.dump - - python3 ../misra.py --rule-texts=misra/misra2012_rules_dummy_utf8.txt -verify misra/misra-test.cpp.dump - - python ../misra.py --rule-texts=misra/misra2012_rules_dummy_windows1250.txt -verify misra/misra-test.cpp.dump - - python3 ../misra.py --rule-texts=misra/misra2012_rules_dummy_windows1250.txt -verify misra/misra-test.cpp.dump - - cd ../../ -# check addons/naming.py - - cd addons/test - - ${CPPCHECK} --dump naming_test.c - - python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump - - ${CPPCHECK} --dump naming_test.cpp - - python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump - - cd ../.. -# check addons/namingng.py - - cd addons/test - - ${CPPCHECK} --dump namingng_test.c - - python3 ../namingng.py --configfile ../naming.json --verify namingng_test.c.dump - - cd ../.. - -# bug hunting - - name: "bug hunting" - compiler: gcc - script: - - make clean - - make USE_Z3=yes -j$(nproc) all - - ./testrunner TestExprEngine - # FIXME: this is slowish - #- python3 test/bug-hunting/cve.py - #- git clone https://github.com/regehr/itc-benchmarks.git ~/itc - #- python3 test/bug-hunting/itc.py - #- mkdir ~/juliet - #- curl https://samate.nist.gov/SARD/testsuites/juliet/Juliet_Test_Suite_v1.3_for_C_Cpp.zip -o ~/juliet/juliet.zip - #- cd ~/juliet - #- unzip -qq ~/juliet/juliet.zip - #- cd - - #- python3 test/bug-hunting/juliet.py - -script: -# fail the entire job as soon as one of the subcommands exits non-zero to save time and resources - - set -e -# check with TEST_MATHLIB_VALUE enabled - - touch lib/mathlib.cpp test/testmathlib.cpp - - echo $CXXFLAGS - - make -s check -j$(nproc) CPPFLAGS=-DTEST_MATHLIB_VALUE - - touch lib/mathlib.cpp test/testmathlib.cpp -# compile cppcheck, default build - - echo $CXXFLAGS - - make -s check -j$(nproc) diff --git a/.travis_llvmcheck_suppressions b/.travis_llvmcheck_suppressions deleted file mode 100644 index f95909b7d27..00000000000 --- a/.travis_llvmcheck_suppressions +++ /dev/null @@ -1,8 +0,0 @@ -unreadVariable -shadowVar -shadowFunction -unusedStructMember -nullPointer -uninitvar -noExplicitConstructor - diff --git a/.travis_suppressions b/.travis_suppressions deleted file mode 100644 index b616b148010..00000000000 --- a/.travis_suppressions +++ /dev/null @@ -1,23 +0,0 @@ -unusedPrivateFunction:test/testbufferoverrun.cpp -unusedPrivateFunction:test/testcmdlineparser.cpp -shadowFunction -functionConst -functionStatic -bitwiseOnBoolean - -# temporary suppressions - fix the warnings! -unusedPrivateFunction:test/test*.cpp -useStlAlgorithm -simplifyUsing:lib/valueptr.h - -# debug suppressions -valueFlowBailout -valueFlowBailoutIncompleteVar -varid0 -autoNoType -bailoutUninitVar - -*:gui/test/* -*:test/test.cxx -*:test/cfg/* -*:externals/*/* diff --git a/.uncrustify.cfg b/.uncrustify.cfg new file mode 100644 index 00000000000..81722ff7249 --- /dev/null +++ b/.uncrustify.cfg @@ -0,0 +1,170 @@ +# Uncrustify-0.80.1_f + +# The original size of tabs in the input. +# +# Default: 8 +input_tab_size = 4 # unsigned number + +# The size of tabs in the output (only used if align_with_tabs=true). +# +# Default: 8 +output_tab_size = 4 # unsigned number + +# Add or remove space between 'while' and '('. +sp_while_paren_open = add # ignore/add/remove/force + +# Add or remove space around boolean operators '&&' and '||'. +sp_bool = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')'. +sp_inside_paren = remove # ignore/add/remove/force + +# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. +sp_paren_paren = remove # ignore/add/remove/force + +# Add or remove space between ')' and '{'. +sp_paren_brace = force # ignore/add/remove/force + +# Add or remove space between pointer stars '*'. +sp_between_ptr_star = remove # ignore/add/remove/force + +# Add or remove space before '<'. +sp_before_angle = remove # ignore/add/remove/force + +# Add or remove space inside '<' and '>'. +sp_inside_angle = remove # ignore/add/remove/force + +# Add or remove space after '>'. +sp_after_angle = add # ignore/add/remove/force + +# Add or remove space between '>' and '(' as found in 'new List(foo);'. +sp_angle_paren = remove # ignore/add/remove/force + +# Add or remove space between '>' and a word as in 'List m;' or +# 'template static ...'. +sp_angle_word = add # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff). +# +# Default: add +sp_angle_shift = ignore # ignore/add/remove/force + +# (C++11) Permit removal of the space between '>>' in 'foo >'. Note +# that sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = true # true/false + +# Add or remove space before '(' of control statements ('if', 'for', 'switch', +# 'while', etc.). +sp_before_sparen = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')' of control statements. +sp_inside_sparen = remove # ignore/add/remove/force + +# Add or remove space after ')' of control statements. +sp_after_sparen = force # ignore/add/remove/force + +# Add or remove space between ')' and '{' of of control statements. +sp_sparen_brace = force # ignore/add/remove/force + +# Add or remove space before ';' in non-empty 'for' statements. +sp_before_semi_for = remove # ignore/add/remove/force + +# Add or remove space after the final semicolon of an empty part of a for +# statement, as in 'for ( ; ; )'. +sp_after_semi_for_empty = remove # ignore/add/remove/force + +# Add or remove space before '[]'. +sp_before_squares = remove # ignore/add/remove/force + +# Add or remove space before C++17 structured bindings. +sp_cpp_before_struct_binding = ignore # ignore/add/remove/force + +# Add or remove space inside a non-empty '[' and ']'. +sp_inside_square = remove # ignore/add/remove/force + +# Add or remove space after class ':'. +sp_after_class_colon = force # ignore/add/remove/force + +# Add or remove space before class ':'. +sp_before_class_colon = force # ignore/add/remove/force + +# Add or remove space inside '{}'. +sp_inside_braces_empty = remove # ignore/add/remove/force + +# Add or remove space between 'else' and '{' if on the same line. +sp_else_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'else' if on the same line. +sp_brace_else = force # ignore/add/remove/force + +# Add or remove space before the '{' of a 'catch' statement, if the '{' and +# 'catch' are on the same line, as in 'catch (decl) {'. +sp_catch_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'catch' if on the same line. +sp_brace_catch = force # ignore/add/remove/force + +# The number of columns to indent per level. Usually 2, 3, 4, or 8. +# +# Default: 8 +indent_columns = 4 # unsigned number + +# How to use tabs when indenting code. +# +# 0: Spaces only +# 1: Indent with tabs to brace level, align with spaces (default) +# 2: Indent and align with tabs, using spaces when not on a tabstop +# +# Default: 1 +indent_with_tabs = 0 # unsigned number + +# Whether to indent the body of a 'namespace'. +indent_namespace = true # true/false + +# Whether the 'class' body is indented. +indent_class = true # true/false + +# How to indent access specifiers that are followed by a +# colon. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_access_spec = -4 # number + +# Whether to collapse empty blocks between '{' and '}' except for functions. +# Use nl_collapse_empty_body_functions to specify how empty function braces +# should be formatted. +nl_collapse_empty_body = true # true/false + +# Whether to collapse empty blocks between '{' and '}' for functions only. +# If true, overrides nl_inside_empty_func. +nl_collapse_empty_body_functions = true # true/false + +# Whether to convert all tabs to spaces in comments. If false, tabs in +# comments are left alone, unless used for indenting. +cmt_convert_tab_to_spaces = true # true/false + +# An offset value that controls the indentation of the body of a multiline #define. +# 'body' refers to all the lines of a multiline #define except the first line. +# Requires 'pp_ignore_define_body = false'. +# +# <0: Absolute column: the body indentation starts off at the specified column +# (ex. -3 ==> the body is indented starting from column 3) +# >=0: Relative to the column of the '#' of '#define' +# (ex. 3 ==> the body is indented starting 3 columns at the right of '#') +# +# Default: 8 +pp_multiline_define_body_indent = 4 # number + +# The value might be used twice: +# - at the assignment +# - at the opening brace +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indentation will be used only once +# false: indentation will be used every time (default) +indent_cpp_lambda_only_once = true # true/false diff --git a/AUTHORS b/AUTHORS index 88c61726831..6c72fe81730 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,5 +1,6 @@ The cppcheck team, in alphabetical order: +0x41head Abhijit Sawant Abhishek Bharadwaj Abigail Buccaneer @@ -12,34 +13,47 @@ Albert Aribaud Aleksandr Pikalev Aleksey Palazhchenko Alexander Alekseev +Alexander Festini Alexander Gushchin Alexander Mai Alexander Tkachev Alexandre Chouvellon Alexey Eryomenko Alexey Zhikhartsev +Alfi Maulana Ali Can Demiralp +Allen Winter +Alon Alexander Alon Liberman Ameen Ali Andreas Bacher Andreas Bießmann Andreas Grob +Andreas Lutsch Andreas Pokorny Andreas Rönnquist Andreas Vollenweider Andrei Karas +Andrew C Aitchison Andrew C. Martin +Andrew D. Bancroft +Andy Holmes Andy Maloney +Andy Mac Gregor Aneesh Azhakesan S Ankita Gupta +anoymouserver +Anton Lindqvist Antti Tuppurainen Anurag Garg Armin Müller Arpit Chaudhary +Artemis Meursault Gerrard August Sodora Ayaz Salikhov Balázs Tóth Baris Demiray +Bart vdr. Meulen Bartlomiej Grzeskowiak bbennetts Benjamin Bannier @@ -52,42 +66,58 @@ Ben T Bernd Buschinski Bill Egert Björge Dijkstra +Björn Blissing booga Boris Barbulovski Boris Egorov Boussaffa Walid Bo Rydberg +bzgec Carl Michael Grüner Monzón +Carl Morgan Carlo Marcelo Arenas Belón Carlos Gomes Martinho Carl-Oskar Larsson +Cary Converse Cary R +Caspar Kielwein Changkyoon Kim +Chris Lalancette Christian Ehrlicher Christian Franke +Christian Göttsche +Christoph Grüninger Christoph Schmidt Christoph Strehle Chuck Larson +Cilyan Olowen +Claus Jensby Madsen Colomban Wendling Conrado Gouvea daisuke-chiba Daniel Friedrich +David Korczynski Daniel Marjamäki David Hallas David Korth +Dávid Slivka Debrard Sebastien Deepak Gupta +Degen's Regens dencat Diego de las Heras Dirk Jagdmann +Dirk Mueller Dmitriy Dmitry Marakasov Dmitry-Me +dsamo Duraffort Edoardo Prezioso Eivind Tagseth Elbert Pol Emmanuel Blot +Eric Lemanissier Eric Malenfant Eric Sesterhenn Erik Hovland @@ -95,12 +125,16 @@ Erik Lax Ettl Martin Even Rouault Evgeny Mandrikov +feelamee Felipe Pena +Felix Faber Felix Geyer Felix Passenberg Felix Wolff Florin Iucha Francesc Elies +François Berder +Frank Winklmeier Frank Zingsheim Frederik Schwarzer fu7mu4 @@ -109,17 +143,23 @@ Garrett Bodily Gary Leutheuser gaurav kaushik Gennady Feldman +Georgi D. Sotirov Georgy Komarov +Gerbo Engels Gerhard Zlabinger +Gerik Rhoden Gianfranco Costamagna Gianluca Scacco Gleydson Soares Goran Džaferi Graham Whitted Greg Hewgill +Guillaume A. +Guillaume Chauvel Guillaume Miossec Gustav Palmqvist Günther Makulik +Haowei Hsu Harald Scheidl Heiko Bauke Heiko Eißfeldt @@ -129,6 +169,7 @@ He Yuqi Hoang Tuan Su Igor Rondarev Igor Zhukov +Ilya Shipitsin Ivan Maidanski Iván Matellanes Ivan Ryabov @@ -138,54 +179,72 @@ Jan Egil Ruud Jan Hellwig János Maros Jay Sigbrandt +Jedrzej Klocek Jens Bäckman +Jens Yllman Jérémy Lefaure Jes Ramsing Jesse Boswell +Jim Kuhn Jim Zhou jlguardi +Joel Johnson +Johan Bertrand Johan Samuelson John Marshall John-Paul Ore John Smits Jonathan Clohessy +Jonathan Haehne Jonathan Neuschäfer Jonathan Thackray +José Martins Jose Roquette Joshua Beck Joshua Rogers Julian Santander +Julien Marrec Julien Peyregne Jure Menart Jussi Lehtola Jørgen Kvalsvik Kamil Dudka Kartik Bajaj +Kefu Chai keinflue Ken-Patrick Lehrmann Ketil Skjerve Kevin Christian Kevin Kendzia Kimmo Varis +Kitsios Konstantinos +Kleber Tarcísio Konrad Grochowski Konrad Windszus Kumar Ashwani +Kushal Chandar Kyle Chisholm Lars Even Almaas larudwer Lau bakman Lauri Nurmi +Leander Schulten Leandro Lisboa Penz +Leila F. Rahman Lena Herscheid +Leon De Andrade Lieven de Cock lioncash Lionel Gimbert Lucas Manuel Rodriguez +Ludvig Gunne Lindström Luis Díaz Más +Luís Pereira Lukas Grützmacher Lukasz Czajczyk Łukasz Jankowski Luxon Jean-Pierre +Maarten van der Schrieck Maksim Derbasov Malcolm Parsons Marc-Antoine Perennou @@ -194,7 +253,9 @@ Marco Trevisan Marek Zmysłowski Marian Klymov Mark de Wever +Mark Hermeling Markus Elfring +Martin Delille Martin Ettl Martin Exner Martin Güthle @@ -202,6 +263,8 @@ Martin Herren Márton Csordás Masafumi Koba Massimo Paladin +Mateusz Michalak +Mateusz Patyk Mateusz Pusz Mathias De Maré Mathias Schmid @@ -209,7 +272,10 @@ Matthias Krüger Matthias Kuhn Matthias Schmieder Matt Johnson +Maurice Gilden Mavik +Michael Drake +Michael Løiten Miika-Petteri Matikainen Mika Attila Mike Tzou @@ -230,26 +296,37 @@ Nicolás Alvarez Nicolas Le Cam Nilesh Kumar Ogawa KenIchi +Oleksandr Labetskyi Oleksandr Redko Oliver Schode Oliver Stöneberg Olivier Croquette +Patrick Oppenlander Paul Aitken +Paul Bersee Paul Fultz II Pavel Bibergal Pavel Pimenov Pavel Roschin Pavel Skipenes +Pavel Šimovec Pavol Misik Pete Johns Peter Pentchev +Peter Schops +Philip Chimento Philipp Kloke Pierre Schweitzer +Pieter Duchi Pino Toscano Pranav Khanna +Radek Jarecki +Rainer Wiesenfarth Ramzan Bekbulatov Raphael Geissert +Razvan Ioan Alexe Reijo Tomperi +Rainer Wiesenfarth Riccardo Ghetta Richard A. Smith Richard Quirk @@ -262,21 +339,30 @@ Roberto Martelloni Robert Reif rofl0r Roman Zaytsev Borisovich +Ronald Hiemstra root Rosen Penev +Rudi Danner Rudolf Grauberger +Ryan M. Lederman Ryan Pavlik Samir Aguiar Sam Truscott Samuel Degrande +Samuel Poláček Sandeep Dutta Savvas Etairidis +Scott Ehlert Scott Furry +Seafarix Ltd. Sebastian Held Sebastian Matuschka Sébastien Debrard +Sergei Chernykh +Sergei Trofimovich Sergey Burgsdorf Shane Tapp +Shohei YOSHIDA Simon Cornell Simon Kagstrom Simon Large @@ -285,7 +371,9 @@ Simon Shanks Slava Semushin Stas Cymbalov Stefan Beller +Stefan Hagen Stefan Naewe +Stefan van Kessel Stefan Weil Stéphane Michel Steve Browne @@ -293,37 +381,51 @@ Steve Duan Steve Mokris Steven Cook Steven Myint +Sune Stolborg Vuorela Susi Lehtola +Sven Wienand Swasti Shrivastava Sylvain Joubert Tam Do Thanh Teddy Didé +Temuri Doghonadze Thomas Arnhold +Tomasz Edward Posluszny Thomas Jarosch Thomas Niederberger Thomas Otto +Thomas P. K. Healy Thomas Sondergaard Thorsten Sick +Tim Blume Tim Gerundt tititiou36 +Tobias Weber Tobias Weibel Tomasz Kłoczko Tom Pollok +Tomo Dote +Tommy Bergman Toralf Förster Troshin V.S. Tyson Nottingham +Valentin Batz Valerii Lashmanov Vasily Maslyukov Veli-Matti Visuri -WenChung Chiu Vesa Pikki Ville-Pekka Vahteala Ville Skyttä Vincent Le Garrec +Vladimir Petrigo +Wang Haoyu +Wang Yang +WenChung Chiu Wolfgang Stöggl x29a XhmikosR Xuecheng Zhang +Yichen Yan Yurii Putin Zachary Blair Zhao Qifa diff --git a/CMakeLists.txt b/CMakeLists.txt index e52750acecd..e2cd3029058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,50 +1,111 @@ -cmake_minimum_required(VERSION 2.8.12) -project(Cppcheck) +cmake_minimum_required(VERSION 3.13) +project(Cppcheck VERSION 2.18.99 LANGUAGES CXX) + +include(cmake/options.cmake) + +include(cmake/cxx11.cmake) +use_cxx11() +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(GNUInstallDirs) +include(cmake/compilerCheck.cmake) include(cmake/versions.cmake) -include(cmake/options.cmake) include(cmake/findDependencies.cmake) include(cmake/compileroptions.cmake) include(cmake/compilerDefinitions.cmake) include(cmake/buildFiles.cmake) -include(cmake/cxx11.cmake) +if(BUILD_GUI) + include(cmake/qtCompat.cmake) +endif() +include(cmake/printInfo.cmake) -use_cxx11() -file(GLOB addons "addons/*.py") +file(GLOB addons_py "addons/*.py") +file(GLOB addons_json "addons/*.json") file(GLOB cfgs "cfg/*.cfg") file(GLOB platforms "platforms/*.xml") -find_program(LIBXML2_XMLLINT_EXECUTABLE xmllint) -if (LIBXML2_XMLLINT_EXECUTABLE) - add_custom_target(validateCFG ${LIBXML2_XMLLINT_EXECUTABLE} --noout ${CMAKE_SOURCE_DIR}/cfg/cppcheck-cfg.rng) +if(LIBXML2_XMLLINT_EXECUTABLE) + add_custom_target(validateCFG DEPENDS validateCFG-cmd) + add_custom_command(OUTPUT validateCFG-cmd + COMMAND ${LIBXML2_XMLLINT_EXECUTABLE} --noout ${CMAKE_SOURCE_DIR}/cfg/cppcheck-cfg.rng) foreach(cfg ${cfgs}) - get_filename_component(cfgname ${cfg} NAME_WE) - add_custom_target(validateCFG-${cfgname} ${LIBXML2_XMLLINT_EXECUTABLE} --noout --relaxng ${CMAKE_SOURCE_DIR}/cfg/cppcheck-cfg.rng ${cfg}) - add_dependencies(validateCFG validateCFG-${cfgname}) + add_custom_command(OUTPUT validateCFG-cmd APPEND + COMMAND ${LIBXML2_XMLLINT_EXECUTABLE} --noout --relaxng ${CMAKE_SOURCE_DIR}/cfg/cppcheck-cfg.rng ${cfg}) + endforeach() + # this is a symbolic name for a build rule and not an output file + set_source_files_properties(validateCFG-cmd PROPERTIES SYMBOLIC "true") + + add_custom_target(validatePlatforms ${LIBXML2_XMLLINT_EXECUTABLE} --noout ${CMAKE_SOURCE_DIR}/platforms/cppcheck-platforms.rng) + foreach(platform ${platforms}) + get_filename_component(platformname ${platform} NAME_WE) + add_custom_target(validatePlatforms-${platformname} ${LIBXML2_XMLLINT_EXECUTABLE} --noout --relaxng ${CMAKE_SOURCE_DIR}/platforms/cppcheck-platforms.rng ${platform}) + add_dependencies(validatePlatforms validatePlatforms-${platformname}) endforeach() + + add_custom_target(errorlist-xml $ --errorlist > ${CMAKE_BINARY_DIR}/errorlist.xml + DEPENDS cppcheck) + + add_custom_target(example-xml $ --xml --enable=all --inconclusive --max-configs=1 ${CMAKE_SOURCE_DIR}/samples 2> ${CMAKE_BINARY_DIR}/example.xml + DEPENDS cppcheck) + + add_custom_target(createXMLExamples DEPENDS errorlist-xml example-xml) + + if(Python_EXECUTABLE) + add_custom_target(checkCWEEntries ${Python_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/listErrorsWithoutCWE.py -F ${CMAKE_BINARY_DIR}/errorlist.xml + DEPENDS errorlist-xml) + endif() + + add_custom_target(validateXML ${LIBXML2_XMLLINT_EXECUTABLE} --noout ${CMAKE_SOURCE_DIR}/cppcheck-errors.rng + COMMAND ${LIBXML2_XMLLINT_EXECUTABLE} --noout --relaxng ${CMAKE_SOURCE_DIR}/cppcheck-errors.rng ${CMAKE_BINARY_DIR}/errorlist.xml + COMMAND ${LIBXML2_XMLLINT_EXECUTABLE} --noout --relaxng ${CMAKE_SOURCE_DIR}/cppcheck-errors.rng ${CMAKE_BINARY_DIR}/example.xml + DEPENDS createXMLExamples + ) + + add_custom_target(validateRules ${LIBXML2_XMLLINT_EXECUTABLE} --noout ${CMAKE_SOURCE_DIR}/rules/*.xml) endif() -if (BUILD_TESTS) +# TODO: add the following Makefile features: +# - "man/cppcheck.1" target +# - "tags" target +# - 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" + COMMENT "Copying cfg files to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}") + +# TODO: copy *.py and *.json only +add_custom_target(copy_addons ALL + ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/addons" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/addons" + COMMENT "Copying addons files to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}") + +add_custom_target(copy_platforms ALL + ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/platforms" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/platforms" + COMMENT "Copying platforms files to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}") + if(USE_BUNDLED_TINYXML2) message(STATUS "Using bundled version of tinyxml2") add_subdirectory(externals/tinyxml2) endif() add_subdirectory(externals/simplecpp) -add_subdirectory(lib) # CppCheck Library +add_subdirectory(lib) # CppCheck Library +add_subdirectory(frontend) add_subdirectory(cli) # Client application add_subdirectory(test) # Tests add_subdirectory(gui) # Graphical application -add_subdirectory(tools/triage) # Triage tool -add_subdirectory(oss-fuzz) # OSS-Fuzz clients add_subdirectory(tools) +add_subdirectory(man) -include(cmake/printInfo.cmake) include(cmake/clang_tidy.cmake) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..e80e4a3b581 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,53 @@ +# Contributing To Cppcheck + +These are some guidelines *any* contributor should follow. They will help to make for better contributions which will most likely allow for them to be processed. + +(TODO: move daca@home section here?) + +## Code Changes + +Code contributions are handled via GitHub pull requests: https://github.com/danmar/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. + +Any kind of contribution is welcome but we might reject it. In that case we usually provide an explanation for the reasons but everything is always open to discussion. + +Changes in the `externals` folder need to be submitted to the respective upstream projects and will be pulled downstream with their next stable release (`picojson` is an exception because it is no longer maintained - the handling of such changes is not yet determined - see also https://trac.cppcheck.net/ticket/12233). + +Also after you filed a pull request please be ready to reply to questions and feedback. If you just "dump and leave" it might lower the chances of your change being accepted. This also applies after the PR was successfully merged as it might cause issues which were not exposed by the CI. + +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. + +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`. + +The CI is already doing a lot of work but there are certain parts it cannot ensure. + +(TODO: mention test_pr.py) + +The CI has an "always green" approach which means that failing tests are not allowed. Flakey tests might be acceptable depending on the frequency of their failures but they should be accompanied by ticket so they are being tracked. If introduce a test which is expected to fail you should use the `TODO_*` macros (C++) or `@pytest.mark.xfail(strict=False)` annotations. + +Note: Usually you can run the CI on your own fork to verify that it passes before even open an PR. Unfortunately some changes to avoid duplicated builds in our CI disabled this (TODO: file a ticket about this). + +### Targets + +Cppcheck is tracking its issues at https://trac.cppcheck.net. + +[False Positives](https://trac.cppcheck.net/query?status=accepted&status=assigned&status=new&status=reopened&component=False+positive&col=id&col=summary&col=status&col=component&col=type&col=priority&col=milestone&order=priority) + +Since Cppcheck aims to be low on false positives, these kind of issues are obviously of the highest priority. + +[Detection Regressions](https://trac.cppcheck.net/query?status=accepted&status=assigned&status=new&status=reopened&keywords=~regression&component=Improve+check&col=id&col=summary&col=status&col=type&col=priority&col=milestone&col=component&order=priority) + +Changes might lead to fewer findings being reported. In very few cases this might be intentional but we should not regress in what findings are being reported. + +[Other Defects](https://trac.cppcheck.net/query?status=accepted&status=assigned&status=new&status=reopened&type=defect&component=!False+positive&col=id&col=summary&col=type&col=status&col=component&col=priority&col=milestone&order=priority) + +## Translations + +We are also maintaining various translations for `cppcheck-gui`. + +Several of these are not complete or might be out-of-date so contributions are welcome. We will also accept additional languages but such contributions should be complete. + +(TODO: provide more details) diff --git a/Makefile b/Makefile index 995ec70f1ba..9ba42bb6bb1 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,26 @@ -# This file is generated by tools/dmake, do not edit. +# This file is generated by dmake, do not edit. +ifndef VERBOSE + VERBOSE= +endif # To compile with rules, use 'make HAVE_RULES=yes' ifndef HAVE_RULES - HAVE_RULES=no -endif - -ifndef USE_Z3 - USE_Z3=no + HAVE_RULES= endif -ifeq ($(USE_Z3),yes) - CPPFLAGS += -DUSE_Z3 - LIBS += -lz3 +ifndef MATCHCOMPILER + MATCHCOMPILER= endif # use match compiler -ifeq ($(SRCDIR),build) - $(warning Usage of SRCDIR to activate match compiler is deprecated. Use MATCHCOMPILER=yes instead.) - MATCHCOMPILER:=yes -endif ifeq ($(MATCHCOMPILER),yes) # Find available Python interpreter - PYTHON_INTERPRETER := $(shell which python) - ifndef PYTHON_INTERPRETER + ifeq ($(PYTHON_INTERPRETER),) PYTHON_INTERPRETER := $(shell which python3) endif - ifndef PYTHON_INTERPRETER + ifeq ($(PYTHON_INTERPRETER),) + PYTHON_INTERPRETER := $(shell which python) + endif + ifeq ($(PYTHON_INTERPRETER),) $(error Did not find a Python interpreter) endif ifdef VERIFY @@ -33,40 +29,76 @@ ifeq ($(MATCHCOMPILER),yes) matchcompiler_S := $(shell $(PYTHON_INTERPRETER) tools/matchcompiler.py) endif libcppdir:=build -else +else ifeq ($(MATCHCOMPILER),) libcppdir:=lib +else + $(error invalid MATCHCOMPILER value '$(MATCHCOMPILER)') +endif + +ifndef CPPFLAGS + CPPFLAGS= endif ifdef FILESDIR - CPPFILESDIR=-DFILESDIR=\"$(FILESDIR)\" -else - CPPFILESDIR= + override CPPFLAGS+=-DFILESDIR=\"$(FILESDIR)\" endif RDYNAMIC=-rdynamic # Set the CPPCHK_GLIBCXX_DEBUG flag. This flag is not used in release Makefiles. # The _GLIBCXX_DEBUG define doesn't work in Cygwin or other Win32 systems. ifndef COMSPEC + ifeq ($(VERBOSE),1) + $(info COMSPEC not found) + endif ifdef ComSpec + ifeq ($(VERBOSE),1) + $(info ComSpec found) + endif #### ComSpec is defined on some WIN32's. - COMSPEC=$(ComSpec) + WINNT=1 + + ifeq ($(VERBOSE),1) + $(info PATH=$(PATH)) + endif + + ifneq (,$(findstring /cygdrive/,$(PATH))) + ifeq ($(VERBOSE),1) + $(info /cygdrive/ found in PATH) + endif + CYGWIN=1 + endif # CYGWIN endif # ComSpec endif # COMSPEC -ifdef COMSPEC +ifdef WINNT + ifeq ($(VERBOSE),1) + $(info WINNT found) + endif #### Maybe Windows ifndef CPPCHK_GLIBCXX_DEBUG CPPCHK_GLIBCXX_DEBUG= endif # !CPPCHK_GLIBCXX_DEBUG - ifeq ($(MSYSTEM),MINGW32 MINGW64) - LDFLAGS=-lshlwapi - else - RDYNAMIC=-lshlwapi + ifeq ($(VERBOSE),1) + $(info MSYSTEM=$(MSYSTEM)) + endif + + ifneq ($(MSYSTEM),MINGW32 MINGW64) + RDYNAMIC= + endif + + LDFLAGS+=-lshlwapi +else # !WINNT + ifeq ($(VERBOSE),1) + $(info WINNT not found) endif -else # !COMSPEC + uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') + ifeq ($(VERBOSE),1) + $(info uname_S=$(uname_S)) + endif + ifeq ($(uname_S),Linux) ifndef CPPCHK_GLIBCXX_DEBUG CPPCHK_GLIBCXX_DEBUG=-D_GLIBCXX_DEBUG @@ -79,17 +111,18 @@ else # !COMSPEC endif # !CPPCHK_GLIBCXX_DEBUG endif # GNU/kFreeBSD -endif # COMSPEC + LDFLAGS+=-pthread -# Set the UNDEF_STRICT_ANSI flag to address compile time warnings -# with tinyxml2 and Cygwin. -ifdef COMSPEC - uname_S := $(shell uname -s) +endif # WINNT - ifneq (,$(findstring CYGWIN,$(uname_S))) - UNDEF_STRICT_ANSI=-U__STRICT_ANSI__ - endif # CYGWIN -endif # COMSPEC +ifdef CYGWIN + ifeq ($(VERBOSE),1) + $(info CYGWIN found) + endif + + # Increase stack size for Cygwin builds to avoid segmentation fault in limited recursive tests. + CXXFLAGS+=-Wl,--stack,8388608 +endif # CYGWIN ifndef CXX CXX=g++ @@ -99,35 +132,26 @@ ifeq (clang++, $(findstring clang++,$(CXX))) CPPCHK_GLIBCXX_DEBUG= endif ifndef CXXFLAGS - CXXFLAGS=-std=c++0x -O2 -DNDEBUG -Wall -Wno-sign-compare + CXXFLAGS=-pedantic -Wall -Wextra -Wcast-qual -Wfloat-equal -Wmissing-declarations -Wmissing-format-attribute -Wno-long-long -Wpacked -Wredundant-decls -Wundef -Wno-sign-compare -Wno-multichar -Woverloaded-virtual $(CPPCHK_GLIBCXX_DEBUG) -g endif -# Increase stack size for Cygwin builds to avoid segmentation fault in limited recursive tests. -ifdef COMSPEC - uname_S := $(shell uname -s) - - ifneq (,$(findstring CYGWIN,$(uname_S))) - CXXFLAGS+=-Wl,--stack,8388608 - endif # CYGWIN -endif # COMSPEC - ifeq (g++, $(findstring g++,$(CXX))) - override CXXFLAGS += -std=c++0x -else ifeq (clang++, $(findstring clang++,$(CXX))) - override CXXFLAGS += -std=c++0x -else ifeq ($(CXX), c++) - ifeq ($(shell uname -s), Darwin) - override CXXFLAGS += -std=c++0x - endif + override CXXFLAGS += -pipe endif - +override CXXFLAGS += -std=c++11 ifeq ($(HAVE_RULES),yes) - override CXXFLAGS += -DHAVE_RULES -DTIXML_USE_STL $(shell pcre-config --cflags) + PCRE_CONFIG = $(shell which pcre-config) + ifeq ($(PCRE_CONFIG),) + $(error Did not find pcre-config) + endif + override CXXFLAGS += -DHAVE_RULES $(shell $(PCRE_CONFIG) --cflags) ifdef LIBS - LIBS += $(shell pcre-config --libs) + LIBS += $(shell $(PCRE_CONFIG) --libs) else - LIBS=$(shell pcre-config --libs) + LIBS=$(shell $(PCRE_CONFIG) --libs) endif +else ifneq ($(HAVE_RULES),) + $(error invalid HAVE_RULES value '$(HAVE_RULES)') endif ifndef PREFIX @@ -138,12 +162,16 @@ ifndef INCLUDE_FOR_LIB INCLUDE_FOR_LIB=-Ilib -isystem externals -isystem externals/picojson -isystem externals/simplecpp -isystem externals/tinyxml2 endif +ifndef INCLUDE_FOR_FE + INCLUDE_FOR_FE=-Ilib +endif + ifndef INCLUDE_FOR_CLI - INCLUDE_FOR_CLI=-Ilib -isystem externals/simplecpp -isystem externals/tinyxml2 + INCLUDE_FOR_CLI=-Ilib -Ifrontend -isystem externals/picojson -isystem externals/simplecpp -isystem externals/tinyxml2 endif ifndef INCLUDE_FOR_TEST - INCLUDE_FOR_TEST=-Ilib -Icli -isystem externals/simplecpp -isystem externals/tinyxml2 + INCLUDE_FOR_TEST=-Ilib -Ifrontend -Icli -isystem externals/simplecpp -isystem externals/tinyxml2 endif BIN=$(DESTDIR)$(PREFIX)/bin @@ -156,18 +184,23 @@ MAN_SOURCE=man/cppcheck.1.xml ###### Object Files -LIBOBJ = $(libcppdir)/analyzerinfo.o \ +LIBOBJ = $(libcppdir)/valueflow.o \ + $(libcppdir)/tokenize.o \ + $(libcppdir)/symboldatabase.o \ + $(libcppdir)/addoninfo.o \ + $(libcppdir)/analyzerinfo.o \ $(libcppdir)/astutils.o \ - $(libcppdir)/bughuntingchecks.o \ $(libcppdir)/check.o \ $(libcppdir)/check64bit.o \ $(libcppdir)/checkassert.o \ $(libcppdir)/checkautovariables.o \ $(libcppdir)/checkbool.o \ - $(libcppdir)/checkboost.o \ $(libcppdir)/checkbufferoverrun.o \ $(libcppdir)/checkclass.o \ $(libcppdir)/checkcondition.o \ + $(libcppdir)/checkers.o \ + $(libcppdir)/checkersidmapping.o \ + $(libcppdir)/checkersreport.o \ $(libcppdir)/checkexceptionsafety.o \ $(libcppdir)/checkfunctions.o \ $(libcppdir)/checkinternal.o \ @@ -186,13 +219,17 @@ LIBOBJ = $(libcppdir)/analyzerinfo.o \ $(libcppdir)/checkunusedvar.o \ $(libcppdir)/checkvaarg.o \ $(libcppdir)/clangimport.o \ + $(libcppdir)/color.o \ $(libcppdir)/cppcheck.o \ $(libcppdir)/ctu.o \ $(libcppdir)/errorlogger.o \ $(libcppdir)/errortypes.o \ - $(libcppdir)/exprengine.o \ + $(libcppdir)/findtoken.o \ $(libcppdir)/forwardanalyzer.o \ + $(libcppdir)/fwdanalysis.o \ $(libcppdir)/importproject.o \ + $(libcppdir)/infer.o \ + $(libcppdir)/keywords.o \ $(libcppdir)/library.o \ $(libcppdir)/mathlib.o \ $(libcppdir)/path.o \ @@ -203,46 +240,62 @@ LIBOBJ = $(libcppdir)/analyzerinfo.o \ $(libcppdir)/programmemory.o \ $(libcppdir)/reverseanalyzer.o \ $(libcppdir)/settings.o \ + $(libcppdir)/standards.o \ $(libcppdir)/summaries.o \ $(libcppdir)/suppressions.o \ - $(libcppdir)/symboldatabase.o \ $(libcppdir)/templatesimplifier.o \ $(libcppdir)/timer.o \ $(libcppdir)/token.o \ - $(libcppdir)/tokenize.o \ $(libcppdir)/tokenlist.o \ $(libcppdir)/utils.o \ - $(libcppdir)/valueflow.o + $(libcppdir)/vf_analyzers.o \ + $(libcppdir)/vf_common.o \ + $(libcppdir)/vf_settokenvalue.o \ + $(libcppdir)/vfvalue.o EXTOBJ = externals/simplecpp/simplecpp.o \ externals/tinyxml2/tinyxml2.o +FEOBJ = frontend/frontend.o + CLIOBJ = cli/cmdlineparser.o \ cli/cppcheckexecutor.o \ + cli/executor.o \ cli/filelister.o \ cli/main.o \ + cli/processexecutor.o \ + cli/sehwrapper.o \ + cli/signalhandler.o \ + cli/singleexecutor.o \ + cli/stacktrace.o \ cli/threadexecutor.o -TESTOBJ = test/options.o \ +TESTOBJ = test/fixture.o \ + test/helpers.o \ + test/main.o \ + test/options.o \ test/test64bit.o \ + test/testanalyzerinformation.o \ test/testassert.o \ test/testastutils.o \ test/testautovariables.o \ test/testbool.o \ - test/testboost.o \ test/testbufferoverrun.o \ - test/testbughuntingchecks.o \ test/testcharvar.o \ + test/testcheck.o \ test/testclangimport.o \ test/testclass.o \ test/testcmdlineparser.o \ + test/testcolor.o \ test/testcondition.o \ test/testconstructors.o \ test/testcppcheck.o \ test/testerrorlogger.o \ test/testexceptionsafety.o \ - test/testexprengine.o \ + test/testexecutor.o \ test/testfilelister.o \ + test/testfilesettings.o \ + test/testfrontend.o \ test/testfunctions.o \ test/testgarbage.o \ test/testimportproject.o \ @@ -261,16 +314,18 @@ TESTOBJ = test/options.o \ test/testplatform.o \ test/testpostfixoperator.o \ test/testpreprocessor.o \ - test/testrunner.o \ - test/testsamples.o \ + test/testprocessexecutor.o \ + test/testprogrammemory.o \ + test/testsettings.o \ test/testsimplifytemplate.o \ test/testsimplifytokens.o \ test/testsimplifytypedef.o \ test/testsimplifyusing.o \ + test/testsingleexecutor.o \ test/testsizeof.o \ + test/teststandards.o \ test/teststl.o \ test/teststring.o \ - test/testsuite.o \ test/testsummaries.o \ test/testsuppressions.o \ test/testsymboldatabase.o \ @@ -288,19 +343,20 @@ TESTOBJ = test/options.o \ test/testutils.o \ test/testvaarg.o \ test/testvalueflow.o \ - test/testvarid.o + test/testvarid.o \ + test/testvfvalue.o .PHONY: run-dmake tags ###### Targets -cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ) +cppcheck: $(EXTOBJ) $(LIBOBJ) $(FEOBJ) $(CLIOBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) $(LDFLAGS) $(RDYNAMIC) all: cppcheck testrunner -testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o +testrunner: $(EXTOBJ) $(TESTOBJ) $(LIBOBJ) $(FEOBJ) cli/cmdlineparser.o cli/cppcheckexecutor.o cli/executor.o cli/filelister.o cli/processexecutor.o cli/sehwrapper.o cli/signalhandler.o cli/singleexecutor.o cli/stacktrace.o cli/threadexecutor.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) $(LDFLAGS) $(RDYNAMIC) test: all @@ -312,16 +368,14 @@ check: all checkcfg: cppcheck validateCFG ./test/cfg/runtests.sh -dmake: tools/dmake.o cli/filelister.o $(libcppdir)/pathmatch.o $(libcppdir)/path.o $(libcppdir)/utils.o externals/simplecpp/simplecpp.o +dmake: tools/dmake/dmake.o cli/filelister.o $(libcppdir)/pathmatch.o $(libcppdir)/path.o $(libcppdir)/utils.o externals/simplecpp/simplecpp.o $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) run-dmake: dmake ./dmake -generate_cfg_tests: tools/generate_cfg_tests.o $(EXTOBJ) - g++ -isystem externals/tinyxml2 -o generate_cfg_tests tools/generate_cfg_tests.o $(EXTOBJ) clean: - rm -f build/*.o lib/*.o cli/*.o test/*.o tools/*.o externals/*/*.o testrunner dmake cppcheck cppcheck.exe cppcheck.1 + rm -f build/*.cpp build/*.o lib/*.o cli/*.o frontend/*.o test/*.o tools/dmake/*.o externals/*/*.o testrunner dmake cppcheck cppcheck.exe cppcheck.1 man: man/cppcheck.1 @@ -330,7 +384,7 @@ man/cppcheck.1: $(MAN_SOURCE) $(XP) $(DB2MAN) $(MAN_SOURCE) tags: - ctags -R --exclude=doxyoutput --exclude=test/cfg --exclude=test/synthetic cli externals gui lib test + ctags -R --exclude=doxyoutput --exclude=test/cfg cli externals gui lib test install: cppcheck install -d ${BIN} @@ -339,6 +393,7 @@ install: cppcheck ifdef FILESDIR install -d ${DESTDIR}${FILESDIR} install -d ${DESTDIR}${FILESDIR}/addons + install -m 644 addons/*.json ${DESTDIR}${FILESDIR}/addons install -m 644 addons/*.py ${DESTDIR}${FILESDIR}/addons install -d ${DESTDIR}${FILESDIR}/cfg install -m 644 cfg/*.cfg ${DESTDIR}${FILESDIR}/cfg @@ -360,16 +415,6 @@ ifdef FILESDIR rm -rf ${DESTDIR}${FILESDIR}; \ fi endif -ifdef CFGDIR - @if test -d ${DESTDIR}${CFGDIR}; then \ - files="`cd cfg 2>/dev/null && ls`"; \ - if test -n "$$files"; then \ - echo '(' cd ${DESTDIR}${CFGDIR} '&&' rm -f $$files ')'; \ - ( cd ${DESTDIR}${CFGDIR} && rm -f $$files ); \ - fi; \ - fi -endif - # Validation of library files: ConfigFiles := $(wildcard cfg/*.cfg) ConfigFilesCHECKED := $(patsubst %.cfg,%.checked,$(ConfigFiles)) @@ -386,6 +431,7 @@ PlatformFilesCHECKED := $(patsubst %.xml,%.checked,$(PlatformFiles)) %.checked:%.xml xmllint --noout --relaxng platforms/cppcheck-platforms.rng $< validatePlatforms: ${PlatformFilesCHECKED} + xmllint --noout platforms/cppcheck-platforms.rng # Validate XML output (to detect regressions) /tmp/errorlist.xml: cppcheck @@ -400,406 +446,487 @@ validateXML: createXMLExamples xmllint --noout --relaxng cppcheck-errors.rng /tmp/example.xml checkCWEEntries: /tmp/errorlist.xml - ./tools/listErrorsWithoutCWE.py -F /tmp/errorlist.xml + $(eval PYTHON_INTERPRETER := $(if $(PYTHON_INTERPRETER),$(PYTHON_INTERPRETER),$(shell which python3))) + $(eval PYTHON_INTERPRETER := $(if $(PYTHON_INTERPRETER),$(PYTHON_INTERPRETER),$(shell which python))) + $(eval PYTHON_INTERPRETER := $(if $(PYTHON_INTERPRETER),$(PYTHON_INTERPRETER),$(error Did not find a Python interpreter))) + $(PYTHON_INTERPRETER) tools/listErrorsWithoutCWE.py -F /tmp/errorlist.xml .PHONY: validateRules validateRules: xmllint --noout rules/*.xml ###### Build -$(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/path.h lib/platform.h lib/suppressions.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/analyzerinfo.o $(libcppdir)/analyzerinfo.cpp +$(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 + $(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 + $(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 + $(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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/addoninfo.cpp -$(libcppdir)/astutils.o: lib/astutils.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/astutils.o $(libcppdir)/astutils.cpp +$(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)/bughuntingchecks.o: lib/bughuntingchecks.cpp lib/astutils.h lib/bughuntingchecks.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/bughuntingchecks.o $(libcppdir)/bughuntingchecks.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/astutils.cpp -$(libcppdir)/check.o: lib/check.cpp lib/astutils.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/check.o $(libcppdir)/check.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/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/astutils.h lib/check.h lib/check64bit.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/check64bit.o $(libcppdir)/check64bit.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/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/astutils.h lib/check.h lib/checkassert.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkassert.o $(libcppdir)/checkassert.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkassert.cpp -$(libcppdir)/checkautovariables.o: lib/checkautovariables.cpp lib/astutils.h lib/check.h lib/checkautovariables.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkautovariables.o $(libcppdir)/checkautovariables.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkautovariables.cpp -$(libcppdir)/checkbool.o: lib/checkbool.cpp lib/astutils.h lib/check.h lib/checkbool.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkbool.o $(libcppdir)/checkbool.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbool.cpp -$(libcppdir)/checkboost.o: lib/checkboost.cpp lib/astutils.h lib/check.h lib/checkboost.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkboost.o $(libcppdir)/checkboost.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbufferoverrun.cpp -$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkbufferoverrun.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkclass.cpp -$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkclass.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkcondition.cpp -$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/astutils.h lib/check.h lib/checkcondition.h lib/checkother.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkcondition.o $(libcppdir)/checkcondition.cpp +$(libcppdir)/checkers.o: lib/checkers.cpp lib/checkers.h lib/config.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkers.cpp -$(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/astutils.h lib/check.h lib/checkexceptionsafety.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkexceptionsafety.o $(libcppdir)/checkexceptionsafety.cpp +$(libcppdir)/checkersidmapping.o: lib/checkersidmapping.cpp lib/checkers.h lib/config.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersidmapping.cpp -$(libcppdir)/checkfunctions.o: lib/checkfunctions.cpp lib/astutils.h lib/check.h lib/checkfunctions.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkfunctions.o $(libcppdir)/checkfunctions.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersreport.cpp -$(libcppdir)/checkinternal.o: lib/checkinternal.cpp lib/astutils.h lib/check.h lib/checkinternal.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkinternal.o $(libcppdir)/checkinternal.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkexceptionsafety.cpp -$(libcppdir)/checkio.o: lib/checkio.cpp lib/astutils.h lib/check.h lib/checkio.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkio.o $(libcppdir)/checkio.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkfunctions.cpp -$(libcppdir)/checkleakautovar.o: lib/checkleakautovar.cpp lib/astutils.h lib/check.h lib/checkleakautovar.h lib/checkmemoryleak.h lib/checknullpointer.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkleakautovar.o $(libcppdir)/checkleakautovar.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkinternal.cpp -$(libcppdir)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/astutils.h lib/check.h lib/checkmemoryleak.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkmemoryleak.o $(libcppdir)/checkmemoryleak.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkio.cpp -$(libcppdir)/checknullpointer.o: lib/checknullpointer.cpp lib/astutils.h lib/check.h lib/checknullpointer.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checknullpointer.o $(libcppdir)/checknullpointer.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkleakautovar.cpp -$(libcppdir)/checkother.o: lib/checkother.cpp lib/astutils.h lib/check.h lib/checkother.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkother.o $(libcppdir)/checkother.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkmemoryleak.cpp -$(libcppdir)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/astutils.h lib/check.h lib/checkpostfixoperator.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkpostfixoperator.o $(libcppdir)/checkpostfixoperator.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checknullpointer.cpp -$(libcppdir)/checksizeof.o: lib/checksizeof.cpp lib/astutils.h lib/check.h lib/checksizeof.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checksizeof.o $(libcppdir)/checksizeof.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkother.cpp -$(libcppdir)/checkstl.o: lib/checkstl.cpp lib/astutils.h lib/check.h lib/checknullpointer.h lib/checkstl.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/pathanalysis.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkstl.o $(libcppdir)/checkstl.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/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)/checkstring.o: lib/checkstring.cpp lib/astutils.h lib/check.h lib/checkstring.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkstring.o $(libcppdir)/checkstring.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/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)/checktype.o: lib/checktype.cpp lib/astutils.h lib/check.h lib/checktype.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checktype.o $(libcppdir)/checktype.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstl.cpp -$(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/astutils.h lib/check.h lib/checknullpointer.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkuninitvar.o $(libcppdir)/checkuninitvar.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstring.cpp -$(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkunusedfunctions.o $(libcppdir)/checkunusedfunctions.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checktype.cpp -$(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkunusedvar.o $(libcppdir)/checkunusedvar.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkuninitvar.cpp -$(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/astutils.h lib/check.h lib/checkvaarg.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkvaarg.o $(libcppdir)/checkvaarg.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedfunctions.cpp -$(libcppdir)/clangimport.o: lib/clangimport.cpp lib/astutils.h lib/clangimport.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/clangimport.o $(libcppdir)/clangimport.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedvar.cpp -$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/astutils.h lib/check.h lib/checkunusedfunctions.h lib/clangimport.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.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/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/cppcheck.o $(libcppdir)/cppcheck.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkvaarg.cpp -$(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/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/ctu.o $(libcppdir)/ctu.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/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)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/astutils.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.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/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/errorlogger.o $(libcppdir)/errorlogger.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)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/errortypes.o $(libcppdir)/errortypes.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/settings.h lib/standards.h lib/suppressions.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/cppcheck.cpp -$(libcppdir)/exprengine.o: lib/exprengine.cpp lib/astutils.h lib/bughuntingchecks.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/exprengine.o $(libcppdir)/exprengine.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/ctu.cpp -$(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/analyzer.h lib/astutils.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/forwardanalyzer.o $(libcppdir)/forwardanalyzer.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/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)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.h lib/errortypes.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/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/importproject.o $(libcppdir)/importproject.cpp +$(libcppdir)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h lib/utils.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/errortypes.cpp -$(libcppdir)/library.o: lib/library.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/library.o $(libcppdir)/library.cpp +$(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)/mathlib.o: lib/mathlib.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errortypes.h lib/mathlib.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/mathlib.o $(libcppdir)/mathlib.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/forwardanalyzer.cpp -$(libcppdir)/path.o: lib/path.cpp externals/simplecpp/simplecpp.h lib/config.h lib/path.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/path.o $(libcppdir)/path.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/fwdanalysis.cpp -$(libcppdir)/pathanalysis.o: lib/pathanalysis.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/pathanalysis.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/pathanalysis.o $(libcppdir)/pathanalysis.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/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)/pathmatch.o: lib/pathmatch.cpp lib/config.h lib/path.h lib/pathmatch.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/pathmatch.o $(libcppdir)/pathmatch.cpp +$(libcppdir)/infer.o: lib/infer.cpp lib/calculate.h lib/config.h lib/errortypes.h lib/infer.h lib/mathlib.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)/infer.cpp -$(libcppdir)/platform.o: lib/platform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/path.h lib/platform.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/platform.o $(libcppdir)/platform.cpp +$(libcppdir)/keywords.o: lib/keywords.cpp lib/config.h lib/keywords.h lib/standards.h lib/utils.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/keywords.cpp -$(libcppdir)/preprocessor.o: lib/preprocessor.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.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/timer.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/preprocessor.o $(libcppdir)/preprocessor.cpp +$(libcppdir)/library.o: lib/library.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.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/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/library.cpp -$(libcppdir)/programmemory.o: lib/programmemory.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/programmemory.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/programmemory.o $(libcppdir)/programmemory.cpp +$(libcppdir)/mathlib.o: lib/mathlib.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errortypes.h lib/mathlib.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/mathlib.cpp -$(libcppdir)/reverseanalyzer.o: lib/reverseanalyzer.cpp lib/analyzer.h lib/astutils.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/reverseanalyzer.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/reverseanalyzer.o $(libcppdir)/reverseanalyzer.cpp +$(libcppdir)/path.o: lib/path.cpp externals/simplecpp/simplecpp.h lib/config.h lib/path.h lib/standards.h lib/utils.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/path.cpp -$(libcppdir)/settings.o: lib/settings.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/timer.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/settings.o $(libcppdir)/settings.cpp +$(libcppdir)/pathanalysis.o: lib/pathanalysis.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/pathanalysis.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)/pathanalysis.cpp -$(libcppdir)/summaries.o: lib/summaries.cpp lib/analyzerinfo.h lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/summaries.o $(libcppdir)/summaries.cpp +$(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)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/path.h lib/suppressions.h lib/utils.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/suppressions.o $(libcppdir)/suppressions.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/platform.cpp -$(libcppdir)/symboldatabase.o: lib/symboldatabase.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/symboldatabase.o $(libcppdir)/symboldatabase.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/preprocessor.cpp -$(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/templatesimplifier.o $(libcppdir)/templatesimplifier.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/programmemory.cpp -$(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/timer.o $(libcppdir)/timer.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/reverseanalyzer.cpp -$(libcppdir)/token.o: lib/token.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/token.o $(libcppdir)/token.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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/settings.cpp -$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/summaries.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/tokenize.o $(libcppdir)/tokenize.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)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.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/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/tokenlist.o $(libcppdir)/tokenlist.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/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/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 + $(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/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 + $(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 + $(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 + $(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) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/utils.o $(libcppdir)/utils.cpp + $(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 + $(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 + $(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 + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_settokenvalue.cpp -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/analyzer.h lib/astutils.h lib/check.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/forwardanalyzer.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/standards.h lib/suppressions.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 - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/valueflow.o $(libcppdir)/valueflow.cpp +$(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vfvalue.cpp -cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h cli/threadexecutor.h externals/tinyxml2/tinyxml2.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.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/timer.h lib/utils.h - $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/cmdlineparser.o cli/cmdlineparser.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 + $(CXX) ${INCLUDE_FOR_FE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ frontend/frontend.cpp -cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h cli/threadexecutor.h externals/simplecpp/simplecpp.h lib/analyzerinfo.h lib/check.h lib/checkunusedfunctions.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.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/suppressions.h lib/timer.h lib/utils.h - $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/cppcheckexecutor.o cli/cppcheckexecutor.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/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h lib/xml.h + $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp -cli/filelister.o: cli/filelister.cpp cli/filelister.h lib/config.h lib/path.h lib/pathmatch.h lib/utils.h - $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/filelister.o cli/filelister.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/settings.h lib/standards.h lib/suppressions.h lib/utils.h + $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp -cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h - $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/main.o cli/main.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 + $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/executor.cpp -cli/threadexecutor.o: cli/threadexecutor.cpp cli/cppcheckexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h - $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/threadexecutor.o cli/threadexecutor.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 + $(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 + $(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 + $(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 + $(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 + $(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 + $(CXX) ${INCLUDE_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 + $(CXX) ${INCLUDE_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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/main.cpp test/options.o: test/options.cpp test/options.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/options.o test/options.cpp + $(CXX) ${INCLUDE_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 + $(CXX) ${INCLUDE_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 + $(CXX) ${INCLUDE_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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testassert.cpp -test/test64bit.o: test/test64bit.cpp lib/astutils.h lib/check.h lib/check64bit.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/test64bit.o test/test64bit.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testastutils.cpp -test/testassert.o: test/testassert.cpp lib/astutils.h lib/check.h lib/checkassert.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testassert.o test/testassert.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testautovariables.cpp -test/testastutils.o: test/testastutils.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testastutils.o test/testastutils.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testbool.cpp -test/testautovariables.o: test/testautovariables.cpp lib/astutils.h lib/check.h lib/checkautovariables.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testautovariables.o test/testautovariables.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testbufferoverrun.cpp -test/testbool.o: test/testbool.cpp lib/astutils.h lib/check.h lib/checkbool.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testbool.o test/testbool.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcharvar.cpp -test/testboost.o: test/testboost.cpp lib/astutils.h lib/check.h lib/checkboost.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testboost.o test/testboost.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcheck.cpp -test/testbufferoverrun.o: test/testbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testbufferoverrun.o test/testbufferoverrun.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclangimport.cpp -test/testbughuntingchecks.o: test/testbughuntingchecks.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testbughuntingchecks.o test/testbughuntingchecks.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclass.cpp -test/testcharvar.o: test/testcharvar.cpp lib/astutils.h lib/check.h lib/checkother.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcharvar.o test/testcharvar.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcmdlineparser.cpp -test/testclangimport.o: test/testclangimport.cpp lib/astutils.h lib/clangimport.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testclangimport.o test/testclangimport.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcolor.cpp -test/testclass.o: test/testclass.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testclass.o test/testclass.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcondition.cpp -test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/redirect.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcmdlineparser.o test/testcmdlineparser.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testconstructors.cpp -test/testcondition.o: test/testcondition.cpp externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkcondition.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcondition.o test/testcondition.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcppcheck.cpp -test/testconstructors.o: test/testconstructors.cpp lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testconstructors.o test/testconstructors.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testerrorlogger.cpp -test/testcppcheck.o: test/testcppcheck.cpp lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcppcheck.o test/testcppcheck.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testexceptionsafety.cpp -test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testerrorlogger.o test/testerrorlogger.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testexecutor.cpp -test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/astutils.h lib/check.h lib/checkexceptionsafety.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testexceptionsafety.o test/testexceptionsafety.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfilelister.cpp -test/testexprengine.o: test/testexprengine.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testexprengine.o test/testexprengine.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfilesettings.cpp -test/testfilelister.o: test/testfilelister.cpp cli/filelister.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/pathmatch.h lib/suppressions.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testfilelister.o test/testfilelister.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfrontend.cpp -test/testfunctions.o: test/testfunctions.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testfunctions.o test/testfunctions.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testfunctions.cpp -test/testgarbage.o: test/testgarbage.cpp lib/astutils.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testgarbage.o test/testgarbage.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testgarbage.cpp -test/testimportproject.o: test/testimportproject.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testimportproject.o test/testimportproject.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testimportproject.cpp -test/testincompletestatement.o: test/testincompletestatement.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/checkother.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testincompletestatement.o test/testincompletestatement.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testincompletestatement.cpp -test/testinternal.o: test/testinternal.cpp lib/astutils.h lib/check.h lib/checkinternal.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testinternal.o test/testinternal.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testinternal.cpp -test/testio.o: test/testio.cpp lib/astutils.h lib/check.h lib/checkio.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testio.o test/testio.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testio.cpp -test/testleakautovar.o: test/testleakautovar.cpp externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkleakautovar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testleakautovar.o test/testleakautovar.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testleakautovar.cpp -test/testlibrary.o: test/testlibrary.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testlibrary.o test/testlibrary.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testlibrary.cpp -test/testmathlib.o: test/testmathlib.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/suppressions.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testmathlib.o test/testmathlib.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/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testmathlib.cpp -test/testmemleak.o: test/testmemleak.cpp lib/astutils.h lib/check.h lib/checkmemoryleak.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testmemleak.o test/testmemleak.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testmemleak.cpp -test/testnullpointer.o: test/testnullpointer.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/checknullpointer.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testnullpointer.o test/testnullpointer.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testnullpointer.cpp -test/testoptions.o: test/testoptions.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h test/options.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testoptions.o test/testoptions.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testoptions.cpp -test/testother.o: test/testother.cpp externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkother.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testother.o test/testother.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testother.cpp -test/testpath.o: test/testpath.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/path.h lib/suppressions.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testpath.o test/testpath.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpath.cpp -test/testpathmatch.o: test/testpathmatch.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/pathmatch.h lib/suppressions.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testpathmatch.o test/testpathmatch.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpathmatch.cpp -test/testplatform.o: test/testplatform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/platform.h lib/suppressions.h lib/utils.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testplatform.o test/testplatform.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testplatform.cpp -test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/astutils.h lib/check.h lib/checkpostfixoperator.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testpostfixoperator.o test/testpostfixoperator.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpostfixoperator.cpp -test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testpreprocessor.o test/testpreprocessor.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpreprocessor.cpp -test/testrunner.o: test/testrunner.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/preprocessor.h lib/suppressions.h test/options.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testrunner.o test/testrunner.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testprocessexecutor.cpp -test/testsamples.o: test/testsamples.cpp cli/cppcheckexecutor.h cli/filelister.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/redirect.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsamples.o test/testsamples.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testprogrammemory.cpp -test/testsimplifytemplate.o: test/testsimplifytemplate.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsimplifytemplate.o test/testsimplifytemplate.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsettings.cpp -test/testsimplifytokens.o: test/testsimplifytokens.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsimplifytokens.o test/testsimplifytokens.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifytemplate.cpp -test/testsimplifytypedef.o: test/testsimplifytypedef.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsimplifytypedef.o test/testsimplifytypedef.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifytokens.cpp -test/testsimplifyusing.o: test/testsimplifyusing.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsimplifyusing.o test/testsimplifyusing.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifytypedef.cpp -test/testsizeof.o: test/testsizeof.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/checksizeof.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsizeof.o test/testsizeof.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsimplifyusing.cpp -test/teststl.o: test/teststl.cpp lib/astutils.h lib/check.h lib/checkstl.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/teststl.o test/teststl.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsingleexecutor.cpp -test/teststring.o: test/teststring.cpp lib/astutils.h lib/check.h lib/checkstring.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/teststring.o test/teststring.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsizeof.cpp -test/testsuite.o: test/testsuite.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h test/options.h test/redirect.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsuite.o test/testsuite.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststandards.cpp -test/testsummaries.o: test/testsummaries.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsummaries.o test/testsummaries.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststl.cpp -test/testsuppressions.o: test/testsuppressions.cpp cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsuppressions.o test/testsuppressions.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/teststring.cpp -test/testsymboldatabase.o: test/testsymboldatabase.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 test/testsuite.h test/testutils.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsymboldatabase.o test/testsymboldatabase.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsummaries.cpp -test/testthreadexecutor.o: test/testthreadexecutor.cpp cli/threadexecutor.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testthreadexecutor.o test/testthreadexecutor.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsuppressions.cpp -test/testtimer.o: test/testtimer.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h lib/timer.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testtimer.o test/testtimer.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsymboldatabase.cpp -test/testtoken.o: test/testtoken.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h test/testutils.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testtoken.o test/testtoken.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testthreadexecutor.cpp -test/testtokenize.o: test/testtokenize.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testtokenize.o test/testtokenize.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtimer.cpp -test/testtokenlist.o: test/testtokenlist.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testtokenlist.o test/testtokenlist.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtoken.cpp -test/testtokenrange.o: test/testtokenrange.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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/tokenrange.h lib/utils.h lib/valueflow.h test/testsuite.h test/testutils.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testtokenrange.o test/testtokenrange.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenize.cpp -test/testtype.o: test/testtype.cpp lib/astutils.h lib/check.h lib/checktype.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testtype.o test/testtype.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenlist.cpp -test/testuninitvar.o: test/testuninitvar.cpp lib/astutils.h lib/check.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testuninitvar.o test/testuninitvar.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/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} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtokenrange.cpp -test/testunusedfunctions.o: test/testunusedfunctions.cpp lib/astutils.h lib/check.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testunusedfunctions.o test/testunusedfunctions.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testtype.cpp -test/testunusedprivfunc.o: test/testunusedprivfunc.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.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 test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testunusedprivfunc.o test/testunusedprivfunc.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testuninitvar.cpp -test/testunusedvar.o: test/testunusedvar.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/check.h lib/checkunusedvar.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testunusedvar.o test/testunusedvar.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedfunctions.cpp -test/testutils.o: test/testutils.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h test/testutils.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testutils.o test/testutils.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedprivfunc.cpp -test/testvaarg.o: test/testvaarg.cpp lib/astutils.h lib/check.h lib/checkvaarg.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testvaarg.o test/testvaarg.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testunusedvar.cpp -test/testvalueflow.o: test/testvalueflow.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testvalueflow.o test/testvalueflow.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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testutils.cpp -test/testvarid.o: test/testvarid.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testvarid.o test/testvarid.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 + $(CXX) ${INCLUDE_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/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} $(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/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} $(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 + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvfvalue.cpp externals/simplecpp/simplecpp.o: externals/simplecpp/simplecpp.cpp externals/simplecpp/simplecpp.h - $(CXX) $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) -w $(UNDEF_STRICT_ANSI) -c -o externals/simplecpp/simplecpp.o externals/simplecpp/simplecpp.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ externals/simplecpp/simplecpp.cpp externals/tinyxml2/tinyxml2.o: externals/tinyxml2/tinyxml2.cpp externals/tinyxml2/tinyxml2.h - $(CXX) $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) -w $(UNDEF_STRICT_ANSI) -c -o externals/tinyxml2/tinyxml2.o externals/tinyxml2/tinyxml2.cpp - -tools/dmake.o: tools/dmake.cpp cli/filelister.h lib/config.h lib/pathmatch.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o tools/dmake.o tools/dmake.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -w -D_LARGEFILE_SOURCE -c -o $@ externals/tinyxml2/tinyxml2.cpp -tools/generate_cfg_tests.o: tools/generate_cfg_tests.cpp externals/tinyxml2/tinyxml2.h - $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o tools/generate_cfg_tests.o tools/generate_cfg_tests.cpp +tools/dmake/dmake.o: tools/dmake/dmake.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_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ tools/dmake/dmake.cpp diff --git a/TUNING.md b/TUNING.md new file mode 100644 index 00000000000..081846d9ea9 --- /dev/null +++ b/TUNING.md @@ -0,0 +1,153 @@ +# Tuning Cppcheck Analysis + +There are several ways you can potentially improve the runtime of a Cppcheck analysis. + +Note: Most of these suggestions highly depend on your code base so they need to be evaluated before being applied. They might also depend the code of Cppcheck itself and your environment. So you might want to evaluate these on a regular basis. + +## Collecting Information + +To see the time each file took to analyze just specify the `--showtime=file-total` CLI option. + +## Tuning At Build-Level + +It is most likely that a pre-built binary is being used - either an official one or one provided by the packaging manager of my operating system. + +But if you build your own binary it is possible to apply several steps to potentially improve the performance. + +Note: Recently more distribution have opted to use more advanced optimization for their packages so several of the following suggestions might have already been applied. +Please refer to the documentation of your distribution for more insight on this. + +### Use Matchcompiler + +(TODO: document how to use it when using the in-tree Visual Studio project) +(TODO: check with a CMake generated Visual Studio project) + +### Use Boost + +Boost.Container (https://www.boost.org/doc/libs/release/libs/container) is being used for some containers which have a smaller overhead. + +As the used library is header-only implementation you only need to install the package on the system you build the binary on but not on the system you run the analysis on. + +The official Windows binary is currently not using this (TODO: file ticket). + +(TODO: enable usage by default / bail out when it is enforced) + +### Use A Different Compiler + +Analyzing our own code base has shown that using a different compiler might lead to slightly better performance. + +In our case Clang is mostly faster than GCC. See https://trac.cppcheck.net/ticket/10778 for some details. + +### 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. + +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. + +Needs to be evaluated. (TODO: file tickets) + +### Use LTO + +Needs to be evaluated. See https://trac.cppcheck.net/ticket/11671. + +### Use profile-guided optimizations (PGO/BOLT/AutoFDO/Propeller) + +Needs to be evaluated. See https://trac.cppcheck.net/ticket/11672. + +## Tuning At Analysis-Level + +### Use A More Performant Platform + +It seems people assume that you need to run the analysis on the same system you build your code on/for. That is not necessary as the analysis is system-agnostic. +As system headers are not required for analyzing your code you only need to specify the configuration which matches the system you run your code on. + +In case you are using a project as input which can only be generated on the build/target system you can just transfer that to a different system and still run the analysis. + +### Specify A Build Dir + +Using the `--cppcheck-build-dir` allows you to perform incremental runs which omit files which have not been changed. + +Important: As this is currently seriously lacking in testing coverage it might have shortcomings and need to be used with care. (TODO: file ticket) + +### Exclude Static/Generated Files + +If your code base contains files which rarely change (e.g. local copies of external dependencies) or you have generated files (e.g. `moc_*.cpp` for Qt projects) you might consider excluding these from the analysis. +This can be done by using the `-i` option on the CLI, `` in GUI projects or by including them to begin with into the files passed to the analysis. + +Depending on your setup you might also consider to scan these files in a less frequent run (e.g. only when the files have changed or Cppcheck was updated). + +This could also be handled using `--cppcheck-build-dir` (see above). + +### Exclude System Headers + +System headers are not necessary to perform the analysis. So you might consider not providing those to the analysis and specify a library configuration via `--library` instead. + +`pkg-config` for instance will always provide non-system includes. + +(TODO: file ticket about ignoring all braced includes) + +### Limit The Configuration + +By default configuration to analyze will be determined automatically for each file based on the code. The maximum amount is limited and can be controlled by CLI options. + +Depending on your setup you might want to limit it to specific configuration by using `-D` (CLI) or `--project-configuration=` (Visual Studio project). +When you are using a compilation database generated by CMake it is already using a fixed configuration. + +### Use Multiple Jobs + +By default only a single process/thread is being used. You might to scale this up using the `-j` CLI option. Please note that specifying a value that will max out your systems resources might have a detrimental effect. + +### Use A Different Threading Model + +When using multiple job for the analysis (see above) on Linux it will default to using processes. This is done so the analysis is not aborted prematurely aborted in case of a crash. +Unfortunately it has overhead because of a suboptimal implementation and the fact that data needs to be transferred from the child processes to the main process. +So if you do not require the additional safety you might want to switch to the usage of thread instead using `--executor=thread`. + +Note: For Windows binaries we currently do not provide the possibility of using processes so this does not apply. + +## Advanced Tuning + +### Re-order The Files + +Files which take longer to analyze should be processed at first so they might not extended the run time. As the order how the files provided on the CLI or via the project are being honored it is as simple as that. + +### Adjust Thresholds + +There are lots of internal thresholds which limit the work which is put into parts of the analysis. The defaults were chosen as a compromise of time being spent vs. issues being detected but not might not be a good fit in all cases. + +These thresholds are currently neither exposed nor documented so they cannot be changed without the modifying the source which is *highly discouraged*. + +They are being utilized internally by `-check-level` though (see below). + +(TODO: file ticket about providing all bailouts) +(TODO: file ticket about expose these) +(TODO: file ticket about specifying these per file) + +Note: As these will lead to less data being collected for the analysis it might lead to false negatives *and* false positives. + +### Adjust Check Level + +There are several check levels which are basically a collection of different threshold values (see above). This can be adjusted by the CLI option `--check-level`. + +Note: The current default is the lowest available check level. + +Note: As these will lead to less data being collected for the analysis it might lead to false negatives *and* false positives. + +## Reporting Issues + +If you encounter a file which has an unreasonable slow analysis please consider reporting this as an issue. + +Also consider reporting major upticks in the runtime of the analysis after updating to a newer version. Some of these might be expected as the analysis is constantly improved but out-of-the-box we still need aim for reasonable times. + +In all cases please try to provide a small reproducer if possible. + +Note: There might even be cases the analysis will never finish because it is stuck in a cycle. This is quite uncommon but there are still several unresolved known cases so it is possible to encounter this. + +### Known Issues + +https://trac.cppcheck.net/ticket/10663 +https://trac.cppcheck.net/ticket/10765 +https://trac.cppcheck.net/ticket/10778 +https://trac.cppcheck.net/ticket/11262 +https://trac.cppcheck.net/ticket/12528 +https://trac.cppcheck.net/ticket/13698 \ No newline at end of file diff --git a/addons/README.md b/addons/README.md index cd4ecbfdf11..563c0c793f6 100644 --- a/addons/README.md +++ b/addons/README.md @@ -4,27 +4,56 @@ Addons are scripts that analyses Cppcheck dump files to check compatibility with ## Supported addons -+ [cert.py](https://github.com/danmar/cppcheck/blob/main/addons/cert.py) - Checks for compliance with the safe programming standard [CERT](http://www.cert.org/secure-coding/). + [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 Linux system for [year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) safety. This required [modified environment](https://github.com/3adev/y2038). See complete description [here](https://github.com/danmar/cppcheck/blob/main/addons/doc/y2038.txt). + [threadsafety.py](https://github.com/danmar/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) + Enforces naming conventions across the code. ++ [namingng.py](https://github.com/danmar/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) + Locates casts in the code. ++ [misc.py](https://github.com/danmar/cppcheck/blob/main/addons/misc.py) + Performs miscellaneous checks. + +### Other files + +- doc + Additional files for documentation generation. +- tests + Contains various unit tests for the addons. +- cppcheck.py + Internal helper used by Cppcheck binary to run the addons. +- cppcheckdata.doxyfile + Configuration file for documentation generation. +- cppcheckdata.py + Helper class for reading Cppcheck dump files within an addon. +- misra_9.py + Implementation of the MISRA 9.x rules used by `misra` addon. +- namingng.config.json + Example configuration for `namingng` addon. +- namingng.json + Example JSON file that can be used using --addon=namingng.json, referring to namingng.py and namingng.config.json +- ROS_naming.json + Example configuration for the `namingng` addon enforcing the [ROS naming convention for C++ ](http://wiki.ros.org/CppStyleGuide#Files). +- runaddon.py + Internal helper used by Cppcheck binary to run the addons. ## Usage ### Command line interface ```bash -cppcheck --addon=cert --addon=y2038 src/test.c +cppcheck --addon=misc src/test.c ``` It is also possible to call scripts as follows: ```bash cppcheck --dump --quiet src/test.c -python cert.py src/test.c.dump +python misc.py src/test.c.dump python misra.py --rule-texts=~/misra_rules.txt src/test.c.dump ``` diff --git a/addons/ROS_naming.json b/addons/ROS_naming.json index 82c0131cf0a..0262d69c09b 100644 --- a/addons/ROS_naming.json +++ b/addons/ROS_naming.json @@ -1,5 +1,5 @@ { - "RE_FILE": {".*[A-Z]": [true, "under_scored"]}, + "RE_FILE": [".*[A-Z]"], "RE_NAMESPACE": {".*[A-Z]": [true, "under_scored"], ".*\\_$": [true, "under_scored"]}, "RE_FUNCTIONNAME": {".*\\_": [true, "camelCase"], diff --git a/addons/cert.py b/addons/cert.py deleted file mode 100755 index 9bdbf0b4547..00000000000 --- a/addons/cert.py +++ /dev/null @@ -1,440 +0,0 @@ -#!/usr/bin/env python3 -# -# Cert: Some extra CERT checkers -# -# Cppcheck itself handles many CERT rules. Cppcheck warns when there is undefined behaviour. -# CERT Homepage: https://www.cert.org/secure-coding/ -# -# Example usage of this addon (scan a sourcefile main.cpp) -# cppcheck --dump main.cpp -# python cert.py main.cpp.dump - -import argparse -import cppcheckdata -import sys -import re - -VERIFY = ('-verify' in sys.argv) -VERIFY_EXPECTED = [] -VERIFY_ACTUAL = [] - -def reportError(token, severity, msg, id): - if VERIFY: - VERIFY_ACTUAL.append(str(token.linenr) + ':cert-' + id) - else: - cppcheckdata.reportError(token, severity, msg, 'cert', id) - -def simpleMatch(token, pattern): - return cppcheckdata.simpleMatch(token, pattern) - - -def isUnpackedStruct(token): - if token.valueType is None: - return False - if token.valueType.typeScope is None: - return False - if token.valueType.typeScope.type != "Struct": - return False - startToken = token.valueType.typeScope.bodyStart - - linenr = int(startToken.linenr) - for line in open(startToken.file): - linenr -= 1 - if linenr == 0: - return True - if linenr < 3 and re.match(r'#pragma\s+pack\s*\(', line): - return False - return True - - -def isLocalUnpackedStruct(arg): - if arg and arg.str == '&' and not arg.astOperand2: - arg = arg.astOperand1 - return arg and arg.variable and (arg.variable.isLocal or arg.variable.isArgument) and isUnpackedStruct(arg) - - -def isBitwiseOp(token): - return token and (token.str in {'&', '|', '^'}) - - -def isComparisonOp(token): - return token and (token.str in {'==', '!=', '>', '>=', '<', '<='}) - -def isCast(expr): - if not expr or expr.str != '(' or not expr.astOperand1 or expr.astOperand2: - return False - if simpleMatch(expr, '( )'): - return False - return True - -def isStandardFunction(token): - if token.function: - return False - prev = token.previous - if prev: - if prev.str == '.': - return False - if prev.str == '::': - prevprev = prev.previous - if prevprev and not prevprev.str == 'std': - return False - return True - -# Is this a function call -def isFunctionCall(token, function_names, number_of_arguments=None): - if not token.isName: - return False - if token.str not in function_names: - return False - if (token.next is None) or token.next.str != '(' or token.next != token.astParent: - return False - if number_of_arguments is None: - return True - return len(cppcheckdata.getArguments(token)) == number_of_arguments - - -# EXP05-C -# do not attempt to cast away const -def exp05(data): - # TODO Reuse code in misra rule 11.8 - for token in data.tokenlist: - if isCast(token): - # C-style cast - if not token.valueType: - continue - if not token.astOperand1.valueType: - continue - if token.valueType.pointer == 0: - continue - if token.astOperand1.valueType.pointer == 0: - continue - const1 = token.valueType.constness - const2 = token.astOperand1.valueType.constness - if (const1 % 2) < (const2 % 2): - reportError(token, 'style', "Attempt to cast away const", 'EXP05-C') - - elif token.str == '(' and token.astOperand1 and token.astOperand2 and token.astOperand1.function: - function = token.astOperand1.function - arguments = cppcheckdata.getArguments(token.previous) - if not arguments: - continue - for argnr, argvar in function.argument.items(): - if argnr < 1 or argnr > len(arguments): - continue - if not argvar.isPointer: - continue - if (argvar.constness % 2) == 1: # data is const - continue - argtok = arguments[argnr - 1] - if not argtok.valueType: - continue - if argtok.valueType.pointer == 0: - continue - const2 = arguments[argnr - 1].valueType.constness - if (const2 % 2) == 1: - reportError(token, 'style', "Attempt to cast away const", 'EXP05-C') - - -# EXP42-C -# do not compare padding data -def exp42(data): - for token in data.tokenlist: - if token.str != '(' or not token.astOperand1 or token.astOperand1.str != 'memcmp': - continue - - arg1 = None - arg2 = None - if token.astOperand2 and token.astOperand2.str == ',': - if token.astOperand2.astOperand1 and token.astOperand2.astOperand1.str == ',': - arg1 = token.astOperand2.astOperand1.astOperand1 - arg2 = token.astOperand2.astOperand1.astOperand2 - - if isLocalUnpackedStruct(arg1) or isLocalUnpackedStruct(arg2): - reportError( - token, 'style', "Comparison of struct padding data " + - "(fix either by packing the struct using '#pragma pack' or by rewriting the comparison)", 'EXP42-C') - -# EXP15-C -# Do not place a semicolon on the same line as an if, for or while statement -def exp15(data): - for scope in data.scopes: - if scope.type in ('If', 'For', 'While'): - token = scope.bodyStart.next - if token.str==';' and token.linenr==scope.bodyStart.linenr: - reportError(token, 'style', 'Do not place a semicolon on the same line as an IF, FOR or WHILE', 'EXP15-C') - - -# EXP46-C -# Do not use a bitwise operator with a Boolean-like operand -# int x = (a == b) & c; -def exp46(data): - for token in data.tokenlist: - if isBitwiseOp(token) and (isComparisonOp(token.astOperand1) or isComparisonOp(token.astOperand2)): - reportError( - token, 'style', 'Bitwise operator is used with a Boolean-like operand', 'EXP46-c') - -# INT31-C -# Ensure that integer conversions do not result in lost or misinterpreted data -def int31(data, platform): - if not platform: - return - for token in data.tokenlist: - if not isCast(token): - continue - if not token.valueType or not token.astOperand1.values: - continue - bits = None - if token.valueType.type == 'char': - bits = platform.char_bit - elif token.valueType.type == 'short': - bits = platform.short_bit - elif token.valueType.type == 'int': - bits = platform.int_bit - elif token.valueType.type == 'long': - bits = platform.long_bit - elif token.valueType.type == 'long long': - bits = platform.long_long_bit - else: - continue - if token.valueType.sign == 'unsigned': - found = False - for value in token.astOperand1.values: - if value.intvalue and value.intvalue < 0: - found = True - reportError( - token, - 'style', - 'Ensure that integer conversions do not result in lost or misinterpreted data (casting ' + str(value.intvalue) + ' to unsigned ' + token.valueType.type + ')', - 'INT31-c') - break - if found: - continue - if bits >= 64: - continue - minval = 0 - maxval = 1 - if token.valueType.sign == 'signed': - minval = -(1 << (bits - 1)) - maxval = ((1 << (bits - 1)) - 1) - else: - minval = 0 - maxval = ((1 << bits) - 1) - for value in token.astOperand1.values: - if value.intvalue and (value.intvalue < minval or value.intvalue > maxval): - destType = '' - if token.valueType.sign: - destType = token.valueType.sign + ' ' + token.valueType.type - else: - destType = token.valueType.type - reportError( - token, - 'style', - 'Ensure that integer conversions do not result in lost or misinterpreted data (casting ' + str(value.intvalue) + ' to ' + destType + ')', - 'INT31-c') - break - - -# ENV33-C -# Do not call system() -def env33(data): - for token in data.tokenlist: - if isFunctionCall(token, ('system',), 1): - - # Invalid syntax - if not token.next.astOperand2: - continue - - # ENV33-C-EX1: It is permissible to call system() with a null - # pointer argument to determine the presence of a command processor - # for the system. - argValue = token.next.astOperand2.getValue(0) - if argValue and argValue.intvalue == 0 and argValue.isKnown(): - continue - - reportError(token, 'style', 'Do not call system()', 'ENV33-C') - - -# MSC24-C -# Do not use deprecated or obsolescent functions -def msc24(data): - for token in data.tokenlist: - if isFunctionCall(token, ('asctime',), 1): - reportError(token,'style','Do not use asctime() better use asctime_s()', 'MSC24-C') - elif isFunctionCall(token, ('atof',), 1): - reportError(token,'style','Do not use atof() better use strtod()', 'MSC24-C') - elif isFunctionCall(token, ('atoi',), 1): - reportError(token,'style','Do not use atoi() better use strtol()', 'MSC24-C') - elif isFunctionCall(token, ('atol',), 1): - reportError(token,'style','Do not use atol() better use strtol()', 'MSC24-C') - elif isFunctionCall(token, ('atoll',), 1): - reportError(token,'style','Do not use atoll() better use strtoll()', 'MSC24-C') - elif isFunctionCall(token, ('ctime',), 1): - reportError(token,'style','Do not use ctime() better use ctime_s()', 'MSC24-C') - elif isFunctionCall(token, ('fopen',), 2): - reportError(token,'style','Do not use fopen() better use fopen_s()', 'MSC24-C') - elif isFunctionCall(token, ('freopen',), 3): - reportError(token,'style','Do not use freopen() better use freopen_s()', 'MSC24-C') - elif isFunctionCall(token, ('rewind',), 1): - reportError(token,'style','Do not use rewind() better use fseek()', 'MSC24-C') - elif isFunctionCall(token, ('setbuf',), 2): - reportError(token,'style','Do not use setbuf() better use setvbuf()', 'MSC24-C') - -# MSC30-C -# Do not use the rand() function for generating pseudorandom numbers -def msc30(data): - for token in data.tokenlist: - if simpleMatch(token, "rand ( )") and isStandardFunction(token): - reportError(token, 'style', 'Do not use the rand() function for generating pseudorandom numbers', 'MSC30-c') - -# STR03-C -# Do not inadvertently truncate a string -def str03(data): - for token in data.tokenlist: - if not isFunctionCall(token, 'strncpy'): - continue - arguments = cppcheckdata.getArguments(token) - if len(arguments)!=3: - continue - if arguments[2].str=='(' and arguments[2].astOperand1.str=='sizeof': - reportError(token, 'style', 'Do not inadvertently truncate a string', 'STR03-C') - -# STR05-C -# Use pointers to const when referring to string literals -def str05(data): - for token in data.tokenlist: - if token.isString: - parent = token.astParent - if parent is None: - continue - parentOp1 = parent.astOperand1 - if parent.isAssignmentOp and parentOp1.valueType: - if (parentOp1.valueType.type in ('char', 'wchar_t')) and parentOp1.valueType.pointer and not parentOp1.valueType.constness: - reportError(parentOp1, 'style', 'Use pointers to const when referring to string literals', 'STR05-C') - -# STR07-C -# Use the bounds-checking interfaces for string manipulation -def str07(data): - if data.standards.c=='c89' or data.standards.c=='c99': - return - for token in data.tokenlist: - if not isFunctionCall(token, ('strcpy', 'strcat')): - continue - args = cppcheckdata.getArguments(token) - if len(args)!=2: - continue - if args[1].isString: - continue - reportError(token, 'style', 'Use the bounds-checking interfaces %s_s()' % token.str, 'STR07-C') - -# STR11-C -# Do not specify the bound of a character array initialized with a string literal -def str11(data): - for token in data.tokenlist: - if not token.isString: - continue - - strlen = token.strlen - parent = token.astParent - - if parent is None: - continue - parentOp1 = parent.astOperand1 - if parentOp1 is None or parentOp1.str!='[': - continue - - if not parent.isAssignmentOp: - continue - - varToken = parentOp1.astOperand1 - if varToken is None or not varToken.isName: - continue - if varToken.variable is None: - continue - if varToken != varToken.variable.nameToken: - continue - valueToken = parentOp1.astOperand2 - if valueToken is None: - continue - - if valueToken.isNumber and int(valueToken.str)==strlen: - reportError(valueToken, 'style', 'Do not specify the bound of a character array initialized with a string literal', 'STR11-C') - -# API01-C -# Avoid laying out strings in memory directly before sensitive data -def api01(data): - for scope in data.scopes: - if scope.type!='Struct': - continue - token = scope.bodyStart - arrayFound=False - # loop through the complete struct - while token != scope.bodyEnd: - if token.isName and token.variable: - if token.variable.isArray: - arrayFound=True - elif arrayFound and not token.variable.isArray and not token.variable.isConst: - reportError(token, 'style', 'Avoid laying out strings in memory directly before sensitive data', 'API01-C') - # reset flags to report other positions in the same struct - arrayFound=False - token = token.next - - -def get_args(): - parser = cppcheckdata.ArgumentParser() - parser.add_argument("-verify", help=argparse.SUPPRESS, action="store_true") - return parser.parse_args() - -if __name__ == '__main__': - args = get_args() - - if args.verify: - VERIFY = True - - if not args.dumpfile: - if not args.quiet: - print("no input files.") - sys.exit(0) - - for dumpfile in args.dumpfile: - if not args.quiet: - print('Checking %s...' % dumpfile) - - data = cppcheckdata.CppcheckData(dumpfile) - - if VERIFY: - VERIFY_ACTUAL = [] - VERIFY_EXPECTED = [] - for tok in data.rawTokens: - if tok.str.startswith('//') and 'TODO' not in tok.str: - for word in tok.str[2:].split(' '): - if re.match(r'cert-[A-Z][A-Z][A-Z][0-9][0-9].*',word): - VERIFY_EXPECTED.append(str(tok.linenr) + ':' + word) - - for cfg in data.iterconfigurations(): - if not args.quiet: - print('Checking %s, config %s...' % (dumpfile, cfg.name)) - exp05(cfg) - exp42(cfg) - exp46(cfg) - exp15(cfg) - int31(cfg, data.platform) - str03(cfg) - str05(cfg) - str07(cfg) - str11(cfg) - env33(cfg) - msc24(cfg) - msc30(cfg) - api01(cfg) - - if VERIFY: - for expected in VERIFY_EXPECTED: - if expected not in VERIFY_ACTUAL: - print('Expected but not seen: ' + expected) - sys.exit(1) - for actual in VERIFY_ACTUAL: - if actual not in VERIFY_EXPECTED: - print('Not expected: ' + actual) - sys.exit(1) - - sys.exit(cppcheckdata.EXIT_CODE) diff --git a/addons/cppcheck.py b/addons/cppcheck.py new file mode 100644 index 00000000000..735269d32c5 --- /dev/null +++ b/addons/cppcheck.py @@ -0,0 +1,41 @@ + +import cppcheckdata +import sys +import os + +__checkers__ = [] + +def checker(f): + __checkers__.append(f) + return f + + +__errorid__ = '' +__addon_name__ = '' +def reportError(location, severity, message, errorId=None): + cppcheckdata.reportError(location, severity, message, __addon_name__, errorId or __errorid__) + +def runcheckers(): + # If there are no checkers then don't run + if len(__checkers__) == 0: + return + global __addon_name__ + global __errorid__ + addon = sys.argv[0] + parser = cppcheckdata.ArgumentParser() + args = parser.parse_args() + + __addon_name__ = os.path.splitext(os.path.basename(addon))[0] + + for dumpfile in args.dumpfile: + if not args.quiet: + print('Checking %s...' % dumpfile) + + data = cppcheckdata.CppcheckData(dumpfile) + + for cfg in data.iterconfigurations(): + if not args.quiet: + print('Checking %s, config %s...' % (dumpfile, cfg.name)) + for c in __checkers__: + __errorid__ = c.__name__ + c(cfg, data) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index 86a35b2b1f6..b0e53161f3a 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -8,7 +8,28 @@ import argparse import json +import os import sys +import subprocess + +try: + import pathlib +except ImportError: + message = "Failed to load pathlib. Upgrade Python to 3.x or install pathlib with 'pip install pathlib'." + error_id = 'pythonError' + if '--cli' in sys.argv: + msg = { 'file': '', + 'linenr': 0, + 'column': 0, + 'severity': 'error', + 'message': message, + 'addon': 'cppcheckdata', + 'errorId': error_id, + 'extra': ''} + sys.stdout.write(json.dumps(msg) + '\n') + else: + sys.stderr.write('%s [%s]\n' % (message, error_id)) + sys.exit(1) from xml.etree import ElementTree from fnmatch import fnmatch @@ -17,6 +38,27 @@ current_dumpfile_suppressions = [] +def _load_location(location, element): + """Load location from element/dict""" + location.file = element.get('file') + line = element.get('line') + if line is None: + line = element.get('linenr') + if line is None: + line = '0' + location.linenr = int(line) + location.column = int(element.get('column', '0')) + + +class Location: + """Utility location class""" + file = None + linenr = None + column = None + def __init__(self, element): + _load_location(self, element) + + class Directive: """ Directive class. Contains information about each preprocessor directive in the source code. @@ -34,16 +76,16 @@ class Directive: print(directive.str) @endcode """ + #preprocessor.cpp/Preprocessor::dump str = None file = None linenr = None - column = 0 + column = None def __init__(self, element): self.str = element.get('str') - self.file = element.get('file') - self.linenr = int(element.get('linenr')) + _load_location(self, element) def __repr__(self): attrs = ["str", "file", "linenr"] @@ -52,15 +94,91 @@ def __repr__(self): ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) ) +class MacroUsage: + """ + Tracks preprocessor macro usage + + Attributes: + name Name of the macro + usefile + useline + usecolumn + isKnownValue + """ + #preprocessor.cpp/Preprocessor::dump + + name = None # Macro name + file = None + linenr = None + column = None + usefile = None + uselinenr = None + usecolumn = None + + def __init__(self, element): + self.name = element.get('name') + _load_location(self, element) + self.usefile = element.get('usefile') + self.useline = element.get('useline') + self.usecolumn = element.get('usecolumn') + self.isKnownValue = element.get('is-known-value', 'false') == 'true' + + def __repr__(self): + attrs = ["name", "file", "linenr", "column", "usefile", "useline", "usecolumn", "isKnownValue"] + return "{}({})".format( + "MacroUsage", + ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) + ) + + +class PreprocessorIfCondition: + """ + Information about #if/#elif conditions + + Attributes: + E + result + """ + #preprocessor.cpp/Preprocessor::dump + + file = None + linenr = None + column = None + E = None + result = None + + def __init__(self, element): + _load_location(self, element) + self.E = element.get('E') + self.result = int(element.get('result')) + + def __repr__(self): + attrs = ["file", "linenr", "column", "E", "result"] + return "{}({})".format( + "PreprocessorIfCondition", + ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) + ) class ValueType: """ ValueType class. Contains (promoted) type information for each node in the AST. + + Attributes: + type nonstd/pod/record/smart-pointer/container/iterator/void/bool/char/short/wchar_t/int/long/long long/unknown int/float/double/long double + sign signed/unsigned + bits bit count for bit-fields, otherwise None + pointer + constness + reference + typeScopeId + originalTypeName bool/const char */long/char */size_t/int/double/std::string/.. + """ + #symboldatabase.cpp/ValueType::dump type = None sign = None - bits = 0 + bits = None constness = 0 pointer = 0 typeScopeId = None @@ -70,25 +188,19 @@ class ValueType: def __init__(self, element): self.type = element.get('valueType-type') self.sign = element.get('valueType-sign') - bits = element.get('valueType-bits') - if bits: - self.bits = int(bits) + self.bits = element.get('valueType-bits', None) + self.bits = int(self.bits) if self.bits else None + self.pointer = int(element.get('valueType-pointer', 0)) + self.constness = int(element.get('valueType-constness', 0)) + self.reference = element.get('valueType-reference') self.typeScopeId = element.get('valueType-typeScope') self.originalTypeName = element.get('valueType-originalTypeName') - constness = element.get('valueType-constness') - if constness: - self.constness = int(constness) - else: - self.constness = 0 - pointer = element.get('valueType-pointer') - if pointer: - self.pointer = int(pointer) - else: - self.pointer = 0 + #valueType-containerId TODO add + def __repr__(self): attrs = ["type", "sign", "bits", "typeScopeId", "originalTypeName", - "constness", "constness", "pointer"] + "constness", "pointer"] return "{}({})".format( "ValueType", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -114,7 +226,7 @@ class Token: The CppcheckData.tokenlist is a list of Token items - C++ class: http://cppcheck.net/devinfo/doxyoutput/classToken.html + C++ class: https://cppcheck.sourceforge.io/devinfo/doxyoutput/classToken.html Attributes: str Token string @@ -124,34 +236,46 @@ class Token: corresponding '}', ']' and ')'. For templates, the '<' is linked to the corresponding '>'. scope Scope information for this token. See the Scope class. + type Type information: name/op/number/string/.. isName Is this token a symbol name + isUnsigned Is this token a unsigned type + isSigned Is this token a signed type isNumber Is this token a number, for example 123, 12.34 isInt Is this token a int value such as 1234 - isFloat Is this token a int value such as 12.34 + isFloat Is this token a float value such as 12.34 isString Is this token a string literal such as "hello" strlen string length for string literal isChar Is this token a char literal such as 'x' + isBoolean Is this token a boolean isOp Is this token a operator isArithmeticalOp Is this token a arithmetic operator isAssignmentOp Is this token a assignment operator isComparisonOp Is this token a comparison operator isLogicalOp Is this token a logical operator: && || - isUnsigned Is this token a unsigned type - isSigned Is this token a signed type + isCast + externLang isExpandedMacro Is this token a expanded macro token - isSplittedVarDeclComma Is this a comma changed to semicolon in a splitted variable declaration ('int a,b;' => 'int a; int b;') - isSplittedVarDeclEq Is this a '=' changed to semicolon in a splitted variable declaration ('int a=5;' => 'int a; a=5;') + macroName Macro name that this token is expanded from + isRemovedVoidParameter Has void parameter been removed? + isSplittedVarDeclComma Is this a comma changed to semicolon in a split variable declaration ('int a,b;' => 'int a; int b;') + isSplittedVarDeclEq Is this a '=' changed to semicolon in a split variable declaration ('int a=5;' => 'int a; a=5;') + isImplicitInt Is this token an implicit "int"? + isComplex + isRestrict + isAttributeExport + isAnonymous varId varId for token, each variable has a unique non-zero id + exprId exprId for token, each expression has a unique non-zero id variable Variable information for this token. See the Variable class. function If this token points at a function call, this attribute has the Function information. See the Function class. values Possible/Known values of token - impossible_values Impossible values of token - valueType type information typeScope type scope (token->type()->classScope) astParent ast parent astOperand1 ast operand1 astOperand2 ast operand2 + orriginalName orriginal name of the token + valueType type information: container/.. file file name linenr line number column column @@ -166,6 +290,7 @@ class Token: print(code) @endcode """ + #tokenize.cpp/Tokenizer::dump Id = None str = None @@ -182,16 +307,26 @@ class Token: isString = False strlen = None isChar = False + isBoolean = False isOp = False isArithmeticalOp = False isAssignmentOp = False isComparisonOp = False isLogicalOp = False + isCast = False isUnsigned = False isSigned = False + macroName = None isExpandedMacro = False + isRemovedVoidParameter = False isSplittedVarDeclComma = False isSplittedVarDeclEq = False + isImplicitInt = False + isComplex = False + isRestrict = False + isAttributeExport = False + isAnonymous = False + exprId = None varId = None variableId = None variable = None @@ -204,6 +339,7 @@ class Token: typeScopeId = None typeScope = None + type = None astParentId = None astParent = None @@ -223,25 +359,27 @@ def __init__(self, element): self.previous = None self.scopeId = element.get('scope') self.scope = None - type = element.get('type') - if type == 'name': + self.type = element.get('type') + if self.type == 'name': self.isName = True if element.get('isUnsigned'): self.isUnsigned = True if element.get('isSigned'): self.isSigned = True - elif type == 'number': + elif self.type == 'number': self.isNumber = True if element.get('isInt'): self.isInt = True elif element.get('isFloat'): self.isFloat = True - elif type == 'string': + elif self.type == 'string': self.isString = True self.strlen = int(element.get('strlen')) - elif type == 'char': + elif self.type == 'char': self.isChar = True - elif type == 'op': + elif self.type == 'boolean': + self.isBoolean = True + elif self.type == 'op': self.isOp = True if element.get('isArithmeticalOp'): self.isArithmeticalOp = True @@ -251,26 +389,40 @@ def __init__(self, element): self.isComparisonOp = True elif element.get('isLogicalOp'): self.isLogicalOp = True - if element.get('isExpandedMacro'): + if element.get('isCast'): + self.isCast = True + self.externLang = element.get('externLang') + self.macroName = element.get('macroName') + if self.macroName or element.get('isExpandedMacro'): self.isExpandedMacro = True + if element.get('isRemovedVoidParameter'): + self.isRemovedVoidParameter = True if element.get('isSplittedVarDeclComma'): self.isSplittedVarDeclComma = True if element.get('isSplittedVarDeclEq'): self.isSplittedVarDeclEq = True + if element.get('isImplicitInt'): + self.isImplicitInt = True + if element.get('isComplex'): + self.isComplex = True + if element.get('isRestrict'): + self.isRestrict = True + if element.get('isAttributeExport'): + self.isAttributeExport = True + if element.get('isAnonymous'): + self.isAnonymous = True self.linkId = element.get('link') self.link = None if element.get('varId'): self.varId = int(element.get('varId')) + if element.get('exprId'): + self.exprId = int(element.get('exprId')) self.variableId = element.get('variable') self.variable = None self.functionId = element.get('function') self.function = None self.valuesId = element.get('values') self.values = None - if element.get('valueType-type'): - self.valueType = ValueType(element) - else: - self.valueType = None self.typeScopeId = element.get('type-scope') self.typeScope = None self.astParentId = element.get('astParent') @@ -279,18 +431,23 @@ def __init__(self, element): self.astOperand1 = None self.astOperand2Id = element.get('astOperand2') self.astOperand2 = None - self.file = element.get('file') - self.linenr = int(element.get('linenr')) - self.column = int(element.get('column')) + self.originalName = element.get('originalName') + if element.get('valueType-type'): + self.valueType = ValueType(element) + else: + self.valueType = None + _load_location(self, element) def __repr__(self): attrs = ["Id", "str", "scopeId", "isName", "isUnsigned", "isSigned", "isNumber", "isInt", "isFloat", "isString", "strlen", - "isChar", "isOp", "isArithmeticalOp", "isComparisonOp", - "isLogicalOp", "isExpandedMacro", "isSplittedVarDeclComma", - "isSplittedVarDeclEq","linkId", "varId", "variableId", - "functionId", "valuesId", "valueType", "typeScopeId", - "astParentId", "astOperand1Id", "file", "linenr", "column"] + "isChar", "isBoolean", "isOp", "isArithmeticalOp", "isAssignmentOp", + "isComparisonOp", "isLogicalOp", "isCast", "externLang", "isExpandedMacro", + "isRemovedVoidParameter", "isSplittedVarDeclComma", "isSplittedVarDeclEq", + "isImplicitInt", "isComplex", "isRestrict", "isAttributeExport", "isAnonymous", "linkId", + "varId", "variableId", "functionId", "valuesId", "valueType", + "typeScopeId", "astParentId", "astOperand1Id", "file", + "linenr", "column"] return "{}({})".format( "Token", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -309,6 +466,7 @@ def setId(self, IdMap): self.impossible_values.append(v) else: self.values.append(v) + v.setId(IdMap) self.typeScope = IdMap[self.typeScopeId] self.astParent = IdMap[self.astParentId] self.astOperand1 = IdMap[self.astOperand1Id] @@ -341,11 +499,56 @@ def getKnownIntValue(self): return value.intvalue return None + def isUnaryOp(self, op): + return self.astOperand1 and (self.astOperand2 is None) and self.str == op + + def isBinaryOp(self): + return self.astOperand1 and self.astOperand2 + + def forward(self, end=None): + token = self + while token and token != end: + yield token + token = token.next + + def backward(self, start=None): + token = self + while token and token != start: + yield token + token = token.previous + + def astParents(self): + token = self + while token and token.astParent: + token = token.astParent + yield token + + def astTop(self): + top = None + for parent in self.astParents(): + top = parent + return top + + def tokAt(self, n): + tl = self.forward() + if n < 0: + tl = self.backward() + n = -n + for i, t in enumerate(tl): + if i == n: + return t + return None + + def linkAt(self, n): + token = self.tokAt(n) + if token: + return token.link + return None class Scope: """ Scope. Information about global scope, function scopes, class scopes, inner scopes, etc. - C++ class: http://cppcheck.net/devinfo/doxyoutput/classScope.html + C++ class: https://cppcheck.sourceforge.io/devinfo/doxyoutput/classScope.html Attributes bodyStart The { Token for this scope @@ -355,8 +558,13 @@ class Scope: For a class scope, this is the class name. function If this scope belongs at a function call, this attribute has the Function information. See the Function class. - type Type of scope: Global, Function, Class, If, While + functions if this is a Class type, it may have functions defined + nestedIn + type Type of scope: Function, If/Else/For/While/Switch/Global/Enum/Struct/Namespace/Class/Constructor/Destructor + isExecutable True when the type is: Function/If/Else/For/While/Do/Switch/Try/Catch/Unconditional/Lambda + definedType """ + #symboldatabase.cpp/SymbolDatabase::printXml Id = None bodyStartId = None @@ -368,6 +576,7 @@ class Scope: function = None nestedInId = None nestedIn = None + nestedList = None type = None isExecutable = None varlistId = None @@ -378,21 +587,25 @@ def __init__(self, element): self.className = element.get('className') self.functionId = element.get('function') self.function = None + self.functions = [] self.bodyStartId = element.get('bodyStart') self.bodyStart = None self.bodyEndId = element.get('bodyEnd') self.bodyEnd = None self.nestedInId = element.get('nestedIn') self.nestedIn = None + self.nestedList = [] self.type = element.get('type') + self.definedType = element.get('definedType') self.isExecutable = (self.type in ('Function', 'If', 'Else', 'For', 'While', 'Do', 'Switch', 'Try', 'Catch', 'Unconditional', 'Lambda')) - self.varlistId = list() - self.varlist = list() + + self.varlistId = [] + self.varlist = [] def __repr__(self): attrs = ["Id", "className", "functionId", "bodyStartId", "bodyEndId", - "nestedInId", "nestedIn", "type", "isExecutable"] + "nestedInId", "nestedIn", "type", "definedType", "isExecutable", "functions"] return "{}({})".format( "Scope", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -402,25 +615,36 @@ def setId(self, IdMap): self.bodyStart = IdMap[self.bodyStartId] self.bodyEnd = IdMap[self.bodyEndId] self.nestedIn = IdMap[self.nestedInId] + if self.nestedIn: + self.nestedIn.nestedList.append(self) self.function = IdMap[self.functionId] for v in self.varlistId: - self.varlist.append(IdMap[v]) + value = IdMap.get(v) + if value: + self.varlist.append(value) class Function: """ Information about a function C++ class: - http://cppcheck.net/devinfo/doxyoutput/classFunction.html + https://cppcheck.sourceforge.io/devinfo/doxyoutput/classFunction.html Attributes - argument Argument list + argument Argument list (dict of argument number and variable) token Token in function implementation tokenDef Token in function definition - isVirtual Is this function is virtual + name + type Constructor/CopyConstructor/MoveConstructor/OperatorEqual/Destructor/Function/Lambda/Unknown + hasVirtualSpecifier Is this function is virtual isImplicitlyVirtual Is this function is virtual this in the base classes - isStatic Is this function is static + access Public/Protected/Private + isInlineKeyword Is inline keyword used + isStatic Is this function static + isAttributeNoreturn + overriddenFunction """ + #symboldatabase.cpp/SymbolDatabase::printXml Id = None argument = None @@ -431,9 +655,13 @@ class Function: tokenDefId = None name = None type = None - isVirtual = None + access = None isImplicitlyVirtual = None + hasVirtualSpecifier = None + isInlineKeyword = None isStatic = None + isAttributeNoreturn = None + overriddenFunction = None nestedIn = None def __init__(self, element, nestedIn): @@ -442,20 +670,22 @@ def __init__(self, element, nestedIn): self.tokenDefId = element.get('tokenDef') self.name = element.get('name') self.type = element.get('type') - isVirtual = element.get('isVirtual') - self.isVirtual = (isVirtual and isVirtual == 'true') - isImplicitlyVirtual = element.get('isImplicitlyVirtual') - self.isImplicitlyVirtual = (isImplicitlyVirtual and isImplicitlyVirtual == 'true') - isStatic = element.get('isStatic') - self.isStatic = (isStatic and isStatic == 'true') + self.hasVirtualSpecifier = element.get('hasVirtualSpecifier', 'false') == 'true' + self.isImplicitlyVirtual = element.get('isImplicitlyVirtual', 'false') == 'true' + self.access = element.get('access') + self.isInlineKeyword = element.get('isInlineKeyword', 'false') == 'true' + self.isStatic = element.get('isStatic', 'false') == 'true' + self.isAttributeNoreturn = element.get('isAttributeNoreturn', 'false') == 'true' + self.overriddenFunction = element.get('overriddenFunction', 'false') == 'true' self.nestedIn = nestedIn self.argument = {} self.argumentId = {} def __repr__(self): - attrs = ["Id", "tokenId", "tokenDefId", "name", "type", "isVirtual", - "isImplicitlyVirtual", "isStatic", "argumentId"] + attrs = ["Id", "tokenId", "tokenDefId", "name", "type", "hasVirtualSpecifier", + "isImplicitlyVirtual", "access", "isInlineKeyword", "isStatic", + "isAttributeNoreturn", "overriddenFunction", "nestedIn", "argumentId"] return "{}({})".format( "Function", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -468,30 +698,36 @@ def setId(self, IdMap): self.tokenDef = IdMap[self.tokenDefId] +#todo add class Types: + #symboldatabase.cpp/SymbolDatabase::printXml + + class Variable: """ Information about a variable C++ class: - http://cppcheck.net/devinfo/doxyoutput/classVariable.html + https://cppcheck.sourceforge.io/devinfo/doxyoutput/classVariable.html Attributes: nameToken Name token in variable declaration typeStartToken Start token of variable declaration typeEndToken End token of variable declaration - access Global/Local/Namespace/Public/Protected/Public/Throw/Argument + access Global/Local/Namespace/Public/Protected/Public/Throw/Argument/Unknown scope Variable scope + constness Variable constness (same encoding as ValueType::constness) isArgument Is this variable a function argument? + isGlobal Is this variable a global variable? + isLocal Is this variable a local variable? isArray Is this variable an array? isClass Is this variable a class or struct? isConst Is this variable a const variable? - isGlobal Is this variable a global variable? isExtern Is this variable an extern variable? - isLocal Is this variable a local variable? isPointer Is this variable a pointer isReference Is this variable a reference isStatic Is this variable static? - constness Variable constness (same encoding as ValueType::constness) + isVolatile Is this variable volatile? """ + #symboldatabase.cpp/SymbolDatabase::printXml Id = None nameTokenId = None @@ -513,6 +749,7 @@ class Variable: isPointer = False isReference = False isStatic = False + isVolatile = False constness = 0 def __init__(self, element): @@ -524,27 +761,26 @@ def __init__(self, element): self.typeEndTokenId = element.get('typeEndToken') self.typeEndToken = None self.access = element.get('access') + self.isArgument = (self.access and self.access == 'Argument') + self.isGlobal = (self.access and self.access == 'Global') + self.isLocal = (self.access and self.access == 'Local') self.scopeId = element.get('scope') self.scope = None - self.isArgument = element.get('isArgument') == 'true' + self.constness = int(element.get('constness',0)) self.isArray = element.get('isArray') == 'true' self.isClass = element.get('isClass') == 'true' self.isConst = element.get('isConst') == 'true' - self.isGlobal = element.get('access') == 'Global' self.isExtern = element.get('isExtern') == 'true' - self.isLocal = element.get('isLocal') == 'true' self.isPointer = element.get('isPointer') == 'true' self.isReference = element.get('isReference') == 'true' self.isStatic = element.get('isStatic') == 'true' - self.constness = element.get('constness') - if self.constness: - self.constness = int(self.constness) + self.isVolatile = element.get('isVolatile') == 'true' def __repr__(self): attrs = ["Id", "nameTokenId", "typeStartTokenId", "typeEndTokenId", "access", "scopeId", "isArgument", "isArray", "isClass", "isConst", "isGlobal", "isExtern", "isLocal", "isPointer", - "isReference", "isStatic", "constness", ] + "isReference", "isStatic", "isVolatile", "constness"] return "{}({})".format( "Variable", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -556,6 +792,42 @@ def setId(self, IdMap): self.typeEndToken = IdMap[self.typeEndTokenId] self.scope = IdMap[self.scopeId] +class Container: + """ + Container class -- information about containers + + Attributes: + array-like-index-op true/false + stdStringLike true/false + """ + #tokenizer.cpp/tokenizer::dump + Id = None + + def __init__(self, element): + self.Id = element.get('id') + self.arrayLikeIndexOp = element.get('array-like-index-op') == 'true' + self.stdStringLike = element.get('std-string-like') == 'true' + +class TypedefInfo: + """ + TypedefInfo class -- information about typedefs + + Attributes: + name name of the typedef + used 0/1 + """ + #tokenizer.cpp/tokenizer::dump + + name = None + used = None + file = None + linenr = None + column = None + + def __init__(self, element): + self.name = element.get('name') + _load_location(self, element) + self.used = (element.get('used') == '1') class Value: """ @@ -565,11 +837,19 @@ class Value: intvalue integer value tokvalue token value floatvalue float value + movedvalue + uninit containerSize container size + bufferSize buffer size + lifetimeScope Local/Argument/SubFunction/ThisPointer/ThisValue + lifetimeKind Object/SubObject/Lambda/Iterator/Address + symbolicDelta condition condition where this Value comes from - valueKind 'known' or 'possible' - inconclusive Is value inconclusive? + bound Upper/Lower/Point + valueKind known/possible/impossible/inconclusive + path 0/1/2/3/.. """ + #token.cpp/token::printValueFlow intvalue = None tokvalue = None @@ -577,7 +857,6 @@ class Value: containerSize = None condition = None valueKind = None - inconclusive = False def isKnown(self): return self.valueKind and self.valueKind == 'known' @@ -588,13 +867,27 @@ def isPossible(self): def isImpossible(self): return self.valueKind and self.valueKind == 'impossible' + def isInconclusive(self): + return self.valueKind and self.valueKind == 'inconclusive' + def __init__(self, element): self.intvalue = element.get('intvalue') if self.intvalue: self.intvalue = int(self.intvalue) - self.tokvalue = element.get('tokvalue') + self._tokvalueId = element.get('tokvalue') self.floatvalue = element.get('floatvalue') + self.movedvalue = element.get('movedvalue') + self.uninit = element.get('uninit') + self.bufferSize = element.get('buffer-size') self.containerSize = element.get('container-size') + self.iteratorStart = element.get('iterator-start') + self.iteratorEnd = element.get('iterator-end') + self._lifetimeId = element.get('lifetime') + self.lifetimeScope = element.get('lifetime-scope') + self.lifetimeKind = element.get('lifetime-kind') + self._symbolicId = element.get('symbolic') + self.symbolicDelta = element.get('symbolic-delta') + self.bound = element.get('bound') self.condition = element.get('condition-line') if self.condition: self.condition = int(self.condition) @@ -604,12 +897,18 @@ def __init__(self, element): self.valueKind = 'possible' elif element.get('impossible'): self.valueKind = 'impossible' - if element.get('inconclusive'): - self.inconclusive = True + elif element.get('inconclusive'): + self.valueKind = 'inconclusive' + self.path = element.get('path') + + def setId(self, IdMap): + self.tokvalue = IdMap.get(self._tokvalueId) + self.lifetime = IdMap.get(self._lifetimeId) + self.symbolic = IdMap.get(self._symbolicId) def __repr__(self): - attrs = ["intvalue", "tokvalue", "floatvalue", "containerSize", - "condition", "valueKind", "inconclusive"] + attrs = ["intvalue", "tokvalue", "floatvalue", "movedvalue", "uninit", + "bufferSize", "containerSize", "condition", "valueKind"] return "{}({})".format( "Value", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -622,7 +921,7 @@ class ValueFlow: Each possible value has a ValueFlow::Value item. Each ValueFlow::Value either has a intvalue or tokvalue C++ class: - http://cppcheck.net/devinfo/doxyoutput/classValueFlow_1_1Value.html + https://cppcheck.sourceforge.io/devinfo/doxyoutput/classValueFlow_1_1Value.html Attributes: values Possible values @@ -653,29 +952,60 @@ class Suppression: fileName The name of the file to suppress warnings for, can include wildcards lineNumber The number of the line to suppress warnings from, can be 0 to represent any line symbolName The name of the symbol to match warnings for, can include wildcards + lineBegin The first line to suppress warnings from + lineEnd The last line to suppress warnings from + suppressionType The type of suppression which is applied (unique = None (default), file, block, blockBegin, blockEnd, macro) """ errorId = None fileName = None lineNumber = None symbolName = None + lineBegin = None + lineEnd = None + suppressionType = None def __init__(self, element): self.errorId = element.get('errorId') self.fileName = element.get('fileName') self.lineNumber = element.get('lineNumber') self.symbolName = element.get('symbolName') + self.lineBegin = element.get('lineBegin') + self.lineEnd = element.get('lineEnd') + self.suppressionType = element.get('type') def __repr__(self): - attrs = ['errorId' , "fileName", "lineNumber", "symbolName"] + attrs = ["errorId", "fileName", "lineNumber", "symbolName", "lineBegin", "lineEnd","suppressionType"] return "{}({})".format( "Suppression", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) ) def isMatch(self, file, line, message, errorId): + # Line Suppression if ((self.fileName is None or fnmatch(file, self.fileName)) - and (self.lineNumber is None or int(line) == int(self.lineNumber)) + and (self.suppressionType is None) # Verify use of default suppression type (None = unique) + and (self.lineNumber is not None and int(line) == int(self.lineNumber)) + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True + # File Suppression + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (self.suppressionType is not None and self.suppressionType == "file") # Verify use of file (global) suppression type + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True + # Block Suppression Mode + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (self.suppressionType is not None and self.suppressionType == "block") # Type for Block suppression + and (self.lineBegin is not None and int(line) > int(self.lineBegin)) # Code Match is between the Block suppression + and (self.lineEnd is not None and int(line) < int(self.lineEnd)) # Code Match is between the Block suppression + 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) + 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+'*')) and fnmatch(errorId, self.errorId)): return True @@ -691,8 +1021,11 @@ class Configuration: Attributes: name Name of the configuration, "" for default directives List of Directive items + macro_usage List of used macros + preprocessor_if_conditions List of preprocessor if conditions that was evaluated during preprocessing tokenlist List of Token items scopes List of Scope items + containers List of Container items functions List of Function items variables List of Variable items valueflow List of ValueFlow values @@ -701,22 +1034,32 @@ class Configuration: name = '' directives = [] + macro_usage = [] + preprocessor_if_conditions = [] tokenlist = [] scopes = [] + containers = [] functions = [] variables = [] + typedefInfo = [] valueflow = [] standards = None + clang_warnings = [] def __init__(self, name): self.name = name self.directives = [] + self.macro_usage = [] + self.preprocessor_if_conditions = [] self.tokenlist = [] self.scopes = [] + self.containers = [] self.functions = [] self.variables = [] + self.typedefInfo = [] self.valueflow = [] self.standards = Standards() + self.clang_warnings = [] def set_tokens_links(self): """Set next/previous links between tokens.""" @@ -728,11 +1071,13 @@ def set_tokens_links(self): prev = token def set_id_map(self, arguments): - IdMap = {None: None, '0': None, '00000000': None, '0000000000000000': None} + IdMap = {None: None, '0': None, '00000000': None, '0000000000000000': None, '0x0': None} for token in self.tokenlist: IdMap[token.Id] = token for scope in self.scopes: IdMap[scope.Id] = scope + for container in self.containers: + IdMap[container.Id] = container for function in self.functions: IdMap[function.Id] = function for variable in self.variables: @@ -745,6 +1090,8 @@ def set_id_map(self, arguments): token.setId(IdMap) for scope in self.scopes: scope.setId(IdMap) + #for container in self.containers: + # container.setId(IdMap) for function in self.functions: function.setId(IdMap) for variable in self.variables: @@ -766,7 +1113,7 @@ class Platform: This class contains type sizes Attributes: - name Name of the platform + name Name of the platform: unspecified/native/win32A/win32W/win64/unix32/unix64/platformFile char_bit CHAR_BIT value short_bit SHORT_BIT value int_bit INT_BIT value @@ -876,11 +1223,12 @@ def __init__(self, filename): """ :param filename: Path to Cppcheck dump file """ + self.language = None self.filename = filename self.rawTokens = [] self.platform = None self.suppressions = [] - self.files = [] + self.files = [] # source files for elements occurred in this configuration platform_done = False rawtokens_done = False @@ -892,6 +1240,8 @@ def __init__(self, filename): for event, node in ElementTree.iterparse(self.filename, events=('start', 'end')): if platform_done and rawtokens_done and suppressions_done: break + if node.tag == 'dumps': + self.language = node.get('language') if node.tag == 'platform' and event == 'start': self.platform = Platform(node) platform_done = True @@ -937,6 +1287,12 @@ def iterconfigurations(self): # Iterating in a . iter_scope_varlist = False + # Iterating + iter_typedef_info = False + + # Iterating + iter_directive = False + # Use iterable objects to traverse XML tree for dump files incrementally. # Iterative approach is required to avoid large memory consumption. # Calling .clear() is necessary to let the element be garbage collected. @@ -946,12 +1302,17 @@ def iterconfigurations(self): if event == 'start': cfg = Configuration(node.get('cfg')) continue - elif event == 'end': + if event == 'end': cfg.setIdMap(cfg_arguments) yield cfg cfg = None cfg_arguments = [] + elif node.tag == 'clang-warning' and event == 'start': + cfg.clang_warnings.append({'file': node.get('file'), + 'line': int(node.get('line')), + 'column': int(node.get('column')), + 'message': node.get('message')}) # Parse standards elif node.tag == "standards" and event == 'start': continue @@ -963,13 +1324,24 @@ def iterconfigurations(self): cfg.standards.set_posix(node) # Parse directives list - elif node.tag == 'directive' and event == 'start': - cfg.directives.append(Directive(node)) + elif node.tag == 'directive': + if event == 'start': + cfg.directives.append(Directive(node)) + iter_directive = True + elif event == 'end': + iter_directive = False + # Parse macro usage + elif node.tag == 'macro' and event == 'start': + cfg.macro_usage.append(MacroUsage(node)) + + # Preprocessor #if/#elif condition + elif node.tag == "if-cond" and event == 'start': + cfg.preprocessor_if_conditions.append(PreprocessorIfCondition(node)) # Parse tokens elif node.tag == 'tokenlist' and event == 'start': continue - elif node.tag == 'token' and event == 'start': + elif node.tag == 'token' and event == 'start' and not iter_directive: cfg.tokenlist.append(Token(node)) # Parse scopes @@ -990,7 +1362,7 @@ def iterconfigurations(self): if event == 'start': cfg_function = Function(node, cfg.scopes[-1]) continue - elif event == 'end': + if event == 'end': cfg.functions.append(cfg_function) cfg_function = None @@ -1011,6 +1383,22 @@ def iterconfigurations(self): else: cfg_arguments.append(var) + # Parse containers + elif node.tag == 'containers' and event == 'start': + continue + elif node.tag == 'container' and event == 'start': + cfg.containers.append(Container(node)) + + # Parse typedef info + elif node.tag == 'typedef-info': + iter_typedef_info = (event == 'start') + elif iter_typedef_info and node.tag == 'info' and event == 'start': + cfg.typedefInfo.append(TypedefInfo(node)) + + # Parse template-token + #elif node.tag == 'TokenAndName' and event == 'start': #todo add processing of containers + # cfg.containers.append(Container(node)) + # Parse valueflows (list of values) elif node.tag == 'valueflow' and event == 'start': continue @@ -1018,7 +1406,7 @@ def iterconfigurations(self): if event == 'start': cfg_valueflow = ValueFlow(node) continue - elif event == 'end': + if event == 'end': cfg.valueflow.append(cfg_valueflow) cfg_valueflow = None @@ -1121,12 +1509,31 @@ def ArgumentParser(): parser.add_argument("--cli", help="Addon is executed from Cppcheck", action="store_true") + parser.add_argument("--file-list", metavar='', + default=None, + help="file list in a text file") parser.add_argument("-q", "--quiet", help='do not print "Checking ..." lines', action="store_true") return parser +def get_files(args): + """Return dump_files, ctu_info_files""" + all_files = args.dumpfile + if args.file_list: + with open(args.file_list, 'rt') as f: + for line in f.readlines(): + all_files.append(line.rstrip()) + dump_files = [] + ctu_info_files = [] + for f in all_files: + if f.endswith('.ctu-info'): + ctu_info_files.append(f) + else: + dump_files.append(f) + return dump_files, ctu_info_files + def simpleMatch(token, pattern): for p in pattern.split(' '): if not token or token.str != p: @@ -1134,6 +1541,124 @@ def simpleMatch(token, pattern): token = token.next return True +patterns = { + '%any%': lambda tok: tok, + '%assign%': lambda tok: tok if tok.isAssignmentOp else None, + '%comp%': lambda tok: tok if tok.isComparisonOp else None, + '%name%': lambda tok: tok if tok.isName else None, + '%op%': lambda tok: tok if tok.isOp else None, + '%or%': lambda tok: tok if tok.str == '|' else None, + '%oror%': lambda tok: tok if tok.str == '||' else None, + '%var%': lambda tok: tok if tok.variable else None, + '(*)': lambda tok: tok.link if tok.str == '(' else None, + '[*]': lambda tok: tok.link if tok.str == '[' else None, + '{*}': lambda tok: tok.link if tok.str == '{' else None, + '<*>': lambda tok: tok.link if tok.str == '<' and tok.link else None, +} + +def match_atom(token, p): + if not token: + return None + if not p: + return None + if token.str == p: + return token + if p in ['!', '|', '||', '%', '!=', '*']: + return None + if p in patterns: + return patterns[p](token) + if '|' in p: + for x in p.split('|'): + t = match_atom(token, x) + if t: + return t + elif p.startswith('!!'): + t = match_atom(token, p[2:]) + if not t: + return token + elif p.startswith('**'): + a = p[2:] + t = token + while t: + if match_atom(t, a): + return t + if t.link and t.str in ['(', '[', '<', '{']: + t = t.link + t = t.next + return None + +class MatchResult: + def __init__(self, matches, bindings=None, keys=None): + self.__dict__.update(bindings or {}) + self._matches = matches + self._keys = keys or [] + + def __bool__(self): + return self._matches + + def __nonzero__(self): + return self._matches + + def __getattr__(self, k): + if k in self._keys: + return None + raise AttributeError + +def bind_split(s): + if '@' in s: + p = s.partition('@') + return (p[0], p[2]) + return (s, None) + +def match(token, pattern): + if not pattern: + return MatchResult(False) + end = None + bindings = {} + words = [bind_split(word) for word in pattern.split()] + for p, b in words: + t = match_atom(token, p) + if b: + bindings[b] = token + if not t: + return MatchResult(False, keys=[xx for pp, xx in words]+['end']) + end = t + token = t.next + bindings['end'] = end + return MatchResult(True, bindings=bindings) + +def get_function_call_name_args(token): + """Get function name and arguments for function call + name, args = get_function_call_name_args(tok) + """ + if token is None: + return None, None + if not token.isName or not token.scope.isExecutable: + return None, None + if not simpleMatch(token.next, '('): + return None, None + if token.function: + nametok = token.function.token + if nametok is None: + nametok = token.function.tokenDef + if token in (token.function.token, token.function.tokenDef): + return None, None + name = nametok.str + while nametok.previous and nametok.previous.previous and nametok.previous.str == '::' and nametok.previous.previous.isName: + name = nametok.previous.previous.str + '::' + name + nametok = nametok.previous.previous + scope = token.function.nestedIn + while scope: + if scope.className: + name = scope.className + '::' + name + scope = scope.nestedIn + else: + nametok = token + name = nametok.str + while nametok.previous and nametok.previous.previous and nametok.previous.str == '::' and nametok.previous.previous.isName: + name = nametok.previous.previous.str + '::' + name + nametok = nametok.previous.previous + return name, getArguments(token) def is_suppressed(location, message, errorId): for suppression in current_dumpfile_suppressions: @@ -1141,11 +1666,19 @@ def is_suppressed(location, message, errorId): return True return False -def reportError(location, severity, message, addon, errorId, extra=''): +def log_checker(message, addon): + if '--cli' in sys.argv: + msg = { 'addon': addon, + 'severity': 'none', + 'message': message, + 'errorId': 'logChecker'} + sys.stdout.write(json.dumps(msg) + '\n') + +def reportError(location, severity, message, addon, errorId, extra='', columnOverride=None): if '--cli' in sys.argv: msg = { 'file': location.file, 'linenr': location.linenr, - 'column': location.column, + 'column': location.column if columnOverride is None else columnOverride, 'severity': severity, 'message': message, 'addon': addon, @@ -1161,3 +1694,34 @@ def reportError(location, severity, message, addon, errorId, extra=''): sys.stderr.write('%s (%s) %s [%s-%s]\n' % (loc, severity, message, addon, errorId)) global EXIT_CODE EXIT_CODE = 1 + +def reportSummary(dumpfile, summary_type, summary_data): + msg = {'summary': summary_type, 'data': summary_data} + if '--cli' in sys.argv: + sys.stdout.write(json.dumps(msg) + '\n') + else: + # dumpfile ends with ".dump" + ctu_info_file = dumpfile[:-4] + "ctu-info" + with open(ctu_info_file, 'at') as f: + f.write(json.dumps(msg) + '\n') + + +def get_path_premium_addon(): + p = pathlib.Path(sys.argv[0]).parent.parent + + for ext in ('.exe', ''): + p1 = os.path.join(p, 'premiumaddon' + ext) + p2 = os.path.join(p, 'cppcheck' + ext) + if os.path.isfile(p1) and os.path.isfile(p2): + return p1 + return None + + +def cmd_output(cmd): + with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p: + stdout, stderr = p.communicate() + rc = p.returncode + out = stdout + if rc == 1 and len(stderr) > 2: + out = stderr + return out.decode(encoding='utf-8', errors='ignore') diff --git a/addons/findcasts.py b/addons/findcasts.py index 5f7943d578b..d4842b229a6 100755 --- a/addons/findcasts.py +++ b/addons/findcasts.py @@ -3,40 +3,30 @@ # Locate casts in the code # -import cppcheckdata -import sys +import cppcheck -for arg in sys.argv[1:]: - if arg.startswith('-'): - continue +@cppcheck.checker +def cast(cfg, data): + for token in cfg.tokenlist: + if token.str != '(' or not token.astOperand1 or token.astOperand2: + continue - print('Checking %s...' % arg) - data = cppcheckdata.CppcheckData(arg) + # Is it a lambda? + if token.astOperand1.str == '{': + continue - for cfg in data.iterconfigurations(): - print('Checking %s, config %s...' % (arg, cfg.name)) - for token in cfg.tokenlist: - if token.str != '(' or not token.astOperand1 or token.astOperand2: - continue + # we probably have a cast.. if there is something inside the parentheses + # there is a cast. Otherwise this is a function call. + typetok = token.next + if not typetok.isName: + continue - # Is it a lambda? - if token.astOperand1.str == '{': - continue + # cast number => skip output + if token.astOperand1.isNumber: + continue - # we probably have a cast.. if there is something inside the parentheses - # there is a cast. Otherwise this is a function call. - typetok = token.next - if not typetok.isName: - continue + # void cast => often used to suppress compiler warnings + if typetok.str == 'void': + continue - # cast number => skip output - if token.astOperand1.isNumber: - continue - - # void cast => often used to suppress compiler warnings - if typetok.str == 'void': - continue - - cppcheckdata.reportError(token, 'information', 'found a cast', 'findcasts', 'cast') - -sys.exit(cppcheckdata.EXIT_CODE) + cppcheck.reportError(token, 'information', 'found a cast') diff --git a/addons/misc.py b/addons/misc.py index 15a742c28f9..670d6152ff5 100644 --- a/addons/misc.py +++ b/addons/misc.py @@ -16,7 +16,7 @@ VERIFY_ACTUAL = [] def reportError(token, severity, msg, id): - if id == 'debug' and DEBUG == False: + if id == 'debug' and not DEBUG: return if VERIFY: VERIFY_ACTUAL.append(str(token.linenr) + ':' + id) diff --git a/addons/misra.py b/addons/misra.py index 8c109865775..ca8eb2bfb69 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 # -# MISRA C 2012 checkers +# MISRA C 2012 checkers (including amendment 1 and 2) # # Example usage of this addon (scan a sourcefile main.cpp) # cppcheck --dump main.cpp # python misra.py --rule-texts= main.cpp.dump # -# Limitations: This addon is released as open source. Rule texts can't be freely -# distributed. https://www.misra.org.uk/forum/viewtopic.php?f=56&t=1189 +# Limitations: This addon is released as open source. We are not allowed by +# MISRA to distribute rule texts openly. # # The MISRA standard documents may be obtained from https://www.misra.org.uk # @@ -17,12 +17,14 @@ import cppcheckdata import itertools +import json import sys import re import os import argparse import codecs import string +import copy try: from itertools import izip as zip @@ -43,7 +45,28 @@ def grouped(iterable, n): ['int', 'uint', 'int_least', 'uint_least', 'int_fast', 'uint_fast'], [8, 16, 32, 64])] +STDINT_H_DEFINES_MIN = ['%s%d_MIN' % (n, v) for n, v in itertools.product( + ['INT', 'INT_LEAST', 'INT_FAST',], + [8, 16, 32, 64])] + +STDINT_H_DEFINES_MAX = ['%s%d_MAX' % (n, v) for n, v in itertools.product( + ['INT', 'UINT','INT_LEAST','UINT_LEAST', 'INT_FAST', 'UINT_FAST',], + [8, 16, 32, 64])] + +STDINT_H_DEFINES_C = ['%s%d_C' % (n, v) for n, v in itertools.product( + ['INT', 'UINT'], + [8, 16, 32, 64])] + +INTTYPES_H_DEFINES = ['%s%d' % (n, v) for n, v in itertools.product( + ['PRId', 'PRIi', 'PRIo', 'PRIu', 'PRIx', 'PRIX', 'SCNd', + 'SCNi', 'SCNo', 'SCNu', 'SCNx', 'PRIdLEAST', 'PRIiLEAST', + 'PRIoLEAST', 'PRIuLEAST', 'PRIxLEAST', 'PRIXLEAST', + 'SCNdLEAST', 'SCNiLEAST', 'SCNoLEAST', 'SCNuLEAST', + 'SCNxLEAST', 'PRIdFAST', 'PRIiFAST', 'PRIoFAST', 'PRIuFAST', + 'PRIxFAST', 'PRIXFAST', 'SCNdFAST', 'SCNiFAST', 'SCNoFAST', + 'SCNuFAST', 'SCNxFAST', ], + [8, 16, 32, 64])] typeBits = { 'CHAR': None, 'SHORT': None, @@ -167,7 +190,8 @@ def rawlink(rawtoken): # Identifiers described in Section 7 "Library" of C99 Standard -# Based on ISO/IEC 9899 WF14/N1256 Annex B -- Library summary +# Based on ISO/IEC 9899:1999 (E) Annex B -- Library summary +# (https://www.dii.uchile.cl/~daespino/files/Iso_C_1999_definition.pdf) C99_STDLIB_IDENTIFIERS = { # B.1 Diagnostics 'assert.h': C90_STDLIB_IDENTIFIERS['assert.h'], @@ -218,9 +242,13 @@ def rawlink(rawtoken): 'float.h': C90_STDLIB_IDENTIFIERS['float.h'] + ['FLT_EVAL_METHOD'], # B.7 Format conversion of integer types 'inttypes.h': [ + 'PRIdMAX', 'PRIiMAX', 'PRIoMAX', 'PRIuMAX', 'PRIxMAX', 'PRIXMAX', + 'SCNdMAX', 'SCNiMAX', 'SCNoMAX', 'SCNuMAX', 'SCNxMAX', 'PRIdPTR', + 'PRIiPTR', 'PRIoPTR', 'PRIuPTR', 'PRIxPTR', 'PRIXPTR', 'SCNdPTR', + 'SCNiPTR', 'SCNoPTR', 'SCNuPTR', 'SCNxPTR', 'imaxdiv_t', 'imaxabs', 'imaxdiv', 'strtoimax', 'strtoumax', 'wcstoimax', 'wcstoumax', - ], + ] + INTTYPES_H_DEFINES, # B.8 Alternative spellings 'iso646.h': [ 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not', 'not_eq', @@ -244,11 +272,12 @@ def rawlink(rawtoken): 'acoshl', 'asinh', 'asinhf', 'asinhl', 'atanh', 'atanhf', 'atanhl', 'cosh', 'coshf', 'coshl', 'sinh', 'sinhf', 'sinhl', 'tanh', 'tanhf', 'tanhl', 'expf', 'expl', 'exp2', 'exp2f', 'exp2l', 'expm1', 'expm1f', - 'expm1l', 'frexpf', 'frexpl', 'ilogb', 'ilogbf', 'ilogbl', 'float', + 'expm1l', 'frexpf', 'frexpl', 'ilogb', 'ilogbf', 'ilogbl', 'ldexpf', 'ldexpl', 'logf', 'logl', 'log10f', 'log10l', 'log1p', 'log1pf', 'log1pl', 'log2', 'log2f', 'log2l', 'logb', 'logbf', 'logbl', 'modff', 'modfl', 'scalbn', 'scalbnf', 'scalbnl', 'scalbln', 'scalblnf', - 'scalblnl', 'hypotl', 'powf', 'powl', 'sqrtf', 'sqrtl', 'erf', 'erff', + 'scalblnl','cbrt', 'cbrtf','cbrtl', 'fabs', 'fabsf', 'fabsl', + 'hypotl', 'hypotf', 'powf', 'powl', 'sqrtf', 'sqrtl', 'erf', 'erff', 'erfl', 'erfc', 'erfcf', 'erfcl', 'lgamma', 'lgammaf', 'lgammal', 'tgamma', 'tgammaf', 'tgammal', 'ceilf', 'ceill', 'floorf', 'floorl', 'nearbyint', 'nearbyintf', 'nearbyintl', 'rint', 'rintf', 'rintl', @@ -259,7 +288,7 @@ def rawlink(rawtoken): 'remquol', 'copysign', 'copysignf', 'copysignl', 'nan', 'nanf', 'nanl', 'nextafter', 'nextafterf', 'nextafterl', 'nexttoward', 'nexttowardf', 'nexttowardl', 'fdim', 'fdimf', 'fdiml', 'fmax', - 'fmaxf', 'fmaxl', 'fmin', 'fminf', 'fminl', 'fmal', 'isgreater', + 'fmaxf', 'fmaxl', 'fmin', 'fminf', 'fminl', 'fmaf','fmal', 'isgreater', 'isgreaterequal', 'isless', 'islessequal', 'islessgreater', 'isunordered', ], @@ -282,11 +311,11 @@ def rawlink(rawtoken): 'UINTMAX_MAX', 'PTRDIFF_MIN', 'PTRDIFF_MAX', 'SIG_ATOMIC_MIN', 'SIG_ATOMIC_MAX', 'SIZE_MAX', 'WCHAR_MIN', 'WCHAR_MAX', 'WINT_MIN', 'WINT_MAX', 'INTN_C', 'UINTN_C', 'INTMAX_C', 'UINTMAX_C', - ] + STDINT_TYPES, + ] + STDINT_TYPES + STDINT_H_DEFINES_MIN + STDINT_H_DEFINES_MAX + STDINT_H_DEFINES_C, # B.18 Input/output 'stdio.h': C90_STDLIB_IDENTIFIERS['stdio.h'] + [ 'mode', 'restrict', 'snprintf', 'vfscanf', 'vscanf', - 'vsnprintf', 'vsscanf', + 'vsnprintf', 'vsscanf','ftell' ], # B.19 General utilities 'stdlib.h': C90_STDLIB_IDENTIFIERS['stdlib.h'] + [ @@ -315,57 +344,266 @@ def rawlink(rawtoken): 'vfwprintf', 'vfwscanf', 'vswprintf', 'vswscanf', 'vwprintf', 'vwscanf', 'wprintf', 'wscanf', 'fgetwc', 'fgetws', 'fputwc', 'fputws', 'fwide', 'getwc', 'getwchar', 'putwc', 'putwchar', 'ungetwc', 'wcstod', - 'wcstof', 'double', 'int', 'long', 'long', 'long', 'wcscpy', 'wcsncpy', - 'wmemcpy', 'wmemmove', 'wcscat', 'wcsncat', 'wcscmp', 'wcscoll', + 'wcstof', 'wcstold', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcscpy', + 'wcsncpy', 'wmemcpy', 'wmemmove', 'wcscat', 'wcsncat', 'wcscmp', 'wcscoll', 'wcsncmp', 'wcsxfrm', 'wmemcmp', 'wcschr', 'wcscspn', 'wcspbrk', 'wcsrchr', 'wcsspn', 'wcsstr', 'wcstok', 'wmemchr', 'wcslen', 'wmemset', 'wcsftime', 'btowc', 'wctob', 'mbsinit', 'mbrlen', 'mbrtowc', 'wcrtomb', 'mbsrtowcs', 'wcsrtombs', ], + # B.24 Wide character classification and mapping utilities + 'wctype.h': ['wint_t', 'wctrans_t', 'wctype_t', 'WEOF', + 'iswalnum', 'iswalpha', 'iswblank', 'iswcntrl', 'iswdigit', + 'iswgraph', 'iswlower', 'iswprint', 'iswpunct', 'iswspace', 'iswupper', + 'iswxdigit', 'iswctype', 'wctype', 'towlower', 'towupper', 'towctrans', + 'wctrans'], } +# Identifiers described in Section 7 "Library" of C11 Standard +# Based on ISO/IEC 9899:201x N1570 (Draft 12.04.2011) Annex B -- Library summary +# (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) +C11_STDLIB_IDENTIFIERS = { + # B.1 Diagnostics + 'assert.h': C99_STDLIB_IDENTIFIERS['assert.h']+ ['static_assert'], + # B.2 Complex + 'complex.h': C99_STDLIB_IDENTIFIERS['complex.h']+['__STDC_NO_COMPLEX__','CMPLX','CMPLXF','CMPLXL'], + # B.3 Character handling + 'ctype.h': C99_STDLIB_IDENTIFIERS['ctype.h'], + # B.4 Errors + 'errno.h': C99_STDLIB_IDENTIFIERS['errno.h']+['__STDC_WANT_LIB_EXT1__', 'errno_t'], + # B.5 Floating-point environment + 'fenv.h': C99_STDLIB_IDENTIFIERS['fenv.h'], + # B.6 Characteristics of floating types + 'float.h': C99_STDLIB_IDENTIFIERS['float.h']+[ + 'FLT_HAS_SUBNORM','DBL_HAS_SUBNORM','LDBL_HAS_SUBNORM', + 'FLT_DECIMAL_DIG','DBL_DECIMAL_DIG','LDBL_DECIMAL_DIG', + 'FLT_TRUE_MIN','DBL_TRUE_MIN','LDBL_TRUE_MIN'], + # B.7 Format conversion of integer types + 'inttypes.h': C99_STDLIB_IDENTIFIERS["inttypes.h"], + # B.8 Alternative spellings + 'iso646.h': C99_STDLIB_IDENTIFIERS["iso646.h"], + # B.9 Size of integer types + 'limits.h': C99_STDLIB_IDENTIFIERS['limits.h'], + # B.10 Localization + 'locale.h': C99_STDLIB_IDENTIFIERS['locale.h'], + # B.11 Mathematics + 'math.h': C99_STDLIB_IDENTIFIERS['math.h'], + # B.12 Nonlocal jumps + 'setjmp.h': C99_STDLIB_IDENTIFIERS['setjmp.h'], + # B.13 Signal handling + 'signal.h': C99_STDLIB_IDENTIFIERS['signal.h'], + # B.14 Alignment + 'stdalign.h': ['alignas','__alignas_is_defined'], + # B.15 Variable arguments + 'stdarg.h': C99_STDLIB_IDENTIFIERS['stdarg.h'], + # B.16 Atomics + 'stdatomic.h': ['ATOMIC_BOOL_LOCK_FREE', 'ATOMIC_CHAR_LOCK_FREE', + 'ATOMIC_CHAR16_T_LOCK_FREE', 'ATOMIC_CHAR32_T_LOCK_FREE', 'ATOMIC_WCHAR_T_LOCK_FREE', + 'ATOMIC_SHORT_LOCK_FREE', 'ATOMIC_INT_LOCK_FREE', 'ATOMIC_LONG_LOCK_FREE', + 'ATOMIC_LLONG_LOCK_FREE', 'ATOMIC_POINTER_LOCK_FREE', 'ATOMIC_FLAG_INIT', + 'memory_order', 'atomic_flag', 'memory_order_relaxed', 'memory_order_consume', + 'memory_order_acquire', 'memory_order_release', 'memory_order_acq_rel', 'memory_order_seq_cst', + 'atomic_bool', 'atomic_char', 'atomic_schar', 'atomic_uchar', 'atomic_short', 'atomic_ushort', + 'atomic_int', 'atomic_uint', 'atomic_long', 'atomic_ulong', 'atomic_llong', 'atomic_ullong', + 'atomic_char16_t', 'atomic_char32_t', 'atomic_wchar_t', 'atomic_int_least8_t', + 'atomic_uint_least8_t', 'atomic_int_least16_t', 'atomic_uint_least16_t', + 'atomic_int_least32_t', 'atomic_uint_least32_t', 'atomic_int_least64_t', + 'atomic_uint_least64_t', 'atomic_int_fast8_t', 'atomic_uint_fast8_t', + 'atomic_int_fast16_t', 'atomic_uint_fast16_t', 'atomic_int_fast32_t', + 'atomic_uint_fast32_t', 'atomic_int_fast64_t', 'atomic_uint_fast64_t', + 'atomic_intptr_t', 'atomic_uintptr_t', 'atomic_size_t', 'atomic_ptrdiff_t', + 'atomic_intmax_t', 'atomic_uintmax_t', 'ATOMIC_VAR_INIT', 'type kill_dependency', + 'atomic_thread_fence', 'atomic_signal_fence', 'atomic_is_lock_free', + 'atomic_store', 'atomic_store_explicit', 'atomic_load', 'atomic_load_explicit', + 'atomic_exchange', 'atomic_exchange_explicit', 'atomic_compare_exchange_strong', + 'atomic_compare_exchange_strong_explicit', 'atomic_compare_exchange_weak', + 'atomic_compare_exchange_weak_explicit', 'atomic_fetch_key', 'atomic_fetch_key_explicit', + 'atomic_flag_test_and_set', 'atomic_flag_test_and_set_explicit', + 'atomic_flag_clear', 'atomic_flag_clear_explicit', ], + # B.17 Boolean type and values + 'stdbool.h': C99_STDLIB_IDENTIFIERS['stdbool.h'], + # B.18 Common definitions + 'stddef.h': C99_STDLIB_IDENTIFIERS['stddef.h'] + + ['max_align_t','__STDC_WANT_LIB_EXT1__', 'rsize_t'], + # B.19 Integer types + 'stdint.h': C99_STDLIB_IDENTIFIERS['stdint.h']+ + ['__STDC_WANT_LIB_EXT1__', 'RSIZE_MAX'], + # B.20 Input/output + 'stdio.h': C99_STDLIB_IDENTIFIERS['stdio.h'] + + ['__STDC_WANT_LIB_EXT1__', 'L_tmpnam_s', 'TMP_MAX_S', 'errno_t', 'rsize_t', + 'tmpfile_s', 'tmpnam_s', 'fopen_s', 'freopen_s', 'fprintf_s', 'fscanf_s', + 'printf_s','scanf_s','snprintf_s','sprintf_s','sscanf_s','vfprintf_s', + 'vfscanf_s', 'vsprintf_s', 'vsscanf_s', 'gets_s' + ], + # B.21 General utilities + 'stdlib.h': C99_STDLIB_IDENTIFIERS['stdlib.h'] + + ['constraint_handler_t', 'set_constraint_handler_s', 'abort_handler_s', + 'ignore_handler_s', 'getenv_s', 'bsearch_s', 'qsort_s', 'wctomb_s', + 'mbstowcs_s', 'wcstombs_s'], + # B.22 Noretrun + 'stdnoreturn.h': ['noreturn'], + # B.23 String handling + 'string.h': C99_STDLIB_IDENTIFIERS['string.h'] + + ['memcpy_s', 'memmoce_s', 'strcpy_s', 'strncpy_s','strcat_s', + 'strtok_s', 'memset_s', 'strerror_s', 'strerrorlen_s', 'strnlen_s'], + # B.24 Type-generic math + 'tgmath.h': C99_STDLIB_IDENTIFIERS['tgmath.h'], + # B.25 Threads + 'threads.h': ['thread_local', 'ONCE_FLAG_INIT', 'TSS_DTOR_ITERATIONS', + 'cnd_t', 'thrd_t', 'tss_t', 'mtx_t', 'tss_dtor_t', 'thrd_start_t', + 'once_flag', 'mtx_plain', 'mtx_recursive', 'mtx_timed', 'thrd_timedout', + 'thrd_success', 'thrd_busy', 'thrd_error', 'thrd_nomem', 'call_once', + 'cnd_broadcast', 'cnd_destroy','cnd_init', 'cnd_signal', 'cnd_timedwait', + 'cnd_wait','mtx_destroy', 'mtx_init', 'mtx_lock', 'mtx_timedlock', + 'mtx_trylock', 'mtx_unlock', 'thrd_create', 'thrd_current', + 'thrd_detach', 'thrd_equal', 'thrd_exit', 'thrd_join', 'thrd_sleep', + 'thrd_yield', 'tss_create', 'tss_delete', 'tss_get', 'tss_set' ], + # B.26 Date and time + 'time.h': C99_STDLIB_IDENTIFIERS['time.h'] + [ + 'asctime_s', 'ctime_s', 'gmtime_s', 'localtime_s' + ], + # B.27 Unicode utilities + 'uchar.h': ['mbstate_t', 'size_t', 'char16_t', 'char32_t', + 'mbrtoc16', 'c16rtomb', 'mbrtoc32', 'c32rtomb' + ], + # B.28 Extended multibyte/wide character utilities + 'wchar.h': C99_STDLIB_IDENTIFIERS["wchar.h"]+[ + 'fwprintf_s', 'fwscanf_s', 'snwprintf_s', 'swprintf_s', 'swscanf_s', + 'vfwprintf_s', 'vfwscanf_s', 'vsnwprintf_s', 'vswprintf_s', 'vswscanf_s', + 'vwprintf_s', 'vwscanf_s', 'wprintf_s', 'wscanf_s', 'wcscpy_s', 'wcsncpy_s', + 'wmemcpy_s', 'wmemmove_s', 'wcscat_s', 'wcsncat_s', 'wcstok_s', 'wcsnlen_s', + 'wcrtomb_s', 'mbsrtowcs_s', 'wcsrtombs_s', + ], + # B.29 Wide character classification and mapping utilities + 'wctype.h': C99_STDLIB_IDENTIFIERS['wctype.h'], +} -def isStdLibId(id_, standard='c99'): - id_lists = [] +def getStdLib(standard): if standard == 'c89': - id_lists = C90_STDLIB_IDENTIFIERS.values() - elif standard == 'c99': - id_lists = C99_STDLIB_IDENTIFIERS.values() + return C90_STDLIB_IDENTIFIERS + if standard == 'c99': + return C99_STDLIB_IDENTIFIERS + return C11_STDLIB_IDENTIFIERS + +def isStdLibId(id_, standard='c99'): + id_lists = getStdLib(standard).values() for l in id_lists: if id_ in l: return True return False - # Reserved keywords defined in ISO/IEC9899:1990 -- ch 6.1.1 C90_KEYWORDS = { - 'auto', 'break', 'double', 'else', 'enum', 'extern', 'float', 'for', - 'goto', 'if', 'case', 'char', 'const', 'continue', 'default', 'do', 'int', - 'long', 'struct', 'switch', 'register', 'typedef', 'union', 'unsigned', - 'void', 'volatile', 'while', 'return', 'short', 'signed', 'sizeof', - 'static' + 'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', + 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', + 'int', 'long', 'register', 'return', 'short', 'signed', + 'sizeof', 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', + 'void', 'volatile', 'while' } -# Reserved keywords defined in ISO/IEC 9899 WF14/N1256 -- ch. 6.4.1 -C99_KEYWORDS = { - 'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', - 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'inline', - 'int', 'long', 'register', 'restrict', 'return', 'short', 'signed', - 'sizeof', 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', - 'void', 'volatile', 'while', '_Bool', '_Complex', '_Imaginary' +# Reserved keywords defined in Section 6.4.1 "Language" of C99 Standard +# Based on ISO/IEC 9899:1999 (E) 6.4.1 Keywords +# Adding the expanding macros from Section 7 too +# (https://www.dii.uchile.cl/~daespino/files/Iso_C_1999_definition.pdf) +C99_ADDED_KEYWORDS = { + 'inline', 'restrict', '_Bool', '_Complex', '_Imaginary', + 'bool', 'complex', 'imaginary' } +# Reserved keywords defined in Section 6.4.1 "Language" of C11 Standard +# Based on ISO/IEC 9899:201x N1570 (Draft 12.04.2011) 6.4.1 Keywords +# Adding the expanding macros from Section 7 too +# (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) +C11_ADDED_KEYWORDS = { + '_Alignas', '_Alignof', '_Atomic', '_Generic', '_Noreturn', + '_Static_assert', '_Thread_local' , + 'alignas', 'alignof', 'noreturn', 'static_assert','thread_local' +} def isKeyword(keyword, standard='c99'): kw_set = {} if standard == 'c89': kw_set = C90_KEYWORDS elif standard == 'c99': - kw_set = C99_KEYWORDS + kw_set = copy.copy(C90_KEYWORDS) + kw_set.update(C99_ADDED_KEYWORDS) + else: + kw_set = copy.copy(C90_KEYWORDS) + kw_set.update(C99_ADDED_KEYWORDS) + kw_set.update(C11_ADDED_KEYWORDS) return keyword in kw_set +def is_source_file(file): + return file.endswith('.c') + + +def is_header(file): + return file.endswith('.h') + + +def is_errno_setting_function(function_name): + return function_name and \ + function_name in ('ftell', 'fgetpos', 'fsetpos', 'fgetwc', 'fputwc' + 'strtoimax', 'strtoumax', 'strtol', 'strtoul', + 'strtoll', 'strtoull', 'strtof', 'strtod', 'strtold' + 'wcstoimax', 'wcstoumax', 'wcstol', 'wcstoul', + 'wcstoll', 'wcstoull', 'wcstof', 'wcstod', 'wcstold' + 'wcrtomb', 'wcsrtombs', 'mbrtowc') + + +def get_type_conversion_to_from(token): + def get_vartok(expr): + while expr: + if isCast(expr): + if expr.astOperand2 is None: + expr = expr.astOperand1 + else: + expr = expr.astOperand2 + elif expr.str in ('.', '::'): + expr = expr.astOperand2 + elif expr.str == '[': + expr = expr.astOperand1 + else: + break + return expr if (expr and expr.variable) else None + + if isCast(token): + vartok = get_vartok(token) + if vartok: + return (token.next, vartok.variable.typeStartToken) + + elif token.str == '=': + lhs = get_vartok(token.astOperand1) + rhs = get_vartok(token.astOperand2) + if lhs and rhs: + return (lhs.variable.typeStartToken, rhs.variable.typeStartToken) + + return None + + +def is_composite_expr(expr, composite_operator=False): + """MISRA C 2012, section 8.10.3""" + if expr is None: + return False + + if not composite_operator: + if expr.str == '?' and simpleMatch(expr.astOperand2, ':'): + colon = expr.astOperand2 + return is_composite_expr(colon.astOperand1,True) or is_composite_expr(colon.astOperand2, True) + if (expr.str in ('+', '-', '*', '/', '%', '&', '|', '^', '>>', "<<", "?", ":", '~')): + return is_composite_expr(expr.astOperand1,True) or is_composite_expr(expr.astOperand2, True) + return False + + # non constant expression? + if expr.isNumber: + return False + if expr.astOperand1 or expr.astOperand2: + return is_composite_expr(expr.astOperand1,True) or is_composite_expr(expr.astOperand2, True) + return True + + def getEssentialTypeCategory(expr): if not expr: return None @@ -387,9 +625,20 @@ def getEssentialTypeCategory(expr): return expr.valueType.sign if expr.valueType and expr.valueType.typeScope and expr.valueType.typeScope.className: return "enum<" + expr.valueType.typeScope.className + ">" - if expr.variable: - typeToken = expr.variable.typeStartToken - while typeToken: + # Unwrap membership, dereferences and array indexing + vartok = expr + while True: + if simpleMatch(vartok, '[') or (vartok and vartok.str == '*' and vartok.astOperand2 is None): + vartok = vartok.astOperand1 + elif simpleMatch(vartok, '.'): + vartok = vartok.astOperand2 + else: + break + if vartok and vartok.variable: + typeToken = vartok.variable.typeStartToken + while typeToken and typeToken.isName: + if typeToken.str == 'char' and not typeToken.isSigned and not typeToken.isUnsigned: + return 'char' if typeToken.valueType: if typeToken.valueType.type == 'bool': return typeToken.valueType.type @@ -398,6 +647,20 @@ def getEssentialTypeCategory(expr): if typeToken.valueType.sign: return typeToken.valueType.sign typeToken = typeToken.next + + # See Appendix D, section D.6, Character constants + if expr.str[0] == "'" and expr.str[-1] == "'": + if len(expr.str) == 3 or (len(expr.str) == 4 and expr.str[1] == '\\'): + return 'char' + return expr.valueType.sign + + if (expr.isCast and expr.str == "("): + castTok = expr.next + while castTok.isName or castTok.str == "*": + if castTok.str == 'char' and not castTok.isSigned and not castTok.isUnsigned: + return 'char' + castTok = castTok.next + if expr.valueType: return expr.valueType.sign return None @@ -417,15 +680,66 @@ def getEssentialCategorylist(operand1, operand2): return e1, e2 +def get_essential_type_from_value(value, is_signed): + if value is None: + return None + for t in ('char', 'short', 'int', 'long', 'long long'): + bits = bitsOfEssentialType(t) + if bits >= 64: + continue + if is_signed: + range_min = -(1 << (bits - 1)) + range_max = (1 << (bits - 1)) - 1 + else: + range_min = 0 + range_max = (1 << bits) - 1 + sign = 'signed' if is_signed else 'unsigned' + if is_signed and value < 0 and value >= range_min: + return '%s %s' % (sign, t) + if value >= 0 and value <= range_max: + return '%s %s' % (sign, t) + return None + def getEssentialType(expr): if not expr: return None - if expr.variable: - typeToken = expr.variable.typeStartToken + + # See Appendix D, section D.6, Character constants + if expr.str[0] == "'" and expr.str[-1] == "'": + if len(expr.str) == 3 or (len(expr.str) == 4 and expr.str[1] == '\\'): + return 'char' + return '%s %s' % (expr.valueType.sign, expr.valueType.type) + + if expr.variable or isCast(expr): + typeToken = expr.variable.typeStartToken if expr.variable else expr.next while typeToken and typeToken.isName: - if typeToken.str in INT_TYPES + STDINT_TYPES + ['float', 'double']: - return typeToken.str + if typeToken.str == 'char' and not typeToken.isSigned and not typeToken.isUnsigned: + return 'char' typeToken = typeToken.next + if expr.valueType: + if expr.valueType.type == 'bool': + return 'bool' + if expr.valueType.isFloat(): + return expr.valueType.type + if expr.valueType.isIntegral(): + if (expr.valueType.sign is None) and expr.valueType.type == 'char': + return 'char' + return '%s %s' % (expr.valueType.sign, expr.valueType.type) + + elif expr.isNumber: + # Appendix D, D.6 The essential type of literal constants + # Integer constants + if expr.valueType.type == 'bool': + return 'bool' + if expr.valueType.isFloat(): + return expr.valueType.type + if expr.valueType.isIntegral(): + if expr.valueType.type != 'int': + return '%s %s' % (expr.valueType.sign, expr.valueType.type) + return get_essential_type_from_value(expr.getKnownIntValue(), expr.valueType.sign == 'signed') + + elif expr.str in ('<', '<=', '>=', '>', '==', '!=', '&&', '||', '!'): + return 'bool' elif expr.astOperand1 and expr.astOperand2 and expr.str in ( '+', '-', '*', '/', '%', '&', '|', '^', '>>', "<<", "?", ":"): @@ -435,12 +749,19 @@ def getEssentialType(expr): return None e1 = getEssentialType(expr.astOperand1) e2 = getEssentialType(expr.astOperand2) - if not e1 or not e2: + if e1 is None or e2 is None: return None + if is_constant_integer_expression(expr): + sign1 = e1.split(' ')[0] + sign2 = e2.split(' ')[0] + if sign1 == sign2 and sign1 in ('signed', 'unsigned'): + e = get_essential_type_from_value(expr.getKnownIntValue(), sign1 == 'signed') + if e: + return e if bitsOfEssentialType(e2) >= bitsOfEssentialType(e1): return e2 - else: - return e1 + return e1 + elif expr.str == "~": e1 = getEssentialType(expr.astOperand1) return e1 @@ -451,22 +772,45 @@ def getEssentialType(expr): def bitsOfEssentialType(ty): if ty is None: return 0 - if ty == 'char': + last_type = ty.split(' ')[-1] + if last_type == 'Boolean': + return 1 + if last_type == 'char': return typeBits['CHAR'] - if ty == 'short': + if last_type == 'short': return typeBits['SHORT'] - if ty == 'int': + if last_type == 'int': return typeBits['INT'] - if ty == 'long': - return typeBits['LONG'] - if ty == 'long long': + if ty.endswith('long long'): return typeBits['LONG_LONG'] + if last_type == 'long': + return typeBits['LONG'] for sty in STDINT_TYPES: if ty == sty: return int(''.join(filter(str.isdigit, sty))) return 0 +def get_function_pointer_type(tok): + ret = '' + while tok and (tok.isName or tok.str == '*'): + ret += ' ' + tok.str + tok = tok.next + if tok is None or tok.str != '(': + return None + tok = tok.link + if not simpleMatch(tok, ') ('): + return None + ret += '(' + tok = tok.next.next + while tok and (tok.str not in '()'): + if tok.varId is None: + ret += ' ' + tok.str + tok = tok.next + if (tok is None) or tok.str != ')': + return None + return ret[1:] + ')' + def isCast(expr): if not expr or expr.str != '(' or not expr.astOperand1 or expr.astOperand2: return False @@ -474,6 +818,18 @@ def isCast(expr): return False return True +def is_constant_integer_expression(expr): + if expr is None: + return False + if expr.isInt: + return True + if not expr.isArithmeticalOp: + return False + if expr.astOperand1 and not is_constant_integer_expression(expr.astOperand1): + return False + if expr.astOperand2 and not is_constant_integer_expression(expr.astOperand2): + return False + return True def isFunctionCall(expr, std='c99'): if not expr: @@ -515,7 +871,28 @@ def getForLoopExpressions(forToken): lpar.astOperand2.astOperand2.astOperand2] -def getForLoopCounterVariables(forToken): +def get_function_scope(cfg, func): + if func: + for scope in cfg.scopes: + if scope.function == func: + return scope + return None + + +def is_variable_changed(start_token, end_token, var): + """Check if variable is updated between body_start and body_end""" + tok = start_token + while tok != end_token: + if tok.isAssignmentOp: + vartok = tok.astOperand1 + while vartok.astOperand1: + vartok = vartok.astOperand1 + if vartok and vartok.variable == var: + return True + tok = tok.next + return False + +def getForLoopCounterVariables(forToken, cfg): """ Return a set of Variable objects defined in ``for`` statement and satisfy requirements to loop counter term from section 8.14 of MISRA document. @@ -526,6 +903,7 @@ def getForLoopCounterVariables(forToken): if not tn or tn.str != '(': return None vars_defined = set() + vars_initialized = set() vars_exit = set() vars_modified = set() cur_clause = 1 @@ -537,14 +915,50 @@ def getForLoopCounterVariables(forToken): elif cur_clause == 2: vars_exit.add(tn.variable) elif cur_clause == 3: - if tn.next and hasSideEffectsRecursive(tn.next): + if tn.next and countSideEffectsRecursive(tn.next) > 0: vars_modified.add(tn.variable) elif tn.previous and tn.previous.str in ('++', '--'): - vars_modified.add(tn.variable) + tn_ast = tn.astParent + if tn_ast and tn_ast == tn.previous: + vars_modified.add(tn.variable) + elif tn_ast and tn_ast.str == '.' and tn_ast.astOperand2 and tn_ast.astOperand2.variable: + vars_modified.add(tn_ast.astOperand2.variable) + if cur_clause == 1 and tn.isAssignmentOp: + var_token = tn.astOperand1 + while var_token and var_token.str == '.': + var_token = var_token.astOperand2 + if var_token and var_token.variable: + vars_initialized.add(var_token.variable) + if cur_clause == 1 and tn.isName and tn.next.str == '(': + function_args_in_init = getArguments(tn.next) + function_scope = get_function_scope(cfg, tn.function) + for arg_nr in range(len(function_args_in_init)): + init_arg = function_args_in_init[arg_nr] + if init_arg is None or not init_arg.isUnaryOp('&'): + continue + var_token = init_arg.astOperand1 + while var_token and var_token.str == '.': + var_token = var_token.astOperand2 + if var_token is None or var_token.variable is None: + continue + changed = False + if function_scope is None: + changed = True + elif tn.function is None: + changed = True + else: + function_body_start = function_scope.bodyStart + function_body_end = function_scope.bodyEnd + args = tn.function.argument[arg_nr + 1] + if function_scope is None or is_variable_changed(function_body_start, function_body_end, args): + changed = True + if changed: + vars_initialized.add(var_token.variable) + if tn.str == ';': cur_clause += 1 tn = tn.next - return vars_defined & vars_exit & vars_modified + return vars_defined | vars_initialized, vars_exit & vars_modified def findCounterTokens(cond): @@ -574,6 +988,7 @@ def isFloatCounterInWhileLoop(whileToken): lpar = whileToken.next rpar = lpar.link counterTokens = findCounterTokens(lpar.astOperand2) + tok_varid = tuple(tok.varId for tok in counterTokens if tok.varId) whileBodyStart = None if simpleMatch(rpar, ') {'): whileBodyStart = rpar.next @@ -584,33 +999,41 @@ def isFloatCounterInWhileLoop(whileToken): token = whileBodyStart while token != whileBodyStart.link: token = token.next - for counterToken in counterTokens: - if not counterToken.valueType or not counterToken.valueType.isFloat(): - continue - if token.isAssignmentOp and token.astOperand1.str == counterToken.str: + if not token.varId: + continue + if token.varId not in tok_varid: + continue + if not token.astParent or not token.valueType or not token.valueType.isFloat(): + continue + parent = token.astParent + if parent.str in ('++', '--'): + return True + while parent: + if parent.isAssignmentOp and parent.str != "=" and parent.astOperand1 == token: return True - if token.str == counterToken.str and token.astParent and token.astParent.str in ('++', '--'): + if parent.str == "=" and parent.astOperand1.str == token.str and parent.astOperand1 != token: return True + parent = parent.astParent return False -def hasSideEffectsRecursive(expr): +def countSideEffectsRecursive(expr): if not expr or expr.str == ';': - return False + return 0 if expr.str == '=' and expr.astOperand1 and expr.astOperand1.str == '[': prev = expr.astOperand1.previous if prev and (prev.str == '{' or prev.str == '{'): - return hasSideEffectsRecursive(expr.astOperand2) + return countSideEffectsRecursive(expr.astOperand2) if expr.str == '=' and expr.astOperand1 and expr.astOperand1.str == '.': e = expr.astOperand1 while e and e.str == '.' and e.astOperand2: e = e.astOperand1 if e and e.str == '.': - return False + return 0 if expr.isAssignmentOp or expr.str in {'++', '--'}: - return True + return 1 # Todo: Check function calls - return hasSideEffectsRecursive(expr.astOperand1) or hasSideEffectsRecursive(expr.astOperand2) + return countSideEffectsRecursive(expr.astOperand1) + countSideEffectsRecursive(expr.astOperand2) def isBoolExpression(expr): @@ -641,6 +1064,14 @@ def isConstantExpression(expr): return False return True +def isUnknownConstantExpression(expr): + if expr.isName and not isEnumConstant(expr) and expr.variable is None: + return True + if expr.astOperand1 and isUnknownConstantExpression(expr.astOperand1): + return True + if expr.astOperand2 and isUnknownConstantExpression(expr.astOperand2): + return True + return False def isUnsignedInt(expr): return expr and expr.valueType and expr.valueType.type in ('short', 'int') and expr.valueType.sign == 'unsigned' @@ -847,16 +1278,14 @@ def isNoReturnScope(tok): # Return the token which the value is assigned to -def getAssignedVariableToken(valueToken): - if not valueToken: +def getAssignedVariableToken(vartok): + if not vartok: return None - if not valueToken.astParent: - return None - operator = valueToken.astParent - if operator.isAssignmentOp: - return operator.astOperand1 - if operator.isArithmeticalOp: - return getAssignedVariableToken(operator) + parent = vartok.astParent + while parent and parent.isArithmeticalOp: + parent = parent.astParent + if parent and parent.isAssignmentOp: + return parent.astOperand1 return None # If the value is used as a return value, return the function definition @@ -887,18 +1316,23 @@ def tokenFollowsSequence(token, sequence): class Define: def __init__(self, directive): + self.name = '' self.args = [] self.expansionList = '' - res = re.match(r'#define [A-Za-z0-9_]+\(([A-Za-z0-9_, ]+)\)[ ]+(.*)', directive.str) - if res is None: - return - - self.args = res.group(1).strip().split(',') - self.expansionList = res.group(2) + res = re.match(r'#define ([A-Za-z0-9_]+)\(([A-Za-z0-9_, ]+)\)[ ]+(.*)', directive.str) + if res: + self.name = res.group(1) + self.args = res.group(2).strip().split(',') + self.expansionList = res.group(3) + else: + res = re.match(r'#define ([A-Za-z0-9_]+)[ ]+(.*)', directive.str) + if res: + self.name = res.group(1) + self.expansionList = res.group(2) def __repr__(self): - attrs = ["args", "expansionList"] + attrs = ["name", "args", "expansionList"] return "{}({})".format( "Define", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -909,19 +1343,45 @@ def getAddonRules(): """Returns dict of MISRA rules handled by this addon.""" addon_rules = [] compiled = re.compile(r'.*def[ ]+misra_([0-9]+)_([0-9]+)[(].*') - for line in open(__file__): - res = compiled.match(line) - if res is None: - continue - addon_rules.append(res.group(1) + '.' + res.group(2)) + with open(__file__) as f: + for line in f: + res = compiled.match(line) + if res is None: + continue + addon_rules.append(res.group(1) + '.' + res.group(2)) return addon_rules def getCppcheckRules(): """Returns list of rules handled by cppcheck.""" - return ['1.3', '2.1', '2.2', '2.6', '5.3', '8.3', - '13.2', '13.6', '17.5', '18.1', '18.2', '18.3', - '18.6', '20.6', '22.1', '22.2', '22.4', '22.6'] + return ['1.3', # + '2.1', # alwaysFalse, duplicateBreak + '2.2', # alwaysTrue, redundantCondition, redundantAssignment, redundantAssignInSwitch, unreadVariable + '2.6', # unusedLabel + '5.3', # shadowVariable + '8.3', # funcArgNamesDifferent + '8.13', # constPointer + '9.1', # uninitvar + '14.3', # alwaysTrue, alwaysFalse, compareValueOutOfTypeRangeError + '13.2', # unknownEvaluationOrder + '13.6', # sizeofCalculation + '17.4', # missingReturn + '17.5', # argumentSize + '18.1', # pointerOutOfBounds + '18.2', # comparePointers + '18.3', # comparePointers + '18.6', # danglingLifetime + '19.1', # overlappingWriteUnion, overlappingWriteFunction + '20.6', # preprocessorErrorDirective + '21.13', # invalidFunctionArg + '21.17', # bufferAccessOutOfBounds + '21.18', # bufferAccessOutOfBounds + '22.1', # memleak, resourceLeak, memleakOnRealloc, leakReturnValNotUsed, leakNoVarFunctionCall + '22.2', # autovarInvalidDeallocation + '22.3', # incompatibleFileOpen + '22.4', # writeReadOnlyFile + '22.6' # useClosedFile + ] def generateTable(): @@ -947,8 +1407,8 @@ def generateTable(): numberOfRules[18] = 8 numberOfRules[19] = 2 numberOfRules[20] = 14 - numberOfRules[21] = 12 - numberOfRules[22] = 6 + numberOfRules[21] = 21 + numberOfRules[22] = 10 # Rules that can be checked with compilers: # compiler = ['1.1', '1.2'] @@ -991,7 +1451,7 @@ def remove_file_prefix(file_path, prefix): return result -class Rule(object): +class Rule(): """Class to keep rule text and metadata""" MISRA_SEVERITY_LEVELS = ['Required', 'Mandatory', 'Advisory'] @@ -1025,7 +1485,7 @@ def __repr__(self): return "%d.%d (%s)" % (self.num1, self.num2, self.misra_severity) -class MisraSettings(object): +class MisraSettings(): """Hold settings for misra.py script.""" __slots__ = ["verify", "quiet", "show_summary"] @@ -1066,17 +1526,18 @@ def __init__(self, settings, stdversion="c89"): self.settings = settings # Test validation rules lists - self.verify_expected = list() - self.verify_actual = list() + self.verify_expected = [] + self.verify_actual = [] # List of formatted violation messages - self.violations = dict() + self.violations = {} # if --rule-texts is specified this dictionary # is loaded with descriptions of each rule # by rule number (in hundreds). # ie rule 1.2 becomes 102 - self.ruleTexts = dict() + self.ruleTexts = {} + self.ruleText_filename = None # Dictionary of dictionaries for rules to suppress # Dict1 is keyed by rule number in the hundreds format of @@ -1086,13 +1547,13 @@ def __init__(self, settings, stdversion="c89"): # or an item of None which indicates suppress rule for the entire file. # The line and symbol name tuple may have None as either of its elements but # should not be None for both. - self.suppressedRules = dict() + self.suppressedRules = {} # Prefix to ignore when matching suppression files. self.filePrefix = None # Number of all violations suppressed per rule - self.suppressionStats = dict() + self.suppressionStats = {} self.stdversion = stdversion @@ -1100,6 +1561,13 @@ def __init__(self, settings, stdversion="c89"): self.existing_violations = set() + self._ctu_summary_typedefs = False + self._ctu_summary_tagnames = False + self._ctu_summary_identifiers = False + self._ctu_summary_usage = False + + self.path_premium_addon = None + def __repr__(self): attrs = ["settings", "verify_expected", "verify_actual", "violations", "ruleTexts", "suppressedRules", "filePrefix", @@ -1112,8 +1580,196 @@ def __repr__(self): def get_num_significant_naming_chars(self, cfg): if cfg.standards and cfg.standards.c == "c89": return 31 - else: - return 63 + return 63 + + def _save_ctu_summary_typedefs(self, dumpfile, typedef_info): + if self._ctu_summary_typedefs: + return + + self._ctu_summary_typedefs = True + + summary = [] + for ti in typedef_info: + summary.append({ 'name': ti.name, 'file': ti.file, 'line': ti.linenr, 'column': ti.column, 'used': ti.used }) + if len(summary) > 0: + cppcheckdata.reportSummary(dumpfile, 'MisraTypedefInfo', summary) + + def _save_ctu_summary_tagnames(self, dumpfile, cfg): + if self._ctu_summary_tagnames: + return + + self._ctu_summary_tagnames = True + + summary = [] + # structs/enums + for scope in cfg.scopes: + if scope.className is None: + continue + if scope.className.startswith('Anonymous'): + continue + if scope.type not in ('Struct', 'Enum'): + continue + used = False + tok = scope.bodyEnd + while tok: + if tok.str == scope.className: + used = True + break + tok = tok.next + summary.append({'name': scope.className, 'used':used, 'file': scope.bodyStart.file, 'line': scope.bodyStart.linenr, 'column': scope.bodyStart.column}) + if len(summary) > 0: + cppcheckdata.reportSummary(dumpfile, 'MisraTagName', summary) + + def _save_ctu_summary_identifiers(self, dumpfile, cfg): + if self._ctu_summary_identifiers: + return + self._ctu_summary_identifiers = True + + external_identifiers = [] + internal_identifiers = [] + local_identifiers = [] + + def identifier(nameToken): + return {'name':nameToken.str, 'file':nameToken.file, 'line':nameToken.linenr, 'column':nameToken.column} + + names = [] + + for var in cfg.variables: + if var.nameToken is None: + continue + if var.access != 'Global': + if var.nameToken.str in names: + continue + names.append(var.nameToken.str) + local_identifiers.append(identifier(var.nameToken)) + elif var.isStatic: + names.append(var.nameToken.str) + i = identifier(var.nameToken) + i['inlinefunc'] = False + internal_identifiers.append(i) + else: + names.append(var.nameToken.str) + i = identifier(var.nameToken) + i['decl'] = var.isExtern + external_identifiers.append(i) + + for func in cfg.functions: + if func.tokenDef is None: + continue + if func.isStatic: + i = identifier(func.tokenDef) + i['inlinefunc'] = func.isInlineKeyword + internal_identifiers.append(i) + else: + if func.token is None: + i = identifier(func.tokenDef) + else: + i = identifier(func.token) + i['decl'] = func.token is None + external_identifiers.append(i) + + cppcheckdata.reportSummary(dumpfile, 'MisraExternalIdentifiers', external_identifiers) + cppcheckdata.reportSummary(dumpfile, 'MisraInternalIdentifiers', internal_identifiers) + cppcheckdata.reportSummary(dumpfile, 'MisraLocalIdentifiers', local_identifiers) + + def _save_ctu_summary_usage(self, dumpfile, cfg): + if self._ctu_summary_usage: + return + self._ctu_summary_usage = True + + names = [] + for token in cfg.tokenlist: + if not token.isName: + continue + if token.function and token != token.function.tokenDef: + if (not token.function.isStatic) and (token.str not in names): + names.append({'name': token.str, 'file': token.file}) + elif token.variable: + if token == token.variable.nameToken: + continue + if token.variable.access == 'Global' and (not token.variable.isStatic) and (token.str not in names): + names.append({'name': token.str, 'file': token.file}) + + if len(names) > 0: + cppcheckdata.reportSummary(dumpfile, 'MisraUsage', names) + + + def misra_1_2(self, cfg): + # gcc language extensions: https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html + for token in cfg.tokenlist: + if simpleMatch(token, '? :'): + self.reportError(token, 1, 2) + elif simpleMatch(token, '( {') and simpleMatch(token.next.link.previous, '; } )'): + self.reportError(token, 1, 2) + + + def misra_1_4(self, cfg): + for token in cfg.tokenlist: + if token.str in ('_Atomic', '_Noreturn', '_Generic', '_Thread_local', '_Alignas', '_Alignof'): + self.reportError(token, 1, 4) + if token.str.endswith('_s') and isFunctionCall(token.next, cfg.standards.c): + # See C specification C11 - Annex K, page 578 + if token.str in ('tmpfile_s', 'tmpnam_s', 'fopen_s', 'freopen_s', 'fprintf_s', 'fscanf_s', 'printf_s', 'scanf_s', + 'snprintf_s', 'sprintf_s', 'sscanf_s', 'vfprintf_s', 'vfscanf_s', 'vprintf_s', 'vscanf_s', + 'vsnprintf_s', 'vsprintf_s', 'vsscanf_s', 'gets_s', 'set_constraint_handler_s', 'abort_handler_s', + 'ignore_handler_s', 'getenv_s', 'bsearch_s', 'qsort_s', 'wctomb_s', 'mbstowcs_s', 'wcstombs_s', + 'memcpy_s', 'memmove_s', 'strcpy_s', 'strncpy_s', 'strcat_s', 'strncat_s', 'strtok_s', 'memset_s', + 'strerror_s', 'strerrorlen_s', 'strnlen_s', 'asctime_s', 'ctime_s', 'gmtime_s', 'localtime_s', + 'fwprintf_s', 'fwscanf_s', 'snwprintf_s', 'swprintf_s', 'swscanf_s', 'vfwprintf_s', 'vfwscanf_s', + 'vsnwprintf_s', 'vswprintf_s', 'vswscanf_s', 'vwprintf_s', 'vwscanf_s', 'wprintf_s', 'wscanf_s', + 'wcscpy_s', 'wcsncpy_s', 'wmemcpy_s', 'wmemmove_s', 'wcscat_s', 'wcsncat_s', 'wcstok_s', 'wcsnlen_s', + 'wcrtomb_s', 'mbsrtowcs_s', 'wcsrtombs_s'): + self.reportError(token, 1, 4) + + def misra_2_2(self, cfg): + for token in cfg.tokenlist: + if token.isExpandedMacro: + continue + if (token.str in '+-') and token.astOperand2: + if simpleMatch(token.astOperand1, '0'): + self.reportError(token.astOperand1, 2, 2) + elif simpleMatch(token.astOperand2, '0'): + self.reportError(token.astOperand2, 2, 2) + if token.str == '*' and token.astOperand2: + if simpleMatch(token.astOperand2, '0'): + self.reportError(token.astOperand1, 2, 2) + elif simpleMatch(token.astOperand1, '0'): + self.reportError(token.astOperand2, 2, 2) + elif simpleMatch(token.astOperand1, '1'): + self.reportError(token.astOperand1, 2, 2) + elif simpleMatch(token.astOperand2, '1'): + self.reportError(token.astOperand2, 2, 2) + + def misra_2_3(self, dumpfile, typedefInfo): + self._save_ctu_summary_typedefs(dumpfile, typedefInfo) + + def misra_2_4(self, dumpfile, cfg): + self._save_ctu_summary_tagnames(dumpfile, cfg) + + def misra_2_5(self, dumpfile, cfg): + used_macros = [] + unused_macro = {} + for m in cfg.macro_usage: + used_macros.append(m.name) + for directive in cfg.directives: + res_define = re.match(r'#define[ \t]+([a-zA-Z_][a-zA-Z_0-9]*).*', directive.str) + res_undef = re.match(r'#undef[ \t]+([a-zA-Z_][a-zA-Z_0-9]*).*', directive.str) + if res_define: + macro_name = res_define.group(1) + unused_macro[macro_name] = {'name': macro_name, 'used': (macro_name in used_macros), + 'file': directive.file, 'line': directive.linenr, 'column': directive.column} + elif res_undef: + macro_name = res_undef.group(1) + # assuming that if we have #undef, we also have #define somewhere + if macro_name in unused_macro: + unused_macro[macro_name]['used'] = True + else: + unused_macro[macro_name] = {'name': macro_name, 'used': True, 'file': directive.file, + 'line': directive.linenr, 'column': directive.column} + used_macros.append(macro_name) + + if unused_macro: + cppcheckdata.reportSummary(dumpfile, 'MisraMacro', list(unused_macro.values())) def misra_2_7(self, data): for func in data.functions: @@ -1121,7 +1777,7 @@ def misra_2_7(self, data): if len(func.argument) == 0: continue # Setup list of function parameters - func_param_list = list() + func_param_list = [] for arg in func.argument: func_arg = func.argument[arg] if func_arg.typeStartToken and func_arg.typeStartToken.str == '...': @@ -1153,24 +1809,19 @@ def misra_2_7(self, data): def misra_3_1(self, rawTokens): for token in rawTokens: starts_with_double_slash = token.str.startswith('//') - if token.str.startswith('/*') or starts_with_double_slash: - s = token.str.lstrip('/') - if ((not starts_with_double_slash) and '//' in s) or '/*' in s: - self.reportError(token, 3, 1) - - def misra_3_2(self, rawTokens): - for token in rawTokens: - if token.str.startswith('//'): - # Check for comment ends with trigraph which might be replaced - # by a backslash. - if token.str.endswith('??/'): - self.reportError(token, 3, 2) - # Check for comment which has been merged with subsequent line - # because it ends with backslash. - # The last backslash is no more part of the comment token thus - # check if next token exists and compare line numbers. - elif (token.next is not None) and (token.linenr == token.next.linenr): - self.reportError(token, 3, 2) + starts_with_block_comment = token.str.startswith("/*") + s = token.str.lstrip('/') + if (starts_with_double_slash or starts_with_block_comment) and "/*" in s: + # Block comment inside of regular comment, violation + self.reportError(token, 3, 1) + elif starts_with_block_comment and "//" in s: + # "//" in block comment, check if it's a uri + while "//" in s: + possible_uri, s = s.split("//", 1) + if not re.search(r"\w+:$", possible_uri): + # Violation if no uri was found + self.reportError(token, 3, 1) + break def misra_4_1(self, rawTokens): for token in rawTokens: @@ -1198,8 +1849,7 @@ def misra_4_1(self, rawTokens): if (isHexEscapeSequence(sequence) or isOctalEscapeSequence(sequence) or isSimpleEscapeSequence(sequence)): continue - else: - self.reportError(token, 4, 1) + self.reportError(token, 4, 1) def misra_4_2(self, rawTokens): for token in rawTokens: @@ -1336,12 +1986,24 @@ def misra_5_5(self, data): self.reportError(scope.bodyStart, 5, 5) + def misra_5_6(self, dumpfile, typedefInfo): + self._save_ctu_summary_typedefs(dumpfile, typedefInfo) + + def misra_5_7(self, dumpfile, cfg): + self._save_ctu_summary_tagnames(dumpfile, cfg) + + def misra_5_8(self, dumpfile, cfg): + self._save_ctu_summary_identifiers(dumpfile, cfg) + + def misra_5_9(self, dumpfile, cfg): + self._save_ctu_summary_identifiers(dumpfile, cfg) + def misra_6_1(self, data): # Bitfield type must be bool or explicitly signed/unsigned int for token in data.tokenlist: if not token.valueType: continue - if token.valueType.bits == 0: + if token.valueType.bits is None: continue if not token.variable: continue @@ -1351,16 +2013,16 @@ def misra_6_1(self, data): continue if data.standards.c == 'c89': - if token.valueType.type != 'int': + if token.valueType.type != 'int' and not isUnsignedType(token.variable.typeStartToken.str): self.reportError(token, 6, 1) - elif data.standards.c == 'c99': + elif data.standards.c in ('c99', 'c11', 'c17', 'c18'): if token.valueType.type == 'bool': continue isExplicitlySignedOrUnsigned = False typeToken = token.variable.typeStartToken while typeToken: - if typeToken.isUnsigned or typeToken.isSigned: + if typeToken.isUnsigned or typeToken.isSigned or isUnsignedType(typeToken.str): isExplicitlySignedOrUnsigned = True break @@ -1393,44 +2055,14 @@ def misra_7_1(self, rawTokens): self.reportError(tok, 7, 1) def misra_7_2(self, data): - # Large constant numbers that are assigned to a variable should have an - # u/U suffix if the variable type is unsigned. - def reportErrorIfMissingSuffix(variable, value): - if 'U' in value.str.upper(): - return - if value and value.isNumber: - if variable and variable.valueType and variable.valueType.sign == 'unsigned': - if variable.valueType.type in ['char', 'short', 'int', 'long', 'long long']: - limit = 1 << (bitsOfEssentialType(variable.valueType.type) -1) - v = value.getKnownIntValue() - if v is not None and v >= limit: - self.reportError(value, 7, 2) - for token in data.tokenlist: - # Check normal variable assignment - if token.valueType and token.isNumber: - variable = getAssignedVariableToken(token) - reportErrorIfMissingSuffix(variable, token) - - # Check use as function parameter - if isFunctionCall(token) and token.astOperand1 and token.astOperand1.function: - functionDeclaration = token.astOperand1.function - - if functionDeclaration.tokenDef: - if functionDeclaration.tokenDef is token.astOperand1: - # Token is not a function call, but it is the definition of the function - continue - - parametersUsed = getArguments(token) - for i in range(len(parametersUsed)): - usedParameter = parametersUsed[i] - if usedParameter.isNumber: - parameterDefinition = functionDeclaration.argument.get(i+1) - if parameterDefinition and parameterDefinition.nameToken: - reportErrorIfMissingSuffix(parameterDefinition.nameToken, usedParameter) + if token.isInt and ('U' not in token.str.upper()) and token.valueType and token.valueType.sign == 'unsigned': + self.reportError(token, 7, 2) def misra_7_3(self, rawTokens): - compiled = re.compile(r'^[0-9.]+[Uu]*l+[Uu]*$') + # Match decimal digits, hex digits, decimal point, and e/E p/P floating + # point constant exponent separators. + compiled = re.compile(r'^(0[xX])?[0-9a-fA-FpP.]+[Uu]*l+[Uu]*$') for tok in rawTokens: if compiled.match(tok.str): self.reportError(tok, 7, 3) @@ -1458,7 +2090,7 @@ def reportErrorIfVariableIsNotConst(variable, stringLiteral): self.reportError(token, 7, 4) # Check use as function parameter - if isFunctionCall(token) and token.astOperand1 and token.astOperand1.function: + if isFunctionCall(token, data.standards.c) and token.astOperand1 and token.astOperand1.function: functionDeclaration = token.astOperand1.function if functionDeclaration.tokenDef: @@ -1471,9 +2103,14 @@ def reportErrorIfVariableIsNotConst(variable, stringLiteral): usedParameter = parametersUsed[i] parameterDefinition = functionDeclaration.argument.get(i+1) - if usedParameter.isString and parameterDefinition.nameToken: + if usedParameter.isString and parameterDefinition and parameterDefinition.nameToken: reportErrorIfVariableIsNotConst(parameterDefinition.nameToken, usedParameter) + def misra_8_1(self, cfg): + for token in cfg.tokenlist: + if token.isImplicitInt and not token.isUnsigned and not token.isSigned: + self.reportError(token, 8, 1) + def misra_8_2(self, data, rawTokens): def getFollowingRawTokens(rawTokens, token, count): following =[] @@ -1493,17 +2130,11 @@ def getFollowingRawTokens(rawTokens, token, count): # Zero arguments should be in form ( void ) def checkZeroArguments(func, startCall, endCall): - if (len(func.argument) == 0): - voidArg = startCall.next - while voidArg is not endCall: - if voidArg.str == 'void': - break - voidArg = voidArg.next - if not voidArg.str == 'void': - if func.tokenDef.next: - self.reportError(func.tokenDef.next, 8, 2) - else: - self.reportError(func.tokenDef, 8, 2) + if not startCall.isRemovedVoidParameter and len(func.argument) == 0: + if func.tokenDef.next: + self.reportError(func.tokenDef.next, 8, 2) + else: + self.reportError(func.tokenDef, 8, 2) def checkDeclarationArgumentsViolations(func, startCall, endCall): # Collect the tokens for the arguments in function definition @@ -1523,7 +2154,7 @@ def checkDeclarationArgumentsViolations(func, startCall, endCall): # # TODO: We actually need to check if the names of the arguments are # the same. But we can't do this because we have no links to - # variables in the arguments in function defintion in the dump file. + # variables in the arguments in function definition in the dump file. foundVariables = 0 while startCall and startCall != endCall: if startCall.varId: @@ -1605,6 +2236,116 @@ def checkDefinitionArgumentsViolations(func, startCall, endCall): rawTokensFollowingPtr[2].str == ')'): self.reportError(var.nameToken, 8, 2) + def insert_in_dict(self, dict_name,key, value): + if key not in dict_name: + dict_name[key] = [] + dict_name[key].append(value) + def misra_8_4(self, cfg): + for func in cfg.functions: + if func.isStatic: + continue + if func.token is None: + continue + if not is_source_file(func.token.file): + continue + if func.token != func.tokenDef: + continue + if func.tokenDef.str == 'main': + continue + self.reportError(func.tokenDef, 8, 4) + extern_var_with_def = {} + extern_var_without_def = {} + for var in cfg.variables: + if not var.isGlobal: + continue + if var.isStatic: + continue + if var.nameToken is None: + continue + tok = var.nameToken + if tok.next.str == ";": + if tok.next.isSplittedVarDeclEq: + self.insert_in_dict(extern_var_with_def, tok.str, tok) + else: + self.insert_in_dict(extern_var_without_def, tok.str, tok) + else: + self.insert_in_dict(extern_var_without_def, var.nameToken.str, var.nameToken) + + for var in extern_var_with_def: + if var not in extern_var_without_def: + for t in extern_var_with_def[var]: + self.reportError(t, 8, 4) + + for var_str, var_tok in extern_var_without_def.items(): + warn = True + if var_str not in extern_var_with_def: + for t in var_tok: + if t.variable.isExtern: + warn = False + break + if warn: + for t in var_tok: + self.reportError(t, 8, 4) + + def misra_8_5(self, dumpfile, cfg): + self._save_ctu_summary_identifiers(dumpfile, cfg) + + def misra_8_6(self, dumpfile, cfg): + self._save_ctu_summary_identifiers(dumpfile, cfg) + + def misra_8_7(self, dumpfile, cfg): + self._save_ctu_summary_usage(dumpfile, cfg) + + def misra_8_8(self, cfg): + vars = {} + for var in cfg.variables: + if var.access != 'Global': + continue + if var.nameToken is None: + continue + varname = var.nameToken.str + if varname in vars: + vars[varname].append(var) + else: + vars[varname] = [var] + for varname, varlist in vars.items(): + static_var = None + extern_var = None + for var in varlist: + if var.isStatic: + static_var = var + elif var.isExtern: + extern_var = var + if static_var and extern_var: + self.reportError(extern_var.nameToken, 8, 8) + + def misra_8_9(self, cfg): + variables = {} + for scope in cfg.scopes: + if scope.type != 'Function': + continue + variables_used_in_scope = [] + tok = scope.bodyStart + while tok != scope.bodyEnd: + if tok.variable and tok.variable.access == 'Global' and tok.variable.isStatic: + if tok.variable not in variables_used_in_scope: + variables_used_in_scope.append(tok.variable) + tok = tok.next + for var in variables_used_in_scope: + if var in variables: + variables[var] += 1 + else: + variables[var] = 1 + for var, count in variables.items(): + if count == 1: + self.reportError(var.nameToken, 8, 9) + + + def misra_8_10(self, cfg): + for func in cfg.functions: + if func.isInlineKeyword and not func.isStatic: + self.reportError(func.tokenDef, 8, 10) + def misra_8_11(self, data): for var in data.variables: if var.isExtern and simpleMatch(var.nameToken.next, '[ ]') and var.nameToken.scope.type == 'Global': @@ -1675,44 +2416,66 @@ def misra_10_1(self, data): elif token.str in ('~', '&', '|', '^'): e1_et = getEssentialType(token.astOperand1) e2_et = getEssentialType(token.astOperand2) - if e1_et == 'char' and e2_et == 'char': + if e1_et == 'char' or e2_et == 'char': self.reportError(token, 10, 1) def misra_10_2(self, data): def isEssentiallySignedOrUnsigned(op): - if op and op.valueType: - if op.valueType.sign in ['unsigned', 'signed']: - return True - return False + e = getEssentialType(op) + return e and (e.split(' ')[0] in ('unsigned', 'signed')) def isEssentiallyChar(op): - if op.isName: - return getEssentialType(op) == 'char' + if op is None: + return False + if op.str == '+': + return isEssentiallyChar(op.astOperand1) or isEssentiallyChar(op.astOperand2) return op.isChar for token in data.tokenlist: - if not token.isArithmeticalOp or token.str not in ['+', '-']: + if token.str not in ('+', '-'): continue - operand1 = token.astOperand1 - operand2 = token.astOperand2 - if not operand1 or not operand2: - continue - if not operand1.isChar and not operand2.isChar: + if (not isEssentiallyChar(token.astOperand1)) and (not isEssentiallyChar(token.astOperand2)): continue if token.str == '+': - if isEssentiallyChar(operand1) and not isEssentiallySignedOrUnsigned(operand2): + if isEssentiallyChar(token.astOperand1) and not isEssentiallySignedOrUnsigned(token.astOperand2): self.reportError(token, 10, 2) - if isEssentiallyChar(operand2) and not isEssentiallySignedOrUnsigned(operand1): + if isEssentiallyChar(token.astOperand2) and not isEssentiallySignedOrUnsigned(token.astOperand1): self.reportError(token, 10, 2) if token.str == '-': - if not isEssentiallyChar(operand1): + e1 = getEssentialType(token.astOperand1) + if e1 and e1.split(' ')[-1] != 'char': self.reportError(token, 10, 2) - if not isEssentiallyChar(operand2) and not isEssentiallySignedOrUnsigned(operand2): + if not isEssentiallyChar(token.astOperand2) and not isEssentiallySignedOrUnsigned(token.astOperand2): self.reportError(token, 10, 2) + def misra_10_3(self, cfg): + def get_category(essential_type): + if essential_type: + if essential_type in ('bool', 'char'): + return essential_type + if essential_type.split(' ')[-1] in ('float', 'double'): + return 'floating' + 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: + 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) + def misra_10_4(self, data): op = {'+', '-', '*', '/', '%', '&', '|', '^', '+=', '-=', ':'} for token in data.tokenlist: @@ -1723,7 +2486,7 @@ def misra_10_4(self, data): if not token.astOperand1.valueType or not token.astOperand2.valueType: continue if ((token.astOperand1.str in op or token.astOperand1.isComparisonOp) and - (token.astOperand2.str in op or token.astOperand1.isComparisonOp)): + (token.astOperand2.str in op or token.astOperand2.isComparisonOp)): e1, e2 = getEssentialCategorylist(token.astOperand1.astOperand2, token.astOperand2.astOperand1) elif token.astOperand1.str in op or token.astOperand1.isComparisonOp: e1, e2 = getEssentialCategorylist(token.astOperand1.astOperand2, token.astOperand2) @@ -1746,12 +2509,52 @@ def misra_10_4(self, data): if e1 and e2 and e1 != e2: self.reportError(token, 10, 4) + def misra_10_5(self, cfg): + def _get_essential_category(token): + essential_type = getEssentialType(token) + #print(essential_type) + if essential_type: + if essential_type in ('bool', 'char'): + return essential_type + if essential_type.split(' ')[-1] in ('float', 'double'): + return 'floating' + if essential_type.split(' ')[0] in ('unsigned', 'signed'): + return essential_type.split(' ')[0] + return None + for token in cfg.tokenlist: + if not isCast(token): + continue + to_type = _get_essential_category(token) + #print(to_type) + if to_type is None: + continue + from_type = _get_essential_category(token.astOperand1) + #print(from_type) + if from_type is None: + continue + if to_type == from_type: + continue + if to_type == 'bool' or from_type == 'bool': + if token.astOperand1.isInt and token.astOperand1.getKnownIntValue() == 1: + # Exception + continue + self.reportError(token, 10, 5) + continue + if to_type == 'enum': + self.reportError(token, 10, 5) + continue + if from_type == 'float' and to_type == 'char': + self.reportError(token, 10, 5) + continue + if from_type == 'char' and to_type == 'float': + self.reportError(token, 10, 5) + continue + def misra_10_6(self, data): for token in data.tokenlist: if token.str != '=' or not token.astOperand1 or not token.astOperand2: continue - if (token.astOperand2.str not in ('+', '-', '*', '/', '%', '&', '|', '^', '>>', "<<", "?", ":", '~') and - not isCast(token.astOperand2)): + if not is_composite_expr(token.astOperand2): continue vt1 = token.astOperand1.valueType vt2 = token.astOperand2.valueType @@ -1766,11 +2569,43 @@ def misra_10_6(self, data): e = getEssentialType(token.astOperand2) if not e: continue - if bitsOfEssentialType(vt1.type) > bitsOfEssentialType(e): + if e == "char" and vt1.type == "int": + # When arithmetic operations are performed on char values, they are usually promoted to int + continue + lhsbits = vt1.bits if vt1.bits else bitsOfEssentialType(vt1.type) + if lhsbits > bitsOfEssentialType(e): self.reportError(token, 10, 6) except ValueError: pass + def misra_10_7(self, cfg): + for token in cfg.tokenlist: + if token.astOperand1 is None or token.astOperand2 is None: + continue + if not token.isArithmeticalOp: + continue + if not is_composite_expr(token): + continue + parent = token.astParent + if parent is None: + continue + if not parent.isArithmeticalOp: + if not parent.isAssignmentOp: + continue + if parent.str == '=': + continue + token_type = getEssentialType(token) + if token_type is None: + continue + sibling = parent.astOperand1 if (token == parent.astOperand2) else parent.astOperand2 + sibling_type = getEssentialType(sibling) + if sibling_type is None: + continue + b1 = bitsOfEssentialType(token_type) + b2 = bitsOfEssentialType(sibling_type) + if b1 > 0 and b1 < b2: + self.reportError(token, 10, 7) + def misra_10_8(self, data): for token in data.tokenlist: if not isCast(token): @@ -1804,6 +2639,49 @@ def misra_10_8(self, data): except ValueError: pass + def misra_11_1(self, data): + for token in data.tokenlist: + to_from = get_type_conversion_to_from(token) + if to_from is None: + continue + from_type = get_function_pointer_type(to_from[1]) + if from_type is None: + continue + to_type = get_function_pointer_type(to_from[0]) + if to_type is None or to_type != from_type: + self.reportError(token, 11, 1) + + def misra_11_2(self, data): + def get_pointer_type(type_token): + while type_token and (type_token.str in ('const', 'struct')): + type_token = type_token.next + if type_token is None: + return None + if not type_token.isName: + return None + return type_token if (type_token.next and type_token.next.str == '*') else None + + incomplete_types = [] + + for token in data.tokenlist: + if token.str == 'struct' and token.next and token.next.next and token.next.isName and token.next.next.str == ';': + incomplete_types.append(token.next.str) + to_from = get_type_conversion_to_from(token) + if to_from is None: + continue + to_pointer_type_token = get_pointer_type(to_from[0]) + if to_pointer_type_token is None: + continue + from_pointer_type_token = get_pointer_type(to_from[1]) + if from_pointer_type_token is None: + continue + if to_pointer_type_token.str == from_pointer_type_token.str: + continue + if from_pointer_type_token.typeScope is None and (from_pointer_type_token.str in incomplete_types): + self.reportError(token, 11, 2) + elif to_pointer_type_token.typeScope is None and (to_pointer_type_token.str in incomplete_types): + self.reportError(token, 11, 2) + def misra_11_3(self, data): for token in data.tokenlist: if not isCast(token): @@ -1823,6 +2701,20 @@ def misra_11_3(self, data): self.reportError(token, 11, 3) def misra_11_4(self, data): + # Get list of macro definitions + macros = {} + for directive in data.directives: + #define X ((peripheral_t *)0x40000U) + res = re.match(r'#define ([A-Za-z0-9_]+).*', directive.str) + if res: + if res.group(1) in macros: + macros[res.group(1)].append(directive) + else: + macros[res.group(1)] = [directive] + + # If macro definition is non-compliant then warn about the macro definition instead of + # the macro usages. To reduce diagnostics for a non-compliant macro. + bad_macros = [] for token in data.tokenlist: if not isCast(token): continue @@ -1833,6 +2725,17 @@ def misra_11_4(self, data): if vt2.pointer > 0 and vt1.pointer == 0 and (vt1.isIntegral() or vt1.isEnum()) and vt2.type != 'void': self.reportError(token, 11, 4) elif vt1.pointer > 0 and vt2.pointer == 0 and (vt2.isIntegral() or vt2.isEnum()) and vt1.type != 'void': + if token.macroName is not None and \ + token.macroName == token.astOperand1.macroName and \ + token.astOperand1.isInt and \ + token.link.previous.str == '*' and \ + token.macroName == token.link.previous.macroName and \ + token.macroName in macros and \ + len(macros[token.macroName]) == 1: + if token.macroName not in bad_macros: + bad_macros.append(token.macroName) + self.reportError(macros[token.macroName][0], 11, 4) + continue self.reportError(token, 11, 4) def misra_11_5(self, data): @@ -1860,13 +2763,11 @@ def misra_11_6(self, data): for token in data.tokenlist: if not isCast(token): continue - if token.astOperand1.astOperand1: - continue vt1 = token.valueType vt2 = token.astOperand1.valueType if not vt1 or not vt2: continue - if vt1.pointer == 1 and vt1.type == 'void' and vt2.pointer == 0 and token.astOperand1.str != "0": + if vt1.pointer == 1 and vt1.type == 'void' and vt2.pointer == 0 and token.astOperand1.getKnownIntValue() != 0: self.reportError(token, 11, 6) elif vt1.pointer == 0 and vt1.type != 'void' and vt2.pointer == 1 and vt2.type == 'void': self.reportError(token, 11, 6) @@ -2014,12 +2915,63 @@ def misra_12_3(self, data): if prev.str == ';': self.reportError(token, 12, 3) break - elif prev.str in ')}]': - prev = prev.link - elif prev.str in '({[': + if prev.str in '({[': break + if prev.str in ')}]': + prev = prev.link prev = prev.previous + def misra_12_4_check_expr(self, expr): + if not expr.astOperand2 or not expr.astOperand1: + return + if expr.valueType is None: + return + if expr.valueType.sign is None or expr.valueType.sign != 'unsigned': + return + if expr.valueType.pointer > 0: + return + if not expr.valueType.isIntegral(): + return + op1 = expr.astOperand1.getKnownIntValue() + if op1 is None: + return + op2 = expr.astOperand2.getKnownIntValue() + if op2 is None: + return + bits = bitsOfEssentialType('unsigned ' + expr.valueType.type) + if bits <= 0 or bits >= 64: + return + max_value = (1 << bits) - 1 + if not is_constant_integer_expression(expr): + return + if expr.str == '+' and op1 + op2 > max_value: + self.reportError(expr, 12, 4) + elif expr.str == '-' and op1 - op2 < 0: + self.reportError(expr, 12, 4) + elif expr.str == '*' and op1 * op2 > max_value: + self.reportError(expr, 12, 4) + def misra_12_4(self, cfg): + if not cfg.tokenlist: + return + expr = cfg.tokenlist[0] + while expr.next: + expr = expr.next + if expr.str == "?" and expr.astOperand2.str == ":": + known_value = expr.astOperand1.getKnownIntValue() + if known_value == 1: + tok = expr + while tok != expr.astOperand2: + self.misra_12_4_check_expr(tok) + tok = tok.next + expr = tok + while expr.str not in (";", "{", "}"): + expr = expr.next + continue + if known_value == 0: + expr = expr.astOperand2 + self.misra_12_4_check_expr(expr) + + def misra_13_1(self, data): for token in data.tokenlist: if simpleMatch(token, ") {") and token.next.astParent == token.link: @@ -2038,8 +2990,7 @@ def misra_13_1(self, data): if tn and tn.next and tn.next.str == '=': tn = tn.next.next continue - else: - break + break if tn.str == '.' and tn.next and tn.next.isName: tn = tn.next if tn.next and tn.next.str == '=': @@ -2065,6 +3016,8 @@ def misra_13_4(self, data): continue if not token.astParent: continue + if (token.astOperand1 is None) or (token.astOperand2 is None): + continue if token.astOperand1.str == '[' and token.astOperand1.previous.str in ('{', ','): continue if not (token.astParent.str in [',', ';', '{']): @@ -2072,12 +3025,12 @@ def misra_13_4(self, data): def misra_13_5(self, data): for token in data.tokenlist: - if token.isLogicalOp and hasSideEffectsRecursive(token.astOperand2): + if token.isLogicalOp and countSideEffectsRecursive(token.astOperand2) > 0: self.reportError(token, 13, 5) def misra_13_6(self, data): for token in data.tokenlist: - if token.str == 'sizeof' and hasSideEffectsRecursive(token.next): + if token.str == 'sizeof' and countSideEffectsRecursive(token.next) > 0: self.reportError(token, 13, 6) def misra_14_1(self, data): @@ -2095,34 +3048,46 @@ def misra_14_1(self, data): def misra_14_2(self, data): for token in data.tokenlist: - expressions = getForLoopExpressions(token) - if not expressions: - continue - if expressions[0] and not expressions[0].isAssignmentOp: - self.reportError(token, 14, 2) - elif hasSideEffectsRecursive(expressions[1]): - self.reportError(token, 14, 2) - - # Inspect modification of loop counter in loop body - counter_vars = getForLoopCounterVariables(token) - outer_scope = token.scope - body_scope = None - tn = token.next - while tn and tn.next != outer_scope.bodyEnd: - if tn.scope and tn.scope.nestedIn == outer_scope: - body_scope = tn.scope - break - tn = tn.next - if not body_scope: - continue - tn = body_scope.bodyStart - while tn and tn != body_scope.bodyEnd: - if tn.variable and tn.variable in counter_vars: - if tn.next: - # TODO: Check modifications in function calls - if hasSideEffectsRecursive(tn.next): - self.reportError(tn, 14, 2) - tn = tn.next + if token.str == 'for': + expressions = getForLoopExpressions(token) + if not expressions: + continue + if expressions[0] and not expressions[0].isAssignmentOp: + if expressions[0].str != "(" or not expressions[0].previous.isName: + self.reportError(token, 14, 2) + if countSideEffectsRecursive(expressions[1]) > 0: + self.reportError(token, 14, 2) + if countSideEffectsRecursive(expressions[2]) > 1: + self.reportError(token, 14, 2) + + counter_vars_first_clause, counter_vars_exit_modified = getForLoopCounterVariables(token, data) + if len(counter_vars_exit_modified) == 0: + # if it's not possible to identify a loop counter, all 3 clauses must be empty + for idx in range(len(expressions)): + if expressions[idx]: + self.reportError(token, 14, 2) + break + elif len(counter_vars_exit_modified) > 1: + # there shall be a single loop counter + self.reportError(token, 14, 2) + else: # len(counter_vars_exit_modified) == 1: + loop_counter = counter_vars_exit_modified.pop() + # if the first clause is not empty, then it shall (declare and) initialize the loop counter + if expressions[0] is not None and loop_counter not in counter_vars_first_clause: + self.reportError(token, 14, 2) + + # Inspect modification of loop counter in loop body + body_scope = token.next.link.next.scope + if not body_scope: + continue + tn = body_scope.bodyStart + while tn and tn != body_scope.bodyEnd: + if tn.variable == loop_counter: + if tn.next: + # TODO: Check modifications in function calls + if countSideEffectsRecursive(tn.next) > 0: + self.reportError(tn, 14, 2) + tn = tn.next def misra_14_4(self, data): for token in data.tokenlist: @@ -2130,7 +3095,9 @@ def misra_14_4(self, data): continue if not token.astOperand1 or not (token.astOperand1.str in ['if', 'while']): continue - if not isBoolExpression(token.astOperand2): + if isBoolExpression(token.astOperand2): + continue + if token.astOperand2.valueType: self.reportError(token, 14, 4) def misra_15_1(self, data): @@ -2220,14 +3187,41 @@ def misra_15_6(self, rawTokens): state = 0 indent = 0 tok1 = None + def tokAt(tok,i): + while i < 0 and tok: + tok = tok.previous + if tok.str.startswith('//') or tok.str.startswith('/*'): + continue + i += 1 + while i > 0 and tok: + tok = tok.next + if tok.str.startswith('//') or tok.str.startswith('/*'): + continue + i -= 1 + return tok + + def strtokens(tok, i1, i2): + tok1 = tokAt(tok, i1) + tok2 = tokAt(tok, i2) + tok = tok1 + s = '' + while tok != tok2: + if tok.str.startswith('//') or tok.str.startswith('/*'): + tok = tok.next + continue + s += ' ' + tok.str + tok = tok.next + s += ' ' + tok.str + return s[1:] + for token in rawTokens: if token.str in ['if', 'for', 'while']: - if simpleMatch(token.previous, '# if'): + if strtokens(token,-1,0) == '# if': continue - if simpleMatch(token.previous, "} while"): + if strtokens(token,-1,0) == "} while": # is there a 'do { .. } while'? - start = rawlink(token.previous) - if start and simpleMatch(start.previous, 'do {'): + start = rawlink(tokAt(token,-1)) + if start and strtokens(start, -1, 0) == 'do {': continue if state == 2: self.reportError(tok1, 15, 6) @@ -2235,9 +3229,9 @@ def misra_15_6(self, rawTokens): indent = 0 tok1 = token elif token.str == 'else': - if simpleMatch(token.previous, '# else'): + if strtokens(token,-1,0) == '# else': continue - if simpleMatch(token, 'else if'): + if strtokens(token,0,1) == 'else if': continue if state == 2: self.reportError(tok1, 15, 6) @@ -2278,7 +3272,27 @@ def misra_15_7(self, data): if not simpleMatch(tok, '} else'): self.reportError(tok, 15, 7) - # TODO add 16.1 rule + def misra_16_1(self, cfg): + for scope in cfg.scopes: + if scope.type != 'Switch': + continue + in_case_or_default = False + tok = scope.bodyStart.next + while tok != scope.bodyEnd: + if not in_case_or_default: + if tok.str not in ('case', 'default'): + self.reportError(tok, 16, 1) + else: + in_case_or_default = True + else: + if simpleMatch(tok, 'break ;'): + in_case_or_default = False + tok = tok.next + if tok.str == '{': + tok = tok.link + if tok.scope.type == 'Unconditional' and simpleMatch(tok.previous.previous, 'break ;'): + in_case_or_default = False + tok = tok.next def misra_16_2(self, data): for token in data.tokenlist: @@ -2291,15 +3305,24 @@ def misra_16_3(self, rawTokens): STATE_OK = 2 # a case/default is allowed (we have seen 'break;'/'comment'/'{'/attribute) STATE_SWITCH = 3 # walking through switch statement scope + directive = None state = STATE_NONE - end_swtich_token = None # end '}' for the switch scope + end_switch_token = None # end '}' for the switch scope for token in rawTokens: + if simpleMatch(token, '# define') or simpleMatch(token, '# pragma'): + directive = token + if directive: + if token.linenr != directive.linenr: + directive = None + else: + continue + # Find switch scope borders if token.str == 'switch': state = STATE_SWITCH if state == STATE_SWITCH: if token.str == '{': - end_swtich_token = findRawLink(token) + end_switch_token = findRawLink(token) else: continue @@ -2308,7 +3331,7 @@ def misra_16_3(self, rawTokens): elif token.str == ';': if state == STATE_BREAK: state = STATE_OK - elif token.next and token.next == end_swtich_token: + elif token.next and token.next == end_switch_token: self.reportError(token.next, 16, 3) else: state = STATE_NONE @@ -2356,7 +3379,7 @@ def misra_16_5(self, data): for token in data.tokenlist: if token.str != 'default': continue - if token.previous and token.previous.str == '{': + if token.previous and (token.previous.str == '{'): continue tok2 = token while tok2: @@ -2394,7 +3417,7 @@ def misra_16_7(self, data): def misra_17_1(self, data): for token in data.tokenlist: - if isFunctionCall(token) and token.astOperand1.str in ( + if isFunctionCall(token, data.standards.c) and token.astOperand1.str in ( 'va_list', 'va_arg', 'va_start', 'va_end', 'va_copy'): self.reportError(token, 17, 1) elif token.str == 'va_list': @@ -2450,6 +3473,81 @@ def find_recursive_call(search_for_function, direct_call, calls_map, visited=Non self.reportError(tok, 17, 2) tok = tok.next + def misra_17_3(self, cfg): + # Check for Clang warnings related to implicit function declarations + for w in cfg.clang_warnings: + if w['message'].endswith('[-Wimplicit-function-declaration]'): + self.reportError(cppcheckdata.Location(w), 17, 3) + + # Additional check for implicit function calls in expressions + for token in cfg.tokenlist: + if token.isName and token.function is None and token.valueType is None: + if token.next and token.next.str == "(" and token.next.valueType is None: + if token.next.next.str == "*" and \ + token.next.next.next.isName and token.next.next.next.valueType is not None and \ + token.next.next.next.valueType.pointer > 0 : + # this is a function pointer definition the tokens look like this int16_t ( * misra_8_2_p_a ) () + # and the int16_t causes the detection as the '(' follows + continue + if not isKeyword(token.str,cfg.standards.c) and not isStdLibId(token.str,cfg.standards.c): + self.reportError(token, 17, 3) + + def misra_config(self, data): + for var in data.variables: + if not var.isArray or var.nameToken is None or not cppcheckdata.simpleMatch(var.nameToken.next, '['): + continue + tok = var.nameToken.next + while tok.str == '[': + sz = tok.astOperand2 + if sz and sz.getKnownIntValue() is None: + has_var = False + unknown_constant = False + tokens = [sz] + while len(tokens) > 0: + t = tokens[-1] + tokens = tokens[:-1] + if t: + if t.isName and t.getKnownIntValue() is None: + if t.varId or t.variable: + has_var = True + continue + unknown_constant = True + self.report_config_error(tok, 'Unknown constant {}, please review configuration'.format(t.str)) + if t.isArithmeticalOp: + tokens += [t.astOperand1, t.astOperand2] + if not unknown_constant and not has_var: + self.report_config_error(tok, 'Unknown array size, please review configuration') + tok = tok.link.next + + for token in data.tokenlist: + if token.str not in ("while", "if"): + continue + tok = token.next + if token is None or tok.str != "(": + continue + end_token = tok.link + while tok != end_token: + tok = tok.next + if tok.str == 'sizeof' and tok.next.str == '(': + tok = tok.next.link + continue + if tok.str == "(" and tok.isCast: + tok = tok.link + continue + if not tok.isName: + continue + if tok.function or tok.variable or tok.varId or tok.valueType or tok.typeScope: + continue + if tok.next.str == "(" or tok.str in ["EOF"]: + continue + if isKeyword(tok.str, data.standards.c) or isStdLibId(tok.str, data.standards.c): + continue + if tok.astParent is None: + continue + if tok.astParent.str == "." and tok.astParent.valueType: + continue + self.report_config_error(tok, "Variable '%s' is unknown" % tok.str) + def misra_17_6(self, rawTokens): for token in rawTokens: if simpleMatch(token, '[ static'): @@ -2461,7 +3559,9 @@ def misra_17_7(self, data): continue if token.str != '(' or token.astParent: continue - if not token.previous.isName or token.previous.varId: + if token.astOperand1 is None or not token.astOperand1.isName: + continue + if token.astOperand1.varId and (token.astOperand1.variable is None or get_function_pointer_type(token.astOperand1.variable.typeStartToken) is None): continue if token.valueType is None: continue @@ -2518,7 +3618,10 @@ def misra_18_7(self, data): if token.str == '{': token = token.link - if cppcheckdata.simpleMatch(token, "[ ]"): + # skip function pointer parameter types + if token.astOperand1 is None: + pass + elif cppcheckdata.simpleMatch(token, "[ ]"): self.reportError(token, 18, 7) break token = token.next @@ -2534,7 +3637,7 @@ def misra_18_8(self, data): # Unknown define or syntax error if not typetok.astOperand2: continue - if not isConstantExpression(typetok.astOperand2): + if not isConstantExpression(typetok.astOperand2) and not isUnknownConstantExpression(typetok.astOperand2): self.reportError(var.nameToken, 18, 8) def misra_19_2(self, data): @@ -2682,12 +3785,97 @@ def find_string_concat(exp, arg, directive_args): self.reportError(directive, 20, 7) break + def misra_20_8(self, cfg): + for cond in cfg.preprocessor_if_conditions: + #print(cond) + if cond.result and cond.result not in (0,1): + self.reportError(cond, 20, 8) + + def misra_20_9(self, cfg): + for cond in cfg.preprocessor_if_conditions: + if cond.E is None: + continue + defined = [] + for directive in cfg.directives: + if directive.file == cond.file and directive.linenr == cond.linenr: + for name in re.findall(r'[^_a-zA-Z0-9]defined[ ]*\([ ]*([_a-zA-Z0-9]+)[ ]*\)', directive.str): + defined.append(name) + for name in re.findall(r'[^_a-zA-Z0-9]defined[ ]*([_a-zA-Z0-9]+)', directive.str): + defined.append(name) + break + for s in cond.E.split(' '): + if (s[0] >= 'A' and s[0] <= 'Z') or (s[0] >= 'a' and s[0] <= 'z'): + if isKeyword(s, cfg.standards.c): + continue + if s in defined: + continue + self.reportError(cond, 20, 9) + def misra_20_10(self, data): for directive in data.directives: d = Define(directive) if d.expansionList.find('#') >= 0: self.reportError(directive, 20, 10) + def misra_20_11(self, cfg): + for directive in cfg.directives: + d = Define(directive) + for arg in d.args: + res = re.search(r'[^#]#[ ]*%s[ ]*##' % arg, ' ' + d.expansionList) + if res: + self.reportError(directive, 20, 11) + + def misra_20_12(self, cfg): + def _is_hash_hash_op(expansion_list, arg): + return re.search(r'##[ ]*%s[^a-zA-Z0-9_]' % arg, expansion_list) or \ + re.search(r'[^a-zA-Z0-9_]%s[ ]*##' % arg, expansion_list) + + def _is_other_op(expansion_list, arg): + pos = expansion_list.find(arg) + while pos >= 0: + pos1 = pos - 1 + pos2 = pos + len(arg) + pos = expansion_list.find(arg, pos2) + if isalnum(expansion_list[pos1]) or expansion_list[pos1] == '_': + continue + if isalnum(expansion_list[pos2]) or expansion_list[pos2] == '_': + continue + while expansion_list[pos1] == ' ': + pos1 = pos1 - 1 + if expansion_list[pos1] == '#': + continue + while expansion_list[pos2] == ' ': + pos2 = pos2 + 1 + if expansion_list[pos2] == '#': + continue + return True + return False + + def _is_arg_macro_usage(directive, arg): + for macro_usage in cfg.macro_usage: + if macro_usage.file == directive.file and macro_usage.linenr == directive.linenr: + for macro_usage_arg in cfg.macro_usage: + if macro_usage_arg == macro_usage: + continue + if (macro_usage.usefile == macro_usage_arg.usefile and + macro_usage.uselinenr == macro_usage_arg.uselinenr and + macro_usage.usecolumn == macro_usage_arg.usecolumn): + # TODO: check arg better + return True + return False + + for directive in cfg.directives: + define = Define(directive) + expansion_list = '(%s)' % define.expansionList + for arg in define.args: + if not _is_hash_hash_op(expansion_list, arg): + continue + if not _is_other_op(expansion_list, arg): + continue + if _is_arg_macro_usage(directive, arg): + self.reportError(directive, 20, 12) + break + def misra_20_13(self, data): dir_pattern = re.compile(r'#[ ]*([^ (<]*)') for directive in data.directives: @@ -2739,9 +3927,19 @@ def misra_21_1(self, data): if isStdLibId(name, data.standards.c): self.reportError(d, 21, 1) + def misra_21_2(self, cfg): + for directive in cfg.directives: + define = Define(directive) + if re.match(r'_+BUILTIN_.*', define.name.upper()): + self.reportError(directive, 21, 2) + for func in cfg.functions: + if isStdLibId(func.name, cfg.standards.c): + tok = func.tokenDef if func.tokenDef else func.token + self.reportError(tok, 21, 2) + def misra_21_3(self, data): for token in data.tokenlist: - if isFunctionCall(token) and (token.astOperand1.str in ('malloc', 'calloc', 'realloc', 'free')): + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ('malloc', 'calloc', 'realloc', 'free')): self.reportError(token, 21, 3) def misra_21_4(self, data): @@ -2755,21 +3953,22 @@ def misra_21_5(self, data): self.reportError(directive, 21, 5) def misra_21_6(self, data): - dir_stdio = findInclude(data.directives, '') - dir_wchar = findInclude(data.directives, '') - if dir_stdio: - self.reportError(dir_stdio, 21, 6) - if dir_wchar: - self.reportError(dir_wchar, 21, 6) + for token in data.tokenlist: + if not isFunctionCall(token) or token.previous.function: + continue + standard_id = getStdLib(data.standards.c) + funcname = token.previous.str + if funcname in standard_id.get("stdio.h", []) or funcname in standard_id.get("wchar.h", []): + self.reportError(token, 21, 6) def misra_21_7(self, data): for token in data.tokenlist: - if isFunctionCall(token) and (token.astOperand1.str in ('atof', 'atoi', 'atol', 'atoll')): + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ('atof', 'atoi', 'atol', 'atoll')): self.reportError(token, 21, 7) def misra_21_8(self, data): for token in data.tokenlist: - if isFunctionCall(token) and (token.astOperand1.str in ('abort', 'exit', 'getenv', 'system')): + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ('abort', 'exit', 'getenv')): self.reportError(token, 21, 8) def misra_21_9(self, data): @@ -2796,7 +3995,7 @@ def misra_21_12(self, data): for token in data.tokenlist: if token.str == 'fexcept_t' and token.isName: self.reportError(token, 21, 12) - if isFunctionCall(token) and (token.astOperand1.str in ( + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ( 'feclearexcept', 'fegetexceptflag', 'feraiseexcept', @@ -2804,6 +4003,236 @@ def misra_21_12(self, data): 'fetestexcept')): self.reportError(token, 21, 12) + def misra_21_14(self, data): + # buffers used in strcpy/strlen/etc function calls + string_buffers = [] + for token in data.tokenlist: + if token.str[0] == 's' and isFunctionCall(token.next, data.standards.c): + name, args = cppcheckdata.get_function_call_name_args(token) + if name is None: + continue + def _get_string_buffers(match, args, argnum): + if not match: + return [] + ret = [] + for a in argnum: + if a < len(args): + arg = args[a] + while arg and arg.str in ('.', '::'): + arg = arg.astOperand2 + if arg and arg.varId != 0 and arg.varId not in ret: + ret.append(arg.varId) + return ret + string_buffers += _get_string_buffers(name == 'strcpy', args, [0, 1]) + string_buffers += _get_string_buffers(name == 'strncpy', args, [0, 1]) + string_buffers += _get_string_buffers(name == 'strlen', args, [0]) + string_buffers += _get_string_buffers(name == 'strcmp', args, [0, 1]) + string_buffers += _get_string_buffers(name == 'sprintf', args, [0]) + string_buffers += _get_string_buffers(name == 'snprintf', args, [0, 3]) + + for token in data.tokenlist: + if token.str != 'memcmp': + continue + name, args = cppcheckdata.get_function_call_name_args(token) + if name is None: + continue + if len(args) != 3: + continue + for arg in args[:2]: + if arg.str[-1] == '\"': + self.reportError(arg, 21, 14) + continue + while arg and arg.str in ('.', '::'): + arg = arg.astOperand2 + if arg and arg.varId and arg.varId in string_buffers: + self.reportError(arg, 21, 14) + + def misra_21_15(self, data): + for token in data.tokenlist: + if token.str not in ('memcpy', 'memmove', 'memcmp'): + continue + name, args = cppcheckdata.get_function_call_name_args(token) + if name is None: + continue + if len(args) != 3: + continue + if args[0].valueType is None or args[1].valueType is None: + continue + if args[0].valueType.type == args[1].valueType.type: + continue + if args[0].valueType.type == 'void' or args[1].valueType.type == 'void': + continue + self.reportError(token, 21, 15) + + def misra_21_16(self, cfg): + for token in cfg.tokenlist: + if token.str != 'memcmp': + continue + name, args = cppcheckdata.get_function_call_name_args(token) + if name is None: + continue + if len(args) != 3: + continue + for arg in args[:2]: + if arg.valueType is None: + continue + if arg.valueType.pointer > 1: + continue + if getEssentialTypeCategory(arg) in ('unsigned', 'signed', 'bool'): + continue + if arg.valueType.isEnum(): + continue + self.reportError(token, 21, 16) + + def misra_21_19(self, cfg): + for token in cfg.tokenlist: + if token.str in ('localeconv', 'getenv', 'setlocale', 'strerror') and simpleMatch(token.next, '('): + name, _ = cppcheckdata.get_function_call_name_args(token) + if name is None or name != token.str: + continue + parent = token.next + while simpleMatch(parent.astParent, '+'): + parent = parent.astParent + # x = f() + if simpleMatch(parent.astParent, '=') and parent == parent.astParent.astOperand2: + lhs = parent.astParent.astOperand1 + if lhs and lhs.valueType and lhs.valueType.pointer > 0 and lhs.valueType.constness == 0: + self.reportError(token, 21, 19) + if token.str == '=': + lhs = token.astOperand1 + while simpleMatch(lhs, '*') and lhs.astOperand2 is None: + lhs = lhs.astOperand1 + if not simpleMatch(lhs, '.'): + continue + while simpleMatch(lhs, '.'): + lhs = lhs.astOperand1 + if lhs and lhs.variable and simpleMatch(lhs.variable.typeStartToken, 'lconv'): + self.reportError(token, 21, 19) + + def misra_21_20(self, cfg): + assigned = {} + invalid = [] + for token in cfg.tokenlist: + # No sophisticated data flow analysis, bail out if control flow is "interrupted" + if token.str in ('{', '}', 'break', 'continue', 'return'): + assigned = {} + invalid = [] + continue + + # When pointer is assigned, remove it from 'assigned' and 'invalid' + if token.varId and token.varId > 0 and simpleMatch(token.next, '='): + for name in assigned.keys(): + while token.varId in assigned[name]: + assigned[name].remove(token.varId) + while token.varId in invalid: + invalid.remove(token.varId) + continue + + # Calling dangerous function + if token.str in ('asctime', 'ctime', 'gmtime', 'localtime', 'localeconv', 'getenv', 'setlocale', 'strerror'): + name, _ = cppcheckdata.get_function_call_name_args(token) + if name and name == token.str: + # make assigned pointers invalid + for varId in assigned.get(name, ()): + if varId not in invalid: + invalid.append(varId) + + # assign pointer + parent = token.next + while parent.astParent and (parent.astParent.str == '+' or isCast(parent.astParent)): + parent = parent.astParent + if simpleMatch(parent.astParent, '='): + eq = parent.astParent + vartok = eq.previous + if vartok and vartok.varId and vartok.varId > 0: + if name not in assigned: + assigned[name] = [vartok.varId] + elif vartok.varId not in assigned[name]: + assigned[name].append(vartok.varId) + continue + + # taking value of invalid pointer.. + if token.astParent and token.varId: + if token.varId in invalid: + self.reportError(token, 21, 20) + + def misra_21_21(self, cfg): + for token in cfg.tokenlist: + if token.str == 'system': + name, args = cppcheckdata.get_function_call_name_args(token) + if name == 'system' and len(args) == 1: + self.reportError(token, 21, 21) + + def misra_22_5(self, cfg): + for token in cfg.tokenlist: + if token.isUnaryOp("*") or (token.isBinaryOp() and token.str == '.'): + fileptr = token.astOperand1 + if fileptr.variable and cppcheckdata.simpleMatch(fileptr.variable.typeStartToken, 'FILE *'): + self.reportError(token, 22, 5) + + def misra_22_7(self, cfg): + for eofToken in cfg.tokenlist: + if eofToken.str != 'EOF': + continue + if eofToken.astParent is None or not eofToken.astParent.isComparisonOp: + continue + if eofToken.astParent.astOperand1 == eofToken: + eofTokenSibling = eofToken.astParent.astOperand2 + else: + eofTokenSibling = eofToken.astParent.astOperand1 + while isCast(eofTokenSibling) and eofTokenSibling.valueType and eofTokenSibling.valueType.type and eofTokenSibling.valueType.type == 'int': + eofTokenSibling = eofTokenSibling.astOperand2 if eofTokenSibling.astOperand2 else eofTokenSibling.astOperand1 + if eofTokenSibling is not None and eofTokenSibling.valueType and eofTokenSibling.valueType and eofTokenSibling.valueType.type in ('bool', 'char', 'short'): + self.reportError(eofToken, 22, 7) + + def misra_22_8(self, cfg): + is_zero = False + for token in cfg.tokenlist: + if simpleMatch(token, 'errno = 0'): + is_zero = True + if token.str == '(' and not simpleMatch(token.link, ') {'): + name, _ = cppcheckdata.get_function_call_name_args(token.previous) + if name is None: + continue + if is_errno_setting_function(name): + if not is_zero: + self.reportError(token, 22, 8) + else: + is_zero = False + + def misra_22_9(self, cfg): + errno_is_set = False + for token in cfg.tokenlist: + if token.str == '(' and not simpleMatch(token.link, ') {'): + name, _ = cppcheckdata.get_function_call_name_args(token.previous) + if name is None: + continue + errno_is_set = is_errno_setting_function(name) + if errno_is_set and token.str in '{};': + errno_is_set = False + tok = token.next + while tok and tok.str not in ('{','}',';','errno'): + tok = tok.next + if tok is None or tok.str != 'errno': + self.reportError(token, 22, 9) + elif (tok.astParent is None) or (not tok.astParent.isComparisonOp): + self.reportError(token, 22, 9) + + def misra_22_10(self, cfg): + last_function_call = None + for token in cfg.tokenlist: + if token.isName and token.next and token.next.str == '(' and not simpleMatch(token.next.link, ') {'): + name, _ = cppcheckdata.get_function_call_name_args(token) + last_function_call = name + if token.str == '}': + last_function_call = None + if token.str == 'errno' and token.astParent and token.astParent.isComparisonOp: + if last_function_call is None: + self.reportError(token, 22, 10) + elif not is_errno_setting_function(last_function_call): + self.reportError(token, 22, 10) + + def get_verify_expected(self): """Return the list of expected violations in the verify test""" return self.verify_expected @@ -2816,8 +4245,7 @@ def get_violations(self, violation_type=None): """Return the list of violations for a normal checker run""" if violation_type is None: return self.violations.items() - else: - return self.violations[violation_type] + return self.violations[violation_type] def get_violation_types(self): """Return the list of violations for a normal checker run""" @@ -2857,10 +4285,10 @@ def addSuppressedRule(self, ruleNum, # If the rule is not in the dict already then add it if ruleNum not in self.suppressedRules: - ruleItemList = list() + ruleItemList = [] ruleItemList.append(line_symbol) - fileDict = dict() + fileDict = {} fileDict[normalized_filename] = ruleItemList self.suppressedRules[ruleNum] = fileDict @@ -2876,7 +4304,7 @@ def addSuppressedRule(self, ruleNum, # If the filename is not in the dict already add it if normalized_filename not in fileDict: - ruleItemList = list() + ruleItemList = [] ruleItemList.append(line_symbol) fileDict[normalized_filename] = ruleItemList @@ -2980,7 +4408,7 @@ def showSuppressedRules(self): Print out rules in suppression list sorted by Rule Number """ print("Suppressed Rules List:") - outlist = list() + outlist = [] for ruleNum in self.suppressedRules: fileDict = self.suppressedRules[ruleNum] @@ -3029,9 +4457,21 @@ def setSuppressionList(self, suppressionlist): self.addSuppressedRule(ruleNum) + def report_config_error(self, location, errmsg): + errmsg = 'Because of missing configuration, misra checking is incomplete. There can be false negatives! ' + errmsg + cppcheck_severity = 'error' + error_id = 'config' + if self.settings.verify: + self.verify_actual.append('%s:%d %s' % (location.file, location.linenr, error_id)) + else: + cppcheckdata.reportError(location, cppcheck_severity, errmsg, 'misra', error_id) + def reportError(self, location, num1, num2): ruleNum = num1 * 100 + num2 + if self.isRuleGloballySuppressed(ruleNum): + return + if self.settings.verify: self.verify_actual.append('%s:%d %d.%d' % (location.file, location.linenr, num1, num2)) elif self.isRuleSuppressed(location.file, location.linenr, ruleNum): @@ -3049,9 +4489,12 @@ def reportError(self, location, num1, num2): misra_severity = self.ruleTexts[ruleNum].misra_severity cppcheck_severity = self.ruleTexts[ruleNum].cppcheck_severity elif len(self.ruleTexts) == 0: - errmsg = 'misra violation (use --rule-texts= to get proper output)' + if self.ruleText_filename is None: + errmsg = 'misra violation (use --rule-texts= to get proper output)' + else: + errmsg = 'misra violation (rule-texts-file not found: ' + self.ruleText_filename + ')' else: - return + errmsg = 'misra violation %s with no text in the supplied rule-texts-file' % (ruleNum) if self.severity: cppcheck_severity = self.severity @@ -3060,7 +4503,7 @@ def reportError(self, location, num1, num2): # If this is new violation then record it and show it. If not then # skip it since it has already been displayed. - if not this_violation in self.existing_violations: + if this_violation not in self.existing_violations: self.existing_violations.add(this_violation) cppcheckdata.reportError(location, cppcheck_severity, errmsg, 'misra', errorId, misra_severity) @@ -3072,10 +4515,8 @@ def loadRuleTexts(self, filename): num1 = 0 num2 = 0 appendixA = False - ruleText = False - expect_more = False - Rule_pattern = re.compile(r'^Rule ([0-9]+).([0-9]+)') + Rule_pattern = re.compile(r'^Rule ([0-9]+)\.([0-9]+)') severity_pattern = re.compile(r'.*[ ]*(Advisory|Required|Mandatory)$') xA_Z_pattern = re.compile(r'^[#A-Z].*') a_z_pattern = re.compile(r'^[a-z].*') @@ -3088,6 +4529,7 @@ def loadRuleTexts(self, filename): file_stream.readlines() file_stream.seek(0) except UnicodeDecodeError: + file_stream.close() file_stream = None else: break @@ -3102,12 +4544,13 @@ def loadRuleTexts(self, filename): file_stream = open(filename, 'rt') rule = None - have_severity = False - severity_loc = 0 + rule_line_number = 0 for line in file_stream: - line = line.replace('\r', '').replace('\n', '') + line = line.strip() + if len(line) == 0: + continue if not appendixA: if line.find('Appendix A') >= 0 and line.find('Summary of guidelines') >= 10: @@ -3115,57 +4558,50 @@ def loadRuleTexts(self, filename): continue if line.find('Appendix B') >= 0: break - if len(line) == 0: - continue # Parse rule declaration. res = Rule_pattern.match(line) if res: - have_severity = False - expect_more = False - severity_loc = 0 + rule_line_number = 0 num1 = int(res.group(1)) num2 = int(res.group(2)) rule = Rule(num1, num2) - if not have_severity and rule is not None: res = severity_pattern.match(line) - if res: rule.misra_severity = res.group(1) - have_severity = True - else: - severity_loc += 1 - - # Only look for severity on the Rule line - # or the next non-blank line after - # If it's not in either of those locations then - # assume a severity was not provided. - - if severity_loc < 2: - continue - else: - rule.misra_severity = '' - have_severity = True + rule_line_number = 1 + continue if rule is None: continue - # Parse continuing of rule text. - if expect_more: - if a_z_pattern.match(line): - self.ruleTexts[rule.num].text += ' ' + line + rule_line_number += 1 + + if rule_line_number == 1: + res = severity_pattern.match(line) + + if res: + rule.misra_severity = res.group(1) continue - expect_more = False - continue + rule_line_number = 2 # Parse beginning of rule text. - if xA_Z_pattern.match(line): - rule.text = line + if not rule.text and xA_Z_pattern.match(line): + rule.text = line.strip() self.ruleTexts[rule.num] = rule - expect_more = True + continue + + # Parse continuing of rule text. + if a_z_pattern.match(line): + self.ruleTexts[rule.num].text += ' ' + line.strip() + continue + + rule = None + + file_stream.close() def verifyRuleTexts(self): """Prints rule numbers without rule text.""" @@ -3194,19 +4630,35 @@ def executeCheck(self, rule_num, check_function, *args): :param args: Check function arguments """ if not self.isRuleGloballySuppressed(rule_num): - check_function(*args) - - def parseDump(self, dumpfile): + misra_cpp = ( + 202, # misra-c2012-2.3 : misra c++2008 0-1-9 + 203, # misra-c2012-2.3 : misra c++2008 0-1-5 + 402, # misra-c2012-4.2 : misra c++2008 2-3-1 + 701, # misra-c2012-7.1 : misra c++2008 2-3-1 + 702, # misra-c2012-7.2 : misra c++2008 2-13-2 + 1203, # misra-c2012-12.3 : misra c++2008 5-14-1 + 1204, # misra-c2012-12.4 : misra c++2008 5-18-1 + 1305, # misra-c2012-13.5 : misra c++2008 5-19-1 + 1702, # misra-c2012-17.2 : misra c++2008 7-5-4 + 1901) # misra-c2012-19.1 : misra c++2008 2-13-3 + + if (not self.is_cpp) or rule_num in misra_cpp: + # log checker + errmsg = 'Misra C: %i.%i' % (rule_num // 100, rule_num % 100) + cppcheckdata.log_checker(errmsg, 'misra') + + check_function(*args) + + def parseDump(self, dumpfile, path_premium_addon=None): def fillVerifyExpected(verify_expected, tok): """Add expected suppressions to verify_expected list.""" rule_re = re.compile(r'[0-9]+\.[0-9]+') if tok.str.startswith('//') and 'TODO' not in tok.str: for word in tok.str[2:].split(' '): - if rule_re.match(word): + if rule_re.match(word) or word == "config": verify_expected.append('%s:%d %s' % (tok.file, tok.linenr, word)) data = cppcheckdata.parsedump(dumpfile) - typeBits['CHAR'] = data.platform.char_bit typeBits['SHORT'] = data.platform.short_bit typeBits['INT'] = data.platform.int_bit @@ -3235,21 +4687,34 @@ def fillVerifyExpected(verify_expected, tok): else: self.printStatus('Checking ' + dumpfile + '...') + self.is_cpp = data.language == 'cpp' + for cfgNumber, cfg in enumerate(data.iterconfigurations()): if not self.settings.quiet: self.printStatus('Checking %s, config %s...' % (dumpfile, cfg.name)) + self.executeCheck(102, self.misra_1_2, cfg) + if not path_premium_addon: + self.executeCheck(104, self.misra_1_4, cfg) + self.executeCheck(202, self.misra_2_2, cfg) + self.executeCheck(203, self.misra_2_3, dumpfile, cfg.typedefInfo) + self.executeCheck(204, self.misra_2_4, dumpfile, cfg) + self.executeCheck(205, self.misra_2_5, dumpfile, cfg) self.executeCheck(207, self.misra_2_7, cfg) # data.rawTokens is same for all configurations if cfgNumber == 0: self.executeCheck(301, self.misra_3_1, data.rawTokens) - self.executeCheck(302, self.misra_3_2, data.rawTokens) + #self.executeCheck(302, self.misra_3_2, data.rawTokens) self.executeCheck(401, self.misra_4_1, data.rawTokens) self.executeCheck(402, self.misra_4_2, data.rawTokens) self.executeCheck(501, self.misra_5_1, cfg) self.executeCheck(502, self.misra_5_2, cfg) self.executeCheck(504, self.misra_5_4, cfg) self.executeCheck(505, self.misra_5_5, cfg) + self.executeCheck(506, self.misra_5_6, dumpfile, cfg.typedefInfo) + self.executeCheck(507, self.misra_5_7, dumpfile, cfg) + self.executeCheck(508, self.misra_5_8, dumpfile, cfg) + self.executeCheck(509, self.misra_5_9, dumpfile, cfg) self.executeCheck(601, self.misra_6_1, cfg) self.executeCheck(602, self.misra_6_2, cfg) if cfgNumber == 0: @@ -3258,8 +4723,16 @@ def fillVerifyExpected(verify_expected, tok): if cfgNumber == 0: self.executeCheck(703, self.misra_7_3, data.rawTokens) self.executeCheck(704, self.misra_7_4, cfg) + self.executeCheck(801, self.misra_8_1, cfg) if cfgNumber == 0: self.executeCheck(802, self.misra_8_2, cfg, data.rawTokens) + self.executeCheck(804, self.misra_8_4, cfg) + self.executeCheck(805, self.misra_8_5, dumpfile, cfg) + self.executeCheck(806, self.misra_8_6, dumpfile, cfg) + self.executeCheck(807, self.misra_8_7, dumpfile, cfg) + self.executeCheck(808, self.misra_8_8, cfg) + self.executeCheck(809, self.misra_8_9, cfg) + self.executeCheck(810, self.misra_8_10, cfg) self.executeCheck(811, self.misra_8_11, cfg) self.executeCheck(812, self.misra_8_12, cfg) if cfgNumber == 0: @@ -3269,11 +4742,17 @@ def fillVerifyExpected(verify_expected, tok): self.executeCheck(904, self.misra_9_4, cfg) if cfgNumber == 0: self.executeCheck(905, self.misra_9_5, cfg, data.rawTokens) - self.executeCheck(1001, self.misra_10_1, cfg) - self.executeCheck(1002, self.misra_10_2, cfg) - self.executeCheck(1004, self.misra_10_4, cfg) - self.executeCheck(1006, self.misra_10_6, cfg) - self.executeCheck(1008, self.misra_10_8, cfg) + if not path_premium_addon: + self.executeCheck(1001, self.misra_10_1, cfg) + self.executeCheck(1002, self.misra_10_2, cfg) + self.executeCheck(1003, self.misra_10_3, cfg) + self.executeCheck(1004, self.misra_10_4, cfg) + self.executeCheck(1005, self.misra_10_5, cfg) + self.executeCheck(1006, self.misra_10_6, cfg) + self.executeCheck(1007, self.misra_10_7, cfg) + self.executeCheck(1008, self.misra_10_8, cfg) + self.executeCheck(1101, self.misra_11_1, cfg) + self.executeCheck(1102, self.misra_11_2, cfg) self.executeCheck(1103, self.misra_11_3, cfg) self.executeCheck(1104, self.misra_11_4, cfg) self.executeCheck(1105, self.misra_11_5, cfg) @@ -3286,6 +4765,7 @@ def fillVerifyExpected(verify_expected, tok): self.executeCheck(1201, self.misra_12_1, cfg) self.executeCheck(1202, self.misra_12_2, cfg) self.executeCheck(1203, self.misra_12_3, cfg) + self.executeCheck(1204, self.misra_12_4, cfg) self.executeCheck(1301, self.misra_13_1, cfg) self.executeCheck(1303, self.misra_13_3, cfg) self.executeCheck(1304, self.misra_13_4, cfg) @@ -3302,6 +4782,7 @@ def fillVerifyExpected(verify_expected, tok): if cfgNumber == 0: self.executeCheck(1506, self.misra_15_6, data.rawTokens) self.executeCheck(1507, self.misra_15_7, cfg) + self.executeCheck(1601, self.misra_16_1, cfg) self.executeCheck(1602, self.misra_16_2, cfg) if cfgNumber == 0: self.executeCheck(1603, self.misra_16_3, data.rawTokens) @@ -3311,6 +4792,8 @@ def fillVerifyExpected(verify_expected, tok): self.executeCheck(1607, self.misra_16_7, cfg) self.executeCheck(1701, self.misra_17_1, cfg) self.executeCheck(1702, self.misra_17_2, cfg) + self.executeCheck(1703, self.misra_17_3, cfg) + self.misra_config(cfg) if cfgNumber == 0: self.executeCheck(1706, self.misra_17_6, data.rawTokens) self.executeCheck(1707, self.misra_17_7, cfg) @@ -3325,11 +4808,16 @@ def fillVerifyExpected(verify_expected, tok): self.executeCheck(2003, self.misra_20_3, cfg) self.executeCheck(2004, self.misra_20_4, cfg) self.executeCheck(2005, self.misra_20_5, cfg) - self.executeCheck(2006, self.misra_20_7, cfg) + self.executeCheck(2007, self.misra_20_7, cfg) + self.executeCheck(2008, self.misra_20_8, cfg) + self.executeCheck(2009, self.misra_20_9, cfg) self.executeCheck(2010, self.misra_20_10, cfg) + self.executeCheck(2011, self.misra_20_11, cfg) + self.executeCheck(2012, self.misra_20_12, cfg) self.executeCheck(2013, self.misra_20_13, cfg) self.executeCheck(2014, self.misra_20_14, cfg) self.executeCheck(2101, self.misra_21_1, cfg) + self.executeCheck(2102, self.misra_21_2, cfg) self.executeCheck(2103, self.misra_21_3, cfg) self.executeCheck(2104, self.misra_21_4, cfg) self.executeCheck(2105, self.misra_21_5, cfg) @@ -3340,8 +4828,168 @@ def fillVerifyExpected(verify_expected, tok): self.executeCheck(2110, self.misra_21_10, cfg) self.executeCheck(2111, self.misra_21_11, cfg) self.executeCheck(2112, self.misra_21_12, cfg) + self.executeCheck(2114, self.misra_21_14, cfg) + self.executeCheck(2115, self.misra_21_15, cfg) + self.executeCheck(2116, self.misra_21_16, cfg) + self.executeCheck(2119, self.misra_21_19, cfg) + self.executeCheck(2120, self.misra_21_20, cfg) + self.executeCheck(2121, self.misra_21_21, cfg) # 22.4 is already covered by Cppcheck writeReadOnlyFile + self.executeCheck(2205, self.misra_22_5, cfg) + self.executeCheck(2207, self.misra_22_7, cfg) + self.executeCheck(2208, self.misra_22_8, cfg) + self.executeCheck(2209, self.misra_22_9, cfg) + self.executeCheck(2210, self.misra_22_10, cfg) + + def read_ctu_info_line(self, line): + if not line.startswith('{'): + return None + try: + ctu_info = json.loads(line) + except json.decoder.JSONDecodeError: + return None + if 'summary' not in ctu_info: + return None + if 'data' not in ctu_info: + return None + return ctu_info + + def analyse_ctu_info(self, ctu_info_files): + all_typedef_info = {} + all_tagname_info = {} + all_macro_info = {} + all_external_identifiers_decl = {} + all_external_identifiers_def = {} + all_internal_identifiers = {} + all_local_identifiers = {} + all_usage_files = {} + + from cppcheckdata import Location + + def is_different_location(loc1, loc2): + return loc1['file'] != loc2['file'] or loc1['line'] != loc2['line'] + + def is_different_file(loc1, loc2): + return loc1['file'] != loc2['file'] + + try: + for filename in ctu_info_files: + for line in open(filename, 'rt'): + s = self.read_ctu_info_line(line) + if s is None: + continue + summary_type = s.get('summary', '') + summary_data = s.get('data', None) + + if summary_type == 'MisraTypedefInfo': + for new_typedef_info in summary_data: + key = new_typedef_info['name'] + existing_typedef_info = all_typedef_info.get(key, None) + if existing_typedef_info: + if is_different_location(existing_typedef_info, new_typedef_info): + self.reportError(Location(existing_typedef_info), 5, 6) + self.reportError(Location(new_typedef_info), 5, 6) + else: + existing_typedef_info['used'] = existing_typedef_info['used'] or new_typedef_info['used'] + else: + all_typedef_info[key] = new_typedef_info + + if summary_type == 'MisraTagName': + for new_tagname_info in summary_data: + key = new_tagname_info['name'] + existing_tagname_info = all_tagname_info.get(key, None) + if existing_tagname_info: + if is_different_location(existing_tagname_info, new_tagname_info): + self.reportError(Location(existing_tagname_info), 5, 7) + self.reportError(Location(new_tagname_info), 5, 7) + else: + existing_tagname_info['used'] = existing_tagname_info['used'] or new_tagname_info['used'] + else: + all_tagname_info[key] = new_tagname_info + + if summary_type == 'MisraMacro': + for new_macro in summary_data: + key = new_macro['name'] + existing_macro = all_macro_info.get(key, None) + if existing_macro: + existing_macro['used'] = existing_macro['used'] or new_macro['used'] + else: + all_macro_info[key] = new_macro + + if summary_type == 'MisraExternalIdentifiers': + for s in sorted(summary_data, key=lambda d: "%s %s %s" %(d['file'],d['line'], d['column'] )): + is_declaration = s['decl'] + if is_declaration: + all_external_identifiers = all_external_identifiers_decl + else: + all_external_identifiers = all_external_identifiers_def + + name = s['name'] + if name in all_external_identifiers: + if is_declaration and is_different_location(s, all_external_identifiers[name]): + self.reportError(Location(s), 8, 5) + self.reportError(Location(all_external_identifiers[name]), 8, 5) + elif is_different_file(s, all_external_identifiers[name]): + self.reportError(Location(s), 8, 6) + self.reportError(Location(all_external_identifiers[name]), 8, 6) + all_external_identifiers[name] = s + + if summary_type == 'MisraInternalIdentifiers': + for s in summary_data: + if s['name'] in all_internal_identifiers: + if not s['inlinefunc'] or s['file'] != all_internal_identifiers[s['name']]['file']: + self.reportError(Location(s), 5, 9) + self.reportError(Location(all_internal_identifiers[s['name']]), 5, 9) + all_internal_identifiers[s['name']] = s + + if summary_type == 'MisraLocalIdentifiers': + for s in summary_data: + all_local_identifiers[s['name']] = s + + if summary_type == 'MisraUsage': + for s in summary_data: + if s['name'] in all_usage_files: + all_usage_files[s['name']].append(s['file']) + else: + all_usage_files[s['name']] = [s['file']] + + except FileNotFoundError: + return + unused_typedefs = [tdi for tdi in all_typedef_info.values() if not tdi['used']] + for tdi in unused_typedefs: + self.reportError(Location(tdi), 2, 3) + + unused_tags = [tag for tag in all_tagname_info.values() if not tag['used']] + for tag in unused_tags: + self.reportError(Location(tag), 2, 4) + + unused_macros = [m for m in all_macro_info.values() if not m['used']] + for m in unused_macros: + self.reportError(Location(m), 2, 5) + + all_external_identifiers = all_external_identifiers_decl + all_external_identifiers.update(all_external_identifiers_def) + for name, external_identifier in all_external_identifiers.items(): + internal_identifier = all_internal_identifiers.get(name) + if internal_identifier: + self.reportError(Location(internal_identifier), 5, 8) + self.reportError(Location(external_identifier), 5, 8) + + local_identifier = all_local_identifiers.get(name) + if local_identifier: + self.reportError(Location(local_identifier), 5, 8) + self.reportError(Location(external_identifier), 5, 8) + + for name, files in all_usage_files.items(): + #print('%s:%i' % (name, count)) + count = len(files) + if count != 1 or name not in all_external_identifiers_def: + continue + if files[0] != Location(all_external_identifiers_def[name]).file: + continue + if name in all_external_identifiers: + self.reportError(Location(all_external_identifiers[name]), 8, 7) RULE_TEXTS_HELP = '''Path to text file of MISRA rules @@ -3359,10 +5007,12 @@ def fillVerifyExpected(verify_expected, tok): <..arbitrary text..> Appendix A Summary of guidelines -Rule 1.1 +Rule 1.1 Required Rule text for 1.1 -Rule 1.2 +continuation of rule text for 1.1 +Rule 1.2 Mandatory Rule text for 1.2 +continuation of rule text for 1.2 <...> ''' @@ -3377,7 +5027,7 @@ def fillVerifyExpected(verify_expected, tok): ''' -def get_args(): +def get_args_parser(): """Generates list of command-line arguments acceptable by misra.py script.""" parser = cppcheckdata.ArgumentParser() parser.add_argument("--rule-texts", type=str, help=RULE_TEXTS_HELP) @@ -3391,14 +5041,17 @@ def get_args(): parser.add_argument("-generate-table", help=argparse.SUPPRESS, action="store_true") parser.add_argument("-verify", help=argparse.SUPPRESS, action="store_true") parser.add_argument("--severity", type=str, help="Set a custom severity string, for example 'error' or 'warning'. ") - return parser.parse_args() + return parser def main(): - args = get_args() + parser = get_args_parser() + args = parser.parse_args() settings = MisraSettings(args) checker = MisraChecker(settings) + checker.path_premium_addon = cppcheckdata.get_path_premium_addon() + if args.generate_table: generateTable() sys.exit(0) @@ -3406,13 +5059,17 @@ def main(): if args.rule_texts: filename = os.path.expanduser(args.rule_texts) filename = os.path.normpath(filename) - if not os.path.isfile(filename): - print('Fatal error: file is not found: ' + filename) - sys.exit(1) - checker.loadRuleTexts(filename) - if args.verify_rule_texts: - checker.verifyRuleTexts() - sys.exit(0) + checker.ruleText_filename = filename + if os.path.isfile(filename): + checker.loadRuleTexts(filename) + if args.verify_rule_texts: + checker.verifyRuleTexts() + sys.exit(0) + else: + if args.verify_rule_texts: + print('Fatal error: file is not found: ' + filename) + sys.exit(1) + if args.verify_rule_texts and not args.rule_texts: print("Error: Please specify rule texts file with --rule-texts=") @@ -3424,7 +5081,9 @@ def main(): if args.file_prefix: checker.setFilePrefix(args.file_prefix) - if not args.dumpfile: + dump_files, ctu_info_files = cppcheckdata.get_files(args) + + if (not dump_files) and (not ctu_info_files): if not args.quiet: print("No input files.") sys.exit(0) @@ -3432,8 +5091,8 @@ def main(): if args.severity: checker.setSeverity(args.severity) - for item in args.dumpfile: - checker.parseDump(item) + for item in dump_files: + checker.parseDump(item,checker.path_premium_addon) if settings.verify: verify_expected = checker.get_verify_expected() @@ -3456,6 +5115,8 @@ def main(): if exitCode != 0: sys.exit(exitCode) + checker.analyse_ctu_info(ctu_info_files) + if settings.verify: sys.exit(exitCode) @@ -3471,7 +5132,7 @@ def main(): for misra_id in ids: rules_violated[misra_id] = rules_violated.get(misra_id, 0) + 1 print("MISRA rules violated:") - convert = lambda text: int(text) if text.isdigit() else text + convert = lambda text: int(text) if text.isdigit() else 0 misra_sort = lambda key: [convert(c) for c in re.split(r'[\.-]([0-9]*)', key)] for misra_id in sorted(rules_violated.keys(), key=misra_sort): res = re.match(r'misra-c2012-([0-9]+)\\.([0-9]+)', misra_id) diff --git a/addons/misra_9.py b/addons/misra_9.py index e3f360d6868..1ca1b7ce3e0 100644 --- a/addons/misra_9.py +++ b/addons/misra_9.py @@ -30,7 +30,7 @@ def __repr__(self): attrs = ["childIndex", "elementType", "valueType"] return "{}({}, {}, {})".format( - "ED", + "ElementDef", self.getLongName(), inits, ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) @@ -86,7 +86,7 @@ def getNextChild(self): def getChildByIndex(self, index): if self.isFlexible: while len(self.children) <= index: - createChild(self, self.flexibleToken, len(self.children)) + createChild(self, self.flexibleToken, len(self.children), None) return self.children[index] if 0 <= index < len(self.children) else None def getChildByName(self, name): @@ -138,8 +138,7 @@ def getChildByValueElement(self, ed): def getEffectiveLevel(self): if self.parent and self.parent.elementType == "array": return self.parent.getEffectiveLevel() + 1 - else: - return 0 + return 0 def setInitialized(self, designated=False, positional=False): if designated: @@ -201,11 +200,10 @@ def isMisra93Compliant(self): self.isOnlyDesignated()) and all([not (child.isDesignated or child.isPositional) or child.isMisra93Compliant() for child in self.children])) return result - elif self.elementType == 'record': + if self.elementType == 'record': result = all([child.isMisra93Compliant() for child in self.children]) return result - else: - return True + return True def isMisra94Compliant(self): return self.numInits <= 1 and all([child.isMisra94Compliant() for child in self.children]) @@ -253,6 +251,16 @@ def parseInitializer(self, root, token): isFirstElement = False isDesignated = True + elif self.token.isString and self.ed and self.ed.isArray: + self.ed.setInitialized(isDesignated) + if self.token == self.token.astParent.astOperand1 and self.token.astParent.astOperand2: + self.token = self.token.astParent.astOperand2 + self.ed.markAsCurrent() + self.ed = self.root.getNextChild() + else: + self.unwindAndContinue() + continue + elif self.token.str == '{': nextChild = self.root.getNextChild() if self.root is not None else None @@ -281,7 +289,7 @@ def parseInitializer(self, root, token): # Fake dummy as nextChild (of current root) nextChild = dummyRoot - if self.token.astOperand1: + if nextChild and self.token.astOperand1: self.root = nextChild self.token = self.token.astOperand1 isFirstElement = True @@ -299,7 +307,6 @@ def parseInitializer(self, root, token): if self.ed and self.ed.isValue: if not isDesignated and len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root: self.rootStack[-1][0].markStuctureViolation(self.token) - if isFirstElement and self.token.str == '0' and self.token.next.str == '}': # Zero initializer causes recursive initialization self.root.initializeChildren() @@ -314,12 +321,14 @@ def parseInitializer(self, root, token): else: self.ed.parent.setInitialized(isDesignated) self.ed.parent.initializeChildren() + else: - if self.ed.parent != self.root: + if self.root is not None and self.ed.parent != self.root: # Check if token is correct value type for self.root.children[?] child = self.root.getChildByValueElement(self.ed) - if child.elementType != 'record' or self.token.valueType.type != 'record' or child.valueType.typeScope != self.token.valueType.typeScope: - self.root.markStuctureViolation(self.token) + if self.token.valueType: + if child.elementType != 'record' or self.token.valueType.type != 'record' or child.valueType.typeScope != self.token.valueType.typeScope: + self.root.markStuctureViolation(self.token) self.ed.setInitialized(isDesignated) @@ -332,6 +341,8 @@ def parseInitializer(self, root, token): parent = parent.parent isDesignated = False + if self.token.isString and self.ed.parent.isArray: + self.ed = self.ed.parent self.unwindAndContinue() def pushToRootStackAndMarkAsDesignated(self): @@ -357,33 +368,37 @@ def unwindAndContinue(self): while self.token: if self.token.astParent.astOperand1 == self.token and self.token.astParent.astOperand2: if self.ed: - self.ed.markAsCurrent() - self.ed = self.ed.getNextValueElement(self.root) + if self.token.astParent.astOperand2.str == "{" and self.ed.isDesignated: + self.popFromStackIfExitElement() + else: + self.ed.markAsCurrent() + self.ed = self.ed.getNextValueElement(self.root) self.token = self.token.astParent.astOperand2 break - else: - self.token = self.token.astParent - if self.token.str == '{': - if self.root: - self.ed = self.root.getLastValueElement() - self.ed.markAsCurrent() - # Cleanup if root is dummy node representing excess levels in initializer - if self.root.name == '<-': - self.root.children[0].parent = self.root.parent + self.token = self.token.astParent + if self.token.str == '{': + if self.root: + self.ed = self.root.getLastValueElement() + self.ed.markAsCurrent() - self.root = self.root.parent + # Cleanup if root is dummy node representing excess levels in initializer + if self.root.name == '<-': + self.root.children[0].parent = self.root.parent - if self.token.astParent is None: - self.token = None - break + self.root = self.root.parent + + if self.token.astParent is None: + self.token = None + break def misra_9_x(self, data, rule, rawTokens = None): + parser = InitializerParser() for variable in data.variables: - if not variable.nameToken: + if variable.nameToken is None: continue nameToken = variable.nameToken @@ -409,12 +424,18 @@ def misra_9_x(self, data, rule, rawTokens = None): # without it. if ed.valueType is None and not variable.isArray: continue - parser.parseInitializer(ed, eq.astOperand2) # print(rule, nameToken.str + '=', ed.getInitDump()) if rule == 902 and not ed.isMisra92Compliant(): self.reportError(nameToken, 9, 2) if rule == 903 and not ed.isMisra93Compliant(): + # Do not check when variable is pointer type + type_token = variable.nameToken + while type_token and type_token.isName: + type_token = type_token.previous + if type_token and type_token.str == '*': + continue + self.reportError(nameToken, 9, 3) if rule == 904 and not ed.isMisra94Compliant(): self.reportError(nameToken, 9, 4) @@ -424,16 +445,16 @@ def misra_9_x(self, data, rule, rawTokens = None): def getElementDef(nameToken, rawTokens = None): if nameToken.variable.isArray: ed = ElementDef("array", nameToken.str, nameToken.valueType) - createArrayChildrenDefs(ed, nameToken.astParent, rawTokens) + createArrayChildrenDefs(ed, nameToken.astParent, nameToken.variable, rawTokens) elif nameToken.variable.isClass: ed = ElementDef("record", nameToken.str, nameToken.valueType) - createRecordChildrenDefs(ed) + createRecordChildrenDefs(ed, nameToken.variable) else: ed = ElementDef("value", nameToken.str, nameToken.valueType) return ed -def createArrayChildrenDefs(ed, token, rawTokens = None): - if token.str == '[': +def createArrayChildrenDefs(ed, token, var, rawTokens = None): + if token and token.str == '[': if rawTokens is not None: foundToken = next((rawToken for rawToken in rawTokens if rawToken.file == token.file @@ -446,32 +467,60 @@ def createArrayChildrenDefs(ed, token, rawTokens = None): if (token.astOperand2 is not None) and (token.astOperand2.getKnownIntValue() is not None): for i in range(token.astOperand2.getKnownIntValue()): - createChild(ed, token, i) + createChild(ed, token, i, var) else: ed.markAsFlexibleArray(token) -def createChild(ed, token, name): +def createChild(ed, token, name, var): if token.astParent and token.astParent.str == '[': child = ElementDef("array", name, ed.valueType) - createArrayChildrenDefs(child, token.astParent) + createArrayChildrenDefs(child, token.astParent, var) else: if ed.valueType and ed.valueType.type == "record": child = ElementDef("record", name, ed.valueType) - createRecordChildrenDefs(child) + createRecordChildrenDefs(child, var) else: child = ElementDef("value", name, ed.valueType) ed.addChild(child) -def createRecordChildrenDefs(ed): +def createRecordChildrenDefs(ed, var): valueType = ed.valueType if not valueType or not valueType.typeScope: return - + if var is None: + return + typeToken = var.typeEndToken + while typeToken and typeToken.isName: + typeToken = typeToken.previous + if typeToken and typeToken.str == '*': + child = ElementDef("pointer", var.nameToken, var.nameToken.valueType) + ed.addChild(child) + return + child_dict = {} for variable in valueType.typeScope.varlist: + if variable is var: + continue child = getElementDef(variable.nameToken) - ed.addChild(child) + child_dict[variable.nameToken] = child + for scopes in valueType.typeScope.nestedList: + varscope = False + if scopes.nestedIn == valueType.typeScope: + for variable in valueType.typeScope.varlist: + if variable.nameToken and variable.nameToken.valueType and variable.nameToken.valueType.typeScope == scopes: + varscope = True + break + if not varscope: + ed1 = ElementDef("record", scopes.Id, valueType) + for variable in scopes.varlist: + child = getElementDef(variable.nameToken) + ed1.addChild(child) + child_dict[scopes.bodyStart] = ed1 + sorted_keys = sorted(list(child_dict.keys()), key=lambda k: (k.file, k.linenr, k.column)) + for _key in sorted_keys: + ed.addChild(child_dict[_key]) + def getElementByDesignator(ed, token): if not token.str in [ '.', '[' ]: diff --git a/addons/naming.py b/addons/naming.py index faaf5327e2e..2893779f2e0 100755 --- a/addons/naming.py +++ b/addons/naming.py @@ -17,7 +17,7 @@ def validate_regex(expr): re.compile(expr) except re.error: print('Error: "{}" is not a valid regular expression.'.format(expr)) - exit(1) + sys.exit(1) RE_VARNAME = None @@ -37,6 +37,7 @@ def validate_regex(expr): elif arg[:11] == '--function=': RE_FUNCTIONNAME = arg[11:] validate_regex(RE_FUNCTIONNAME) + # TODO: bail out on unknown parameter def reportError(token, severity, msg, errorId): @@ -81,7 +82,7 @@ def reportError(token, severity, msg, errorId): for scope in cfg.scopes: if scope.type == 'Function': function = scope.function - if function is not None and function.type in ('Constructor', 'Destructor'): + if function is not None and function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'): continue res = re.match(RE_FUNCTIONNAME, scope.className) if not res: diff --git a/addons/naming.json b/addons/namingng.config.json similarity index 61% rename from addons/naming.json rename to addons/namingng.config.json index 26cb4bbce7a..0abba4f15ac 100644 --- a/addons/naming.json +++ b/addons/namingng.config.json @@ -2,6 +2,15 @@ "RE_VARNAME": ["[a-z]*[a-zA-Z0-9_]*\\Z"], "RE_PRIVATE_MEMBER_VARIABLE": null, "RE_FUNCTIONNAME": ["[a-z0-9A-Z]*\\Z"], + "include_guard": { + "input": "path", + "prefix": "", + "suffix": "", + "case": "upper", + "max_linenr": 5, + "RE_HEADERFILE": "[^/].*\\.h\\Z", + "required": true + }, "var_prefixes": {"uint32_t": "ui32", "int*": "intp"}, "function_prefixes": {"uint16_t": "ui16", diff --git a/addons/namingng.json b/addons/namingng.json new file mode 100644 index 00000000000..83f9a5a55d8 --- /dev/null +++ b/addons/namingng.json @@ -0,0 +1,6 @@ +{ + "script":"namingng.py", + "args":[ + "--configfile=namingng.config.json" + ] +} diff --git a/addons/namingng.py b/addons/namingng.py index 84f5ed31b28..9da177321ef 100755 --- a/addons/namingng.py +++ b/addons/namingng.py @@ -3,6 +3,7 @@ # cppcheck addon for naming conventions # An enhanced version. Configuration is taken from a json file # It supports to check for type-based prefixes in function or variable names. +# Aside from include guard naming, include guard presence can also be tested. # # Example usage (variable name must start with lowercase, function name must start with uppercase): # $ cppcheck --dump path-to-src/ @@ -11,9 +12,18 @@ # JSON format: # # { -# "RE_VARNAME": "[a-z]*[a-zA-Z0-9_]*\\Z", +# "RE_VARNAME": ["[a-z]*[a-zA-Z0-9_]*\\Z"], # "RE_PRIVATE_MEMBER_VARIABLE": null, -# "RE_FUNCTIONNAME": "[a-z0-9A-Z]*\\Z", +# "RE_FUNCTIONNAME": ["[a-z0-9A-Z]*\\Z"], +# "_comment": "comments can be added to the config with underscore-prefixed keys", +# "include_guard": { +# "input": "path", +# "prefix": "GUARD_", +# "case": "upper", +# "max_linenr": 5, +# "RE_HEADERFILE": "[^/].*\\.h\\Z", +# "required": true +# }, # "var_prefixes": {"uint32_t": "ui32"}, # "function_prefixes": {"uint16_t": "ui16", # "uint32_t": "ui32"} @@ -24,230 +34,387 @@ import cppcheckdata import sys +import os import re -import argparse import json - # Auxiliary class class DataStruct: - def __init__(self, file, linenr, string): + def __init__(self, file, linenr, string, column=0): self.file = file self.linenr = linenr self.str = string + self.column = column + +def reportNamingError(location,message,errorId='namingConvention',severity='style',extra='',column=None): + cppcheckdata.reportError(location,severity,message,'namingng',errorId,extra,columnOverride=column) +def configError(error,fatal=True): + print('config error: %s'%error) + if fatal: + sys.exit(1) -def reportError(filename, linenr, severity, msg): - message = "[{filename}:{linenr}] ( {severity} ) naming.py: {msg}\n".format( - filename=filename, - linenr=linenr, - severity=severity, - msg=msg - ) - sys.stderr.write(message) - return message +def validateConfigREs(list_or_dict,json_key): + have_error = False + for item in list_or_dict: + try: + re.compile(item) + except re.error as err: + configError("item '%s' of '%s' is not a valid regular expression: %s"%(item,json_key,err),fatal=False) + have_error = True + continue + if not isinstance(list_or_dict,dict): + continue + # item is actually a dict key; check value + value = list_or_dict[item] + if (not isinstance(value,list) or len(value) != 2 + or not isinstance(value[0],bool) or not isinstance(value[1],str)): + configError("item '%s' of '%s' must be an array [bool,string]"%(item,json_key),fatal=False) + have_error = True + return have_error def loadConfig(configfile): - with open(configfile) as fh: - data = json.load(fh) - return data + if not os.path.exists(configfile): + configError("cannot find config file '%s'"%configfile) + + try: + with open(configfile) as fh: + data = json.load(fh) + except json.JSONDecodeError as e: + configError("error parsing config file as JSON at line %d: %s"%(e.lineno,e.msg)) + except Exception as e: + configError("error opening config file '%s': %s"%(configfile,e)) + + if not isinstance(data, dict): + configError('config file must contain a JSON object at the top level') + + # All errors are emitted before bailing out, to make the unit test more + # effective. + have_error = False + + # Put config items in a class, so that settings can be accessed using + # config.feature + class Config: + pass + config = Config() + + mapping = { + 'file': ('RE_FILE', (list,)), + 'namespace': ('RE_NAMESPACE', (list,dict)), + 'include_guard': ('include_guard', (dict,)), + 'variable': ('RE_VARNAME', (list,dict)), + 'variable_prefixes': ('var_prefixes', (dict,), {}), + 'private_member': ('RE_PRIVATE_MEMBER_VARIABLE', (list,dict)), + 'public_member': ('RE_PUBLIC_MEMBER_VARIABLE', (list,dict)), + 'global_variable': ('RE_GLOBAL_VARNAME', (list,dict)), + 'function_name': ('RE_FUNCTIONNAME', (list,dict)), + 'function_prefixes': ('function_prefixes', (dict,), {}), + 'class_name': ('RE_CLASS_NAME', (list,dict)), + 'skip_one_char_variables': ('skip_one_char_variables', (bool,)), + } + + # parse defined keys and store as members of config object + for key,opts in mapping.items(): + json_key = opts[0] + req_type = opts[1] + default = None if len(opts)<3 else opts[2] + + value = data.pop(json_key,default) + if value is not None and type(value) not in req_type: + req_typename = ' or '.join([tp.__name__ for tp in req_type]) + got_typename = type(value).__name__ + configError('%s must be %s (not %s), or not set'%(json_key,req_typename,got_typename),fatal=False) + have_error = True + continue + # type list implies that this is either a list of REs or a dict with RE keys + if list in req_type and value is not None: + re_error = validateConfigREs(value,json_key) + if re_error: + have_error = True -def checkTrueRegex(data, expr, msg, errors): - res = re.match(expr, data.str) - if res: - errors.append(reportError(data.file, data.linenr, 'style', msg)) + setattr(config,key,value) + # check remaining keys, only accept underscore-prefixed comments + for key,value in data.items(): + if key == '' or key[0] != '_': + configError("unknown config key '%s'"%key,fatal=False) + have_error = True -def checkFalseRegex(data, expr, msg, errors): - res = re.match(expr, data.str) - if not res: - errors.append(reportError(data.file, data.linenr, 'style', msg)) + if have_error: + sys.exit(1) + + # pylint: disable-next=no-member - TODO: fix this + if config.include_guard: + # pylint: disable-next=no-member - TODO: fix this + config.include_guard_header_re = config.include_guard.get('RE_HEADERFILE',"[^/].*\\.h\\Z") + + return config -def evalExpr(conf, exp, mockToken, msgType, errors): +def evalExpr(conf, exp, mockToken, msgType): + report_as_error = False + msg = msgType + ' ' + mockToken.str + ' violates naming convention' + if isinstance(conf, dict): - if conf[exp][0]: - msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1] - checkTrueRegex(mockToken, exp, msg, errors) - elif ~conf[exp][0]: - msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1] - checkFalseRegex(mockToken, exp, msg, errors) - else: - msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][0] - checkFalseRegex(mockToken, exp, msg, errors) + report_as_error = conf[exp][0] + msg += ': ' + conf[exp][1] + + res = re.match(exp,mockToken.str) + if bool(res) == report_as_error: + reportNamingError(mockToken,msg) + +def check_include_guard_name(conf,directive): + parts = directive.str.split() + if len(parts) != 2: + msg = 'syntax error' + reportNamingError(directive,msg,'syntax') + return None,None + guard_name = parts[1] + guard_column = 1+directive.str.find(guard_name) + + filename = directive.file + if conf.include_guard.get('input','path') == 'basename': + filename = os.path.basename(filename) + use_case = conf.include_guard.get('case','upper') + if use_case == 'upper': + filename = filename.upper() + elif use_case == 'lower': + filename = filename.lower() + elif use_case == 'keep': + pass # keep filename case as-is else: - msg = msgType + ' ' + mockToken.str + ' violates naming convention' - checkFalseRegex(mockToken, exp, msg, errors) - + print("invalid config value for 'case': '%s'"%use_case,file=sys.stderr) + sys.exit(1) -def process(dumpfiles, configfile, debugprint=False): + barename = re.sub('[^A-Za-z0-9]','_',filename).strip('_') + expect_guard_name = conf.include_guard.get('prefix','') + barename + conf.include_guard.get('suffix','') + if expect_guard_name != guard_name: + msg = 'include guard naming violation; %s != %s'%(guard_name,expect_guard_name) + reportNamingError(directive,msg,'includeGuardName',column=guard_column) + + return guard_name,guard_column + +def check_include_guards(conf,cfg,unguarded_include_files): + # Scan for '#ifndef FILE_H' as the first directive, in the first N lines. + # Then test whether the next directive #defines the found name. + # Various tests are done: + # - check include guards for their naming and consistency + # - test whether include guards are in place + max_linenr = conf.include_guard.get('max_linenr', 5) + + def report(directive,msg,errorId,severity='style',column=0): + reportNamingError(directive,msg,errorId,severity=severity,column=column) + + def report_pending_ifndef(directive,column): + report(directive,'include guard #ifndef is not followed by #define','includeGuardIncomplete',column=column) + + last_fn = None + pending_ifndef = None + guard_column = None + phase = 0 + for directive in cfg.directives: + if last_fn != directive.file: + if pending_ifndef: + report_pending_ifndef(pending_ifndef,guard_column) + pending_ifndef = None + last_fn = directive.file + phase = 0 + if phase == -1: + # ignore (the remainder of) this file + continue + if not re.match(conf.include_guard_header_re,directive.file): + phase = -1 + continue - errors = [] + if directive.linenr > max_linenr: + if phase == 0 and conf.include_guard.get('required',1): + report(directive,'include guard not found before line %d'%max_linenr,'includeGuardMissing') + phase = -1 + continue + if phase == 0: + # looking for '#ifndef FILE_H' + if not directive.str.startswith('#ifndef'): + if conf.include_guard.get('required',1): + report(directive,'first preprocessor directive should be include guard #ifndef','includeGuardMissing') + phase = -1 + continue + guard_name,guard_column = check_include_guard_name(conf,directive) + if guard_name is None: + phase = -1 + continue + pending_ifndef = directive + phase = 1 + elif phase == 1: + pending_ifndef = None + # looking for '#define FILE_H' + if not directive.str.startswith('#define'): + report(directive,'second preprocessor directive should be include guard #define','includeGuardIncomplete') + phase = -1 + continue + parts = directive.str.split() + if len(parts) == 1: + report(directive,'syntax error','syntax') + phase = -1 + continue + if guard_name != parts[1]: + report(directive,'include guard does not guard; %s != %s'%(guard_name,parts[1]),'includeGuardAwayFromDuty',severity='warning',column=guard_column) + + unguarded_include_files.remove(directive.file) + + phase = -1 + if pending_ifndef: + report_pending_ifndef(pending_ifndef,guard_column) + +def process(dumpfiles, configfile, cli, debugprint): conf = loadConfig(configfile) for afile in dumpfiles: if not afile[-5:] == '.dump': continue - print('Checking ' + afile + '...') + if not cli: + print('Checking ' + afile + '...') data = cppcheckdata.CppcheckData(afile) + process_data(conf,data,cli,debugprint) + +def check_file_naming(conf,data): + for source_file in data.files: + basename = os.path.basename(source_file) + good = False + for exp in conf.file: + good |= bool(re.match(exp, source_file)) + good |= bool(re.match(exp, basename)) + if not good: + mockToken = DataStruct(source_file, 0, basename) + reportNamingError(mockToken, 'File name ' + basename + ' violates naming convention') + +def check_namespace_naming(conf,data): + for tk in data.rawTokens: + if tk.str != 'namespace': + continue + mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str, tk.next.column) + for exp in conf.namespace: + evalExpr(conf.namespace, exp, mockToken, 'Namespace') - # Check File naming - if "RE_FILE" in conf and conf["RE_FILE"]: - mockToken = DataStruct(afile[:-5], "0", afile[afile.rfind('/') + 1:-5]) - msgType = 'File name' - for exp in conf["RE_FILE"]: - evalExpr(conf["RE_FILE"], exp, mockToken, msgType, errors) - - # Check Namespace naming - if "RE_NAMESPACE" in conf and conf["RE_NAMESPACE"]: - for tk in data.rawTokens: - if tk.str == 'namespace': - mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str) - msgType = 'Namespace' - for exp in conf["RE_NAMESPACE"]: - evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors) - - for cfg in data.configurations: - print('Checking %s, config %s...' % (afile, cfg.name)) - if "RE_VARNAME" in conf and conf["RE_VARNAME"]: - for var in cfg.variables: - if var.nameToken and var.access != 'Global' and var.access != 'Public' and var.access != 'Private': - prev = var.nameToken.previous - varType = prev.str - while "*" in varType and len(varType.replace("*", "")) == 0: - prev = prev.previous - varType = prev.str + varType - - if debugprint: - print("Variable Name: " + str(var.nameToken.str)) - print("original Type Name: " + str(var.nameToken.valueType.originalTypeName)) - print("Type Name: " + var.nameToken.valueType.type) - print("Sign: " + str(var.nameToken.valueType.sign)) - print("variable type: " + varType) - print("\n") - print("\t-- {} {}".format(varType, str(var.nameToken.str))) - - if conf["skip_one_char_variables"] and len(var.nameToken.str) == 1: - continue - if varType in conf["var_prefixes"]: - if not var.nameToken.str.startswith(conf["var_prefixes"][varType]): - errors.append(reportError( - var.typeStartToken.file, - var.typeStartToken.linenr, - 'style', - 'Variable ' + - var.nameToken.str + - ' violates naming convention')) - - mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) - msgType = 'Variable' - for exp in conf["RE_VARNAME"]: - evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType, errors) - - # Check Private Variable naming - if "RE_PRIVATE_MEMBER_VARIABLE" in conf and conf["RE_PRIVATE_MEMBER_VARIABLE"]: - # TODO: Not converted yet - for var in cfg.variables: - if (var.access is None) or var.access != 'Private': - continue - mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) - msgType = 'Private member variable' - for exp in conf["RE_PRIVATE_MEMBER_VARIABLE"]: - evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType, errors) - - # Check Public Member Variable naming - if "RE_PUBLIC_MEMBER_VARIABLE" in conf and conf["RE_PUBLIC_MEMBER_VARIABLE"]: - for var in cfg.variables: - if (var.access is None) or var.access != 'Public': - continue - mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) - msgType = 'Public member variable' - for exp in conf["RE_PUBLIC_MEMBER_VARIABLE"]: - evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType, errors) - - # Check Global Variable naming - if "RE_GLOBAL_VARNAME" in conf and conf["RE_GLOBAL_VARNAME"]: - for var in cfg.variables: - if (var.access is None) or var.access != 'Global': - continue - mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str) - msgType = 'Public member variable' - for exp in conf["RE_GLOBAL_VARNAME"]: - evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType, errors) - - # Check Functions naming - if "RE_FUNCTIONNAME" in conf and conf["RE_FUNCTIONNAME"]: - for token in cfg.tokenlist: - if token.function: - if token.function.type == 'Constructor' or token.function.type == 'Destructor': - continue - retval = token.previous.str - prev = token.previous - while "*" in retval and len(retval.replace("*", "")) == 0: - prev = prev.previous - retval = prev.str + retval - if debugprint: - print("\t:: {} {}".format(retval, token.function.name)) - - if retval and retval in conf["function_prefixes"]: - if not token.function.name.startswith(conf["function_prefixes"][retval]): - errors.append(reportError( - token.file, token.linenr, 'style', 'Function ' + token.function.name + ' violates naming convention')) - mockToken = DataStruct(token.file, token.linenr, token.function.name) - msgType = 'Function' - for exp in conf["RE_FUNCTIONNAME"]: - evalExpr(conf["RE_FUNCTIONNAME"], exp, mockToken, msgType, errors) - - # Check Class naming - if "RE_CLASS_NAME" in conf and conf["RE_CLASS_NAME"]: - for fnc in cfg.functions: - # Check if it is Constructor/Destructor - if fnc.type == 'Constructor' or fnc.type == 'Destructor': - mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name) - msgType = 'Class ' + fnc.type - for exp in conf["RE_CLASS_NAME"]: - evalExpr(conf["RE_CLASS_NAME"], exp, mockToken, msgType, errors) - return errors +def check_variable_naming(conf,cfg,debugprint): + for var in cfg.variables: + if not var.nameToken: + continue + if var.access in ('Global','Public','Private'): + continue + prev = var.nameToken.previous + varType = prev.str + while "*" in varType and len(varType.replace("*", "")) == 0: + prev = prev.previous + varType = prev.str + varType + + if debugprint: + print("Variable Name: " + str(var.nameToken.str)) + print("original Type Name: " + str(var.nameToken.valueType.originalTypeName)) + print("Type Name: " + var.nameToken.valueType.type) + print("Sign: " + str(var.nameToken.valueType.sign)) + print("variable type: " + varType) + print("\n") + print("\t-- {} {}".format(varType, str(var.nameToken.str))) + + if conf.skip_one_char_variables and len(var.nameToken.str) == 1: + continue + if varType in conf.variable_prefixes: + prefix = conf.variable_prefixes[varType] + if not var.nameToken.str.startswith(prefix): + reportNamingError(var.typeStartToken, + 'Variable ' + + var.nameToken.str + + ' violates naming convention', + column=var.nameToken.column) + + mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column) + for exp in conf.variable: + evalExpr(conf.variable, exp, mockToken, 'Variable') + +# Naming check for Global, Private and Public member variables +def check_gpp_naming(conf_list,cfg,access,message): + for var in cfg.variables: + if var.access != access: + continue + mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column) + for exp in conf_list: + evalExpr(conf_list, exp, mockToken, message) +def check_function_naming(conf,cfg,debugprint): + for token in cfg.tokenlist: + if not token.function: + continue + if token.function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'): + continue + retval = token.previous.str + prev = token.previous + while "*" in retval and len(retval.replace("*", "")) == 0: + prev = prev.previous + retval = prev.str + retval + if debugprint: + print("\t:: {} {}".format(retval, token.function.name)) + + if retval and retval in conf.function_prefixes: + if not token.function.name.startswith(conf.function_prefixes[retval]): + reportNamingError(token, 'Function ' + token.function.name + ' violates naming convention', column=token.column) + mockToken = DataStruct(token.file, token.linenr, token.function.name, token.column) + msgType = 'Function' + for exp in conf.function_name: + evalExpr(conf.function_name, exp, mockToken, msgType) + +def check_class_naming(conf,cfg): + for fnc in cfg.functions: + if fnc.type not in ('Constructor','Destructor'): + continue + mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name, fnc.tokenDef.column) + msgType = 'Class ' + fnc.type + for exp in conf.class_name: + evalExpr(conf.class_name, exp, mockToken, msgType) + +def process_data(conf,data,cli,debugprint): + if conf.file: + check_file_naming(conf,data) + + if conf.namespace: + check_namespace_naming(conf,data) + + unguarded_include_files = [] + if conf.include_guard and conf.include_guard.get('required',1): + unguarded_include_files = [fn for fn in data.files if re.match(conf.include_guard_header_re,fn)] + + for cfg in data.configurations: + if not cli: + print('Checking config %s...' % cfg.name) + if conf.variable: + check_variable_naming(conf,cfg,debugprint) + if conf.private_member: + check_gpp_naming(conf.private_member,cfg,'Private','Private member variable') + if conf.public_member: + check_gpp_naming(conf.public_member,cfg,'Public','Public member variable') + if conf.global_variable: + check_gpp_naming(conf.global_variable,cfg,'Global','Global variable') + if conf.function_name: + check_function_naming(conf,cfg,debugprint) + if conf.class_name: + check_class_naming(conf,cfg) + if conf.include_guard: + check_include_guards(conf,cfg,unguarded_include_files) + + for fn in unguarded_include_files: + mockToken = DataStruct(fn,0,os.path.basename(fn)) + reportNamingError(mockToken,'Missing include guard','includeGuardMissing') if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Naming verification') - parser.add_argument('dumpfiles', type=str, nargs='+', - help='A set of dumpfiles to process') + parser = cppcheckdata.ArgumentParser() parser.add_argument("--debugprint", action="store_true", default=False, help="Add debug prints") - parser.add_argument("--configfile", type=str, default="naming.json", + parser.add_argument("--configfile", type=str, default="namingng.config.json", help="Naming check config file") - parser.add_argument("--verify", action="store_true", default=False, - help="verify this script. Must be executed in test folder !") args = parser.parse_args() - errors = process(args.dumpfiles, args.configfile, args.debugprint) - - if args.verify: - print(errors) - if len(errors) < 6: - print("Not enough errors found") - sys.exit(1) - target = [ - '[namingng_test.c:8] ( style ) naming.py: Variable badui32 violates naming convention\n', - '[namingng_test.c:11] ( style ) naming.py: Variable a violates naming convention\n', - '[namingng_test.c:29] ( style ) naming.py: Variable badui32 violates naming convention\n', - '[namingng_test.c:20] ( style ) naming.py: Function ui16bad_underscore violates naming convention\n', - '[namingng_test.c:25] ( style ) naming.py: Function u32Bad violates naming convention\n', - '[namingng_test.c:37] ( style ) naming.py: Function Badui16 violates naming convention\n'] - diff = set(errors) - set(target) - if len(diff): - print("Not the right errors found {}".format(str(diff))) - sys.exit(1) - print("Verification done\n") - sys.exit(0) - - if len(errors): - print('Found errors: {}'.format(len(errors))) - sys.exit(1) + process(args.dumpfile, args.configfile, args.cli, args.debugprint) sys.exit(0) diff --git a/addons/runaddon.py b/addons/runaddon.py new file mode 100644 index 00000000000..26ad7e9fa73 --- /dev/null +++ b/addons/runaddon.py @@ -0,0 +1,16 @@ +import cppcheckdata +import cppcheck +import runpy +import sys +import os + +if __name__ == '__main__': + addon = sys.argv[1] + __addon_name__ = os.path.splitext(os.path.basename(addon))[0] + sys.argv.pop(0) + + runpy.run_path(addon, run_name='__main__') + + # Run registered checkers + cppcheck.runcheckers() + sys.exit(cppcheckdata.EXIT_CODE) \ No newline at end of file diff --git a/addons/test/cert-test.c b/addons/test/cert-test.c deleted file mode 100644 index 2b6d826b14b..00000000000 --- a/addons/test/cert-test.c +++ /dev/null @@ -1,194 +0,0 @@ -// To test: -// ~/cppcheck/cppcheck --dump cert-test.c && python ../cert.py -verify cert-test.c.dump - -#include -#include -#include -#include -#include - -struct S { - short a; - short b; -}; - -#pragma pack() -struct PackedStruct { - short a; - short b; -}; - -void api01() -{ - const size_t String_Size = 20; - struct bad_node_s - { - char name[String_Size]; - struct bad_node_s* next; // cert-API01-C - }; - struct good_node_s - { - struct good_node_s* next; - char name[String_Size]; - }; - struct also_good_node_s - { - struct also_good_node_s* next; - char *name; - }; -} - -void dostuff(int *data); - -void exp05() -{ - const int x = 42; - int y = (int)x; - - int *p; - p = (int *)&x; // cert-EXP05-C - - const int data[] = {1,2,3,4}; - dostuff(data); // cert-EXP05-C -} - -void print(const char *p); -void exp05_fp() { - print("hello"); -} - -void exp42() -{ - struct S s1 = {1,2}; - struct S s2 = {1,2}; - memcmp(&s1, &s2, sizeof(struct S)); // cert-EXP42-C - - struct PackedStruct s3 = {1,2}; - struct PackedStruct s4 = {1,2}; - memcmp(&s3, &s4, sizeof(struct S)); -} - -void exp46(int x, int y, int z) -{ - if ((x == y) & z) {} // cert-EXP46-c -} - -unsigned char int31(int x) -{ - x = (unsigned char)1000; // cert-INT31-c - x = (signed char)0xff; // cert-INT31-c - x = (unsigned char)-1; // cert-INT31-c - x = (unsigned long long)-1; // cert-INT31-c -} - -void env33() -{ - system("chmod -x $(which chmod)"); // cert-ENV33-C - system(""); // cert-ENV33-C - system(NULL); // no-warning - system(0); // no-warning - const int *np = NULL; - system(np); // no-warning - int system; -} - -void msc24() -{ - struct S { - int x; int fopen; - }; - - struct S s; - time_t rawtime; - struct tm *timeinfo; - char buffer[256]; - int i; - long int li; - long long int lli; - FILE *f; - - s.fopen = 123; - - f = fopen ("myfile.txt","w+"); //cert-MSC24-C - setbuf ( f , buffer ); //cert-MSC24-C - for ( i='A' ; i<='Z' ; i++) - fputc ( i, f); - rewind (f); //cert-MSC24-C - fclose (f); - - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - printf ( "The current date/time is: %s", asctime (timeinfo) ); //cert-MSC24-C - - float n = atof (buffer); //cert-MSC24-C - float m = sin (n*M_PI/180); - - i = atoi (buffer); //cert-MSC24-C - - li = atol(buffer); //cert-MSC24-C - - lli = atoll(buffer); //cert-MSC24-C - - time (&rawtime); - printf ("The current local time is: %s", ctime (&rawtime)); //cert-MSC24-C - - freopen ("myfile.txt","w",stdout); //cert-MSC24-C - printf ("This sentence is redirected to a file."); - fclose (stdout); -} - -void msc30() -{ - unsigned int num = rand(); // cert-MSC30-c - int rand = 5; - int a = rand; -} - -void exp15() -{ - int x=5, y=7; - - if(x==y); //cert-EXP15-C - { - printf("not working\n"); - } - if(x) - ; -} - -void str03() -{ - char *string_data=(char*)malloc(16); - char a[16]; - int d; - strncpy(a, string_data, sizeof(a)); //cert-STR03-C - strncpy(a, string_data, 5); d=sizeof(int); -} - -void str05() -{ - int x=5, y=7; - - if(x==y); //cert-EXP15-C - { - printf("not working\n"); - } - if(x) - ; -} - -void str07(char *buf, const char *newBuf) -{ - const char *str = "test"; - strcat(buf,"bla"); - strcat(buf, str); //cert-STR07-C - strcat(buf, newBuf); //cert-STR07-C - strcpy(buf, newBuf); //cert-STR07-C -} - -void str11() -{ - const char str[3]="abc"; //cert-STR11-C - const char *x[10]; x[3]="def"; -} - diff --git a/addons/test/cert-test.cpp b/addons/test/cert-test.cpp deleted file mode 100644 index dc6e0129e2e..00000000000 --- a/addons/test/cert-test.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// To test: -// ~/cppcheck/cppcheck --dump cert-test.cpp && python ../cert.py -verify cert-test.cpp.dump - -#include - -class msc30TestClass { -public: - static int rand(); -}; - -namespace exp05c { - using uint32 = std::uint32_t; - static const uint32 a = static_cast(0xFFFFFFFF); -} - -void msc30(msc30TestClass & testClass) -{ - unsigned int num = rand(); // cert-MSC30-c - num = std::rand(); // cert-MSC30-c - num = msc30TestClass::rand(); - num = unknownClass::rand(); - num = testClass.rand(); - num = unknownClass.rand(); - int rand = 5; - int a = rand; -} diff --git a/addons/test/misra/config1.c b/addons/test/misra/config1.c new file mode 100644 index 00000000000..31aa2a4d6b5 --- /dev/null +++ b/addons/test/misra/config1.c @@ -0,0 +1,10 @@ + +struct S { + uint32_t some[100]; +}; + +void foo( void ) +{ + if (((S *)0x8000)->some[0] != 0U) { } +} + diff --git a/addons/test/misra/crash1.c b/addons/test/misra/crash1.c new file mode 100644 index 00000000000..d00a72c3aaa --- /dev/null +++ b/addons/test/misra/crash1.c @@ -0,0 +1,8 @@ + +struct expression { + int nargs; + struct expression *args[3]; +}; + +struct expression plvar = {0}; + diff --git a/addons/test/misra/crash10.c b/addons/test/misra/crash10.c new file mode 100644 index 00000000000..455d86e57ec --- /dev/null +++ b/addons/test/misra/crash10.c @@ -0,0 +1,12 @@ +//#12267 + +extern uint32_t end; + +//#define KEEP // if uncomment this then wont crash + +KEEP static const int32_t ptr_to_end = &end; + +void foo(void) +{ + (void)ptr_to_end; +} diff --git a/addons/test/misra/crash11.c b/addons/test/misra/crash11.c new file mode 100644 index 00000000000..b758e69f31e --- /dev/null +++ b/addons/test/misra/crash11.c @@ -0,0 +1,2 @@ +// #12651 +__arm__ diff --git a/addons/test/misra/crash12.c b/addons/test/misra/crash12.c new file mode 100644 index 00000000000..b16198ea2e7 --- /dev/null +++ b/addons/test/misra/crash12.c @@ -0,0 +1,33 @@ +// 13140 +#line 78 "tmp.h" +typedef struct +{ +int vara [30] ; +int varb [5] ; +} S0 ; + + + +typedef struct +{ +bool var1 ; +S2 var2 ; +S2 var3 ; +S2 var4 ; +short var5 ; +short var6 ; +S1 var7 ; +S1 var8 ; +S1 var9 ; +S1 var10 ; +S1 var11 ; +float var12 ; +short var13 [ 3 ] ; +} S3 ; + +#line 33 "tmp.c" +static const S3 s3 = +{ +0 , +{ 0, 0 } , +} ; \ No newline at end of file diff --git a/addons/test/misra/crash2.c b/addons/test/misra/crash2.c new file mode 100644 index 00000000000..c736a265d15 --- /dev/null +++ b/addons/test/misra/crash2.c @@ -0,0 +1,9 @@ + +// #11793 + +typedef struct pfmlib_pmu { + int flags ; + int (*get_event_encoding[10])(void* this, pfmlib_event_desc_t* e); +} pfmlib_pmu_t ; + +pfmlib_pmu_t sparc_ultra3_support = { .flags = 0 }; diff --git a/addons/test/misra/crash3.c b/addons/test/misra/crash3.c new file mode 100644 index 00000000000..19583f009a5 --- /dev/null +++ b/addons/test/misra/crash3.c @@ -0,0 +1,30 @@ + + + + +/* This is the representation of the expressions to determine the + plural form. */ +struct expression +{ + int nargs; /* Number of arguments. */ + union + { + unsigned long int num; /* Number value for `num'. */ + struct expression *args[3]; /* Up to three arguments. */ + } val; +}; + + +struct expression GERMANIC_PLURAL = +{ + .nargs = 2, + .val = + { + .args = + { + [0] = (struct expression *) &plvar, + [1] = (struct expression *) &plone + } + } +}; + diff --git a/addons/test/misra/crash4.c b/addons/test/misra/crash4.c new file mode 100644 index 00000000000..7862581849f --- /dev/null +++ b/addons/test/misra/crash4.c @@ -0,0 +1,11 @@ + +struct ConDesDesc { + unsigned Order; + unsigned Import; +}; + +// cppcheck-suppress misra-config +static ConDesDesc ConDes[CD_TYPE_COUNT] = { + { 0, 0 }, + { 0, 0 }, +}; diff --git a/addons/test/misra/crash5.c b/addons/test/misra/crash5.c new file mode 100644 index 00000000000..860101539da --- /dev/null +++ b/addons/test/misra/crash5.c @@ -0,0 +1,23 @@ + +struct _boardcnf_ch { + // cppcheck-suppress misra-config + uint8_t ddr_density[CS_CNT]; + uint64_t ca_swap; +}; + +struct _boardcnf { + + uint16_t dqdm_dly_r; + // cppcheck-suppress misra-config + struct _boardcnf_ch ch[DRAM_CH_CNT]; +}; + +static const struct _boardcnf boardcnfs[1] = { + { + 0x0a0, + { + { {0x02, 0x02}, 0x00345201 }, + { {0x02, 0x02}, 0x00302154 } + } + }, +}; diff --git a/addons/test/misra/crash6.c b/addons/test/misra/crash6.c new file mode 100644 index 00000000000..bf77e5f650b --- /dev/null +++ b/addons/test/misra/crash6.c @@ -0,0 +1,17 @@ + + +typedef struct _tGames +{ + char magicdirname[10]; + unsigned int expectedmask; + unsigned char pictureorder[3]; +} tGames; + +static const tGames games[1]={ + {"Pawn", 1, {0,1,2}} +}; + + + + + diff --git a/addons/test/misra/crash7.c b/addons/test/misra/crash7.c new file mode 100644 index 00000000000..210cfeb4df8 --- /dev/null +++ b/addons/test/misra/crash7.c @@ -0,0 +1,8 @@ + + +static const struct id3_frametype wordlist[] = +{ + {0, "Encryption method registration"}, + {1, "Popularimeter"}, +}; + diff --git a/addons/test/misra/crash8.c b/addons/test/misra/crash8.c new file mode 100644 index 00000000000..970d72540f0 --- /dev/null +++ b/addons/test/misra/crash8.c @@ -0,0 +1,10 @@ + +struct three_d_filter_t { + char name[16]; + double elem[2]; +}; + +static three_d_filter_t base_filters[] = { + {"Identity", { 1.0, 0.0 } }, + {"Echo", { 0.4, 0.0 } } +}; diff --git a/addons/test/misra/crash9.c b/addons/test/misra/crash9.c new file mode 100644 index 00000000000..5abf2b8ad02 --- /dev/null +++ b/addons/test/misra/crash9.c @@ -0,0 +1,3 @@ + +#line 3 "" +typedef int8_t flex_int8_t; diff --git a/addons/test/misra/crash_misra9_parseInitializer.c b/addons/test/misra/crash_misra9_parseInitializer.c new file mode 100644 index 00000000000..8e3dcfd5757 --- /dev/null +++ b/addons/test/misra/crash_misra9_parseInitializer.c @@ -0,0 +1,18 @@ +union { + struct { + uint8_t a; + uint8_t b; + } a; +} bar; + +struct foo { + uint8_t a; + union bar w; + uint8_t b; +}; + +struct foo asdf = { + 0, + {{0,0}}, + 1 +}; diff --git a/addons/test/misra/misra-ctu-1-test.c b/addons/test/misra/misra-ctu-1-test.c new file mode 100644 index 00000000000..a003e66ae01 --- /dev/null +++ b/addons/test/misra/misra-ctu-1-test.c @@ -0,0 +1,55 @@ +// Test with command: +// ./cppcheck --enable=information --enable=style --addon=misra --inline-suppr addons/test/misra/misra-ctu-*-test.c + +#include "misra-ctu-test.h" + +extern MISRA_2_3_A misra_2_3_a; + +x = MISRA_2_5_OK_1; + +// cppcheck-suppress misra-c2012-20.5 +#undef MISRA_2_5_OK_3 + +// cppcheck-suppress misra-c2012-2.3 +// cppcheck-suppress misra-c2012-5.6 +typedef int MISRA_5_6_VIOLATION; + +// cppcheck-suppress misra-c2012-5.7 +struct misra_5_7_violation_t { + int x; // cppcheck-suppress unusedStructMember +}; +static misra_5_7_violation_t misra_5_7_use_type_1; + +// #11443 - FP +static struct +{ // no warning + uint16_t x; // cppcheck-suppress unusedStructMember +} misra_5_7_false_positive_1; + +// cppcheck-suppress misra-c2012-8.4 +// cppcheck-suppress misra-c2012-5.8 +int misra_5_8_var1; +// cppcheck-suppress misra-c2012-8.4 +// cppcheck-suppress misra-c2012-5.8 +int misra_5_8_var2; +// cppcheck-suppress misra-c2012-5.8 +static void misra_5_8_f(void) {} + + +// cppcheck-suppress misra-c2012-5.9 +static int misra_5_9_count; +// cppcheck-suppress misra-c2012-5.9 +static void misra_5_8_foo(void) {} + +// cppcheck-suppress misra-c2012-8.5 +extern int misra_8_5; + +// cppcheck-suppress misra-c2012-8.4 +// cppcheck-suppress misra-c2012-8.6 +int32_t misra_8_6 = 1; + +void misra_8_7_external(void) {} + +// #12362 +void misra_8_7_compliant( void ){} +static void misra_8_7_call(void) { misra_8_7_compliant(); } \ No newline at end of file diff --git a/addons/test/misra/misra-ctu-2-test.c b/addons/test/misra/misra-ctu-2-test.c new file mode 100644 index 00000000000..e08bd6d04a7 --- /dev/null +++ b/addons/test/misra/misra-ctu-2-test.c @@ -0,0 +1,59 @@ +// Test with command: +// ./cppcheck --enable=information --enable=style --addon=misra --inline-suppr addons/test/misra/misra-ctu-*-test.c + +#include "misra-ctu-test.h" + +extern MISRA_2_3_B misra_2_3_b; + +x = MISRA_2_5_OK_2; + +// cppcheck-suppress misra-c2012-5.6 +typedef int MISRA_5_6_VIOLATION; +static MISRA_5_6_VIOLATION misra_5_6_x; + +// cppcheck-suppress misra-c2012-5.7 +struct misra_5_7_violation_t { + int x; // cppcheck-suppress unusedStructMember +}; +static misra_5_7_violation_t misra_5_7_use_type_2; + +// #11443 - FP +static struct +{ // no warning + uint16_t x; // cppcheck-suppress unusedStructMember +} misra_5_7_false_positive_2; + +// cppcheck-suppress misra-c2012-5.8 +static int misra_5_8_var1; +// cppcheck-suppress misra-c2012-8.4 +// cppcheck-suppress misra-c2012-5.8 +void misra_5_8_f(void) { + // cppcheck-suppress [misra-c2012-5.8, unusedVariable] + char misra_5_8_var2; +} + +// cppcheck-suppress misra-c2012-5.9 +static int misra_5_9_count; +// cppcheck-suppress misra-c2012-5.9 +static void misra_5_8_foo(void) {} + +// cppcheck-suppress misra-c2012-8.5 +extern int misra_8_5; + +// cppcheck-suppress misra-c2012-8.4 +// cppcheck-suppress misra-c2012-8.6 +int32_t misra_8_6 = 2; +int32_t misra_8_6_1; +// cppcheck-suppress misra-c2012-8.7 +int32_t misra_8_6_1 = 2; +// cppcheck-suppress misra-c2012-8.4 +// cppcheck-suppress misra-c2012-8.7 +void misra_8_7(void) {} +static void misra_8_7_caller(void) { + misra_8_7(); + misra_8_7_external(); +} + +// #12362 +typedef void(*misra_8_7_func_ptr)( void ); +static const misra_8_7_func_ptr ptrs[] = { misra_8_7_compliant, NULL }; \ No newline at end of file diff --git a/addons/test/misra/misra-ctu-test.h b/addons/test/misra/misra-ctu-test.h new file mode 100644 index 00000000000..803e850b1f2 --- /dev/null +++ b/addons/test/misra/misra-ctu-test.h @@ -0,0 +1,24 @@ + + +typedef int MISRA_2_3_A; +typedef int MISRA_2_3_B; +typedef int MISRA_2_3_VIOLATION; // cppcheck-suppress misra-c2012-2.3 + +// cppcheck-suppress misra-c2012-2.4 +struct misra_2_4_violation_t { + int x; +}; + +static inline void misra_5_9_exception(void) {} + +void misra_8_7_external(void); + +#define MISRA_2_5_OK_1 1 +#define MISRA_2_5_OK_2 2 +// cppcheck-suppress misra-c2012-2.5 +#define MISRA_2_5_VIOLATION 0 + +// #12362 +extern void misra_8_7_compliant( void ); + +#define MISRA_2_5_OK_3 This \ No newline at end of file diff --git a/addons/test/misra/misra-suppressions1-test.c b/addons/test/misra/misra-suppressions1-test.c index 59c77598e8f..403d71f73ea 100644 --- a/addons/test/misra/misra-suppressions1-test.c +++ b/addons/test/misra/misra-suppressions1-test.c @@ -4,15 +4,18 @@ // This needs to stay at line number 7 to make the test pass // If it is changed update suppressions.txt with the new line number +// cppcheck-suppress-file misra-c2012-5.2 #include //21.6 -extern int misra_5_2_var_hides_var______31x; +extern int misra_5_2_var_hides_var______31x;//8.4 static int misra_5_2_var_hides_var______31y;//5.2 static int misra_5_2_function_hides_var_31x; -void misra_5_2_function_hides_var_31y(void) {}//5.2 -void foo(void) +static void misra_5_2_function_hides_var_31y(void) {}//5.2 +static void foo(void) { int i; + // cppcheck-suppress-begin misra-c2012-16.4 + // cppcheck-suppress misra-c2012-16.6 switch(misra_5_2_func1()) //16.4 16.6 { case 1: @@ -21,13 +24,14 @@ void foo(void) { for(i = 0; i < 10; i++) { - if(misra_5_2_func3()) //14.4 + if(misra_5_2_func3()) //17.3 { int misra_5_2_var_hides_var_1____31x; int misra_5_2_var_hides_var_1____31y;//5.2 } } - } while(misra_5_2_func2()); //14.4 + } while(misra_5_2_func2()); //17.3 } } + // cppcheck-suppress-end misra-c2012-16.4 } diff --git a/addons/test/misra/misra-suppressions2-test.c b/addons/test/misra/misra-suppressions2-test.c index 7fadf186959..79d3f68191e 100644 --- a/addons/test/misra/misra-suppressions2-test.c +++ b/addons/test/misra/misra-suppressions2-test.c @@ -2,6 +2,7 @@ // ../../cppcheck --suppressions-list=suppressions.txt --dump misra-suppressions*-test.c && python ../misra.py misra-suppressions*-test.c.dump // There should be no violations reported +// cppcheck-suppress-file misra-c2012-5.2 union misra_5_2_field_hides_field__63x { //19.2 int misra_5_2_field_hides_field__31x; int misra_5_2_field_hides_field__31y;//5.2 @@ -10,5 +11,10 @@ struct misra_5_2_field_hides_field__63y { //5.2 int misra_5_2_field_hides_field1_31x; int misra_5_2_field_hides_field1_31y;//5.2 }; -const char *s41_1 = "\x41g"; // 4.1 -const char *s41_2 = "\x41\x42"; +const char *s41_1 = "\x41g"; // 4.1 8.4 +const char *s41_2 = "\x41\x42"; // 8.4 + +// cppcheck-suppress misra-c2012-5.7 +struct misra_5_7_violation_t { + int x; +}; diff --git a/addons/test/misra/misra-test-avr8.c b/addons/test/misra/misra-test-avr8.c new file mode 100644 index 00000000000..faa6eb6b615 --- /dev/null +++ b/addons/test/misra/misra-test-avr8.c @@ -0,0 +1,29 @@ +// To test: +// ~/cppcheck/cppcheck--dump -DDUMMY --suppress=uninitvar misra/misra-test-avr8.c --std=c89 --platform=avr8 && python3 ../misra.py -verify misra/misra-test-avr8.c.dump + +static void misra_10_4(void) +{ + // #10480 + const char buf1[1] = {a}; + const char c = '0'; + x = buf1[0] - c; + + const char buf2[2] = {x,y}; + x = 'a' == buf2[0]; // no-warning + + typedef struct { + int t; + char buf[2]; + } foo_t; + const foo_t cmd = {0}; + x = 'b' == cmd.buf[0]; // no-warning + + const foo_t * pcmd = &cmd; + x='c' == pcmd->buf[0]; // no-warning + (void)cmd.t; +} + +static void misra_12_2(void) { + a = (((uint64_t)0xFF) << 32); +} + diff --git a/addons/test/misra/misra-test-c11.c b/addons/test/misra/misra-test-c11.c new file mode 100644 index 00000000000..031bc361e5f --- /dev/null +++ b/addons/test/misra/misra-test-c11.c @@ -0,0 +1,25 @@ +// To test: +// ~/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 + +typedef unsigned int UINT_TYPEDEF; +struct struct_with_bitfields +{ + unsigned int a:2; // Compliant + signed int b:2; // Compliant + UINT_TYPEDEF c:2; // Compliant + int d:2; // 6.1 - plain int not compliant + signed long f:2; // Compliant in c99 or later - explicitly signed integer type + unsigned int g:1; // Compliant + signed int h:1; // 6.2 - signed int with size 1 is not compliant + uint16_t i:1; // Compliant + bool j:1; // Compliant in C99 or later +}; + +static void misra6_1_fn(void) { + // "Use" occurrence should not generate warnings + struct_with_bitfields s; + s.h = 61; +} diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index c6306db2940..2435dcf253a 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -1,6 +1,8 @@ // To test: // ~/cppcheck/cppcheck --dump misra/misra-test.h --std=c89 -// ~/cppcheck/cppcheck --dump --suppress=uninitvar --suppress=uninitStructMember misra/misra-test.c --std=c89 && python3 ../misra.py -verify misra/misra-test.c.dump +// ~/cppcheck/cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra/misra-test.c --std=c89 --platform=unix64 && python3 ../misra.py -verify misra/misra-test.c.dump + +#pragma ghs section rodata=default // no warning #include "path\file.h" // 20.2 #include "file//.h" // 20.2 @@ -35,12 +37,22 @@ #include // 21.4 #include // 21.5 -#include //21.6 -#include //21.6 +#include +#include #include // 21.10 #include // 21.11 #include +// Check that the addon doesn't crash +typedef struct { + union { // 19.2 + struct { + unsigned a : 2; + unsigned : 14; + }; + uint16_t value; + }; +} STRUCT_BITS; typedef unsigned char u8; typedef unsigned short u16; @@ -48,73 +60,85 @@ typedef unsigned int u32; typedef signed int s32; typedef unsigned long long u64; +static void misra_1_2(bool expr) +{ + (void)(condition ? : 0); // 1.2 + a = 1 + ({if (!expr) {code;} 1;}); // 1.2 +} + +static _Atomic int misra_1_4_var; // 1.4 +static _Noreturn void misra_1_4_func(void) // 1.4 +{ + if (0 != _Generic(misra_1_4_var)) {} // 1.4 17.3 + printf_s("hello"); // 1.4 17.3 +} + +#define MISRA_2_2 (1*60) + +static void misra_2_2(int x) { + int a; + a = x + 0; // 2.2 + a = 0 + x; // 2.2 + a = x * 0; // 2.2 + a = 0 * x; // 2.2 + a = x * 1; // 2.2 + a = 1 * x; // 2.2 + a = MISRA_2_2; + (void)a; +} + /* // */ // 3.1 /* /* */ // 3.1 //// +/* https://cppcheck.net */ // http://example.com // no warning -void misra_2_7_unused_param (int *param1, int unused_param) // 2.7 +static void misra_2_7_unused_param (int *param1, int unused_param) // 2.7 { *param1 = 42U; } -void misra_2_7_used_params (int *param1, int param2, int param3) +static void misra_2_7_used_params (int *param1, int param2, int param3) { (void)param3; *param1 = param2; } -void misra_2_7_a(int a, - int b, // 2.7 - int c, - int d) // 2.7 +static void misra_2_7_a(int a, + int b, // 2.7 + int c, + int d) // 2.7 { (void)a; (void)c; } -void misra_2_7_b(int a, int b, int c, // 2.7 - int d) // 2.7 +static void misra_2_7_b(int a, int b, int c, // 2.7 + int d) // 2.7 { (void)a; } -void misra_2_7_c(int a, ...) { (void)a; } -void misra_2_7_d(int) { } // 2.7 8.2 - -void misra_3_2(int enable) -{ - // This won't generate a violation because of subsequent blank line \ - - int y = 0; - int x = 0; // 3.2 non-compliant comment ends with backslash \ - if (enable != 0) - { - ++x; // This is always executed - // 3.2 potentially non-compliant comment ends with trigraph resolved to backslash ??/ - ++y; // This is hidden if trigraph replacement is active - } - - (void)printf("x=%i, y=%i\n", x, y); -} +static void misra_2_7_c(int a, ...) { (void)a; } +static void misra_2_7_d(int) { } // 2.7 8.2 extern int misra_5_1_extern_var_hides_var_x; extern int misra_5_1_extern_var_hides_var_y; //5.1 -int misra_5_1_var_hides_var________a; -int misra_5_1_var_hides_var________b; int misra_5_1_var_hides_var________b1; int misra_5_1_var_hides_var________b2; //5.1 -int misra_5_1_var_hides_var________c; //5.1 -int misra_5_1_var_hides_var________d; //5.1 -int misra_5_1_var_hides_var________e; //5.1 +int misra_5_1_var_hides_var________a; // 8.4 +int misra_5_1_var_hides_var________b; int misra_5_1_var_hides_var________b1; int misra_5_1_var_hides_var________b2; //5.1 8.4 +int misra_5_1_var_hides_var________c; //5.1 8.4 +int misra_5_1_var_hides_var________d; //5.1 8.4 +int misra_5_1_var_hides_var________e; //5.1 8.4 extern const uint8_t misra_5_2_var1; -const uint8_t misra_5_2_var1 = 3; // no warning +const uint8_t misra_5_2_var1 = 3; static int misra_5_2_var_hides_var______31x; static int misra_5_2_var_hides_var______31y;//5.2 static int misra_5_2_function_hides_var_31x; -void misra_5_2_function_hides_var_31y(void) {}//5.2 -void foo(void) +static void misra_5_2_function_hides_var_31y(void) {}//5.2 +static void foo(void) { int i; - switch(misra_5_2_func1()) //16.4 16.6 + switch(misra_5_2_func1()) //16.4 16.6 17.3 { case 1: { @@ -122,14 +146,15 @@ void foo(void) { for(i = 0; i < 10; i++) { - if(misra_5_2_func3()) //14.4 + if(misra_5_2_func3()) //17.3 { int misra_5_2_var_hides_var_1____31x; int misra_5_2_var_hides_var_1____31y;//5.2 } } - } while(misra_5_2_func2()); //14.4 + } while(misra_5_2_func2()); //17.3 } + break; } } @@ -141,46 +166,46 @@ struct misra_5_2_field_hides_field__63y { //5.2 int misra_5_2_field_hides_field1_31x; int misra_5_2_field_hides_field1_31y;//5.2 }; -const char *s41_1 = "\x41g"; // 4.1 -const char *s41_2 = "\x41\x42"; -const char *s41_3 = "\x41" "\x42"; -const char *s41_4 = "\x41" "g"; -const char *s41_5 = "\x41\xA"; -const char *s41_6 = "\xA\x41"; -const char *s41_7 = "\xAA\xg\x41"; // 4.1 -const char *s41_8 = "\xAA\x\x41"; // 4.1 -const char *s41_9 = "unknown\gsequence"; -const char *s41_10 = "simple\nsequence"; -const char *s41_11 = "string"; -int c41_3 = '\141t'; // 4.1 -int c41_4 = '\141\t'; -int c41_5 = '\0'; -int c41_6 = '\0\t'; -int c41_7 = '\12\t'; -int c41_8 = '\0t'; // 4.1 -int c41_9 = '\12'; -int c41_10 = '\12\n'; -int c41_11 = '\12n'; // 4.1 -int c41_12 = '\12323'; // 4.1 -int c41_13 = '\123\3'; +const char *s41_1 = "\x41g"; // 4.1 8.4 +const char *s41_2 = "\x41\x42"; // 8.4 +const char *s41_3 = "\x41" "\x42"; // 8.4 +const char *s41_4 = "\x41" "g"; // 8.4 +const char *s41_5 = "\x41\xA"; // 8.4 +const char *s41_6 = "\xA\x41"; // 8.4 +const char *s41_7 = "\xAA\xg\x41"; // 4.1 8.4 +const char *s41_8 = "\xAA\x\x41"; // 4.1 8.4 +const char *s41_9 = "unknown\gsequence"; // 8.4 +const char *s41_10 = "simple\nsequence"; // 8.4 +const char *s41_11 = "string"; // 8.4 +int c41_3 = '\141t'; // 4.1 8.4 +int c41_4 = '\141\t'; // 8.4 +int c41_5 = '\0'; // 10.3 8.4 +int c41_6 = '\0\t'; // 8.4 +int c41_7 = '\12\t'; // 8.4 +int c41_8 = '\0t'; // 4.1 8.4 +int c41_9 = '\12'; // 8.4 +int c41_10 = '\12\n'; // 8.4 +int c41_11 = '\12n'; // 4.1 8.4 +int c41_12 = '\12323'; // 4.1 8.4 +int c41_13 = '\123\3'; // 8.4 // TODO int c41_14 = '\777\777'; -int c41_15 = 'a'; +int c41_15 = 'a'; // 10.3 8.4 -void misra_4_1(void) +static void misra_4_1(void) { - (void)printf("\x41g"); // 4.1 - (void)printf("\x41\x42"); - (void)printf("\x41" "g"); + (void)printf("\x41g"); // 4.1 21.6 + (void)printf("\x41\x42"); //21.6 + (void)printf("\x41" "g"); //21.6 } -const char *s42_1 = "String containing trigraphs ??-??-??"; // 4.2 -const char *s42_2 = "String containing trigraph???=preceded by question mark"; // 4.2 -const char *s42_3 = "No trigraph?(?'?)"; +const char *s42_1 = "String containing trigraphs ??-??-??"; // 4.2 8.4 +const char *s42_2 = "String containing trigraph???=preceded by question mark"; // 4.2 8.4 +const char *s42_3 = "No trigraph?(?'?)"; // 8.4 -void misra_4_2(void) +static void misra_4_2(void) { - (void)printf("??=Trigraph\n"); // 4.2 - (void)printf("No?/Trigraph\n"); + (void)printf("??=Trigraph\n"); // 4.2 21.6 + (void)printf("No?/Trigraph\n"); //21.6 } #define misra_5_4_macro_hides_macro__31x 1 @@ -200,25 +225,26 @@ void misra_4_2(void) #define misra_5_5_tag_hides_macro____31x 1 #define misra_5_5_hides_macro________31x 1 -int misra_5_5_var_hides_macro____31y; //5.5 -void misra_5_5_functionhides_macro31y(int misra_5_5_param_hides_macro__31y){(void)misra_5_5_param_hides_macro__31y;} //5.5 +int misra_5_5_var_hides_macro____31y; //5.5 8.4 +static void misra_5_5_functionhides_macro31y(int misra_5_5_param_hides_macro__31y){(void)misra_5_5_param_hides_macro__31y;} //5.5 struct misra_5_5_tag_hides_macro____31y { //5.5 int x; }; -void misra_5_5_func1(void) +static void misra_5_5_func1(void) { - switch(misra_5_5_func2()) //16.4 16.6 + switch(misra_5_5_func2()) //16.4 16.6 17.3 { case 1: { do { - if(misra_5_5_func3()) //14.4 + if(misra_5_5_func3()) //17.3 { int misra_5_5_hides_macro________31y; //5.5 } - } while(misra_5_5_func2()); //14.4 + } while(misra_5_5_func2()); //17.3 } + break; } } @@ -232,43 +258,27 @@ struct struct_with_bitfields signed long f:2; // 6.1 - signed long not compliant unsigned int g:1; // Compliant signed int h:1; // 6.2 - signed int with size 1 is not compliant + uint16_t i:1; // Compliant + bool j:1; // 6.1 - bool not legal until c99 }; -void misra6_1_fn(void) { +static void misra6_1_fn(void) { // "Use" occurrence should not generate warnings struct_with_bitfields s; s.h = 61; } -void misra_7_1(void) { +static void misra_7_1(void) { int x = 066; // 7.1 } -void misra_7_2_call_test(int a, unsigned int b, unsigned int c) { } // 2.7 - -void misra_7_2_call_va_test(int a, ...) { } // 2.7 - -void misra_7_2(void) { - unsigned int a = 2147483647; - const unsigned int b = 2147483648U; - const unsigned int c = 2147483648; // 7.2 - unsigned int d = 2147483649; // 7.2 - - unsigned char e = 0x80; // 7.2 - unsigned char f = 0x80U; - unsigned short g = 0x8000; // 7.2 - unsigned short h = 0x8000U; - unsigned int i = 0x80000000; // 7.2 - unsigned int j = 0x80000000U; - unsigned long long k = 0x8000000000000000; // TODO 7.2 - unsigned long long l = 0x8000000000000000ULL; - - unsigned int m = 1 + 0x80000000; // 7.2 10.4 - - misra_7_2_call_test(1, 2, 2147483648U); - misra_7_2_call_test(1, 2, 2147483648); // 7.2 - misra_7_2_call_test(1, 0x80000000, 3); // 7.2 - misra_7_2_call_va_test(1, 2, 3); +static void misra_7_2(void) { + uint32_t a = 0x7fffffff; + uint32_t b = 0x80000000; // 7.2 + uint32_t c = 0x80000000U; + uint32_t d = 2147483647; + uint64_t e = 2147483648; + uint32_t f = 2147483648U; } // The addon should not generate false positives for the identifiers. @@ -276,9 +286,23 @@ struct misra_7_3_s { uint32_t ul_clka; uint32_t test123l; + float t = 6.02E23l; // 7.3 + float t1 = 6.02E23L; + float u = 0xa1B2.p12l; // 7.3 + float u1 = 0xa1B2.p12L; + float v = 0xa1B2.P12l; // 7.3 + float v1 = 0xa1B2.P12L; + float w = 6.02e23l; // 7.3 + float w1 = 6.02e23L; + unsigned long x = 0xabcul; // 7.3 + unsigned long x1 = 0xabcuL; + unsigned long y = 0xABCUl; // 7.3 + unsigned long y1 = 0xABCUL; + unsigned long z = 0XdeadBeEfUl; // 7.3 + unsigned long z1 = 0XdeadBeEfUL; }; -void misra_7_3(void) { +static void misra_7_3(void) { long misra_7_3_a = 0l; //7.3 long misra_7_3_b = 0lU; //7.3 long long misra_7_3_c = 0Ull; //7.3 @@ -292,15 +316,16 @@ void misra_7_3(void) { } typedef const char* MISRA_7_4_CHAR_CONST; -MISRA_7_4_CHAR_CONST misra_7_4_return_const_type_def (void) { return "return_typedef_const"; } -char *misra_7_4_return_non_const (void) { return 1 + "return_non_const"; } // 7.4 18.4 -const char *misra_7_4_return_const (void) { return 1 + "return_const"; } // 18.4 +static MISRA_7_4_CHAR_CONST misra_7_4_return_const_type_def (void) { return "return_typedef_const"; } +static char *misra_7_4_return_non_const (void) { return 1 + "return_non_const"; } // 7.4 18.4 +static const char *misra_7_4_return_const (void) { return 1 + "return_const"; } // 18.4 -void misra_7_4_const_call(int a, const char* b) { } // 2.7 -void misra_7_4_const_ptr_call(int a, const char const* b) { } // 2.7 -void misra_7_4_call(int a, char* b) { } // 2.7 +static void misra_7_4_const_call(int a, const char* b) { } // 2.7 +static void misra_7_4_const_ptr_call(int a, const char const* b) { } // 2.7 +static void misra_7_4_call(int a, char* b) { } // 2.7 +static void misra_7_4_call_2(int a, ...) { } // 2.7 -void misra_7_4(void) +static void misra_7_4(void) { const char *a = "text a"; char* const b = "text_b"; // 7.4 @@ -314,8 +339,11 @@ void misra_7_4(void) misra_7_4_const_call(1, ("text_const_call")); misra_7_4_const_ptr_call(1, ("text_const_call")); misra_7_4_call(1, "text_call"); // 7.4 11.8 + misra_7_4_call_2(1, "a", "b"); } +const misra_8_1_a; // 8.1 8.4 + static int misra_8_2_a (int n, ...); extern int misra_8_2_b (int n); extern int misra_8_2_c (int); // 8.2 @@ -331,32 +359,59 @@ static int misra_8_2_g ( /* comment */ ); // 8.2 static int misra_8_2_h ( /* comment 1 */ /* comment 2 */ ); // 8.2 static int misra_8_2_i ( /* comment */ void); static int misra_8_2_j ( /* comment */ void /* comment */); -static int misra_8_2_k ( // +static int misra_8_2_k ( // void); static int misra_8_2_l ( // 8.2 ); -void misra_8_2_m(uint8_t * const x); -void misra_8_2_m(uint8_t * const x) +static void misra_8_2_m(uint8_t * const x); +static void misra_8_2_m(uint8_t * const x) { (void)x; } -int16_t ( *misra_8_2_p_a ) (); // 8.2 -int16_t ( *misra_8_2_p_b ) (void); -int16_t ( *misra_8_2_p_c ) (int); -int misra_8_2_n(int a) +int16_t ( *misra_8_2_p_a ) (); // 8.2 8.4 +int16_t ( *misra_8_2_p_b ) (void); // 8.4 +int16_t ( *misra_8_2_p_c ) (int); // 8.4 +static int misra_8_2_n(int a) { return a + 42; } -int misra_8_2_o( +static int misra_8_2_o( const uint32_t a1, const uint8_t *const a2 ) { return *a2 + a1; } -int misra_8_2_p( +static int misra_8_2_p( const uint32_t a1, const uint8_t *const a2 ); -int misra_8_2_q +static int misra_8_2_q (); // 8.2 +void misra_8_4_foo(void) {} // 8.4 +extern void misra_8_4_func(void); +void misra_8_4_func(void) {} +static void misra_8_4_bar(void) {} // Declared in header +extern int16_t misra_8_4_count; // no-warning +int16_t misra_8_4_count = 0; // Compliant +extern uint8_t misra_8_4_buf1[13]; // no-warning +uint8_t misra_8_4_buf2[24]; // 8.4 +typedef struct { uint16_t a; uint16_t b; } misra_8_4_struct; +extern misra_8_4_struct bar[42]; +misra_8_4_struct bar[42]; // compliant +extern uint16_t misra_8_4_speed = 6000u; //8.4 +uint8_t misra_8_4_pressure = 101u; //8.4 +int32_t misra_8_4_ext_val2; +int32_t misra_8_4_ext_val2 = 3; // compliant +int32_t misra_8_4_ext_val4; //8.4 +// #12978 +const stError_t * m8_4_pubTestPointer; //compliant + +static int32_t misra_8_8 = 123; +extern int32_t misra_8_8; // 8.8 + +static int32_t misra_8_9_i; // 8.9 +static int32_t misra_8_9_foo(void) { return misra_8_9_i++; } + +inline int32_t misra_8_10_value(void) { return 123; } // 8.10 8.4 + extern int a811[]; // 8.11 enum misra_8_12_a { misra_a1 = 1, misra_a2 = 2, misra_a3, misra_a4 = 3 }; //8.12 @@ -365,9 +420,28 @@ enum misra_8_12_c { misra_c1 = misra_a1, misra_c2 = 1 }; // no-warning enum misra_8_12_d { misra_d1 = 1, misra_d2 = 2, misra_d3 = misra_d1 }; // no-warning enum misra_8_12_e { misra_e1 = sizeof(int), misra_e2}; // no-crash -void misra_8_14(char * restrict str) {(void)str;} // 8.14 +static void misra_8_14(char * restrict str) {(void)str;} // 8.14 -void misra_9_empty_or_zero_initializers(void) { +// #11707 -- false positive +struct S_9_3 { struct S_9_3* p; int x; }; +struct S_9_3* s_9_3_array[] = { x, NULL }; // 8.4 + +// #10854 +struct Entry_9_2{ + union{ // 19.2 + const int *p; + int x; + }; + int y; +}; + +static void misra_9_2_10854(void){ + struct Entry_9_2 e1[] = + { + {{ .x = 1 }, .y = 2 } + }; +} +static void misra_9_empty_or_zero_initializers(void) { int a[2] = {}; // 9.2 int b[2][2] = {}; // 9.2 int c[2][2] = { {} }; // 9.2 9.3 @@ -375,6 +449,10 @@ void misra_9_empty_or_zero_initializers(void) { int e[2][2] = { { 1 , 2 }, {} }; // 9.2 int f[5] = { 0 }; + int f1[5] = { 0u }; // 9.3 + unsigned int f1[ 3 ][ 2 ] = { 0U }; // 9.3 9.2 + unsigned int f2[ 3 ] = { 0U }; // 9.3 + float f3[ 3 ][ 2 ] = { 0.0F }; // 9.3 9.2 int g[5][2] = { 0 }; int h[2][2] = { { 0 } }; // 9.3 int i[2][2] = { { 0 }, { 0 } }; @@ -391,7 +469,7 @@ void misra_9_empty_or_zero_initializers(void) { struct1 n = { 0 }; } -void misra_9_string_initializers(void) { +static void misra_9_string_initializers(void) { const char a[12] = { "Hello world" }; // 9.2 const char b[2][20] = "Hello world"; // 9.2 9.3 const char c[] = "Hello world"; @@ -408,7 +486,7 @@ void misra_9_string_initializers(void) { char **j[1] = { { str_p } }; // 9.2 } -void misra_9_array_initializers(void) { +static void misra_9_array_initializers(void) { char a[4] = { 1, 2, 3, 4 }; char b[2][2] = { {1, 2}, {3, 4} }; char c[2][2] = { 1, 2, 3, 4 }; // 9.2 @@ -425,12 +503,13 @@ void misra_9_array_initializers(void) { char l[3] = { 1, { 2, 3 } }; // 9.2 9.3 } -void misra_9_array_initializers_with_designators(void) { +static void misra_9_array_initializers_with_designators(void) { char a[1] = { [0][1] = 1 }; // 9.2 char b[1] = { [0] = { 1, 2 } }; // 9.2 char c[2][2] = { [0] = {1, 2, 3} }; char d[1][2] = { [0] = 1 }; // 9.2 char e[2][2] = { { 1, 2 }, [1][0] = {3, 4} }; // 9.2 + int e1[2][2] = { [ 0 ][ 1 ] = 0, { 5, 6 } }; // no warning #12419 char f[2] = { [0] = 1, 2 }; char g[2] = { [1] = 2, [0] = 1 }; char h[2][2] = { { 1, 2 }, [1] = { 3 } }; // 9.3 @@ -442,6 +521,7 @@ void misra_9_array_initializers_with_designators(void) { char n[2][2] = { [0] = { 1 } }; // 9.3 char o[2][2] = { { 1 }, [1][0] = 3 }; // 9.3 char p[2][2] = { { 1, 2 }, { 3, 4 }, [1] = { 3 } }; // 9.3 9.4 + // cppcheck-suppress unknownEvaluationOrder char q[2][2] = { { 1, 2 }, { 1 }, [1] = { [1] = 3 } }; // 9.4 char r[2][2][2] = { [0][0] = { 1, 2 }, [1] = { [0] = {5, 6} } }; char s[2][2][2] = { [0][0] = { 1, 2 }, [1] = {5, 6, 7, 8}}; // 9.2 @@ -450,7 +530,7 @@ void misra_9_array_initializers_with_designators(void) { char v[2][2][2] = { [0] = { 1, 2, [1] = {3, 4} }}; // 9.2 } -void misra_9_struct_initializers(void) { +static void misra_9_struct_initializers(void) { typedef struct { int i1; int i2; @@ -526,13 +606,13 @@ void misra_9_struct_initializers(void) { // Struct with fields of unknown type struct_with_unknown_fields ufa = { 1, { 1, 2 }, { 1, 2 } }; struct_with_unknown_fields ufb = { 1, 1, 2 }; // 9.2 - struct_with_unknown_fields[2] ufc = { {1, { 1, 2 }, { 1, 2 } }, + struct_with_unknown_fields ufc[2] = { {1, { 1, 2 }, { 1, 2 } }, { 2, { 1, 2 }, { 1, 2 } } }; - struct_with_unknown_fields[2][2] ufd = { {1, { 1, 2 }, { 1, 2 } }, + struct_with_unknown_fields ufd[2][2] = { {1, { 1, 2 }, { 1, 2 } }, // 9.2 9.3 { 2, { 1, 2 }, { 1, 2 } } }; - struct_with_unknown_fields[2] ufe = { 1, { 1, 2 }, { 1, 2 }, // TODO: 9.2 + struct_with_unknown_fields ufe[2] = { 1, { 1, 2 }, { 1, 2 }, // 9.2 9.3 2, { 1, 2 }, { 1, 2 } }; - struct_with_unknown_fields[3] uff = { { 1, { 1, 2 }, { 1, 2 }}, // TODO: 9.3 9.4 + struct_with_unknown_fields uff[3] = { { 1, { 1, 2 }, { 1, 2 }}, // 9.3 9.4 {2, { 1, 2 }, { 1, 2 }}, [1] = { 2, { 1, 2 }, { 1, 2 }} }; @@ -540,18 +620,14 @@ void misra_9_struct_initializers(void) { struct1 os1 = { i1: 1, i2: 2 }; // 10.4 13.4 } -void misra_9_broken_initializers(void) { - char a[UNKNOWN_MACRO] = { 19, 23, 0 }; // 18.8 -} - -void misra_9_2(void) { +static void misra_9_2(void) { union misra_9_2_union { // 19.2 char c; struct1 i; } u = { 3 }; // 19.2 } -void misra_9_5(void) { +static void misra_9_5(void) { char a[] = { 1, 2, 3 }; char b[] = { [2] = 5 }; // 9.5 char c[] = { 1, [1] = 5 }; // 9.5 @@ -565,7 +641,7 @@ void misra_9_5(void) { typedef char misra_10_1_char_t; #define MISRA_10_1_CHAR char -void misra_10_1(uint8_t u, char c1, char c2) { +static void misra_10_1(uint32_t u, char c1, char c2, uint8_t u8) { int32_t i; char c; enum { E1 = 1 }; @@ -573,7 +649,7 @@ void misra_10_1(uint8_t u, char c1, char c2) { i = (u & u) << 4; // no-warning c = c1 & c2; // 10.1 c = c1 << 1; // 10.1 - i = c1 > c2; // no-warning + i = c1 > c2; // 10.3 i = E1 + i; // no-warning char ch1 = 'a'; @@ -590,8 +666,10 @@ void misra_10_1(uint8_t u, char c1, char c2) { MISRA_10_1_CHAR cd2 = 'b'; MISRA_10_1_CHAR cd3; cd3 = cd1 & cd2; // 10.1 + + uint8_t temp1 = u8 & 0x42U; // no-warning } -void misra_10_1_ternary(void) +static void misra_10_1_ternary(void) { int a; uint8_t ui8; @@ -600,42 +678,57 @@ void misra_10_1_ternary(void) int16_t i16; a = ui16 << ui16; // 10.6 - a = ui16 << (get_bool(42) ? ui16 : ui16); - a = ui16 << (get_bool(42) ? ui16 : (get_bool(34) ? ui16 : ui16)); // 10.4 - a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui16) : ui16); // 10.4 - a = ui16 << (get_bool(42) ? i16 : (get_bool(34) ? ui16 : ui16)); // 10.1 - a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : i16) : ui16); // 10.1 10.4 - a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui16) : i16); // 10.1 - a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8); // 10.4 - a = ui16 << (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8); // 10.1 10.4 - a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << ui16; // 10.4 - a = (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8) << ui16; // 10.1 10.4 - a = (get_bool(42) ? (get_bool(34) ? ui16 : i8) : ui8) << ui16; // 10.1 10.4 - a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : i8) << ui16; // 10.1 - a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << (get_bool(19) ? ui16 : ui8); // 10.4 - a = (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8) << (get_bool(19) ? ui16 : ui8); // 10.1 10.4 - a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << (get_bool(19) ? i16 : ui8); // 10.1 10.4 -} - -void misra_10_2(void) { - unsigned int u8a = 0; - signed char cha = 0; - signed int s8a = 0; - signed short s16a = 0; + a = ui16 << (get_bool(42) ? ui16 : ui16); // 17.3 + a = ui16 << (get_bool(42) ? ui16 : (get_bool(34) ? ui16 : ui16)); // 17.3 + a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui16) : ui16); // 17.3 + a = ui16 << (get_bool(42) ? i16 : (get_bool(34) ? ui16 : ui16)); // 10.1 10.4 17.3 + a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : i16) : ui16); // 10.1 10.4 17.3 + a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui16) : i16); // 10.1 10.4 17.3 + a = ui16 << (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8); // 10.4 17.3 + a = ui16 << (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8); // 10.1 10.4 17.3 + a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << ui16; // 10.4 17.3 + a = (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8) << ui16; // 10.1 10.4 17.3 + a = (get_bool(42) ? (get_bool(34) ? ui16 : i8) : ui8) << ui16; // 10.1 10.4 17.3 + a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : i8) << ui16; // 10.1 17.3 + a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << (get_bool(19) ? ui16 : ui8); // 10.4 17.3 + a = (get_bool(42) ? (get_bool(34) ? i16 : ui8) : ui8) << (get_bool(19) ? ui16 : ui8); // 10.1 10.4 17.3 + a = (get_bool(42) ? (get_bool(34) ? ui16 : ui8) : ui8) << (get_bool(19) ? i16 : ui8); // 10.1 10.4 17.3 +} + +static void misra_10_2(void) { + uint8_t u8a = 0; + char cha = 0; + int8_t s8a = 0; + int16_t s16a = 0; float f32a = 0.0; char res; - res = '0' + u8a; // 10.4 + res = '0' + u8a; // Convert u8a to digit res = s8a + '0'; res = cha - '0'; res = '0' - s8a; - res = cha + ':'; + res = cha + ':'; // 10.2 - res = s16a - 'a'; // 10.2 + res = s16a - 'a'; // 10.2 10.3 10.4 res = '0' + f32a; // 10.2 10.4 + + // 10481 - crash + char buf[1] = {'f'}; + x = buf[0] - '0'; +} + +static void misra_10_3(uint32_t u32a, uint32_t u32b) { + uint8_t res; + res = u32a + u32b; // 10.3 + res = (uint16_t)(2U + 3U); // 10.3 10.8 + res = 2U + 3U; // no warning, utlr=unsigned char + res = 0.1f; // 10.3 + const char c = '0'; // no-warning + bool b = true; // no-warning + uint32_t u = UINT32_C(10); // 17.3 no-warning } -void misra_10_4(u32 x, s32 y) { +static void misra_10_4(u32 x, s32 y) { z = x + 3; // 10.4 enum misra_10_4_enuma { misra_10_4_A1, misra_10_4_A2, misra_10_4_A3 } a; enum misra_10_4_enumb { misra_10_4_B1, misra_10_4_B2, misra_10_4_B3 }; @@ -646,67 +739,143 @@ void misra_10_4(u32 x, s32 y) { z = x + y; //10.4 z = (a == misra_10_4_A3) ? x : y; //10.4 z = (a == misra_10_4_A3) ? y : y; // no-warning + + // #10499 + const char buf[10] = {0}; + if ('0' == buf[x]) // no-warning + { + } + + const struct foo_s{ + int t; + char buf[2]; + } cmd = {0}; + if ('\0' == cmd.buf[0]) //no-warning + { + } + + // #10652 + char c; + if ((char)'1' == c) {} // no warning + if ((unsigned char)'1' == c) {} //10.4 + if ((signed char)'1' == c) {} //10.4 +} + +static void misra_10_5(uint16_t x) { + // bool + res = (uint16_t) (x > 10u); // 10.5 + res = (bool) 1u; // no-warning + + // char <=> float + res = (char) 0.1f; + res = (float) 'x'; } -void misra_10_6(u8 x, u32 a, u32 b, char c1, char c2) { - u16 y = x+x; // 10.6 +struct misra_10_6_s { + unsigned int a:4; +}; +static void misra_10_6(u8 x, char c1, char c2) { + u16 y1 = x+x; // 10.6 + u16 y2 = (0x100u - 0x80u); // rhs is not a composite expression because it's a constant expression + int b = (y2 == y2) ? 0 : 1; // no-warning u16 z = ~u8 x ;//10.6 - u32 c = ( u16) ( u32 a + u32 b ); //10.6 - s32 i = c1 - c2; // FIXME: False positive for 10.6 (this is compliant). Trac #9488 + s32 i = c1 - c2; // 10.3 + struct misra_10_6_s s; + s.a = x & 1U; // no-warning (#10487) } -void misra_10_6_1(uint32_t *a, uint16_t b, uint16_t c) +static void misra_10_6_1(uint32_t *a, uint16_t b, uint16_t c) { *a = b + c ; // 10.6 } -void misra_10_8(u8 x, s32 a, s32 b) { +static void misra_10_7_f1(struct Timer *pSelf, uint32_t interval_ms); +static void misra_10_7(uint16_t u16a, uint16_t u16b) { + uint32_t u32a = 100u; + res = u32a * u16a + u16b; // 12.1 no-warning + res = (u32a * u16a) + u16b; // no-warning + res = u32a * ( ( uint32_t ) u16a + u16b ); // no-warning + res = u32a * (u16a + u16b); // 10.7 + u32a *= u16a + u16b; // 10.7 + u32a = ((uint32_t)4 * (uint32_t)2 * (uint32_t)4 ); // no-warning (#10488) + dostuff(&t, (2*60*1000)); // 17.3 no-warning +} + +static void misra_10_8(u8 x, s32 a, s32 b) { y = (u16)x; y = (u16)(x+x); // 10.8 y = (u16) (a + b) //10.8 } +int (*misra_11_1_p)(void); // 8.4 +void *misra_11_1_bad1 = (void*)misra_11_1_p; // 11.1 8.4 + +// #12172 +typedef void (*pfFunc_11_1)(uint32_t some); +extern pfFunc_11_1 data_11_1[10]; +void func_11_1(pfFunc_11_1 ptr){ //8.4 + data_11_1[index] = ptr; // no-warning +} + +struct misra_11_2_s; +struct misra_11_2_t; + +static struct misra_11_2_s * sp; +static struct misra_11_2_t * tp = sp; // 11.2 + struct Fred {}; struct Wilma {}; -void misra_11_3(u8* p, struct Fred *fred) { +static void misra_11_3(u8* p, struct Fred *fred) { x = (u64*)p; // 11.3 struct Wilma *wilma = (struct Wilma *)fred; // 11.3 } -void misra_11_4(u8*p) { +typedef struct { uint32_t something; } struct_11_4; +#define A_11_4 ((struct_11_4 *)0x40000U) // 11.4 + +static void misra_11_4(u8*p) { u64 y = (u64)p; // 11.4 u8 *misra_11_4_A = ( u8 * ) 0x0005;// 11.4 s32 misra_11_4_B; u8 *q = ( u8 * ) misra_11_4_B; // 11.4 - + dummy = A_11_4->something; // no-warning } -void misra_11_5(void *p) { +static void misra_11_5(void *p) { u16 *p16; x = (u8 *)p; // 11.5 p16 = p; // 11.5 } -void misra_11_6(void) { +static intptr_t get_intptr_constant(void) { return 456; } +static void misra_11_6(void) { void *p; + struct { + int i; + } s = { .i = 7 }; p = (void*)123; // 11.6 x = (u64)p; // 11.6 + p = (void*)(1+1);// 11.6 + p = (void*)get_intptr_constant(); // 11.6 + p = (void*)s.i; // 11.6 p = ( void * )0; // no-warning (void)p; // no-warning + // # 12184 + p = (void*)0U; // no-warning } -void misra_11_7(int *p, float f) { +static void misra_11_7(int *p, float f) { x = ( float ) p; //11.7 y = ( int * ) f; //11.7 } -void misra_11_7_extra(int *p, float f, bool b) { +static void misra_11_7_extra(int *p, float f, bool b) { (void) p; // no-warning (void) f; // no-warning (void) b; // no-warning } -char * misra_11_8_const(const char *str) {(void)str;} -char * misra_11_8(const char *str) { +static void misra_11_8_const(const char *str) {(void)str;} +static char * misra_11_8(const char *str) { (void)misra_11_8_const(str); // no-warning return (char *)str; // 11.8 } @@ -714,7 +883,7 @@ char * misra_11_8(const char *str) { #define MISRA_11_9_NULL_1 (1-1) #define MISRA_11_9_NULL_2 ( void * ) 0 #define MISRA_11_9_NULL_3 NULL -void misra_11_9(void) { +static void misra_11_9(void) { int *p1 = (5-5); //11.9 int *p2 = MISRA_11_9_NULL_2 ; // no-warning int *p3 = MISRA_11_9_NULL_3 ; // no-warning @@ -726,13 +895,13 @@ void misra_11_9(void) { } -void misra_12_1(void) { +static void misra_12_1(void) { sz = sizeof x + y; // 12.1 a = (b * c) + d; a = b << c + d; // 12.1 } -void misra_12_2(u8 x) { +static void misra_12_2(u8 x) { a = x << 8; // 12.2 } @@ -750,19 +919,19 @@ static struct misra_12_3_s1 misra_12_3_s1_inst = { }; typedef struct misra_12_3_s2 { int a; int b; int c, d; } misra_12_3_s2_t; // 12.3 typedef struct { int a; int b; int c, d; } misra_12_3_s3_t; // 12.3 -void misra_12_3_fn1(int, int); static int misra_12_3_v5, misra_12_4_v6; // 12.3 8.2 -void misra_12_3_fn2(int a, int b) // 2.7 +static void misra_12_3_fn1(int, int); static int misra_12_3_v5, misra_12_4_v6; // 12.3 8.2 +static void misra_12_3_fn2(int a, int b) // 2.7 { int d, e; } // 12.3 -int misra_12_3_fn3(int a, int b) { return a+b;} static int misra_12_3_v5, misra_12_4_v6; // 12.3 -void misra_12_3_fn4(const uint32_t value, uint8_t * const y) {} // 2.7 -uint32_t misra_12_3_fn5(const uint32_t * const, const uint8_t) {} // 2.7 8.2 +static int misra_12_3_fn3(int a, int b) { return a+b;} static int misra_12_3_v5, misra_12_4_v6; // 12.3 +static void misra_12_3_fn4(const uint32_t value, uint8_t * const y) {} // 2.7 +static void misra_12_3_fn5(const uint32_t * const, const uint8_t) {} // 2.7 8.2 extern void misra_12_3_fn6(const uint32_t value, uint8_t * const y); extern uint32_t misra_12_3_fn7(const uint32_t * const, const uint8_t); // 8.2 #define MISRA_12_3_FN3_1(A, B) (misra_12_3_fn3(A, B)) #define MISRA_12_3_FN3_2(A, B) (misra_12_3_fn3(A, \ B)) #define MISRA_12_3_FN3_2_MSG(x) x, fflush(stderr) -void misra_12_3(int, int, int); // 8.2 +static void misra_12_3(int, int, int); // 8.2 void misra_12_3(int a, int b, int c) { int a1, a2; // 12.3 int a3; int a4; // no warning @@ -788,16 +957,18 @@ void misra_12_3(int a, int b, int c) { struct misra_12_3_s2 a32, a33; // 12.3 struct misra_12_3_s2 a34, a35 = {1, 2}, a36; // 12.3 + // cppcheck-suppress uninitStructMember int a37 = MISRA_12_3_FN3_1(a34, a35), a38; // 12.3 int a39, a40 = MISRA_12_3_FN3_1(a34, a35); // 12.3 int a41 = MISRA_12_3_FN3_2(a34, a35), a42; // 12.3 int a43, a44 = MISRA_12_3_FN3_2(a34, a35); // 12.3 - MISRA_12_3_FN3_2_MSG(fprintf(stderr, "test\n")); // 12.3 - - f((1,2),3); // TODO + MISRA_12_3_FN3_2_MSG(fprintf(stderr, "test\n")); // 12.3 21.6 + // TODO + f((1,2),3); // 17.3 - for (i=0; i<10; i++, j++){} // 12.3 + // third clause: 2 persistent side effects instead of 1 (14.2) + for (i=0; i<10; i++, j++){} // 12.3 14.2 for (int i = 0, p = &a1; // 12.3 14.2 i < 42; ++i, ++p ) // 12.3 @@ -808,8 +979,8 @@ void misra_12_3(int a, int b, int c) { misra_12_3_fn4(misra_12_3_fn7(&a1, 32), &a1); misra_12_3_fn6(misra_12_3_fn5(&a1, 32), &a1); misra_12_3_fn6(misra_12_3_fn7(&a1, 32), &a1); - misra_12_3_fn7(maxlen, fn(va, unsigned long), false); - misra_12_3_fn8(maxlen, (unsigned long)((uintptr_t)fn(va, void*)), false); + misra_12_3_fn7(maxlen, fn(va, unsigned long), false); // 17.3 + misra_12_3_fn8(maxlen, (unsigned long)((uintptr_t)fn(va, void*)), false); // 17.3 const struct fun_t { @@ -824,22 +995,20 @@ void misra_12_3(int a, int b, int c) { #define MISRA12_4a 2000000000u #define MISRA12_4b 4000000000u -#define volatile_macro_12_4 (*(volatile U32 *) 0xFFFFFC10u) -void misra_12_4(void) { - uint32_t x; - bool t; - x = 123456u * 123456u; // TODO 12.4 - x = MISRA12_4a + MISRA12_4b; // TODO 12.4 - x = 0u - 1u; // TODO 12.4 - x = t ? 0u : (0u-1u); // TODO 12.4 - x = 556200230913ULL; - foo(&volatile_macro_12_4); // no crash +static void misra_12_4(uint8_t t) { + x = 123456u * 123456u; // 12.4 + x = MISRA12_4a + MISRA12_4b; // 12.4 + x = 0u - 1u; // 12.4 + x = t ? 0u : (0u-1u); // 12.4 + x = (0u==0u) ? 0u : (0u-1u); + x = (0u!=0u) ? 0u : (0u-1u); // 12.4 + x = (0u==0u) ? 0u : (2*(0u-1u)); // 10.4 } struct misra_13_1_t { int a; int b; }; -uint8_t misra_13_1_x = 0; -void misra_13_1_bar(uint8_t a[2]); -void misra_13_1(int *p) { +uint8_t misra_13_1_x = 0; // 8.4 +static void misra_13_1_bar(uint8_t a[2]); +static void misra_13_1(int *p) { volatile int v; int a1[3] = {0, (*p)++, 2}; // 13.1 int a2[3] = {0, ((*p) += 1), 2}; // 13.1 @@ -876,7 +1045,141 @@ void misra_13_1(int *p) { struct misra_13_1_t c14 = { (*p)/=(int)(4.5) }; // 13.1 } -void misra_13_3(void) { +// Large arrays for R13.1. Size exceeds default Python's max recursion depth. +static uint8_t misra_13_1_large_ok[1024] = { +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static uint8_t misra_13_1_large_bad[1024] = { // 13.1 +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, i++, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static void misra_13_3(void) { x = y++; // 13.3 } @@ -892,12 +1195,15 @@ static s13_4_t s13_4 = .string = STRING_DEF_13_4 // no-warning }; -void misra_13_4(void) { +static void misra_13_4(int x, int z) { + int y; if (x != (y = z)) {} // 13.4 else {} } -void misra_13_5(void) { +static void misra_13_5(void) { + int x = 0; + int y = 0; if (x && (y++ < 123)){} // 13.5 if (x || ((y += 19) > 33)){} // 13.5 if (x || ((y = 25) > 33)){} // 13.5 13.4 @@ -905,13 +1211,13 @@ void misra_13_5(void) { else {} } -void misra_13_6(void) { +static void misra_13_6(void) { int a = sizeof(x|=42); // 13.6 a = sizeof(--x); // 13.6 13.3 return sizeof(x++); // 13.6 } -void misra_14_1(void) { +static void misra_14_1(void) { for (float f=0.1f; f<1.0f; f += 0.1f){} // 14.1 float a = 0.0f; int b = 10; @@ -925,13 +1231,42 @@ void misra_14_1(void) { } while ( a < 10.0f ); // no-warning } +//13143 +static bool misra_14_1_is_increasing (const double* const x, const size_t n) +{ + double last = -INFINITY; + size_t i = ((size_t) 0); + while ((i < n) && isfinite(x[i]) && (x[i] > last)) { //no-warning for 14_1 + last = x[i]; + i++; + } + return i == n; +} -void misra_14_2_init_value(int32_t *var) { +static void misra_14_1_compliant1_foo(float x){ + int i = 0; + while(i < x){ // 10.4 + i += x + x; // 10.3 10.4 no-warning for 14_1 + } +} + +static void misra_14_1_compliant2_foo(void){ + int i = 0; + float f = 0f; + while (f < 10 && i < 10) { //10.4 12.1 + float f = 0f; + f = f + i; // 10.3 10.4 no warning for 14_1 + i++; + } +} +static void misra_14_2_init_value(int32_t *var) { *var = 0; } -void misra_14_2_fn1(bool b) { +static void misra_14_2_init_value_1(int32_t *var); + +static void misra_14_2_fn1(bool b) { for (;i++<10;) {} // 14.2 - for (;i<10;dostuff()) {} // TODO + for (;i<10;dostuff()) {} // 14.2 17.3 int32_t g = 0; int g_arr[42]; g += 2; // no-warning @@ -941,15 +1276,23 @@ void misra_14_2_fn1(bool b) { g += 2; i2 ^= 2; // 14.2 if (i2 == 2) { - g += g_arr[i2]; + g += g_arr[i2]; // cppcheck-suppress legacyUninitvar } misra_14_2_init_value(&i2); // TODO: Fix false negative in function call } - - for (misra_14_2_init_value(&i); i < 10; ++i) {} // no-warning FIXME: False positive for 14.2 Trac #9491 + int i1; + int i2; + for (misra_14_2_init_value(&i1); i1 < 10; ++i1) {} // no-warning + for (misra_14_2_init_value_1(&i2); i2 < 10; ++i2) {} // no-warning + for (misra_14_2_init_value_2(&i2); i2 < 10; ++i2) {} // 17.3 no-warning bool abort = false; - for (i = 0; (i < 10) && !abort; ++i) { // no-warning + for (i = 0; (i < 10) && !abort; ++i) { // 14.2 as 'i' is not a variable + if (b) { + abort = true; + } + } + for (int i = 0; (i < 10) && !abort; ++i) { // no warning if (b) { abort = true; } @@ -960,6 +1303,18 @@ void misra_14_2_fn1(bool b) { for (int i = x; i < 42; i++) { x++; // no warning } + // 1st clause item 2 + loop counter modification + for(x = 0; x < 10; x++) { + x++; // 14.2 + } + // third clause: 2 persistent side effects instead of 1 (14.2) + for (int i = 0; i < 10; i++, x++) { // 12.3 14.2 + } + + // 2 loop counters, there shall be only 1 + for(int i=0, j=0; (i<10) && (j<10); i++, j++) { // 12.3 14.2 + } + for (int i = (x - 3); i < 42; i++) { x ^= 3; // no warning } @@ -979,6 +1334,17 @@ void misra_14_2_fn1(bool b) { } } } + + static struct + { + uint16_t block; + bool readSuccessful; + int32_t i; + } + opState; + for (opState.block = 0U; opState.block < 10U; opState.block++) {;} //no-warning + + for (misra_14_2_init_value(&opState.i); opState.i < 10; ++opState.i) {} //no-warning } static void misra_14_2_fn2(void) { @@ -992,16 +1358,18 @@ static void misra_14_2_fn2(void) for (int i = 0, j = 19; y < 10, --j > 10; y++, j--) { // 14.2 12.3 i++; // no warning } - for (int i = 0; y < 10; y++) { // TODO: 14.2 + // 1st clause is not empty, but is not used in 2nd and 3rd clause + for (int i = 0; y < 10; y++) { // 14.2 i++; // no warning } - for (int i = 0; i < 10; y++) { // TODO: 14.2 + for (; y < 10; y++) {} // without 1st clause, no error + for (int i = 0; i < 10; y++) { // 14.2 i++; // no warning } - for (int i = 0; y < 10; i++) { // TODO: 14.2 + for (int i = 0; y < 10; i++) { // 14.2 i++; // no warning } - for (int i = 0; i < 10; (y+=i)) { + for (int i = 0; i < 10; (y+=i)) { // 14.2 i++; // no warning } @@ -1025,28 +1393,43 @@ static void misra_14_2_fn2(void) struct { unsigned int x:1; unsigned int y:1; -} r14_4_struct; -void misra_14_4(bool b) { - if (x+4){} // 14.4 +} r14_4_struct; // 8.4 +static void misra_14_4(bool b) { + if (x+4){} //config else {} if (b) {} else {} if (r14_4_struct.x) {} + + // #12079 + if (z) {} //config } -void misra_15_1(void) { +// #12417 +struct bar_12417{ int a; }; +static int foo_12417(void){ + int ret = 1; + if (sizeof(struct bar_12417) == 0U){ // no warning for misra-config + ret = 0; + } + return ret; +} + +static void misra_15_1(void) { goto a1; // 15.1 a1: } -void misra_15_2(void) { +static void misra_15_2(void) { label: goto label; // 15.2 15.1 } -void misra_15_3(void) { +static void misra_15_3(int a) { + int x = 0; + int y; if (x!=0) { goto L1; // 15.3 15.1 if (y!=0) { @@ -1077,7 +1460,7 @@ void misra_15_3(void) { } } -void misra_15_4(void) { +static void misra_15_4(void) { misra_15_4_label: return; @@ -1097,7 +1480,7 @@ void misra_15_4(void) { if (y==2) { break; } - for (z = 0; y < 42; ++z) { + for (z = 0; y < 42; ++z) { // 14.2 if (z==1) { break; } @@ -1161,22 +1544,22 @@ void misra_15_4(void) { } } -int misra_15_5(void) { +static int misra_15_5(int x) { if (x!=0) { return 1; // 15.5 } else {} return 2; } -void misra_15_6(void) { +static void misra_15_6(int x) { if (x!=0); // 15.6 else{} -#if A>1 // no-warning +#if A>1 // 20.9 (void)0; #endif -#if A > 0x42 +#if A > 0x42 // 20.9 if (true) { (void)0; } @@ -1187,7 +1570,20 @@ void misra_15_6(void) { do {} while (x<0); // no-warning } -void misra_15_7(void) { +static void misra_15_6_fp(void) +{ + uint8_t value = 0U; + do // Test + { + value++; + } + while (value < 2U); +} + +#if defined(M_20_9) && M_20_9 > 1 // no-warning (#10380) +#endif + +static void misra_15_7(int x, int a, int b) { uint32_t var = 0; uint32_t var2 = 0; @@ -1212,7 +1608,18 @@ void misra_15_7(void) { if (a==2) {} else { if (b==4) {} } // no-warning } -void misra_16_2(void) { +static void misra_16_1(int32_t i) { + switch (i) { + int8_t x; // 16.1 + default: // 16.3 16.5 + break; + if (i != 18) {} // 16.1 + case 1: // 16.3 + break; + } +} + +static void misra_16_2(int y) { switch (x) { default: break; @@ -1224,7 +1631,8 @@ void misra_16_2(void) { } } -void misra_16_3(void) { +static void misra_16_3(int b) { + int a; switch (x) { case 1: case 2: @@ -1307,9 +1715,11 @@ void misra_16_3(void) { case 2: x++; } // 16.3 + + #define M_16_3(a,b,default) { (a), (b), (default) }, } -void misra_16_4(void) { +static void misra_16_4(void) { switch (x) { // 16.4 case 1: break; @@ -1318,7 +1728,7 @@ void misra_16_4(void) { } } -void misra_16_5(void) { +static void misra_16_5(void) { switch (x) { case 1: break; @@ -1329,7 +1739,7 @@ void misra_16_5(void) { } } -void misra_16_6(void) { +static void misra_16_6(void) { switch (x) { // 16.6 default: break; @@ -1350,7 +1760,7 @@ void misra_16_6(void) { } } -void misra_16_7(void) { +static void misra_16_7(void) { switch (x != 123) { // 16.7 case 1: break; @@ -1359,53 +1769,73 @@ void misra_16_7(void) { } } -void misra_17_1(void) { - va_list(); // 17.1 +static void misra_17_1(void) { + va_list(); // 17.1 17.7 va_arg(); // 17.1 va_start(); // 17.1 va_end(); // 17.1 - va_copy(); // 17.1 + va_copy(); // 17.1 17.3 } -void misra_17_2_ok_1(void) { ; } -void misra_17_2_ok_2(void) { +static void misra_17_2_ok_1(void) { ; } +static void misra_17_2_ok_2(void) { misra_17_2_ok_1(); // no-warning } -void misra_17_2_1(void) { +static void misra_17_2_1(void) { misra_17_2_ok_1(); // no-warning misra_17_2_1(); // 17.2 misra_17_2_ok_2(); // no-warning misra_17_2_1(); // 17.2 } -void misra_17_2_2(void) { +static void misra_17_2_2(void) { misra_17_2_3(); // 17.2 } -void misra_17_2_3(void) { +static void misra_17_2_3(void) { misra_17_2_4(); // 17.2 } -void misra_17_2_4(void) { +static void misra_17_2_4(void) { misra_17_2_2(); // 17.2 misra_17_2_3(); // 17.2 } -void misra_17_2_5(void) { +static void misra_17_2_5(void) { misra_17_2_ok_1(); // no-warning misra_17_2_5(); // 17.2 misra_17_2_1(); // no-warning } -void misra_17_6(int x[static 20]) {(void)x;} // 17.6 +bool (*dostuff)(); //8.2 8.4 +struct s173{ + int a; + int b; +} +static void misra_17_3(void) { + if (dostuff()) {} // no-warning + bool a = dostuff(); // no-warning + dostuff2(); // 17.3 + s173 ( *misra_8_2_p_a ) (void); // no-warning +} -int calculation(int x) { return x + 1; } -void misra_17_7(void) { +static void misra_config(const char* str) { + if (strlen(str) > 3){} //10.4 + if (sizeof(int) > 1){} //10.4 +} + +static void misra_17_6(int x[static 20]) {(void)x;} // 17.6 + +static int calculation(int x) { return x + 1; } +static void misra_17_7(void) { calculation(123); // 17.7 + int (*calc_ptr)(int) = &calculation; + calc_ptr(123); // 17.7 + int y = calc_ptr(123); } -void misra_17_8(int x) { +static void misra_17_8(int x) { x = 3; // 17.8 } -void misra_18_4(void) +static void misra_18_4(void) { int b = 42; int *bp = &b; @@ -1419,7 +1849,7 @@ void misra_18_4(void) b = b + 9; // no-warning } -void misra_18_5(void) { +static void misra_18_5(void) { int *** p; // 18.5 } @@ -1435,22 +1865,25 @@ struct { } nested_2; uint8_t data_3[]; // 18.7 } nested_3; -} r18_7_struct; +} r18_7_struct; // 8.4 struct { uint16_t len; + int (*array_param_func_ptr)(char const *argv[], int argc); // no-warning uint8_t data_1[ 19 ]; uint8_t data_2[ ]; // 18.7 -} r18_7_struct; +} r18_7_struct; // 8.4 typedef enum { R18_8_ENUM_CONSTANT_0, R18_8_ENUM_CONSTANT_1, } r18_8_enum; -void misra_18_8(int x) { +static void misra_18_8(int x) { int buf1[10]; int buf2[sizeof(int)]; int vla[x]; // 18.8 + // #9498 + int vlb[y]; // config static const unsigned char arr18_8_1[] = UNDEFINED_ID; static uint32_t enum_test_0[R18_8_ENUM_CONSTANT_0] = {0}; } @@ -1482,17 +1915,32 @@ union misra_19_2 { }; // 19.2 #define M_20_7_17(STRING1, STRING2, STRING3) (STRING1 + STRING2 " " STRING3) // 20.7 // Compliant: M is a structure member name, not an expression -struct { int a; } struct_20_7_s; +struct { int a; } struct_20_7_s; // 8.4 #define M_20_7_6(M) struct_20_7.M #define M_20_7_7(M) (struct_20_7).M #define MUL(a ,b ) ( a * b ) // 20.7 +#if __LINE__ // 20.8 +#elif 2+5 // 20.8 +#elif 2-2 +#endif + +#if A // 20.9 +#elif B || C // 20.9 +#endif + #define M_20_10(a) (#a) // 20.10 +#define M_20_11(a) # a ## 1 // 20.11 20.10 + +#define M_20_12_AA 0xffff +#define M_20_12_BB(x) (x) + wow ## x // 20.12 20.10 +misra_20_12 = M_20_12_BB(M_20_12_AA); + #else1 // 20.13 -#ifdef A>1 +#ifdef A # define somethingis 5 // no warning # define func_20_13(v) (v) // no warning #else @@ -1507,43 +1955,46 @@ struct { int a; } struct_20_7_s; #define _macro_starts_with_lower 1 // no warning static int _file_scope_id_21_1 = 42; // no warning static int _file_scope_id_21_1_fn(void) { return 42; } // no warning -int misra_21_1(void) { +static int misra_21_1(void) { int _a = 42; // no warning: only directives affected errno = EINVAL; // no warning _a ++; // no warning - _exit(1); // no warning + _exit(1); // 17.3 no warning return _a; // no warning } static int _misra_21_1_2(void); // no warning #define errno 11 // 21.1 +#undef errno // 20.5 -void misra_21_3(void) { +#define __BUILTIN_SOMETHING 123 // 21.2 21.1 +extern void *memcpy ( void *restrict s1, const void *restrict s2, size_t n ); // 21.2 8.14 + +static void misra_21_3(void) { p1=malloc(10); // 21.3 p2=calloc(10); // 21.3 realloc(10); // 21.3 free(p1); // 21.3 } -void misra_21_7(void) { +static void misra_21_7(void) { (void)atof(str); // 21.7 (void)atoi(str); // 21.7 (void)atol(str); // 21.7 (void)atoll(str); // 21.7 } -void misra_21_8(void) { +static void misra_21_8(void) { abort(); // 21.8 (void)getenv("foo"); // 21.8 - (void)system(""); // 21.8 exit(-1); // 21.8 } -void misra_21_9(void) { +static void misra_21_9(void) { (void)bsearch(key,base,num,size,cmp); // 21.9 qsort(base,num,size,cmp); // 21.9 } -void misra_21_12(void) { +static void misra_21_12(void) { int rc; fexcept_t f; // 21.12 rc = feclearexcept(1); // 21.12 @@ -1553,136 +2004,108 @@ void misra_21_12(void) { rc = fetestexcept(1); // 21.12 } -// Large arrays for R13.1. Size exceeds default Python's max recursion depth. -static uint8_t misra_13_1_large_ok[1024] = { -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; -static uint8_t misra_13_1_large_bad[1024] = { // 13.1 -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, i++, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; +static void misra_21_14(uint8_t *x) { + (void)strcpy(x, "123"); + (void)memcmp(x, y, 100); // 21.14 + (void)memcmp("abc", y, 100); // 21.14 21.16 +} + +static void misra_21_15(uint8_t *x, uint16_t *y) { + (void)memcpy(x, y, 10); // 21.15 + (void)memmove(x, y, 10); // 21.15 + (void)memcmp(x, y, 10); // 21.15 +} + +struct misra_21_16_S { int a; int b; }; +static void misra_21_16_f1(struct misra_21_16_S *s1, struct misra_21_16_S *s2) { + (void)memcmp(s1, s2, 10); // 21.16 +} +static void misra_21_16_f2(char *x, char *y) { + (void)memcmp(x, y, 10); // 21.16 +} +typedef enum { R21_16_A, R21_16_B} r21_16_enum; +static void misra_21_16_f3(void) { + int const a[2] = {0}; + int const b[2] = {0}; + (void)memcmp(a, b, 2); // no-warning + uint8_t const c[2] = {0}; + uint8_t const d[2] = {0}; + (void)memcmp(c, d, 2); // no-warning + bool const e[2] = {0}; + bool const f[2] = {0}; + (void)memcmp(e, f, 2); // no-warning + r21_16_enum const g[2] = {0}; + r21_16_enum const h[2] = {0}; + (void)memcmp(g, h, 2); // no-warning + char const i[2] = {0}; + char const j[2] = {0}; + (void)memcmp(i, j, 2); // 21.16 +} + +static void misra_21_19(void) { + char *s = setlocale(LC_ALL,0); // 21.19 + const struct lconv *conv = localeconv (); + conv->decimal_point = "^"; // 21.19 +} + +static void misra_21_20(void) { + const char *res1 = setlocale ( LC_ALL, 0 ); + (void) setlocale ( LC_MONETARY, "French" ); + if (res1) {} // 21.20 14.4 +} + +static void misra_21_21(void) { + (void)system("ls"); // 21.21 +} + +static void misra_22_5(FILE *f) { + int x = *f; // 22.5 + int y = f->pos; // 22.5 +} + +static void misra_22_7(char ch) +{ + if (EOF == ch) {} // 22.7 +} + +static void misra_22_8(void) +{ + (void)strtoll("123", NULL, 10); // 22.8 + if (errno == 0) {} +} + +static void misra_22_9(void) +{ + errno = 0; + (void)strtoll("123", NULL, 10); // 22.9 +} + +static void misra_22_10(void) +{ + errno = 0; + f = atof ( "A.12" ); // 21.7 + if ( 0 == errno ) {} // 22.10 + + errno = 0; + f = strtod ( "A.12", NULL ); + if ( 0 == errno ) {} + + // #10855 + f = strtol(numbuf, 0, (formatHex == 0U) ? 0 : 16); + if (errno != 0) {} + + // #11752 + #define NULL_PTR ((void*)0) + f = strtod(inStr, NULL_PTR); + if(errno != 0) {} +} + +// #12448 +static void check_misra_config(void) +{ + if (sizeof(struct bar) == 0U) {} //no warning + if (sizeof(int abc) == 0U) {} //no warning + if (sizeof(xyz) == 0U) {} //no warning + if (sizeof(const pqr) == 0U) {} //no warning + if (sizeof(const int* const pqrs) == 0U) {} //no-warning +} diff --git a/addons/test/misra/misra-test.cpp b/addons/test/misra/misra-test.cpp index 284e02d215e..0aa9a0b9d1c 100644 --- a/addons/test/misra/misra-test.cpp +++ b/addons/test/misra/misra-test.cpp @@ -7,7 +7,7 @@ class C { class misra_21_1_C { public: - misra_21_1_C operator=(const misra_21_1_C &); // 8.2 + misra_21_1_C operator=(const misra_21_1_C &); }; class C2 { @@ -16,9 +16,9 @@ class C2 { private: void* f; }; -C2::C2() : f(NULL) {} +C2::C2(void) : f(NULL) {} -static bool test_misra_21_1_crash(void) +static void test_misra_21_1_crash(void) { auto misra_21_1_C a, b; // 12.3 a = b; diff --git a/addons/test/misra/misra-test.h b/addons/test/misra/misra-test.h index 74e49e58ba6..b455134893c 100644 --- a/addons/test/misra/misra-test.h +++ b/addons/test/misra/misra-test.h @@ -1,7 +1,13 @@ #ifndef MISRA_TEST_H #define MISRA_TEST_H struct misra_h_s { int foo; }; -bool test(char *); // 8.2 bool test(char *a); // OK int misra_8_2_no_fp(int a); +void misra_8_4_bar(void); +// #12978 +typedef struct m8_4_stErrorDef +{ + uint8_t ubReturnVal; +} m8_4_stErrorDef; +extern const m8_4_stErrorDef * m8_4_pubTestPointer; #endif // MISRA_TEST_H diff --git a/addons/test/misra/misra_rules_structure.txt b/addons/test/misra/misra_rules_structure.txt index 41d2d456f85..a8223fde948 100644 --- a/addons/test/misra/misra_rules_structure.txt +++ b/addons/test/misra/misra_rules_structure.txt @@ -11,7 +11,10 @@ Here we go: Appendix A Summary of guidelines Rule 1.2 -Rule text. + Rule text. + +Rule 2.1 +Rule text for 2.1. Stop parsing after this line: Appendix B diff --git a/addons/test/misra/suppressions.txt b/addons/test/misra/suppressions.txt index a81b6b661a0..139e088552e 100644 --- a/addons/test/misra/suppressions.txt +++ b/addons/test/misra/suppressions.txt @@ -1,7 +1,6 @@ misra-c2012-21.6:*/misra-suppressions1-test.c:7 -misra-c2012-14.4 -misra-c2012-5.2 -misra-c2012-16.4:*/misra-suppressions1-test.c -misra-c2012-16.6:*/misra-suppressions1-test.c +misra-c2012-17.3 +misra-c2012-8.4:*/misra-suppressions1-test.c misra-c2012-4.1:*/misra-suppressions2-test.c +misra-c2012-8.4:*/misra-suppressions2-test.c misra-c2012-19.2:*/misra-suppressions2-test.c diff --git a/addons/test/misra_test.py b/addons/test/misra_test.py new file mode 100644 index 00000000000..55a24cb4b27 --- /dev/null +++ b/addons/test/misra_test.py @@ -0,0 +1,244 @@ +# Running the test with Python 3: +# Command in cppcheck directory: +# PYTHONPATH=./addons python3 -m pytest addons/test/misra_test.py + +import pytest +import re +import sys +import os + +from .util import dump_create, dump_remove, convert_json_output +from addons.misra import C11_STDLIB_IDENTIFIERS, C99_STDLIB_IDENTIFIERS,C90_STDLIB_IDENTIFIERS, isStdLibId, isKeyword + +TEST_SOURCE_FILES = [os.path.join('addons','test','misra','misra-test.c')] + + +def remove_misra_config(s:str): + ret = '' + for line in s.splitlines(): + if '[misra-config]' not in line: + ret += line + '\n' + return ret + + +@pytest.fixture(scope="function") +def checker(): + from addons.misra import MisraChecker, MisraSettings, get_args_parser + parser = get_args_parser() + args = parser.parse_args([]) + settings = MisraSettings(args) + return MisraChecker(settings) + + +# FIXME: files are generates in the source tree so it will cause issues if tests are run with xdist. +@pytest.fixture +def test_files(): + for f in TEST_SOURCE_FILES: + dump_create(f) + yield + for f in TEST_SOURCE_FILES: + dump_remove(f) + + +def test_loadRuleTexts_structure(checker): + checker.loadRuleTexts("./addons/test/misra/misra_rules_structure.txt") + assert(checker.ruleTexts.get(101, None) is None) + assert(checker.ruleTexts[102].text == "Rule text.") + assert(checker.ruleTexts.get(103, None) is None) + assert(checker.ruleTexts[201].text == "Rule text for 2.1.") + assert(checker.ruleTexts.get(202, None) is None) + + +def test_loadRuleTexts_empty_lines(checker): + checker.loadRuleTexts("./addons/test/misra/misra_rules_empty_lines.txt") + assert(len(checker.ruleTexts) == 3) + assert(len(checker.ruleTexts[102].text) == len("Rule text.")) + + +def test_loadRuleTexts_mutiple_lines(checker): + checker.loadRuleTexts("./addons/test/misra/misra_rules_multiple_lines.txt") + assert(checker.ruleTexts[101].text == "Multiple lines text.") + assert(checker.ruleTexts[102].text == "Multiple lines text.") + assert(checker.ruleTexts[103].text == "Multiple lines text.") + assert(checker.ruleTexts[104].text == "Should") + assert(checker.ruleTexts[105].text == "Should starts from lowercase letter.") + assert(checker.ruleTexts[106].text == "Can contain empty lines.") + + +def test_verifyRuleTexts(checker, capsys): + checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") + checker.verifyRuleTexts() + captured = capsys.readouterr().out + assert("21.3" not in captured) + assert("1.3" in captured) + + +def test_rules_misra_severity(checker): + checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") + assert(checker.ruleTexts[1004].misra_severity == 'Mandatory') + assert(checker.ruleTexts[401].misra_severity == 'Required') + assert(checker.ruleTexts[1505].misra_severity == 'Advisory') + assert(checker.ruleTexts[2104].misra_severity == '') + + +def test_json_out(checker, capsys, test_files): + sys.argv.append("--cli") + checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") + checker.parseDump("./addons/test/misra/misra-test.c.dump") + captured = capsys.readouterr() + captured = captured.out.splitlines() + sys.argv.remove("--cli") + json_output = convert_json_output(captured) + assert("Mandatory" in json_output['c2012-10.4'][0]['extra']) + assert("Required" in json_output['c2012-21.3'][0]['extra']) + assert("Advisory" in json_output['c2012-20.1'][0]['extra']) + + +def test_rules_cppcheck_severity(checker, capsys, test_files): + checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") + checker.parseDump("./addons/test/misra/misra-test.c.dump") + captured = capsys.readouterr().err + assert("(error)" not in remove_misra_config(captured)) + assert("(warning)" not in captured) + assert("(style)" in captured) + +def test_rules_cppcheck_severity_custom(checker, capsys, test_files): + checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") + checker.setSeverity("custom-severity") + checker.parseDump("./addons/test/misra/misra-test.c.dump") + captured = capsys.readouterr().err + assert("(error)" not in remove_misra_config(captured)) + assert("(warning)" not in captured) + assert("(style)" not in captured) + assert("(custom-severity)" in captured) + +def test_rules_suppression(checker, capsys): + test_sources = ["addons/test/misra/misra-suppressions1-test.c", + "addons/test/misra/misra-suppressions2-test.c"] + + for src in test_sources: + re_suppressed= r"\[%s\:[0-9]+\]" % src + dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt","--inline-suppr") + checker.parseDump(src + ".dump") + captured = capsys.readouterr().err + found = re.search(re_suppressed, captured) + assert found is None, 'Unexptected output:\n' + captured + dump_remove(src) + +def test_arguments_regression(): + args_ok = ["-generate-table", + "--rule-texts=./addons/test/assets/misra_rules_multiple_lines.txt", + "--verify-rule-texts", + "-t=foo", "--template=foo", + "--suppress-rules=15.1", + "--quiet", + "--cli", + "--no-summary", + "--show-suppressed-rules", + "-P=src/", "--file-prefix=src/", + "--severity=misra-warning"] + # Arguments with expected SystemExit + args_exit = ["--non-exists", "--non-exists-param=42", "-h", "--help"] + + from addons.misra import get_args_parser + + # sys.argv contains all pytest arguments - so clear all existing arguments first and restore afterwards + sys_argv_old = sys.argv + sys.argv = [sys.argv[0]] + + try: + for arg in args_exit: + sys.argv.append(arg) + with pytest.raises(SystemExit): + parser = get_args_parser() + parser.parse_args() + sys.argv.remove(arg) + + for arg in args_ok: + sys.argv.append(arg) + try: + parser = get_args_parser() + parser.parse_args() + except SystemExit: + pytest.fail("Unexpected SystemExit with '%s'" % arg) + sys.argv.remove(arg) + finally: + sys.argv = sys_argv_old + + +def test_read_ctu_info_line(checker): + assert checker.read_ctu_info_line('{') is None + assert checker.read_ctu_info_line('{"summary":"123"}') is None + assert checker.read_ctu_info_line('{"data":123}') is None + assert checker.read_ctu_info_line('{"summary":"123","data":123}') is not None + +def test_platform(checker): + test_file = os.path.join('addons','test','misra','misra-test.c') + dump_create(test_file, "--language=c++") + checker.parseDump(test_file + ".dump") + assert checker.is_cpp is True + + dump_create(test_file, "--language=c") + checker.parseDump(test_file + ".dump") + assert checker.is_cpp is False + +def test_std99_identifiers(): + for headerfile in C90_STDLIB_IDENTIFIERS: + for identifier in C90_STDLIB_IDENTIFIERS[headerfile]: + assert identifier in C99_STDLIB_IDENTIFIERS[headerfile], f"{identifier} of C90 not found in C99_STDLIB_IDENTIFIERS" + +def test_stdC11_identifiers(): + for headerfile in C90_STDLIB_IDENTIFIERS: + for identifier in C90_STDLIB_IDENTIFIERS[headerfile]: + assert identifier in C99_STDLIB_IDENTIFIERS[headerfile], f"{identifier} of C90 not found in C11_STDLIB_IDENTIFIERS" + for headerfile in C99_STDLIB_IDENTIFIERS: + for identifier in C99_STDLIB_IDENTIFIERS[headerfile]: + assert identifier in C11_STDLIB_IDENTIFIERS[headerfile], f"{identifier} of C99 not found in C11_STDLIB_IDENTIFIERS" + +def test_isStdLibId(): + # Check that Identifiers from C90 are correctly classified + assert isStdLibId("assert", 'c89') is True + assert isStdLibId("assert", 'c99') is True + assert isStdLibId("assert", 'c11') is True + assert isStdLibId("assert", 'c23') is True + + # Check that Identifiers from C99 are correctly classified + assert isStdLibId("UINT32_C", 'c89') is False + assert isStdLibId("UINT32_C", 'c99') is True + assert isStdLibId("UINT32_C", 'c11') is True + assert isStdLibId("UINT32_C", 'c23') is True + + # Check that Identifiers from C11 are correctly classified + assert isStdLibId("sprintf_s", 'c89') is False + assert isStdLibId("sprintf_s", 'c99') is False + assert isStdLibId("sprintf_s", 'c11') is True + assert isStdLibId("sprintf_s", 'c23') is True + + # Function Defaulting to C99 + assert isStdLibId("assert") is True + assert isStdLibId("UINT32_C") is True + assert isStdLibId("sprintf_s") is False + +def test_isKeyword(): + # Check that Keywords from C90 are correctly classified + assert isKeyword("if", 'c89') is True + assert isKeyword("if", 'c99') is True + assert isKeyword("if", 'c11') is True + assert isKeyword("if", 'c23') is True + + # Check that Keywords from C99 are correctly classified + assert isKeyword("inline", 'c89') is False + assert isKeyword("inline", 'c99') is True + assert isKeyword("inline", 'c11') is True + assert isKeyword("inline", 'c23') is True + + # Check that Keywords from C11 are correctly classified + assert isKeyword("static_assert", 'c89') is False + assert isKeyword("static_assert", 'c99') is False + assert isKeyword("static_assert", 'c11') is True + assert isKeyword("static_assert", 'c23') is True + + # Function Defaulting to C99 + assert isKeyword("if") is True + assert isKeyword("inline") is True + assert isKeyword("static_assert") is False diff --git a/addons/test/naming_test.c b/addons/test/naming_test.c index 928d51dab06..bf021b87125 100644 --- a/addons/test/naming_test.c +++ b/addons/test/naming_test.c @@ -1,5 +1,5 @@ -// To test: -// ~/cppcheck/cppcheck --dump naming_test.c && python ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump - -// Should not crash when there is no name -void func(int number, int); +// To test: +// ~/cppcheck/cppcheck --dump naming_test.c && python ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump + +// Should not crash when there is no name +void func(int number, int); diff --git a/addons/test/naming_test.cpp b/addons/test/naming_test.cpp index 1c5bf382610..07297dbbf27 100644 --- a/addons/test/naming_test.cpp +++ b/addons/test/naming_test.cpp @@ -1,9 +1,11 @@ -// To test: -// ~/cppcheck/cppcheck --dump naming_test.cpp && python ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump - -// No error for mismatching Constructor/Destructor names should be issued, they can not be changed. -class TestClass1 -{ - TestClass1() {} - ~TestClass1() {} -}; +// To test: +// ~/cppcheck/cppcheck --dump naming_test.cpp && python ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump + +// No error for mismatching Constructor/Destructor names should be issued, they can not be changed. +class TestClass1 +{ + TestClass1() {} + ~TestClass1() {} + TestClass1(const TestClass1 &) {} + TestClass1(TestClass1 &&) {} +}; diff --git a/addons/test/namingng_test.c b/addons/test/namingng_test.c deleted file mode 100644 index 2eaf3899666..00000000000 --- a/addons/test/namingng_test.c +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include - -uint32_t ui32Good (int abc) -{ - uint32_t ui32good; - int32_t i32good; - uint32_t badui32; - int32_t badi32; - - uint32_t a; // Short - return 5; -} - -uint16_t ui16Good (int a) -{ - return 5; -} - -uint16_t ui16bad_underscore (int a) -{ - return 5; -} - -uint32_t u32Bad (int a) -{ - uint32_t ui32good; - int32_t i32good; - uint32_t badui32; - int32_t badi32; - int * intpointer=NULL; - int ** intppointer=NULL; - int *** intpppointer=NULL; - return 5; -} - -uint16_t Badui16 (int a) -{ - return 5; -} - -void * Pointer() -{ - return NULL; -} - -void ** PPointer() -{ - return NULL; -} diff --git a/addons/test/test-cert.py b/addons/test/test-cert.py deleted file mode 100644 index 8475e8b79a0..00000000000 --- a/addons/test/test-cert.py +++ /dev/null @@ -1,35 +0,0 @@ -# Running the test with Python 2: -# Be sure to install pytest version 4.6.4 (newer should also work) -# Command in cppcheck directory: -# python -m pytest addons/test/test-cert.py -# -# Running the test with Python 3: -# Command in cppcheck directory: -# PYTHONPATH=./addons python3 -m pytest addons/test/test-cert.py - -import sys -import pytest - - -def test_arguments_regression(): - args_ok = ["-q", "--quiet", - "-verify", - "--cli"] - # Arguments with expected SystemExit - args_exit = ["--non-exists", "--non-exists-param=42", "-h", "--help"] - - from addons.cert import get_args - - for arg in args_exit: - sys.argv.append(arg) - with pytest.raises(SystemExit): - get_args() - sys.argv.remove(arg) - - for arg in args_ok: - sys.argv.append(arg) - try: - get_args() - except SystemExit: - pytest.fail("Unexpected SystemExit with '%s'" % arg) - sys.argv.remove(arg) diff --git a/addons/test/test-misra.py b/addons/test/test-misra.py deleted file mode 100644 index cc300f8ab83..00000000000 --- a/addons/test/test-misra.py +++ /dev/null @@ -1,152 +0,0 @@ -# Running the test with Python 2: -# Be sure to install pytest version 4.6.4 (newer should also work) -# Command in cppcheck directory: -# python -m pytest addons/test/test-misra.py -# -# Running the test with Python 3: -# Command in cppcheck directory: -# PYTHONPATH=./addons python3 -m pytest addons/test/test-misra.py - -import pytest -import re -import sys - -from .util import dump_create, dump_remove, convert_json_output - - -TEST_SOURCE_FILES = ['./addons/test/misra/misra-test.c'] - - -def setup_module(module): - for f in TEST_SOURCE_FILES: - dump_create(f) - - -def teardown_module(module): - for f in TEST_SOURCE_FILES: - dump_remove(f) - - -@pytest.fixture(scope="function") -def checker(): - from addons.misra import MisraChecker, MisraSettings, get_args - args = get_args() - settings = MisraSettings(args) - return MisraChecker(settings) - - -def test_loadRuleTexts_structure(checker): - checker.loadRuleTexts("./addons/test/misra/misra_rules_structure.txt") - assert(checker.ruleTexts.get(101, None) is None) - assert(checker.ruleTexts[102].text == "Rule text.") - assert(checker.ruleTexts.get(103, None) is None) - - -def test_loadRuleTexts_empty_lines(checker): - checker.loadRuleTexts("./addons/test/misra/misra_rules_empty_lines.txt") - assert(len(checker.ruleTexts) == 3) - assert(len(checker.ruleTexts[102].text) == len("Rule text.")) - - -def test_loadRuleTexts_mutiple_lines(checker): - checker.loadRuleTexts("./addons/test/misra/misra_rules_multiple_lines.txt") - assert(checker.ruleTexts[101].text == "Multiple lines text.") - assert(checker.ruleTexts[102].text == "Multiple lines text.") - assert(checker.ruleTexts[103].text == "Multiple lines text.") - assert(checker.ruleTexts[104].text == "Should") - assert(checker.ruleTexts[105].text == "Should") - assert(checker.ruleTexts[106].text == "Can contain empty lines.") - - -def test_verifyRuleTexts(checker, capsys): - checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") - checker.verifyRuleTexts() - captured = capsys.readouterr().out - assert("21.3" not in captured) - assert("1.3" in captured) - - -def test_rules_misra_severity(checker): - checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") - assert(checker.ruleTexts[1004].misra_severity == 'Mandatory') - assert(checker.ruleTexts[401].misra_severity == 'Required') - assert(checker.ruleTexts[1505].misra_severity == 'Advisory') - assert(checker.ruleTexts[2104].misra_severity == '') - - -def test_json_out(checker, capsys): - sys.argv.append("--cli") - checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") - checker.parseDump("./addons/test/misra/misra-test.c.dump") - captured = capsys.readouterr() - captured = captured.out.splitlines() - sys.argv.remove("--cli") - json_output = convert_json_output(captured) - assert("Mandatory" in json_output['c2012-10.4'][0]['extra']) - assert("Required" in json_output['c2012-21.3'][0]['extra']) - assert("Advisory" in json_output['c2012-20.1'][0]['extra']) - - -def test_rules_cppcheck_severity(checker, capsys): - checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") - checker.parseDump("./addons/test/misra/misra-test.c.dump") - captured = capsys.readouterr().err - assert("(error)" not in captured) - assert("(warning)" not in captured) - assert("(style)" in captured) - -def test_rules_cppcheck_severity_custom(checker, capsys): - checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") - checker.setSeverity("custom-severity") - checker.parseDump("./addons/test/misra/misra-test.c.dump") - captured = capsys.readouterr().err - assert("(error)" not in captured) - assert("(warning)" not in captured) - assert("(style)" not in captured) - assert("(custom-severity)" in captured) - -def test_rules_suppression(checker, capsys): - test_sources = ["addons/test/misra/misra-suppressions1-test.c", - "addons/test/misra/misra-suppressions2-test.c"] - - for src in test_sources: - re_suppressed= r"\[%s\:[0-9]+\]" % src - dump_remove(src) - dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt") - checker.parseDump(src + ".dump") - captured = capsys.readouterr().err - found = re.search(re_suppressed, captured) - assert found is None, 'Unexptected output:\n' + captured - dump_remove(src) - - -def test_arguments_regression(): - args_ok = ["-generate-table", - "--rule-texts=./addons/test/assets/misra_rules_multiple_lines.txt", - "--verify-rule-texts", - "-t=foo", "--template=foo", - "--suppress-rules=15.1", - "--quiet", - "--cli", - "--no-summary", - "--show-suppressed-rules", - "-P=src/", "--file-prefix=src/", - "--severity=misra-warning"] - # Arguments with expected SystemExit - args_exit = ["--non-exists", "--non-exists-param=42", "-h", "--help"] - - from addons.misra import get_args - - for arg in args_exit: - sys.argv.append(arg) - with pytest.raises(SystemExit): - get_args() - sys.argv.remove(arg) - - for arg in args_ok: - sys.argv.append(arg) - try: - get_args() - except SystemExit: - pytest.fail("Unexpected SystemExit with '%s'" % arg) - sys.argv.remove(arg) diff --git a/addons/test/threadsafety/MT-Unsafe.cpp b/addons/test/threadsafety/MT-Unsafe.cpp new file mode 100644 index 00000000000..5b23cefe87d --- /dev/null +++ b/addons/test/threadsafety/MT-Unsafe.cpp @@ -0,0 +1,67 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2023 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 . + */ + +/* + * This does not match the standard cppchek test code, + * because I haven't figured that out yet. + * This code does compile and run, and does demonstrate + * the issues that the threadsafety.py addon is supposed to find. + * It does not use threads ! + */ + +#include +#include +#include + +void threadsafety_static() +{ + // cppcheck-suppress threadsafety-threadsafety + static unsigned int nCount = 0; + + nCount++; + printf("%d\n", nCount); +} + +void threadsafety_call() +{ + time_t now = time(nullptr); + // cppcheck-suppress threadsafety-unsafe-call + printf("%s\n", ctime(&now)); +} + +// cppcheck --addon=threadsafety +// should *not* find any problems with this function. +void threadsafety_safecall() +{ + char haystack[] = "alphabet"; + char needle[] = "Alph"; + char* found = strcasestr(haystack, needle); + printf("%s %sin %s\n", needle, found ? "" : "not ", haystack); +} + +int main() { + threadsafety_static(); + + threadsafety_call(); + + threadsafety_safecall(); + + threadsafety_static(); + + return 0; +} diff --git a/addons/test/threadsafety/local_static.cpp b/addons/test/threadsafety/local_static.cpp index 433cbaa775b..b41a0571ba8 100644 --- a/addons/test/threadsafety/local_static.cpp +++ b/addons/test/threadsafety/local_static.cpp @@ -2,5 +2,6 @@ struct Dummy { int x; }; void func() { - static Dummy dummy; + // cppcheck-suppress threadsafety-threadsafety + static Dummy dummy; } diff --git a/addons/test/threadsafety/local_static_const.cpp b/addons/test/threadsafety/local_static_const.cpp index 12ab715af0c..eaed48be949 100644 --- a/addons/test/threadsafety/local_static_const.cpp +++ b/addons/test/threadsafety/local_static_const.cpp @@ -2,5 +2,6 @@ struct Dummy { int x; }; void func() { + // cppcheck-suppress threadsafety-threadsafety-const static const Dummy dummy; } diff --git a/addons/test/util.py b/addons/test/util.py index 21dd345bb12..0f99534edc6 100644 --- a/addons/test/util.py +++ b/addons/test/util.py @@ -20,22 +20,23 @@ def find_cppcheck_binary(): def dump_create(fpath, *argv): cppcheck_binary = find_cppcheck_binary() - cmd = [cppcheck_binary, "--dump", "--quiet", fpath] + list(argv) - p = subprocess.Popen(cmd) - p.communicate() - if p.returncode != 0: - raise OSError("cppcheck returns error code: %d" % p.returncode) - subprocess.Popen(["sync"]) + cmd = [cppcheck_binary, "--dump", "-DDUMMY", "--quiet", fpath] + list(argv) + with subprocess.Popen(cmd) as p: + p.communicate() + if p.returncode != 0: + raise OSError("cppcheck returns error code: %d" % p.returncode) def dump_remove(fpath): - subprocess.Popen(["rm", "-f", fpath + ".dump"]) + os.remove(fpath + ".dump") def convert_json_output(raw_json_strings): """Convert raw stdout/stderr cppcheck JSON output to python dict.""" json_output = {} for line in raw_json_strings: + if line.startswith('{"summary":'): + continue try: json_line = json.loads(line) # json_output[json_line['errorId']] = json_line diff --git a/addons/test/test-y2038.py b/addons/test/y2038_test.py similarity index 83% rename from addons/test/test-y2038.py rename to addons/test/y2038_test.py index 8beaa5ab930..282e55650d7 100644 --- a/addons/test/test-y2038.py +++ b/addons/test/y2038_test.py @@ -81,6 +81,7 @@ def test_3_no_use_time_bits(capsys): def test_4_good(capsys): + # pylint: disable-next=unused-variable - FIXME is_safe = check_y2038_safe('./addons/test/y2038/y2038-test-4-good.c.dump', quiet=True) # assert(is_safe is True) # FIXME: This should be a "good" example returning "True" instead of "False" captured = capsys.readouterr() @@ -113,18 +114,27 @@ def test_arguments_regression(): # Arguments with expected SystemExit args_exit = ["--non-exists", "--non-exists-param=42", "-h", "--help"] - from addons.y2038 import get_args - - for arg in args_exit: - sys.argv.append(arg) - with pytest.raises(SystemExit): - get_args() - sys.argv.remove(arg) - - for arg in args_ok: - sys.argv.append(arg) - try: - get_args() - except SystemExit: - pytest.fail("Unexpected SystemExit with '%s'" % arg) - sys.argv.remove(arg) + from addons.y2038 import get_args_parser + + # sys.argv contains all pytest arguments - so clear all existing arguments first and restore afterwards + sys_argv_old = sys.argv + sys.argv = [sys.argv[0]] + + try: + for arg in args_exit: + sys.argv.append(arg) + with pytest.raises(SystemExit): + parser = get_args_parser() + parser.parse_args() + sys.argv.remove(arg) + + for arg in args_ok: + sys.argv.append(arg) + try: + parser = get_args_parser() + parser.parse_args() + except SystemExit: + pytest.fail("Unexpected SystemExit with '%s'" % arg) + sys.argv.remove(arg) + finally: + sys.argv = sys_argv_old \ No newline at end of file diff --git a/addons/threadsafety.py b/addons/threadsafety.py index 81538a27466..9475e1a5b0d 100755 --- a/addons/threadsafety.py +++ b/addons/threadsafety.py @@ -1,39 +1,350 @@ #!/usr/bin/env python3 -# -# This script analyses Cppcheck dump files to locate threadsafety issues -# - warn about static local objects -# +""" +cppcheck addon for threadsafety detection. -import cppcheckdata + This script analyses Cppcheck dump files to locate threadsafety issues. + It warns about + - static local objects + - MT-Unsafe symbols listed in the "Attributes" sections of man pages. + +""" + +import re import sys -def reportError(token, severity, msg, id): - cppcheckdata.reportError(token, severity, msg, 'threadsafety', id) +import cppcheckdata + +# -------------------------------- +# List of MT-Unsafe identifiers +# -------------------------------- + +# This is Work In Progress. +# Eventually it should contain all identifiers (types +# and functions) which are MT-Unsafe. + +# The script tools/MT-Unsafe.py can help to re-generate this list. +# It reads a man-page tree and report identifiers marked as "MT-Unsafe" +# (see man 7 attributes for what this means), eg +# MT-Unsafe.py /usr/share/man/man3 + +id_MTunsafe_full = { + # MT-Unsafe types by definition + # 'pthread_t', + # Types marked MT-Unsafe + 'const:env', + 'const:hostid', + 'const:mallopt', + 'const:sigintr', + 'race:LogMask', + 'race:asctime', + 'race:crypt', + 'race:crypt_gensalt', + 'race:cuserid/!string', + 'race:dirstream', + 'race:drand48', + 'race:ecvt', + 'race:exit', + 'race:fcvt', + 'race:fgetgrent', + 'race:fgetpwent', + 'race:fgetspent', + 'race:fsent', + 'race:getdate', + 'race:getlogin', + 'race:getopt', + 'race:getspent', + 'race:getspnam', + 'race:grent', + 'race:grgid', + 'race:grnam', + 'race:hostbyaddr', + 'race:hostbyname', + 'race:hostbyname2', + 'race:hostent', + 'race:hsearch', + 'race:l64a', + 'race:localeconv', + 'race:mbrlen/!ps', + 'race:mbrtowc/!ps', + 'race:mbsnrtowcs/!ps', + 'race:mbsrtowcs/!ps', + 'race:mcheck', + 'race:mntentbuf', + 'race:netbyaddr', + 'race:netbyname', + 'race:netent', + 'race:netgrent', + 'race:protobyname', + 'race:protobynumber', + 'race:protoent', + 'race:ptsname', + 'race:pwent', + 'race:pwnam', + 'race:pwuid', + 'race:qecvt', + 'race:qfcvt', + 'race:servbyname', + 'race:servbyport', + 'race:servent', + 'race:sgetspent', + 'race:signgam', + 'race:stdin', + 'race:stdout', + 'race:streams', + 'race:strerror', + 'race:strsignal', + 'race:strtok', + 'race:tmbuf', + 'race:tmpnam/!s', + 'race:ttyent', + 'race:ttyname', + 'race:utent', + 'race:wcrtomb/!ps', + 'race:wcsnrtombs/!ps', + 'race:wcsrtombs/!ps', + 'sig:ALRM', + 'sig:SIGCHLD/linux', + # APIs marked MT-Unsafe + 'asctime', + 'clearenv', + 'ctime', + 'cuserid', + 'drand48', + 'ecvt', + 'encrypt', + 'endfsent', + 'endgrent', + 'endhostent', + 'endnetent', + 'endnetgrent', + 'endprotoent', + 'endpwent', + 'endservent', + 'endspent', + 'endttyent', + 'endusershell', + 'endutent', + 'erand48', + 'error_at_line', + 'ether_aton', + 'ether_ntoa', + 'exit', + 'fcloseall', + 'fcvt', + 'fgetgrent', + 'fgetpwent', + 'fgetspent', + 'fts_children', + 'fts_read', + 'gamma', + 'gammaf', + 'gammal', + 'getaliasbyname', + 'getaliasent', + 'getchar_unlocked', + 'getdate', + 'getfsent', + 'getfsfile', + 'getfsspec', + 'getgrent', + 'getgrent_r', + 'getgrgid', + 'getgrnam', + 'gethostbyaddr', + 'gethostbyname', + 'gethostbyname2', + 'gethostent', + 'gethostent_r', + 'getlogin', + 'getlogin_r', + 'getmntent', + 'getnetbyaddr', + 'getnetbyname', + 'getnetent', + 'getnetgrent', + 'getnetgrent_r', + 'getopt', + 'getopt_long', + 'getopt_long_only', + 'getpass', + 'getprotobyname', + 'getprotobynumber', + 'getprotoent', + 'getpwent', + 'getpwent_r', + 'getpwnam', + 'getpwuid', + 'getrpcbyname', + 'getrpcbynumber', + 'getrpcent', + 'getservbyname', + 'getservbyport', + 'getservent', + 'getspent', + 'getspent_r', + 'getspnam', + 'getttyent', + 'getttynam', + 'getusershell', + 'getutent', + 'getutid', + 'getutline', + 'getwchar_unlocked', + 'glob', + 'gmtime', + 'hcreate', + 'hdestroy', + 'hsearch', + 'innetgr', + 'jrand48', + 'l64a', + 'lcong48', + 'localeconv', + 'localtime', + 'login', + 'login_tty', + 'logout', + 'logwtmp', + 'lrand48', + 'mallinfo', + 'mallinfo2', + 'mblen', + 'mbrlen', + 'mbrtowc', + 'mbsnrtowcs', + 'mbsrtowcs', + 'mbtowc', + 'mcheck', + 'mcheck_check_all', + 'mcheck_pedantic', + 'mprobe', + 'mrand48', + 'mtrace', + 'muntrace', + 'nrand48', + 'profil', + 'ptsname', + 'putchar_unlocked', + 'putenv', + 'pututline', + 'putwchar_unlocked', + 'pvalloc', + 'qecvt', + 'qfcvt', + 'rcmd', + 'rcmd_af', + 're_comp', + 're_exec', + 'readdir', + 'rexec', + 'rexec_af', + 'seed48', + 'setenv', + 'setfsent', + 'setgrent', + 'sethostent', + 'sethostid', + 'setkey', + 'setlogmask', + 'setnetent', + 'setnetgrent', + 'setprotoent', + 'setpwent', + 'setservent', + 'setspent', + 'setttyent', + 'setusershell', + 'setutent', + 'sgetspent', + 'siginterrupt', + 'sleep', + 'srand48', + 'strerror', + 'strsignal', + 'strtok', + 'tmpnam', + 'ttyname', + 'ttyslot', + 'unsetenv', + 'updwtmp', + 'utmpname', + 'valloc', + 'wcrtomb', + 'wcsnrtombs', + 'wcsrtombs', + 'wctomb', + 'wordexp' +} + +# From man 7 attributes +# the full token could be feature:function/condition - we just want function. +id_MTunsafe = [re.sub('^.*:', '', re.sub('/.*$', '', x)) + for x in id_MTunsafe_full + ] -def checkstatic(data): +def reportError(token, severity, msg, errid): # noqa: D103 + cppcheckdata.reportError(token, severity, msg, 'threadsafety', errid) + + +def checkstatic(data): # noqa: D103 for var in data.variables: if var.isStatic and var.isLocal: - type = None + vartype = None if var.isClass: - type = 'object' + vartype = 'object' else: - type = 'variable' + vartype = 'variable' if var.isConst: if data.standards.cpp == 'c++03': - reportError(var.typeStartToken, 'warning', 'Local constant static ' + type + ' \'' + var.nameToken.str + '\', dangerous if it is initialized in parallel threads', 'threadsafety-const') + reportError( + var.typeStartToken, + 'warning', + 'Local constant static ' + + vartype + "'" + var.nameToken.str + + "', dangerous if it is initialized" + + ' in parallel threads', + 'threadsafety-const') else: - reportError(var.typeStartToken, 'warning', 'Local static ' + type + ': ' + var.nameToken.str, 'threadsafety') + reportError(var.typeStartToken, 'warning', + 'Local static ' + vartype + ': ' + + var.nameToken.str, + 'threadsafety') + + +def check_MTunsafe(cfg): + """ + Look for functions marked MT-unsafe in their man pages. + + The MT-unsafe functions are listed in id_MTunsafe (and id_MTunsafe_full). + That section of code can be regenerated by the external script MT-Unsafe.py + """ + for token in cfg.tokenlist: + if token.str in id_MTunsafe: + reportError(token, 'warning', token.str + ' is MT-unsafe', + 'unsafe-call') + + +if __name__ == '__main__': + parser = cppcheckdata.ArgumentParser() + args = parser.parse_args() + + quiet = args.quiet or args.cli -for arg in sys.argv[1:]: - if arg.startswith('-'): - continue + if not args.dumpfile: + if not args.quiet: + print('no input files.') + sys.exit(0) - print('Checking %s...' % arg) - data = cppcheckdata.CppcheckData(arg) + for dumpfile in args.dumpfile: + # load XML from .dump file + data = cppcheckdata.CppcheckData(dumpfile) - for cfg in data.iterconfigurations(): - print('Checking %s, config %s...' % (arg, cfg.name)) - checkstatic(cfg) + for cfg in data.iterconfigurations(): + if not args.quiet: + srcfile = data.files[0] + print('Checking %s, config %s...' % (srcfile, cfg.name)) + check_MTunsafe(cfg) + checkstatic(cfg) sys.exit(cppcheckdata.EXIT_CODE) diff --git a/addons/y2038.py b/addons/y2038.py index 9b8e94aefd2..93d237afd06 100755 --- a/addons/y2038.py +++ b/addons/y2038.py @@ -9,15 +9,13 @@ # 3. Any Y2038-unsafe symbol when _USE_TIME_BITS64 is not defined. # # Example usage: -# $ cppcheck --dump path-to-src/test.c -# $ y2038.py path-to-src/test.c.dump +# $ cppcheck --addon=y2038 path-to-src/test.c # -# y2038.py will walk the source tree for .dump files. + from __future__ import print_function import cppcheckdata import sys -import os import re @@ -59,7 +57,6 @@ 'timeval', 'utimbuf', 'itimerspec', - 'stat', 'clnt_ops', 'elf_prstatus', 'itimerval', @@ -156,22 +153,14 @@ def check_y2038_safe(dumpfile, quiet=False): # load XML from .dump file data = cppcheckdata.CppcheckData(dumpfile) - # Convert dump file path to source file in format generated by cppcheck. - # For example after the following call: - # cppcheck ./src/my-src.c --dump - # We got 'src/my-src.c' value for 'file' field in cppcheckdata. - srcfile = dumpfile.rstrip('.dump') - srcfile = os.path.expanduser(srcfile) - srcfile = os.path.normpath(srcfile) - - # go through each configuration + srcfile = data.files[0] for cfg in data.iterconfigurations(): if not quiet: print('Checking %s, config %s...' % (srcfile, cfg.name)) safe_ranges = [] safe = -1 time_bits_defined = False - srclinenr = '0' + srclinenr = 0 for directive in cfg.directives: # track source line number @@ -226,16 +215,17 @@ def check_y2038_safe(dumpfile, quiet=False): return y2038safe -def get_args(): +def get_args_parser(): parser = cppcheckdata.ArgumentParser() - return parser.parse_args() + return parser if __name__ == '__main__': - args = get_args() + parser = get_args_parser() + args = parser.parse_args() exit_code = 0 - quiet = not any((args.quiet, args.cli)) + quiet = args.quiet or args.cli if not args.dumpfile: if not args.quiet: @@ -243,7 +233,7 @@ def get_args(): sys.exit(0) for dumpfile in args.dumpfile: - if not args.quiet: + if not quiet: print('Checking ' + dumpfile + '...') check_y2038_safe(dumpfile, quiet) diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index a0f0a18934f..00000000000 --- a/appveyor.yml +++ /dev/null @@ -1,68 +0,0 @@ -version: '{build}' - -clone_depth: 10 - -matrix: - fast_finish: true - -environment: - matrix: - - VisualStudioVersion: 12.0 - platform: x64 - configuration: Debug - vcvarsall_platform: x64 - PlatformToolset: v120 - MYQTDIR: C:\Qt\5.6\msvc2013_64 - - VisualStudioVersion: 12.0 - platform: x64 - configuration: Release - vcvarsall_platform: x64 - PlatformToolset: v120 -# FIXME: These are disabled for now. They were broken by ae8653612802b41b70424ec9a5eefe8a1178f6d1 -# - VisualStudioVersion: 14.0 -# platform: x64 -# configuration: Debug -# vcvarsall_platform: x64 -# PlatformToolset: v140 -# MYQTDIR: C:\Qt\5.11\msvc2015_64 -# That platform causes frequent errors on appveyor due to an unknown infrastructure failure -# - VisualStudioVersion: 14.0 -# platform: x64 -# configuration: Release -# vcvarsall_platform: x64 -# PlatformToolset: v140 - -install: - - curl -fsSL https://github.com/Z3Prover/z3/releases/download/z3-4.8.9/z3-4.8.9-%platform%-win.zip -o z3-4.8.9-win.zip - - 7z x z3-4.8.9-win.zip -oexternals -r -y - - move externals\z3-4.8.9-%platform%-win externals\z3 - -build_script: - - ECHO Building %configuration% %platform% with MSVC %VisualStudioVersion% using %PlatformToolset% PlatformToolset - - 'CALL "C:\Program Files (x86)\Microsoft Visual Studio %VisualStudioVersion%\VC\vcvarsall.bat" %vcvarsall_platform%' - # Visual studio project.. - - msbuild "cppcheck.sln" /consoleloggerparameters:Verbosity=minimal /target:Build /property:Configuration="%configuration%";Platform=%platform% /p:PlatformToolset=%PlatformToolset% /maxcpucount /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - # the following builds are Debug ones so do not perform them in Release jobs - - 'IF "%configuration%" == "Release" exit /b 0' - # use all available processes for nmake - - set CL=/MP - # cmake.. - - mkdir build - - cd build - - cmake -DBUILD_TESTS=ON -G"NMake Makefiles" .. - - nmake - - copy bin\cppcheck.exe .. - - cd .. - # build gui.. - - ECHO MYQTDIR=%MYQTDIR% - - 'IF defined MYQTDIR cd gui' - - 'IF defined MYQTDIR set QTDIR=%MYQTDIR%' - - 'IF defined MYQTDIR set PATH=%PATH%;%QTDIR%\bin' - - 'IF defined MYQTDIR %QTDIR%\bin\qmake' - - 'IF defined MYQTDIR nmake' - - 'IF defined MYQTDIR cd ..' - -test_script: - - build\bin\testrunner.exe -q - - IF EXIST bin\debug\testrunner.exe bin\debug\testrunner.exe -q - - IF EXIST bin\testrunner.exe bin\testrunner.exe -q diff --git a/benchmarks.txt b/benchmarks.txt deleted file mode 100644 index d902aa12996..00000000000 --- a/benchmarks.txt +++ /dev/null @@ -1,22 +0,0 @@ - -========== -Benchmarks -========== - -In this file we can document some good code repos / code samples to use when working on optimisations. - -Trac tickets ------------- - -http://trac.cppcheck.net/ticket/2435 -- Tokenizer::simplifyTypedef -http://trac.cppcheck.net/ticket/8355 -- TokenList::createAst -http://trac.cppcheck.net/ticket/9007 -- Unused types - - -Repos ------ - -Small C++ library with lots of templates: -https://framagit.org/dtschump/CImg -Just check the file examples/use_tinymatwriter.cpp - diff --git a/build-pcre.txt b/build-pcre.txt index 5289f430ed0..9f4e8e06e29 100644 --- a/build-pcre.txt +++ b/build-pcre.txt @@ -1,76 +1,63 @@ -PCRE is a library that is used by the optional "rules" feature for the command -line version of cppcheck. It is readily available on Linux and Mac OS X, but -must be obtained separately for Windows. - -If you're using qmake to generate makefiles, the following behavior applies: - -- If you're not on Windows, it assumes by default that you have PCRE and want - to enable rules support. You can disable rules support (removing the PCRE - dependency) by passing HAVE_RULES=no to qmake. - -- If you are on Windows, but have PCRE available, you can enable rules support - by passing HAVE_RULES=yes to qmake. - - - Note: This includes using build.bat since it calls qmake - to use PCRE and - build.bat, you need to run set HAVE_RULES=yes before each run of build.bat - - -Build instructions ------------------- - -Windows -------- - -Visual Studio - -To build PCRE, download the source code from www.pcre.org and -CMake (https://cmake.org/download/). We assume you use Visual Studio 2015 - -otherwise adapt the commands for your version. - -VS Solution file - cmake . -G "Visual Studio 14 2015" - Open PCRE.sln with VS IDE or via cmd: - call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x86 - MSBuild PCRE.sln /target:Build /property:Configuration="Release" - - For 64-bit target: cmake . -G "Visual Studio 14 2015 Win64" - -or using NMake - call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x86 - cmake . -G "NMake Makefiles" - nmake - -or using MSYS - cmake . -G "MSYS Makefiles" - make - - -Linux ------ - -The normal Makefile should work. - -Install PCRE on Ubuntu might be needed: - sudo apt-get install libpcre3 libpcre3-dev - - -Mac OSX -------- - -Install PCRE: - -homebre - brew install pcre - -or macport - sudo port install pcre - -Ensure /path/to/pcre.h is in CXXFLAGS, e.g: - -for homebrew - export CXXFLAGS=${CXXFLAGS}:/usr/local/include - -or macport - export CXXFLAGS=${CXXFLAGS}:/opt/local/include - -Or for MSVC copy pcre.lib and pcre.h in /externals directory. +PCRE is a library that is used by the optional "rules" feature for the command +line version of cppcheck. It is readily available on Linux and Mac OS X, but +must be obtained separately for Windows. + +Build instructions +------------------ + +Windows +------- + +Visual Studio + +To build PCRE, download the source code from www.pcre.org and +CMake (https://cmake.org/download/). We assume you use Visual Studio 2015 - +otherwise adapt the commands for your version. + +VS Solution file + cmake . -G "Visual Studio 14 2015" + Open PCRE.sln with VS IDE or via cmd: + call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x86 + MSBuild PCRE.sln /target:Build /property:Configuration="Release" + + For 64-bit target: cmake . -G "Visual Studio 14 2015 Win64" + +or using NMake + call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x86 + cmake . -G "NMake Makefiles" + nmake + +or using MSYS + cmake . -G "MSYS Makefiles" + make + + +Linux +----- + +The normal Makefile should work. + +Install PCRE on Ubuntu might be needed: + sudo apt-get install libpcre3 libpcre3-dev + + +Mac OSX +------- + +Install PCRE: + +homebre + brew install pcre + +or macport + sudo port install pcre + +Ensure /path/to/pcre.h is in CXXFLAGS, e.g: + +for homebrew + export CXXFLAGS=${CXXFLAGS}:/usr/local/include + +or macport + export CXXFLAGS=${CXXFLAGS}:/opt/local/include + +Or for MSVC copy pcre.lib and pcre.h in /externals directory. diff --git a/cfg/avr.cfg b/cfg/avr.cfg index 0efb2d5c75b..bb21afac352 100644 --- a/cfg/avr.cfg +++ b/cfg/avr.cfg @@ -3,8 +3,6 @@ - - @@ -86,32 +84,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -137,9 +111,6 @@ - - - false diff --git a/cfg/boost.cfg b/cfg/boost.cfg index ded96a39998..d181860f0bc 100644 --- a/cfg/boost.cfg +++ b/cfg/boost.cfg @@ -12,8 +12,11 @@ + + + @@ -23,21 +26,40 @@ - - - + + - - + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,13 +84,20 @@ - + + + + + + + + - + @@ -78,19 +107,24 @@ + - - + + + + - + + + - false @@ -1234,4 +1268,17 @@ + + + boost::lock_guard + boost::mutex::scoped_lock + boost::recursive_mutex::scoped_lock + boost::unique_lock + boost::shared_lock + + + boost::mutex + boost::recursive_mutex + + diff --git a/cfg/bsd.cfg b/cfg/bsd.cfg index 19e82036a0a..158d7a8a885 100644 --- a/cfg/bsd.cfg +++ b/cfg/bsd.cfg @@ -181,6 +181,7 @@ false + @@ -203,6 +204,7 @@ false + @@ -216,6 +218,176 @@ 0: + + + + + false + + + + + + + + + + + + 0: + + + + + + + false + + + + + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + 0: + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + 0: + + + + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + 0: + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + 0: + + + + + @@ -228,7 +400,7 @@ false - + @@ -293,6 +465,80 @@ + + true + + + + + + + + + + + + true + + + + + + + + + + + + + + + true + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + false + + + + + + 0: + + + + 0: + + + + reallocarray + free + diff --git a/cfg/cairo.cfg b/cfg/cairo.cfg index 85c2a8e0946..e077c2fc40d 100644 --- a/cfg/cairo.cfg +++ b/cfg/cairo.cfg @@ -6,6 +6,7 @@ + diff --git a/cfg/cppcheck-cfg.rng b/cfg/cppcheck-cfg.rng index 4f3758b8e81..a54c967aaac 100644 --- a/cfg/cppcheck-cfg.rng +++ b/cfg/cppcheck-cfg.rng @@ -1,638 +1,751 @@ - - - - - - - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - false - maybe - - - - - - - - - - - - - - - - - - - - error-code - - - - - - - - - - ([a-zA-Z_][a-zA-Z_0-9:]*[ ])*([a-zA-Z_][a-zA-Z_0-9]*::)*([a-zA-Z_][a-zA-Z_0-9]*([ ]?[*&])*)+ - - - - - - - - - - - - all|([0-9]*:[0-9]*) - - - - - - - - - - - - - - - - - - - - - - error - warning - style - performance - portability - information - - - - - - Obsolescent - Obsolete - - - - - - - - - - - c99 - - - - - - - - - - - any - variadic - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (-?[0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+)?[,:])*([-]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)? - - - - - - - - - strlen - argvalue - sizeof - mul - - - - - - - - - - - - - - - value - - - - - - - - - - - - - - - - first - middle - last - - - - - - - - - - - - - - [.][a-z]+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std-like - - - - - std-like - - - - - - - - - erase - insert - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - array-like - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool - char - short - int - long - long long - - - - - - - 1 - 2 - 4 - 8 - - - - - - - s - u - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 20 - - - - - - 0 - 2 - - - - - - in - out - inout - - - - - - true - false - - - - - - [a-zA-Z_][a-zA-Z_0-9]* - - - - - - [a-zA-Z_][a-zA-Z_0-9:]* - - - - - - [a-zA-Z_][a-zA-Z_0-9:,]* - - - - - - malloc(:[1-5])?|calloc(:[1-5],[1-5])?|strdup(:[1-5])? - - - - - - resize - clear - push - pop - find - insert - erase - change-content - change-internal - change - - - - - - at_index - item - buffer - buffer-nt - start-iterator - end-iterator - iterator - size - empty - - - - - - 1 - 9223372036854775807 - - - + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + maybe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error-code + + + + + + + + + + (::)?([a-zA-Z_:][a-zA-Z_0-9:]*[ ])*([a-zA-Z_][a-zA-Z_0-9]*::)*([a-zA-Z_][a-zA-Z_0-9]*([ ]?[*& ])*)+ + + + + + + + + + + + + all|([0-9]*:[0-9]*) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + warning + style + performance + portability + information + + + + + + Obsolescent + Obsolete + + + + + + + + + + + c99 + + + + + + + + + + + any + variadic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ([-!]?[0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+)?[,:])*([-!]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)? + + + + + + + + + strlen + sizeof + mul + + + + + + + + + + + + + + + value + + + + + + + + + + + + + argvalue + + + + + + + + + + + + + + + + + + + + + + + + first + middle + last + + + + + + + + + + + + + + [.][a-z]+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + std-like + + + + + std-like + + + + + + + + + erase + insert + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + array-like + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bool + char + short + int + long + long long + + + + + + + 1 + 2 + 4 + 8 + + + + + + + s + u + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 40 + + + + + + 0 + 2 + + + + + + in + out + inout + + + + + + true + false + + + + + + [a-zA-Z_][a-zA-Z_0-9]* + + + + + + [a-zA-Z_][a-zA-Z_0-9:]* + + + + + + [a-zA-Z_][a-zA-Z_0-9:,]* + + + + + + malloc(:[1-5])?|calloc(:[1-5],[1-5])?|strdup(:[1-5])? + + + + + + resize + clear + push + pop + find + find-const + insert + erase + append + change-content + change-internal + change + + + + + + at_index + item + buffer + buffer-nt + start-iterator + end-iterator + iterator + size + empty + + + + + + 1 + 9223372036854775807 + + + diff --git a/cfg/daca.cfg b/cfg/daca.cfg deleted file mode 100644 index b2c21d66494..00000000000 --- a/cfg/daca.cfg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - false - - arg1<arg2?arg1:arg2 - - - - - - - - - - false - - arg1>arg2?arg1:arg2 - - - - - - - - diff --git a/cfg/emscripten.cfg b/cfg/emscripten.cfg index 4f345d3ffca..7a5c5903cf5 100644 --- a/cfg/emscripten.cfg +++ b/cfg/emscripten.cfg @@ -1,5 +1,108 @@ - - + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + emscripten_asm_const_ptr + emscripten_asm_const_ptr_sync_on_main_thread + free + + + + + + + + + + + + + + + + + + diff --git a/cfg/gnu.cfg b/cfg/gnu.cfg index 0dcc2c99c1a..1c8d1597a7f 100644 --- a/cfg/gnu.cfg +++ b/cfg/gnu.cfg @@ -64,6 +64,7 @@ + @@ -75,7 +76,6 @@ - @@ -92,6 +92,34 @@ 0: + + + + false + + + + + + + 0: + + + + + + + + + + 0: + + + + + + + @@ -115,6 +143,7 @@ false + @@ -140,57 +169,64 @@ - - - - - - - false + + + + + false - + + + + + - - + + + false - - + - + + + + + + + + + - - + + + + + + false + - - - - + - - - + + + + false - - - - - - - + - + + + - - false @@ -201,7 +237,8 @@ - + + true @@ -219,6 +256,50 @@ + + + + + false + + + + + + + + + + + + + + + 0: + + + + + + + false + + + + + + + + + + + + + + + 0: + + true @@ -245,6 +326,7 @@ + @@ -312,7 +394,7 @@ - + @@ -369,6 +451,7 @@ + @@ -398,6 +481,7 @@ + @@ -426,6 +510,114 @@ + + + + + false + + + + + + + + + 0: + + + + + + + + + + + + + + + 0: + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + 0: + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + 0: + + + + + + + + + + @@ -476,6 +669,7 @@ + @@ -515,6 +709,7 @@ + @@ -526,6 +721,7 @@ + @@ -533,6 +729,7 @@ false + @@ -626,6 +823,30 @@ + + + + + false + + + + + + + + + + + + + 0: + + + + + + @@ -740,21 +961,23 @@ - + - + false + + @@ -834,6 +1057,7 @@ + @@ -848,6 +1072,7 @@ + @@ -899,6 +1124,7 @@ + @@ -937,6 +1163,7 @@ + @@ -948,6 +1175,7 @@ + @@ -958,7 +1186,7 @@ - @@ -1026,6 +1254,7 @@ + @@ -1055,12 +1284,37 @@ 0: + + + + false + + + + + + + + + + 0: + + + + 0: + + + + + + - - + + arg1==0 &0 false @@ -1215,6 +1469,7 @@ + @@ -1279,6 +1534,7 @@ + @@ -1305,11 +1561,6 @@ - - - - true - false @@ -1381,6 +1632,7 @@ + @@ -1406,6 +1658,7 @@ + @@ -1416,6 +1669,43 @@ + + + + false + + + + + + + + + + + + + + + + + + + + + false + + + + + + true + + + + + + mkostemp @@ -1443,4 +1733,6 @@ + + diff --git a/cfg/googletest.cfg b/cfg/googletest.cfg index 3b2450e6c43..36dd8a40669 100644 --- a/cfg/googletest.cfg +++ b/cfg/googletest.cfg @@ -1,29 +1,29 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + @@ -32,6 +32,8 @@ + + diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg index 494e792ecba..722efb6b76b 100644 --- a/cfg/gtk.cfg +++ b/cfg/gtk.cfg @@ -2,10 +2,12 @@ - - - - + + + + + + @@ -36,13 +38,22 @@ + + + + + + + + + @@ -51,6 +62,9 @@ + + + @@ -166,11 +180,14 @@ + + + @@ -188,690 +205,724 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - g_thread_new - g_thread_try_new + g_thread_new + g_thread_try_new g_thread_ref g_thread_unref g_thread_join - g_variant_iter_copy - g_variant_iter_new + g_variant_iter_copy + g_variant_iter_new g_variant_iter_free - g_source_new - g_idle_source_new - g_timeout_source_new - g_timeout_source_new_seconds - g_child_watch_source_new - g_cancellable_source_new - g_io_create_watch + g_source_new + g_idle_source_new + g_timeout_source_new + g_timeout_source_new_seconds + g_child_watch_source_new + g_cancellable_source_new + g_io_create_watch g_source_ref g_source_unref - g_date_time_new - g_date_time_new_now - g_date_time_new_now_local - g_date_time_new_now_utc - g_date_time_new_from_unix_local - g_date_time_new_from_unix_utc - g_date_time_new_from_timeval_local - g_date_time_new_from_timeval_utc - g_date_time_new_local - g_date_time_new_utc - g_date_time_add - g_date_time_add_years - g_date_time_add_months - g_date_time_add_weeks - g_date_time_add_days - g_date_time_add_hours - g_date_time_add_minutes - g_date_time_add_seconds - g_date_time_add_full - g_date_time_to_timezone - g_date_time_to_local - g_date_time_to_utc + g_date_time_new + g_date_time_new_now + g_date_time_new_now_local + g_date_time_new_now_utc + g_date_time_new_from_unix_local + g_date_time_new_from_unix_utc + g_date_time_new_from_timeval_local + g_date_time_new_from_timeval_utc + g_date_time_new_local + g_date_time_new_utc + g_date_time_add + g_date_time_add_years + g_date_time_add_months + g_date_time_add_weeks + g_date_time_add_days + g_date_time_add_hours + g_date_time_add_minutes + g_date_time_add_seconds + g_date_time_add_full + g_date_time_to_timezone + g_date_time_to_local + g_date_time_to_utc g_date_time_ref g_date_time_unref - g_dir_open + g_dir_open g_dir_rewind g_dir_close - g_timer_new + g_timer_new g_timer_destroy - g_file_attribute_info_list_new - g_file_attribute_info_list_dup + g_file_attribute_info_list_new + g_file_attribute_info_list_dup g_file_attribute_info_list_ref g_file_attribute_info_list_unref - g_slist_alloc - g_slist_copy - g_slist_copy_deep + g_slist_alloc + g_slist_copy + g_slist_copy_deep g_slist_free g_slist_free_1 g_slist_free_full - g_variant_new - g_variant_new_va - g_variant_new_boolean - g_variant_new_byte - g_variant_new_int16 - g_variant_new_uint16 - g_variant_new_int32 - g_variant_new_uint32 - g_variant_new_int64 - g_variant_new_uint64 - g_variant_new_handle - g_variant_new_double - g_variant_new_string - g_variant_new_take_string - g_variant_new_printf - g_variant_new_signature - g_variant_new_object_path - g_variant_new_variant - g_variant_new_objv - g_variant_new_strv - g_variant_new_bytestring - g_variant_new_bytestring_array - g_variant_new_maybe - g_variant_new_array - g_variant_new_tuple - g_variant_new_dict_entry - g_variant_new_fixed_array - g_variant_new_from_data - g_variant_new_from_bytes - g_variant_builder_end - g_variant_new_parsed_va - g_variant_new_parsed - g_variant_byteswap - g_variant_get_child_value - g_variant_get_normal_form - g_variant_parse + g_variant_new + g_variant_new_va + g_variant_new_boolean + g_variant_new_byte + g_variant_new_int16 + g_variant_new_uint16 + g_variant_new_int32 + g_variant_new_uint32 + g_variant_new_int64 + g_variant_new_uint64 + g_variant_new_handle + g_variant_new_double + g_variant_new_string + g_variant_new_take_string + g_variant_new_printf + g_variant_new_signature + g_variant_new_object_path + g_variant_new_variant + g_variant_new_objv + g_variant_new_strv + g_variant_new_bytestring + g_variant_new_bytestring_array + g_variant_new_maybe + g_variant_new_array + g_variant_new_tuple + g_variant_new_dict_entry + g_variant_new_fixed_array + g_variant_new_from_data + g_variant_new_from_bytes + g_variant_builder_end + g_variant_new_parsed_va + g_variant_new_parsed + g_variant_byteswap + g_variant_get_child_value + g_variant_get_normal_form + g_variant_parse g_variant_ref g_variant_take_ref + g_variant_builder_add + g_variant_builder_add_value + g_variant_builder_add_parsed g_variant_ref_sink g_variant_unref - g_variant_iter_new + g_variant_iter_new g_variant_iter_free - g_variant_type_new - g_variant_type_copy - g_variant_type_new_array - g_variant_type_new_dict_entry - g_variant_type_new_maybe - g_variant_type_new_tuple + g_variant_type_new + g_variant_type_copy + g_variant_type_new_array + g_variant_type_new_dict_entry + g_variant_type_new_maybe + g_variant_type_new_tuple g_variant_type_free - g_allocator_new + g_allocator_new g_allocator_free - g_bookmark_file_new + g_bookmark_file_new g_bookmark_file_free - g_srv_target_new + g_srv_target_new g_srv_target_free - g_string_chunk_new + g_string_chunk_new g_string_chunk_free - g_test_log_buffer_new + g_test_log_buffer_new g_test_log_buffer_free - g_value_array_new + g_value_array_new g_value_array_free - g_cache_new + g_cache_new g_cache_destroy - g_cclosure_new - g_cclosure_new_swap - g_cclosure_new_object - g_cclosure_new_object_swap - g_closure_new_object - g_closure_new_simple + g_cclosure_new + g_cclosure_new_swap + g_cclosure_new_object + g_cclosure_new_object_swap + g_closure_new_object + g_closure_new_simple g_closure_ref g_closure_unref - g_array_new - g_array_sized_new + g_array_new + g_array_sized_new g_array_ref g_array_free g_array_unref - g_async_queue_new - g_async_queue_new_full + g_async_queue_new + g_async_queue_new_full g_async_queue_ref g_async_queue_unref - g_byte_array_new - g_byte_array_sized_new - g_byte_array_new_take - g_byte_array_sized_new - g_bytes_unref_to_array + g_byte_array_new + g_byte_array_sized_new + g_byte_array_new_take + g_byte_array_sized_new + g_bytes_unref_to_array g_byte_array_ref g_byte_array_free g_byte_array_unref - g_checksum_new - g_checksum_copy + g_checksum_new + g_checksum_copy g_checksum_free - g_main_loop_new - g_main_new + g_main_loop_new + g_main_new g_main_loop_ref g_main_loop_unref g_main_destroy - g_main_context_new + g_main_context_new g_main_context_ref g_main_context_unref g_main_destroy - g_thread_pool_new + g_thread_pool_new g_thread_pool_free - g_error_copy - g_error_new_valist - g_error_new_literal - g_error_new + g_error_copy + g_error_new_valist + g_error_new_literal + g_error_new g_error_free - g_string_new - g_string_new_len - g_string_sized_new - g_variant_print_string + g_string_new + g_string_new_len + g_string_sized_new + g_variant_print_string g_string_free - g_ptr_array_new - g_ptr_array_new_full - g_ptr_array_new_with_free_func + g_ptr_array_new + g_ptr_array_new_full + g_ptr_array_new_with_free_func g_ptr_array_ref g_ptr_array_free g_ptr_array_unref - g_pattern_spec_new + g_pattern_spec_new g_pattern_spec_free - g_key_file_new + g_key_file_new g_key_file_ref g_key_file_free g_key_file_unref - g_io_module_scope_new + g_io_module_scope_new g_io_module_scope_free - g_ascii_strdown - g_ascii_strup - g_base64_decode - g_base64_encode - g_bookmark_file_get_description - g_bookmark_file_get_mime_type - g_bookmark_file_get_title - g_bookmark_file_to_data - g_build_filename - g_build_filenamev - g_build_path - g_build_pathv - g_bytes_unref_to_data - g_compute_checksum_for_bytes - g_compute_checksum_for_data - g_compute_checksum_for_string - g_compute_hmac_for_data - g_compute_hmac_for_string - g_convert - g_convert_with_fallback - g_convert_with_iconv - g_credentials_to_string - g_date_time_format - g_filename_display_basename - g_filename_display_name - g_filename_from_uri - g_filename_to_uri - g_get_codeset - g_get_current_dir - g_get_locale_variants - g_key_file_get_start_group - g_key_file_to_data - g_malloc - g_realloc - g_malloc0 - g_malloc0_n - g_malloc_n - g_realloc_n - g_memdup - g_path_get_basename - g_path_get_dirname - g_slice_alloc - g_slice_alloc0 - g_slice_copy - g_strcompress - g_strconcat - g_strdup - g_strdup_printf - g_strdup_vprintf - g_strescape - g_strjoin - g_strjoinv - g_strndup - g_strnfill - g_time_val_to_iso8601 - g_try_malloc - g_try_realloc - g_try_malloc0 - g_try_malloc0_n - g_try_malloc_n - g_try_realloc_n - g_ucs4_to_utf16 - g_ucs4_to_utf8 - g_unicode_canonical_decomposition - g_utf16_to_ucs4 - g_utf16_to_utf8 - g_utf8_casefold - g_utf8_collate_key - g_utf8_collate_key_for_filename - g_utf8_normalize - g_utf8_strdown - g_utf8_strreverse - g_utf8_strup - g_utf8_substring - g_utf8_to_ucs4 - g_utf8_to_ucs4_fast - g_utf8_to_ucs4_fast - g_utf8_to_utf16 - g_key_file_get_locale_string - g_key_file_get_value - g_key_file_get_string - g_key_file_get_boolean_list - g_key_file_get_integer_list - g_key_file_get_double_list - g_key_file_get_comment - g_dbus_proxy_get_name_owner - g_file_info_get_attribute_as_string - g_file_attribute_matcher_to_string - g_app_launch_context_get_environment - g_app_launch_context_get_startup_notify_id - g_filename_completer_get_completion_suffix - g_inet_address_mask_to_string - g_variant_dup_string - g_variant_dup_bytestring - g_variant_get_objv - g_variant_get_strv - g_variant_print - g_datalist_id_dup_data - g_dir_make_tmp - g_filename_from_utf8 - g_filename_to_utf8 - g_file_read_link - g_find_program_in_path - g_format_size - g_format_size_for_display - g_format_size_full - g_hostname_to_ascii - g_hostname_to_unicode - g_locale_from_utf8 - g_locale_to_utf8 - g_markup_escape_text - g_markup_printf_escaped - g_markup_vprintf_escaped - g_match_info_expand_references - g_match_info_fetch - g_match_info_fetch_named - g_option_context_get_help - g_regex_escape_nul - g_regex_escape_string - g_regex_replace - g_regex_replace_eval - g_regex_replace_literal - g_shell_quote - g_shell_unquote - g_uri_escape_string - g_uri_parse_scheme - g_uri_unescape_segment - g_uri_unescape_string - g_variant_type_dup_string - g_value_dup_string + g_ascii_strdown + g_ascii_strup + g_base64_decode + g_base64_encode + g_bookmark_file_get_description + g_bookmark_file_get_mime_type + g_bookmark_file_get_title + g_bookmark_file_to_data + g_build_filename + g_build_filenamev + g_build_path + g_build_pathv + g_bytes_unref_to_data + g_compute_checksum_for_bytes + g_compute_checksum_for_data + g_compute_checksum_for_string + g_compute_hmac_for_data + g_compute_hmac_for_string + g_convert + g_convert_with_fallback + g_convert_with_iconv + g_credentials_to_string + g_date_time_format + g_filename_display_basename + g_filename_display_name + g_filename_from_uri + g_filename_to_uri + g_get_codeset + g_get_current_dir + g_get_locale_variants + g_key_file_get_start_group + g_key_file_to_data + g_malloc + g_realloc + g_malloc0 + g_malloc0_n + g_malloc_n + g_realloc_n + g_memdup + g_path_get_basename + g_path_get_dirname + g_slice_alloc + g_slice_alloc0 + g_slice_copy + g_strcompress + g_strconcat + g_strdup + g_strdup_printf + g_strdup_vprintf + g_strescape + g_strjoin + g_strjoinv + g_strndup + g_strnfill + g_time_val_to_iso8601 + g_try_malloc + g_try_realloc + g_try_malloc0 + g_try_malloc0_n + g_try_malloc_n + g_try_realloc_n + g_ucs4_to_utf16 + g_ucs4_to_utf8 + g_unicode_canonical_decomposition + g_utf16_to_ucs4 + g_utf16_to_utf8 + g_utf8_casefold + g_utf8_collate_key + g_utf8_collate_key_for_filename + g_utf8_normalize + g_utf8_strdown + g_utf8_strreverse + g_utf8_strup + g_utf8_substring + g_utf8_to_ucs4 + g_utf8_to_ucs4_fast + g_utf8_to_ucs4_fast + g_utf8_to_utf16 + g_key_file_get_locale_string + g_key_file_get_value + g_key_file_get_string + g_key_file_get_boolean_list + g_key_file_get_integer_list + g_key_file_get_double_list + g_key_file_get_comment + g_dbus_proxy_get_name_owner + g_file_info_get_attribute_as_string + g_file_attribute_matcher_to_string + g_app_launch_context_get_environment + g_app_launch_context_get_startup_notify_id + g_filename_completer_get_completion_suffix + g_inet_address_mask_to_string + g_variant_dup_string + g_variant_dup_bytestring + g_variant_get_objv + g_variant_get_strv + g_variant_print + g_datalist_id_dup_data + g_dir_make_tmp + g_filename_from_utf8 + g_filename_to_utf8 + g_file_read_link + g_find_program_in_path + g_format_size + g_format_size_for_display + g_format_size_full + g_hostname_to_ascii + g_hostname_to_unicode + g_locale_from_utf8 + g_locale_to_utf8 + g_markup_escape_text + g_markup_printf_escaped + g_markup_vprintf_escaped + g_match_info_expand_references + g_match_info_fetch + g_match_info_fetch_named + g_option_context_get_help + g_regex_escape_nul + g_regex_escape_string + g_regex_replace + g_regex_replace_eval + g_regex_replace_literal + g_shell_quote + g_shell_unquote + g_uri_escape_string + g_uri_parse_scheme + g_uri_unescape_segment + g_uri_unescape_string + g_variant_type_dup_string + g_value_dup_string g_register_data g_free - g_hash_table_new_full - g_hash_table_new + g_hash_table_new_full + g_hash_table_new g_hash_table_ref g_hash_table_destroy g_hash_table_unref - g_io_channel_unix_new - g_io_channel_win32_new_fd - g_io_channel_win32_new_socket - g_io_channel_win32_new_messages - g_io_channel_new_file + g_io_channel_unix_new + g_io_channel_win32_new_fd + g_io_channel_win32_new_socket + g_io_channel_win32_new_messages + g_io_channel_new_file g_io_channel_ref g_io_channel_close g_io_channel_shutdown g_io_channel_unref - g_emblemed_icon_get_emblems - g_list_alloc - g_list_copy - g_list_copy_deep - g_app_info_get_all - g_app_info_get_all_for_type - g_app_info_get_fallback_for_type - g_app_info_get_recommended_for_type - g_io_modules_load_all_in_directory - g_io_modules_load_all_in_directory_with_scope - g_hash_table_get_keys - g_hash_table_get_values + g_emblemed_icon_get_emblems + g_list_alloc + g_list_copy + g_list_copy_deep + g_app_info_get_all + g_app_info_get_all_for_type + g_app_info_get_fallback_for_type + g_app_info_get_recommended_for_type + g_io_modules_load_all_in_directory + g_io_modules_load_all_in_directory_with_scope + g_hash_table_get_keys + g_hash_table_get_values g_list_free g_list_free_1 g_list_free_full - g_regex_new + g_regex_new g_regex_ref g_regex_unref - g_node_new - g_node_copy - g_node_copy_deep + g_node_new + g_node_copy + g_node_copy_deep g_node_destroy - g_time_zone_new - g_time_zone_new_local - g_time_zone_new_utc + g_time_zone_new + g_time_zone_new_local + g_time_zone_new_utc g_time_zone_ref g_time_zone_unref - g_markup_parse_context_new + g_markup_parse_context_new g_markup_parse_context_free - g_mapped_file_new - g_mapped_file_new_from_fd + g_mapped_file_new + g_mapped_file_new_from_fd g_mapped_file_ref g_mapped_file_free g_mapped_file_unref - g_mutex_new + g_mutex_new g_mutex_free - g_mem_chunk_new + g_mem_chunk_new g_mem_chunk_free - g_option_group_new + g_option_group_new g_option_group_free - g_option_context_new + g_option_context_new g_option_context_free - g_rand_new - g_rand_copy - g_rand_new_with_seed - g_rand_new_with_seed_array + g_rand_new + g_rand_copy + g_rand_new_with_seed + g_rand_new_with_seed_array g_rand_free - g_queue_new - g_queue_copy + g_queue_new + g_queue_copy g_queue_free + g_queue_free_full - g_slice_new + g_slice_new g_slice_free g_slice_free1 - g_sequence_new + g_sequence_new g_sequence_free - g_completion_new + g_completion_new g_completion_free - g_chunk_new + g_chunk_new g_chunk_free - g_bytes_new - g_bytes_new_take - g_bytes_new_static - g_bytes_new_with_free_func - g_bytes_new_from_bytes - g_byte_array_free_to_bytes - g_memory_output_stream_steal_as_bytes - g_variant_get_data_as_bytes - g_mapped_file_get_bytes + g_bytes_new + g_bytes_new_take + g_bytes_new_static + g_bytes_new_with_free_func + g_bytes_new_from_bytes + g_byte_array_free_to_bytes + g_memory_output_stream_steal_as_bytes + g_variant_get_data_as_bytes + g_mapped_file_get_bytes g_bytes_ref g_bytes_unref - g_bookmark_file_get_uris - g_bookmark_file_get_groups - g_bookmark_file_get_applications - g_key_file_get_groups - g_key_file_get_keys - g_strdupv - g_strsplit - g_strsplit_set - g_uri_list_extract_uris - g_key_file_get_string_list - g_key_file_get_locale_string_list - g_file_info_list_attributes - g_file_info_get_attribute_stringv - g_app_launch_context_get_environment - g_filename_completer_get_completions - g_io_module_query - g_variant_dup_objv - g_variant_dup_bytestring_array - g_environ_setenv - g_environ_unsetenv - g_get_environ - g_listenv - g_match_info_fetch_all - g_regex_split - g_regex_split_full - g_regex_split_simple - g_regex_split_simple - g_variant_dup_strv + g_bookmark_file_get_uris + g_bookmark_file_get_groups + g_bookmark_file_get_applications + g_key_file_get_groups + g_key_file_get_keys + g_strdupv + g_strsplit + g_strsplit_set + g_uri_list_extract_uris + g_key_file_get_string_list + g_key_file_get_locale_string_list + g_file_info_list_attributes + g_file_info_get_attribute_stringv + g_app_launch_context_get_environment + g_filename_completer_get_completions + g_io_module_query + g_variant_dup_objv + g_variant_dup_bytestring_array + g_environ_setenv + g_environ_unsetenv + g_get_environ + g_listenv + g_match_info_fetch_all + g_regex_split + g_regex_split_full + g_regex_split_simple + g_regex_split_simple + g_variant_dup_strv g_strfreev - g_hmac_new - g_hmac_copy + g_hmac_new + g_hmac_copy g_hmac_ref g_hmac_unref - g_hook_alloc + g_hook_alloc g_hook_ref g_hook_unref g_hook_destroy g_hook_free - g_date_new - g_date_new_dmy - g_date_new_julian + g_date_new + g_date_new_dmy + g_date_new_julian g_date_free - g_variant_builder_new + g_variant_builder_new g_variant_builder_ref g_variant_builder_unref - g_cond_new + g_cond_new g_cond_free - g_app_launch_context_new - g_app_info_create_from_commandline - g_app_info_dup - g_app_info_get_default_for_type - 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 - g_charset_converter_new - g_converter_input_stream_new - g_converter_output_stream_new - g_credentials_new - g_data_input_stream_new - g_data_output_stream_new - g_dbus_auth_observer_new - g_dbus_connection_new_finish - g_dbus_connection_new_sync - g_dbus_connection_new_for_address_finish - g_dbus_connection_new_for_address_sync - g_dbus_message_new - g_dbus_message_new_signal - g_dbus_message_new_method_call - g_dbus_message_new_method_reply - g_dbus_message_new_method_error - g_dbus_message_new_method_error_valist - g_dbus_message_new_method_error_literal - g_dbus_object_manager_client_new_finish - g_dbus_object_manager_client_new_sync - g_dbus_object_manager_client_new_for_bus_finish - g_dbus_object_manager_client_new_for_bus_sync - g_dbus_object_manager_server_new - g_dbus_object_manager_server_get_connection - g_dbus_object_proxy_new - g_dbus_object_skeleton_new - g_dbus_proxy_new_finish - g_dbus_proxy_new_sync - g_dbus_proxy_new_for_bus_finish - g_dbus_proxy_new_for_bus_sync - g_emblemed_icon_new - g_emblem_new - g_emblem_new_with_origin - g_file_icon_new - g_file_icon_get_file - g_file_info_new - g_file_info_dup - g_file_info_get_icon - g_file_info_get_symbolic_icon - g_file_info_get_attribute_object - g_file_info_get_deletion_date - g_filename_completer_new - g_inet_address_mask_new - g_inet_address_mask_new_from_string - g_inet_address_mask_get_address - g_inet_socket_address_new - g_inet_socket_address_get_address - g_initable_new - g_initable_new_valist - g_initable_newv - g_io_module_new - g_io_module_scope_new - g_keyfile_settings_backend_new - g_memory_input_stream_new - g_memory_input_stream_new_from_data - g_memory_input_stream_new_from_bytes - g_memory_output_stream_new - g_memory_output_stream_new_resizable - g_memory_settings_backend_new - g_null_settings_backend_new - g_menu_item_new - g_menu_item_new_section - g_menu_item_new_submenu - g_menu_item_new_from_model - g_menu_new - g_mount_operation_new - g_network_address_new - g_network_service_new - g_object_new - g_param_spec_pool_new - g_pollable_source_new - g_private_new - g_proxy_address_new - g_ptr_array_sized_new - g_relation_new - g_scanner_new - g_settings_new - g_signal_type_cclosure_new - g_simple_action_group_new - g_simple_action_new - g_simple_async_result_new - g_simple_permission_new - g_socket_client_new - g_socket_listener_new - g_socket_new - g_socket_service_new - g_tcp_wrapper_connection_new - g_test_dbus_new - g_themed_icon_new - g_threaded_socket_service_new - g_tls_client_connection_new - g_tls_file_database_new - g_tls_password_new - g_tls_server_connection_new - g_unix_signal_source_new - g_zlib_compressor_new - g_zlib_decompressor_new + g_app_launch_context_new + g_app_info_create_from_commandline + g_app_info_dup + g_app_info_get_default_for_type + 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 + g_charset_converter_new + g_converter_input_stream_new + g_converter_output_stream_new + g_credentials_new + g_data_input_stream_new + g_data_output_stream_new + g_dbus_auth_observer_new + g_dbus_connection_new_finish + g_dbus_connection_new_sync + g_dbus_connection_new_for_address_finish + g_dbus_connection_new_for_address_sync + g_dbus_message_new + g_dbus_message_new_signal + g_dbus_message_new_method_call + g_dbus_message_new_method_reply + g_dbus_message_new_method_error + g_dbus_message_new_method_error_valist + g_dbus_message_new_method_error_literal + g_dbus_object_manager_client_new_finish + g_dbus_object_manager_client_new_sync + g_dbus_object_manager_client_new_for_bus_finish + g_dbus_object_manager_client_new_for_bus_sync + g_dbus_object_manager_server_new + g_dbus_object_manager_server_get_connection + g_dbus_object_proxy_new + g_dbus_object_skeleton_new + g_dbus_proxy_new_finish + g_dbus_proxy_new_sync + g_dbus_proxy_new_for_bus_finish + g_dbus_proxy_new_for_bus_sync + g_emblemed_icon_new + g_emblem_new + g_emblem_new_with_origin + g_file_icon_new + g_file_icon_get_file + g_file_info_new + g_file_info_dup + g_file_info_get_icon + g_file_info_get_symbolic_icon + g_file_info_get_attribute_object + g_file_info_get_deletion_date + g_filename_completer_new + g_inet_address_mask_new + g_inet_address_mask_new_from_string + g_inet_address_mask_get_address + g_inet_socket_address_new + g_inet_socket_address_get_address + g_initable_new + g_initable_new_valist + g_initable_newv + g_io_module_new + g_io_module_scope_new + g_keyfile_settings_backend_new + g_memory_input_stream_new + g_memory_input_stream_new_from_data + g_memory_input_stream_new_from_bytes + g_memory_output_stream_new + g_memory_output_stream_new_resizable + g_memory_settings_backend_new + g_null_settings_backend_new + g_menu_item_new + g_menu_item_new_section + g_menu_item_new_submenu + g_menu_item_new_from_model + g_menu_new + g_mount_operation_new + g_network_address_new + g_network_service_new + g_object_new + g_param_spec_pool_new + g_pollable_source_new + g_private_new + g_proxy_address_new + g_ptr_array_sized_new + g_relation_new + g_scanner_new + g_settings_new + g_signal_type_cclosure_new + g_simple_action_group_new + g_simple_action_new + g_simple_async_result_new + g_simple_permission_new + g_socket_client_new + g_socket_listener_new + g_socket_new + g_socket_service_new + g_tcp_wrapper_connection_new + g_test_dbus_new + g_themed_icon_new + g_threaded_socket_service_new + g_tls_client_connection_new + g_tls_file_database_new + g_tls_password_new + g_tls_server_connection_new + g_unix_signal_source_new + g_zlib_compressor_new + g_zlib_decompressor_new g_object_ref g_object_unref gtk_widget_destroy - g_tree_new - g_tree_new_full - g_tree_new_with_data + g_tree_new + g_tree_new_full + g_tree_new_with_data g_tree_ref g_tree_unref + g_tree_destroy - g_file_attribute_matcher_new - g_file_attribute_matcher_subtract + g_file_attribute_matcher_new + g_file_attribute_matcher_subtract g_file_attribute_matcher_ref g_file_attribute_matcher_unref @@ -885,31 +936,39 @@ false + + - false + + - + + + false + + + false @@ -919,18 +978,17 @@ - + - + false - @@ -939,7 +997,6 @@ - @@ -948,7 +1005,6 @@ - @@ -959,23 +1015,80 @@ - + + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + false + + + + + + + + false @@ -989,26 +1102,77 @@ false + false + + + + + + + + - + + + false + + + + + + + + + - + + + false + + + + + + + + + false + + + + + + + + + + + + + + false - - - false - - - false + + + + + + + + + + + + false @@ -1025,20 +1189,31 @@ false + false + + + false + + + + + + + false + - @@ -1046,35 +1221,87 @@ false - + false - - + + + + + + false - + + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + @@ -1084,7 +1311,9 @@ - + + + false + + + + false - + @@ -1193,197 +1424,623 @@ + false + + + + + + + + + + + + 0: + + false + + + + + + + false + + + + + + + + + 0: + + + + + + + + 0: + + false + + + + + + + + + + + + 0: + - - - false - - - - false - - + + + false + + + + + + + + + 0: + + + + + + false + + + + + + + + + 0: + + + + + 0: + + false + + + + + + + + + false + + + + + + + + 0: + + false + + + + + + + + + false + + + + + + + + + + - - - false - + false + + + + + + + + + + + + + 0: + + false + + + + + + + + + + + + + 0: + - - - false - - + + + false + + + + + + + + + 0: + + false + + + + + + + + + 0: + + + + + 0: + + false + + + + + + + + 0: + + false + + + + + + + + + false + + + + + + + + + + + false + + + + + + + false + + + + + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + + + 0: + + + + + + + + + + + + false + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + 0: + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + + + + + false + + + + + + + + + false + + + + + + - false + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + + - - - false - - + + + false + + + + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + + - + + + false + + + + + + + + - + + + false + + + + + + false - - - - false - - - - false + + + + + + @@ -1433,21 +2090,40 @@ false + false + + + + + + - - - false - - + + + + + + + false + + false + + + + + + + + @@ -1456,99 +2132,202 @@ - + false + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + - - - false - + false + + + + + + + + + + - - - false - - + + false + + + + + + + + + false - - + + + false + + + + + + + + + 0: + + false + + + + + + + + + 0: + - - - false - + false + + + + + + + + - - - false - - + + + false + + + + + + + + + false + + + + + + + + false + + + + + false + + + + + + + + false + + + + + + + + + + - - - false - - - - false - - + + + + false + + @@ -1558,73 +2337,215 @@ false + false + + + + + + + + + + + - - - false - - - - false - - + + + false + + + + + + + + - + + + false + + + + + + + + + 0: + + false + + + + + + + + + 0: + + + + + 0: + + false + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + - - - false - + false + + + + + + + + + + + + + + + + + + false + + + + + + + + + false + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + @@ -1634,8 +2555,12 @@ - - + + + + + + @@ -1662,6 +2587,7 @@ + false @@ -1670,41 +2596,110 @@ + false + + + + + + + + + 0: + + false + + + + + + + + + 0: + - - - false - - + + false + + + + + + + + - + + + false + + + + + + + + + false + + + + + + + + false + + + + + false + + + + + + + + false + + + + + + + + + + @@ -1750,33 +2745,20 @@ false - - - false - - - - false - - - - false - - - - false - - - - false - + false + + + + + false + @@ -2115,31 +3097,52 @@ - - - false - - - - false - - + + + + false + + + + + + + + false + + + + + + + - - - false - + false + + + + + + + + + + + + + + - + false @@ -2152,14 +3155,6 @@ false - - - false - - - - false - false @@ -2177,9 +3172,31 @@ false + false + + + + + + + + + + + + + + + + + + + + + @@ -2334,11 +3351,13 @@ + + @@ -2348,6 +3367,7 @@ + @@ -2363,9 +3383,11 @@ + + @@ -2496,21 +3518,47 @@ false + false + + + + + + + + + + false + + + + + + + + + false + false + + + + + @@ -2519,10 +3567,21 @@ false + + + + + + false + + + + + @@ -2617,10 +3676,6 @@ false - - - false - false @@ -2629,151 +3684,130 @@ false - - - false - + false + + + + + + + + + + + + false - - - - false - - + + + + + + + + + + + + + + - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - + + false + + + + - + + false + + + + + + + + + - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false @@ -2795,13 +3829,28 @@ + false + + + + + + + + + false + + + + + @@ -2861,21 +3910,85 @@ false + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + false + + + + false + + + + false @@ -2918,29 +4031,29 @@ false - - - false - false - - - false - - + + + false + + false - + + + false + + @@ -2999,50 +4112,6 @@ - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - false @@ -3055,17 +4124,45 @@ false + false + + + + + + + + false + + + + + + + + + + + + + + + false + + + + @@ -3091,13 +4188,54 @@ false + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + @@ -3107,10 +4245,6 @@ false - - - false - false @@ -3666,29 +4800,9 @@ - - - - - - - false - - - - false - - - - false - - - - false - - - - false + + + @@ -3722,9 +4836,19 @@ false + false + + + + + + + + + @@ -3756,18 +4880,6 @@ 0: - - - false - - - - false - - - - false - false @@ -3780,30 +4892,6 @@ false - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - false @@ -3908,7 +4996,7 @@ false - + false @@ -4010,6 +5098,7 @@ + false @@ -4023,13 +5112,23 @@ - - - false - - + + + false + + + + + + + + + + + + @@ -4083,6 +5182,7 @@ + false @@ -4206,17 +5306,53 @@ 0: + false + + + + + + + false + + + + + + + + + + + - + + + false + + + + + + + + + + + + + + + @@ -4240,10 +5376,6 @@ - - - false - false @@ -4256,9 +5388,17 @@ false + false + + + + + + + @@ -4396,65 +5536,47 @@ false - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - + + + false + + + + + + + + + + + + - + + false + + + + + + + + + + + + + + + + + + + @@ -4656,224 +5778,243 @@ false - - - false - - - - false - - - - false - - - - false - - - - false - - - - - false - - - - - - - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - + false - + false - + false - + false - + false - + + false + + + + + + - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + false - + + + false + + + + + + - + + + false + + + + + - + + + + + false + + + + + + - - + + + false + + + + + + + + + - - + + + false + + + + + + + + + + + + + + + - - + + + false + + + + + - + + + false + + + + + + + + + + + - + false + g_async_queue_timed_pop_unlocked is deprecated and should not be used in newly-written code.use g_async_queue_timeout_pop_unlocked(). - + + + false + + + + + + + + 0: + false + g_async_queue_unref_and_unlock has been deprecated since version 2.8 and should not be used in newly-written code. Reference counting is done atomically. so g_async_queue_unref() can be used regardless of the queues lock. @@ -5007,25 +6148,70 @@ + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + false + + + + + + + false + + + + + + @@ -5199,65 +6385,57 @@ false + false + + + + + + + + + + - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - + + + + + + + + + + + + + false + + + + + + false + false - - - - false - - - - false - - - - false + + + + + + @@ -5271,9 +6449,16 @@ false + false + + + + + + @@ -6087,129 +7272,344 @@ false - + + + + false + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + - + + false + + + + + + + + + + + - - + + false + + - - + + false + + + + + + - - + + false + + + + + + - false + + + + + + + + + false + + + + + + + false + + + + + + + + + + false + + + + + - - - false - - + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + false + + + + + + - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - - - false - - + + + + + false + + + + + + - + + + + + false + + + + + - + + + false + + + + + + + + + + 0: + - + + + false + + + + + + + + + 0: + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + false + + + + + + + + + + + + false + + + + + + + + + @@ -6943,53 +8343,158 @@ false + + + false + + + + + + + + - false + + + + + false + + + + + + + + + + + - + + + + + false + + + - + + + + + + false + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + + - - - false - - - - false - - + + + false + + + + + + + + + false + + + + + + + + + + + - + + + false + + + + + + + + + false + g_tree_traverse has been deprecated since version 2.2 and should not be used in newly-written code. The order of a balanced tree is somewhat arbitrary. If you just want to visit all nodes in sorted order, use g_tree_foreach() instead. If you really need to visit nodes in a different order, consider using an n-ary tree. @@ -7199,29 +8704,91 @@ false + - false + + + + + + + + + + + + - - + + false + + + + + + + + - - + + false + + + + + + + + + + + + - - + + + false + + + + + - false + + + + + + + + + - false + + + + + + + + + + + + false + + + + + @@ -7319,6 +8886,174 @@ false + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + + @@ -20431,7 +22166,7 @@ - + @@ -20443,6 +22178,17 @@ + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cfg/icu.cfg b/cfg/icu.cfg index 9932716f2d1..5e1f9163fd0 100644 --- a/cfg/icu.cfg +++ b/cfg/icu.cfg @@ -1,6 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cfg/kde.cfg b/cfg/kde.cfg index 5973916fd60..1131d5e0c50 100644 --- a/cfg/kde.cfg +++ b/cfg/kde.cfg @@ -20,6 +20,11 @@ + + + + + @@ -48,4 +53,40 @@ + + + + false + + + + + + + + false + + + + + + + + + false + + + + + + + + + false + + + + + + diff --git a/cfg/libcerror.cfg b/cfg/libcerror.cfg index 0bdd0874eb8..ce621e99d44 100644 --- a/cfg/libcerror.cfg +++ b/cfg/libcerror.cfg @@ -125,4 +125,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cfg/mfc.cfg b/cfg/mfc.cfg index ad7c420e6c8..1a8100f2ef0 100644 --- a/cfg/mfc.cfg +++ b/cfg/mfc.cfg @@ -253,4 +253,19 @@ + + + + + + + + + + + + + + + diff --git a/cfg/microsoft_atl.cfg b/cfg/microsoft_atl.cfg index 05e26a90b03..3cd784bbf70 100644 --- a/cfg/microsoft_atl.cfg +++ b/cfg/microsoft_atl.cfg @@ -3,6 +3,11 @@ + + + + + @@ -20,8 +25,16 @@ + + + + + + + + diff --git a/cfg/microsoft_sal.cfg b/cfg/microsoft_sal.cfg index 3cdb8299cd4..36371a3610b 100644 --- a/cfg/microsoft_sal.cfg +++ b/cfg/microsoft_sal.cfg @@ -338,7 +338,6 @@ - diff --git a/cfg/opencv2.cfg b/cfg/opencv2.cfg index 797035c1e57..80b51ad7a08 100644 --- a/cfg/opencv2.cfg +++ b/cfg/opencv2.cfg @@ -69,7 +69,7 @@ false - + diff --git a/cfg/opengl.cfg b/cfg/opengl.cfg index 72dcaddb961..ec37abf5516 100644 --- a/cfg/opengl.cfg +++ b/cfg/opengl.cfg @@ -211,6 +211,7 @@ + false diff --git a/cfg/posix.cfg b/cfg/posix.cfg index aee217c9249..751142bacc1 100644 --- a/cfg/posix.cfg +++ b/cfg/posix.cfg @@ -14,6 +14,149 @@ + + + false + + + + + + + 0: + + + + + + + + + + 0: + + + + + + + + false + + + + + + + + + + + + + + 0: + + + + + 0: + + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + 0: + + + + + + + + + + + + false + + + + + + + + + 0: + + + + + + @@ -273,6 +416,7 @@ + @@ -367,6 +511,13 @@ + + + + false + + + @@ -375,6 +526,7 @@ + @@ -393,6 +545,7 @@ + @@ -530,6 +683,7 @@ + @@ -561,6 +715,7 @@ + @@ -641,6 +796,7 @@ + 0: @@ -650,6 +806,7 @@ + @@ -660,11 +817,13 @@ + + @@ -677,6 +836,7 @@ + @@ -701,6 +861,7 @@ + @@ -719,6 +880,7 @@ + @@ -781,6 +943,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + @@ -799,6 +962,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + @@ -864,6 +1028,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + Non reentrant function 'getprotobyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getprotobyname_r'. @@ -896,10 +1061,12 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + + Non reentrant function 'getservbyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getservbyname_r'. @@ -916,6 +1083,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + Non reentrant function 'getservbyport' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getservbyport_r'. @@ -937,6 +1105,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + Non reentrant function 'getnetbyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getnetbyname_r'. @@ -974,6 +1143,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + @@ -986,6 +1156,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + @@ -1064,17 +1235,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func - - - - - false - - - - - - + @@ -1085,6 +1246,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + @@ -1101,6 +1263,7 @@ The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() func + @@ -1160,6 +1323,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1174,6 +1338,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1194,6 +1359,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1214,6 +1380,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1232,6 +1399,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1254,6 +1422,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1277,6 +1446,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1288,6 +1458,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1299,6 +1470,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1309,11 +1481,13 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + @@ -1330,6 +1504,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1339,6 +1514,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1355,6 +1531,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1370,6 +1547,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1380,6 +1558,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1394,6 +1573,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1426,6 +1606,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1444,6 +1625,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1482,6 +1664,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1499,6 +1682,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1544,6 +1728,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1551,6 +1736,20 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + + + false + + + + + + + + + + false @@ -1561,10 +1760,10 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 0: - + - + @@ -1579,11 +1778,12 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + - + @@ -1598,12 +1798,14 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + - + + @@ -1614,6 +1816,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1647,11 +1850,13 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + @@ -1744,6 +1949,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + -20:19 @@ -1803,6 +2009,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1833,6 +2040,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -1845,8 +2053,8 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false - @@ -1895,13 +2103,16 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + + @@ -1912,10 +2123,35 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + + + + + + + + + 0: + + + + + + + + false + + + + + + + @@ -1944,57 +2180,174 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 1: - - + + - + - - 0: - - - - - - - - 0: - - - false + + - + + + - 0: - - - - + - + + + + + + + + - 0: + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + + + + + + + 0: + + + + + + + + 0: + + + + + + + + + false + + + + + + 0: + + + + + + + + + 0: + + + + + + + false + + + 0: + + + + + + + + + + + 0: + + + + + + + + + 0: + + 0: @@ -2011,11 +2364,13 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 0: + + 0: @@ -2047,16 +2402,20 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 0: + + + 0: + @@ -2067,6 +2426,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 0: + @@ -2076,9 +2436,13 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - + + + + + 0: @@ -2184,6 +2548,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -2241,6 +2606,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -2258,6 +2624,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -2404,7 +2771,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - + @@ -2416,14 +2783,14 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - + + see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html --> false @@ -2688,9 +3055,11 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + 0: + 0: @@ -2740,7 +3109,9 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + @@ -2749,6 +3120,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -2761,6 +3133,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -2847,6 +3220,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -2893,9 +3267,11 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + + @@ -2988,6 +3364,56 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'. + + + + + + false + + + + + + + + + + + + + + + 0: + + + + + + + + + + + + false + + + + + + + + + + + 0: + + + + + + @@ -2996,6 +3422,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + Non reentrant function 'getpwnam' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwnam_r'. @@ -3019,6 +3446,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3033,9 +3461,14 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + + + + + - + @@ -3045,6 +3478,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3058,17 +3492,21 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s Non reentrant function 'getpwuid' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwuid_r'. - - + + + false - + + + + @@ -3078,6 +3516,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3115,6 +3554,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3125,6 +3565,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3148,6 +3589,90 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + + + + false + + + + + + + + + + + + + + + + + 1: + + + + + + + + + + + false + + + + + + + + + + + + + + + + 1: + + + + + + + + + + + + false + + + + + + + + + + + 0: + + + + + 0: + + + + @@ -3158,6 +3683,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3194,6 +3720,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3394,7 +3921,52 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + 0:2 + + + + + + + false + + + + + 0: + + + + + + + + + 0:2 + + + + + + + false + + + + + 0: + + + + + + + + + 0:2 + + @@ -3416,6 +3988,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3426,6 +3999,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3435,6 +4009,13 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + + + + + + false + @@ -3454,10 +4035,12 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + @@ -3471,6 +4054,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3478,6 +4062,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + @@ -3510,7 +4095,6 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - Non reentrant function 'readdir' called. For threadsafe applications it is recommended to use the reentrant replacement function 'readdir_r'. @@ -3538,6 +4122,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3557,20 +4142,25 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + 0: + + 0: + + @@ -3579,10 +4169,12 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + 0: + @@ -3594,6 +4186,30 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 0: + + + + + false + + + + + + + + + + + + + + 0: + + + + + @@ -3799,6 +4415,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + false @@ -3846,6 +4463,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3875,11 +4493,13 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + @@ -3888,6 +4508,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + @@ -3908,6 +4529,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -3924,6 +4546,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -4083,6 +4706,23 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + + + + false + + + + + + + + + + + + false @@ -4114,6 +4754,133 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 0: + + + + + false + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + 0: + + + + + + + + + + + + false + + + + + + + + + + + + + + 0: + + + + + + + + + + + + + + + false + + + + 1: + + + + + + + + 0: + + + + + + false + + + + + + + + + + + + + + + + 0: + + + + + + + + + + @@ -4266,6 +5033,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + Non reentrant function 'getspnam' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getspnam_r'. @@ -4300,6 +5068,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + Non reentrant function 'sgetspent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'sgetspent_r'. @@ -4383,6 +5152,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + Non reentrant function 'getgrnam' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getgrnam_r'. @@ -4398,6 +5168,61 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s Non reentrant function 'getgrgid' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getgrgid_r'. + + + + + + false + + + + + + + + + + + + + + + + + 0: + + + + + + + + + + + false + + + + + + + + + + + + + + + + 0: + + + + + @@ -4406,6 +5231,63 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s Non reentrant function 'getlogin' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getlogin_r'. + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + 0:255 + + + + + + + + + + + + false + + + + + + + + + 0: + + @@ -4425,6 +5307,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -4442,8 +5325,28 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + + + + + false + + + + + + + + + + + + 0: + + - @@ -4455,6 +5358,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -4481,8 +5385,9 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - - + + + false @@ -4497,6 +5402,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + 0:2 @@ -4512,7 +5418,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - @@ -4564,6 +5470,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -4571,10 +5478,23 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s 0: + + + + + + false + + + + + + - + + arg1==0 &0 false @@ -4687,6 +5607,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -4717,13 +5638,15 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + - + + @@ -4737,6 +5660,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + @@ -4744,6 +5668,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -4757,6 +5682,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + @@ -4797,6 +5723,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + @@ -4896,7 +5823,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset); --> false @@ -5033,7 +5960,10 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false - + + + + @@ -5266,7 +6196,9 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s false + + @@ -5346,11 +6278,15 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s free - strdup strndup wcsdup free + + getline + getdelim + free + mmap mmap64 @@ -5363,6 +6299,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s openat socket close + fdopen opendir @@ -5399,6 +6336,8 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s + + @@ -5470,7 +6409,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s - diff --git a/cfg/protobuf.cfg b/cfg/protobuf.cfg new file mode 100644 index 00000000000..8ff5570c952 --- /dev/null +++ b/cfg/protobuf.cfg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/cfg/python.cfg b/cfg/python.cfg index 563ede851e4..30479cd87b8 100644 --- a/cfg/python.cfg +++ b/cfg/python.cfg @@ -1,5 +1,9 @@ + + + + diff --git a/cfg/qt.cfg b/cfg/qt.cfg index 2cf9b9abdf5..00cb66c1909 100644 --- a/cfg/qt.cfg +++ b/cfg/qt.cfg @@ -59,10 +59,11 @@ invokeMethod - - + + + false @@ -72,6 +73,7 @@ + false @@ -100,6 +102,7 @@ + false @@ -131,6 +134,7 @@ + false @@ -146,6 +150,7 @@ + false @@ -176,6 +181,7 @@ + false @@ -188,6 +194,7 @@ + false @@ -200,6 +207,7 @@ + false @@ -266,6 +274,7 @@ + false @@ -277,6 +286,7 @@ + false @@ -381,8 +391,9 @@ - + false + @@ -414,6 +425,7 @@ false + @@ -442,10 +454,12 @@ + false - + + @@ -744,6 +758,19 @@ + + + + + + + + false + + + + + false @@ -762,7 +789,7 @@ false - + @@ -882,21 +909,6 @@ - - - false - - - - - false - - - - - false - - false @@ -931,10 +943,6 @@ 0: - - - false - @@ -945,6 +953,7 @@ false + @@ -969,6 +978,25 @@ + + + + + false + + + + + + + + + + false + + + + @@ -1026,14 +1054,6 @@ - - - false - - - - - false @@ -1119,33 +1139,6 @@ - - - - - - - - - - - false - - - - - - - - - - - - false - - - - @@ -1421,13 +1414,6 @@ - - - false - - - - @@ -1468,6 +1454,30 @@ + + + false + + + + + + + + + + false + + + + + + + false + + + + false @@ -1603,7 +1613,7 @@ false - + @@ -1627,7 +1637,7 @@ false - + @@ -1645,7 +1655,7 @@ false - + @@ -1708,7 +1718,7 @@ false - + @@ -2329,7 +2339,7 @@ - + false @@ -2347,7 +2357,7 @@ - + false @@ -2598,7 +2608,7 @@ false - + @@ -2727,6 +2737,7 @@ + @@ -2783,6 +2794,14 @@ + + + + false + + + + false @@ -2814,6 +2833,156 @@ + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + @@ -3125,7 +3294,7 @@ - + @@ -3136,7 +3305,7 @@ - + @@ -3152,7 +3321,7 @@ false - + @@ -3160,10 +3329,10 @@ false - + - + @@ -3200,10 +3369,10 @@ false - + - + @@ -3213,13 +3382,13 @@ false - + - + false @@ -3243,7 +3412,7 @@ - + false @@ -3296,7 +3465,7 @@ - + false @@ -3851,7 +4020,7 @@ - + false @@ -4026,7 +4195,7 @@ false - + @@ -4041,11 +4210,6 @@ 0: - - - false - - false @@ -4053,7 +4217,7 @@ - + @@ -4069,33 +4233,20 @@ - - - - false - - - - - false - - - - false - + false - + @@ -4110,7 +4261,7 @@ - + @@ -4123,23 +4274,16 @@ false - + - + - - - false - - - - false @@ -4147,7 +4291,7 @@ - + @@ -4155,20 +4299,13 @@ - - - false - - - - false - + @@ -4190,7 +4327,7 @@ false - + @@ -4210,7 +4347,7 @@ 0: - + @@ -4249,7 +4386,7 @@ - + @@ -4310,7 +4447,7 @@ false - + @@ -4321,7 +4458,7 @@ - + @@ -4332,7 +4469,7 @@ - + @@ -4361,7 +4498,7 @@ - + @@ -5043,6 +5180,7 @@ + @@ -5071,6 +5209,23 @@ + + + + + + + + + + + + + + + + + @@ -5097,18 +5252,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + QApplication + QMutexLocker + QRect + QRectF + QSize + QSizeF + QPoint + QPointF + QRegion + QTransform + + + QMutex + QRecursiveMutex + QSemaphore + QReadWriteLock + + - @@ -5119,6 +5327,8 @@ + + @@ -5128,13 +5338,19 @@ - + + + + + - + + + @@ -5146,30 +5362,47 @@ - + - + + + - + + + + + + + + + + + + + + + + - + - + - - + + @@ -5178,7 +5411,10 @@ - + + + + @@ -5189,14 +5425,43 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5225,8 +5490,12 @@ - - + + + + + + diff --git a/cfg/selinux.cfg b/cfg/selinux.cfg new file mode 100644 index 00000000000..e2d7ac34dc3 --- /dev/null +++ b/cfg/selinux.cfg @@ -0,0 +1,3621 @@ + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + + + get_default_type + free + + + + + + + + false + + + + + + 0:5 + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + selabel_open + selabel_close + + + + + + false + + + + + + + + + + + + + + + + + + + + + selabel_lookup + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + selabel_lookup_raw + freecon + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + selabel_get_digests_all_partial_matches + free + + + selabel_get_digests_all_partial_matches + free + + + + + false + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + selabel_lookup_best_match + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + selabel_lookup_best_match_raw + freecon + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + context_new + context_free + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + get_ordered_context_list + freeconary + + + + + false + + + + + + + + + + + + + + + + + + + + + get_ordered_context_list_with_level + freeconary + + + + + false + + + + + + + + + + + + + + + + + get_default_context + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + get_default_context_with_level + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + get_default_context_with_role + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + get_default_context_with_rolelevel + freecon + + + + + false + + + + + + + + + + + + query_user_context + freecon + + + + + false + + + + + + + + + + + + + manual_user_enter_context + freecon + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + avc_sid_to_context + freecon + + + + + false + + + + + + + + + + + + avc_sid_to_context + freecon + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + false + + + + + + false + + + + + + + false + + + + + 0,1 + + + + + + false + + + + + + false + + + + + + false + + + + + + + false + + + + + + false + + + + + + + + false + + + + + 0,1 + + + + + false + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + getcon + freecon + + + + + false + + + + + + + + getcon_raw + freecon + + + + + false + + + + + + + + getprevcon + freecon + + + + + false + + + + + + + + getprevcon_raw + freecon + + + + + false + + + + + + + + getexeccon + freecon + + + + + false + + + + + + + + getexeccon_raw + freecon + + + + + false + + + + + + + + + + + + getpidcon + freecon + + + + + false + + + + + + + + + + + + getpidcon_raw + freecon + + + + + false + + + + + + + + + + + + getpidprevcon + freecon + + + + + false + + + + + + + + + + + + getpidprevcon_raw + freecon + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + getfscreatecon + freecon + + + + + false + + + + + + + + getfscreatecon_raw + freecon + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + getkeycreatecon + freecon + + + + + false + + + + + + + + getkeycreatecon_raw + freecon + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + getsockcreatecon + freecon + + + + + false + + + + + + + + getsockcreatecon_raw + freecon + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + 0: + + + + + + + getpeercon + freecon + + + + + false + + + + + + 0: + + + + + + + getpeercon_raw + freecon + + + + + + false + + + + + + + + + + + + + getfilecon + freecon + + + + + false + + + + + + + + + + + + + getfilecon_raw + freecon + + + + + false + + + + + + + + + + + + + lgetfilecon + freecon + + + + + false + + + + + + + + + + + + + lgetfilecon_raw + freecon + + + + + false + + + + + + 0: + + + + + + + fgetfilecon + freecon + + + + + false + + + + + + 0: + + + + + + + fgetfilecon_raw + freecon + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + 0: + + + + + + + + + + + false + + + + + 0: + + + + + + + + + + + false + + + + + + 0:4 + + + + + + false + + + + + 0:4 + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + security_compute_create + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + security_compute_create_raw + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + security_compute_create_name + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + security_compute_create_name_raw + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + security_compute_relabel + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + security_compute_relabel + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + security_compute_member + freecon + + + + + false + + + + + + + + + + + + + + + + + + + + + + security_compute_member_raw + freecon + + + + + false + + + + + + + + + + + + + + + + + + security_compute_user + freeconary + + + + + false + + + + + + + + + + + + + + + + + + security_compute_user_raw + freeconary + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + security_get_initial_context + freecon + + + + + false + + + + + + + + + + + + + security_get_initial_context_raw + freecon + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + 0,1 + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + + 0 + + + + + + false + + + + + + + + + + + security_get_boolean_names + free + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + 0,1 + + + + + + false + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + security_canonicalize_context + freecon + + + + + false + + + + + + + + + + + + + security_canonicalize_context + freecon + + + + + + false + + + + + + + false + + + + + 0,1 + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + + false + + + Disabling SELinux at runtime is deprecated and may not be supported on modern Linux kernels. + + + + + + false + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + security_av_string + free + + + + + false + + + + + + + + + + + + + + false + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + 0:7 + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + matchpathcon + freecon + + + + + false + + + + + + + + + + + + + + + + + matchpathcon_index + freecon + + + + + + false + + + + + + + + + + + + + + + + + + + + false + + + + + + false + + + + + + false + + + + + + + + + + false + + + + + + + + + + + + + matchmediacon + freecon + + + + + + false + + + + + + + + + + + false + + + + + + + + + + selinux_boolean_sub + free + + + + + + false + + + + + + + + selinux_getpolicytype + free + + + + + + false + + + + + + + false + + + + + + + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + false + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + + + selinux_raw_context_to_color + free + + + + + false + + + + + + + + + + + + + selinux_trans_to_raw_context + free + + + + + false + + + + + + + + + + + + + selinux_raw_to_trans_context + free + + + + + + false + + + + + + + + + + + + + + + + getseuserbyname + free + + + getseuserbyname + free + + + + + false + + + + + + + + + + + + + + + + + + + + getseuser + free + + + getseuser + free + + + + + + false + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + false + + This function is not thread safe. Be very sure that no other threads are calling into libselinux when this is called. + + diff --git a/cfg/sqlite3.cfg b/cfg/sqlite3.cfg index 0b0a439b18c..6c5811f1f75 100644 --- a/cfg/sqlite3.cfg +++ b/cfg/sqlite3.cfg @@ -966,6 +966,7 @@ + false @@ -988,6 +989,7 @@ + false @@ -1025,6 +1027,48 @@ + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + @@ -36,6 +37,7 @@ + @@ -49,12 +51,30 @@ + + + + + + + + + - + + + true + + + + + true + + @@ -116,7 +136,7 @@ - + acos(arg1) false @@ -128,7 +148,7 @@ - + acos(arg1) false @@ -140,7 +160,7 @@ - + acos(arg1) false @@ -152,7 +172,7 @@ - + acosh(arg1) false @@ -164,7 +184,7 @@ - + acosh(arg1) false @@ -176,7 +196,7 @@ - + acosh(arg1) false @@ -228,7 +248,7 @@ - + sqrt(arg1) false @@ -240,7 +260,7 @@ - + sqrt(arg1) false @@ -252,7 +272,7 @@ - + sqrt(arg1) false @@ -276,7 +296,7 @@ - + sinh(arg1) false @@ -287,7 +307,7 @@ - + sinh(arg1) false @@ -298,7 +318,7 @@ - + sinh(arg1) false @@ -309,7 +329,7 @@ - + sin(arg1) false @@ -320,7 +340,7 @@ - + sin(arg1) false @@ -331,7 +351,7 @@ - + sin(arg1) false @@ -366,7 +386,7 @@ - + asin(arg1) false @@ -378,7 +398,7 @@ - + asin(arg1) false @@ -390,7 +410,7 @@ - + asin(arg1) false @@ -414,7 +434,7 @@ - + asinh(arg1) false @@ -425,7 +445,7 @@ - + asinh(arg1) false @@ -436,7 +456,7 @@ - + asinh(arg1) false @@ -463,14 +483,16 @@ + + 0: - 0: + @@ -481,7 +503,7 @@ - + tan(arg1) false @@ -492,7 +514,7 @@ - + tan(arg1) false @@ -503,7 +525,7 @@ - + tan(arg1) false @@ -526,7 +548,7 @@ - + tanh(arg1) false @@ -537,7 +559,7 @@ - + tanh(arg1) false @@ -548,7 +570,7 @@ - + tanh(arg1) false @@ -645,6 +667,8 @@ + + 1:31 @@ -663,6 +687,8 @@ + + 1:31 @@ -679,7 +705,7 @@ - + atan(arg1) false @@ -690,7 +716,7 @@ - + atan(arg1) false @@ -701,7 +727,7 @@ - + atan(arg1) false @@ -720,44 +746,53 @@ + - + tgamma(arg1) false + + !0.0: + - + tgamma(arg1) false + + !0.0: + - + tgamma(arg1) false + + !0.0: - + trunc(arg1) false @@ -768,7 +803,7 @@ - + trunc(arg1) false @@ -779,7 +814,7 @@ - + trunc(arg1) false @@ -790,7 +825,7 @@ - + atanh(arg1) false @@ -802,7 +837,7 @@ - + atanh(arg1) false @@ -814,7 +849,7 @@ - + atanh(arg1) false @@ -838,7 +873,7 @@ - + atan2(arg1, arg2) false @@ -852,7 +887,7 @@ - + atan2(arg1, arg2) false @@ -866,7 +901,7 @@ - + atan2(arg1, arg2) false @@ -939,7 +974,7 @@ - + false @@ -956,7 +991,7 @@ - + ceil(arg1) false @@ -967,7 +1002,7 @@ - + ceil(arg1) false @@ -978,7 +1013,7 @@ - + ceil(arg1) false @@ -1048,7 +1083,7 @@ - + cbrt(arg1) false @@ -1059,7 +1094,7 @@ - + cbrt(arg1) false @@ -1070,7 +1105,7 @@ - + cbrt(arg1) false @@ -1081,7 +1116,7 @@ - + cos(arg1) false @@ -1092,7 +1127,7 @@ - + cos(arg1) false @@ -1103,7 +1138,7 @@ - + cos(arg1) false @@ -1245,11 +1280,13 @@ + + - + erf(arg1) false @@ -1260,7 +1297,7 @@ - + erf(arg1) false @@ -1271,7 +1308,7 @@ - + erf(arg1) false @@ -1282,7 +1319,7 @@ - + erfc(arg1) false @@ -1293,7 +1330,7 @@ - + erfc(arg1) false @@ -1304,7 +1341,7 @@ - + erfc(arg1) false @@ -1348,7 +1385,7 @@ - + exp(arg1) false @@ -1359,7 +1396,7 @@ - + exp(arg1) false @@ -1370,7 +1407,7 @@ - + exp(arg1) false @@ -1405,7 +1442,7 @@ - + exp2(arg1) false @@ -1416,7 +1453,7 @@ - + exp2(arg1) false @@ -1427,7 +1464,7 @@ - + exp2(arg1) false @@ -1438,7 +1475,7 @@ - + expm1(arg1) false @@ -1449,7 +1486,7 @@ - + expm1(arg1) false @@ -1460,7 +1497,7 @@ - + expm1(arg1) false @@ -1489,7 +1526,7 @@ - + fabs(arg1) false @@ -1500,7 +1537,7 @@ - + fabs(arg1) false @@ -1511,7 +1548,7 @@ - + fabs(arg1) false @@ -1522,7 +1559,7 @@ - + fdim(arg1, arg2) false @@ -1536,7 +1573,7 @@ - + fdim(arg1, arg2) false @@ -1550,7 +1587,7 @@ - + fdim(arg1, arg2) false @@ -1575,7 +1612,7 @@ false - + @@ -1586,7 +1623,7 @@ false - + @@ -1597,6 +1634,7 @@ false + @@ -1639,7 +1677,7 @@ - + floor(arg1) false @@ -1650,7 +1688,7 @@ - + floor(arg1) false @@ -1661,7 +1699,7 @@ - + floor(arg1) false @@ -1723,7 +1761,7 @@ - + fmax(arg1,arg2) false @@ -1737,7 +1775,7 @@ - + fmax(arg1,arg2) false @@ -1751,7 +1789,7 @@ - + fmax(arg1,arg2) false @@ -1765,7 +1803,7 @@ - + fmin(arg1,arg2) false @@ -1779,7 +1817,7 @@ - + fmin(arg1,arg2) false @@ -1793,7 +1831,7 @@ - + fmin(arg1,arg2) false @@ -1807,7 +1845,7 @@ - + fmod(arg1,arg2) false @@ -1815,13 +1853,14 @@ + !0.0 - + fmod(arg1,arg2) false @@ -1829,13 +1868,14 @@ + !0.0 - + fmod(arg1,arg2) false @@ -1843,6 +1883,7 @@ + !0.0 @@ -1850,7 +1891,8 @@ false - + + @@ -1858,6 +1900,7 @@ + @@ -1866,6 +1909,7 @@ false + @@ -1877,6 +1921,7 @@ + @@ -1891,7 +1936,9 @@ + + @@ -1904,10 +1951,12 @@ + + - + @@ -1917,11 +1966,15 @@ + + + + - + @@ -1975,6 +2028,7 @@ + @@ -2023,6 +2077,7 @@ + @@ -2039,10 +2094,12 @@ + + @@ -2090,7 +2147,7 @@ - + hypot(arg1, arg2) false @@ -2107,7 +2164,7 @@ - + hypot(arg1, arg2) false @@ -2121,7 +2178,7 @@ - + hypot(arg1, arg2) false @@ -2143,6 +2200,7 @@ + @@ -2155,6 +2213,7 @@ + @@ -2169,6 +2228,7 @@ + @@ -2186,6 +2246,8 @@ + + 0:2 @@ -2256,7 +2318,7 @@ false - + @@ -2294,6 +2356,7 @@ + @@ -2369,6 +2432,7 @@ + @@ -2427,6 +2491,7 @@ + @@ -2952,7 +3017,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + ldexp(arg1,arg2) false @@ -2966,7 +3031,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + ldexp(arg1,arg2) false @@ -2980,7 +3045,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + ldexp(arg1,arg2) false @@ -2990,37 +3055,46 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + - + lgamma(arg1) false + + !0.0: + - + lgamma(arg1) false + + !0.0: + - + lgamma(arg1) false + + !0.0: @@ -3109,7 +3183,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + false @@ -3155,6 +3229,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + false @@ -3170,6 +3245,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -3178,7 +3254,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log(arg1) false @@ -3189,7 +3265,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log(arg1) false @@ -3200,7 +3276,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log(arg1) false @@ -3242,11 +3318,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - - - - + @@ -3257,8 +3329,23 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + + + + + + false + + + + + + - + arg1>arg2?1:0 @@ -3271,8 +3358,22 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + + arg1>arg2?1:0 + false + + + + + + + + - + arg1 >= arg2?1:0 @@ -3285,12 +3386,22 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + + arg1 >= arg2?1:0 + false + + + + + + + + - - - - - + @@ -3301,11 +3412,26 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + + + + + + false + + + + + + - + logb(arg1) false @@ -3316,7 +3442,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + logb(arg1) false @@ -3327,7 +3453,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + logb(arg1) false @@ -3387,6 +3513,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -3399,6 +3526,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -3411,6 +3539,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -3469,7 +3598,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + ilogb(arg1) false @@ -3480,7 +3609,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + ilogb(arg1) false @@ -3491,7 +3620,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + ilogb(arg1) false @@ -3502,7 +3631,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log10(arg1) false @@ -3514,7 +3643,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log10(arg1) false @@ -3526,7 +3655,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log10(arg1) false @@ -3538,7 +3667,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log1p(arg1) false @@ -3549,7 +3678,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log1p(arg1) false @@ -3560,7 +3689,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log1p(arg1) false @@ -3571,7 +3700,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log2(arg1) false @@ -3583,7 +3712,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log2(arg1) false @@ -3595,7 +3724,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + log2(arg1) false @@ -3607,7 +3736,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nearbyint(arg1) false @@ -3618,7 +3747,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nearbyint(arg1) false @@ -3629,7 +3758,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nearbyint(arg1) false @@ -3640,7 +3769,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nextafter(arg1) false @@ -3654,7 +3783,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nextafter(arg1) false @@ -3668,7 +3797,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nextafter(arg1) false @@ -3682,7 +3811,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nexttoward(arg1) false @@ -3696,7 +3825,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nexttoward(arg1) false @@ -3710,7 +3839,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + nexttoward(arg1) false @@ -3773,7 +3902,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -3796,7 +3925,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + @@ -3863,6 +3992,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + @@ -3878,11 +4008,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun 0: - + false + @@ -4022,8 +4153,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - + false @@ -4075,13 +4205,14 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + - + pow(arg1, arg2) false @@ -4095,7 +4226,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + pow(arg1, arg2) false @@ -4109,7 +4240,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + pow(arg1, arg2) false @@ -4134,11 +4265,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - + + + + - false @@ -4146,10 +4278,14 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + !0.0 + + + - - + + @@ -4160,10 +4296,14 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + !0.0 + + + - - + + @@ -4174,13 +4314,17 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + !0.0 + + + - - + + - + remainder(arg1,arg2) false @@ -4188,16 +4332,14 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - - + !0.0 - - + + - + remainder(arg1,arg2) false @@ -4205,16 +4347,14 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - - + !0.0 - - + + - + remainder(arg1,arg2) false @@ -4222,9 +4362,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - - + !0.0 @@ -4236,6 +4374,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4246,6 +4385,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4256,6 +4396,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4329,6 +4470,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4338,9 +4480,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun 0: - + + @@ -4438,23 +4581,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun 0: - - - - - false - - - - - - 0: - - - - 0: - - @@ -4496,7 +4622,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + round(arg1) false @@ -4507,7 +4633,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + round(arg1) false @@ -4518,7 +4644,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + round(arg1) false @@ -4581,6 +4707,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4591,10 +4718,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -4606,10 +4735,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -4621,6 +4752,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4631,6 +4763,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4658,9 +4791,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + 0:2 @@ -4679,10 +4815,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + + @@ -4690,17 +4828,19 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + false + + @@ -4716,6 +4856,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + false @@ -4730,7 +4871,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun 0:255 - + @@ -4739,6 +4880,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4767,6 +4909,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun arg1 false + @@ -4802,22 +4945,24 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + + - - + false + @@ -4826,6 +4971,8 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -4848,9 +4995,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + arg1 false + @@ -4883,6 +5031,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4898,10 +5047,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -4909,6 +5060,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + @@ -4944,6 +5096,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4964,6 +5117,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -4974,6 +5128,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + @@ -4991,32 +5146,8 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - - - - false - - - - - - - - - - - - - - - - - 0: - - - + @@ -5038,11 +5169,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + false - + @@ -5060,13 +5192,15 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + + + @@ -5093,7 +5227,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - @@ -5112,11 +5245,13 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + + @@ -5133,10 +5268,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -5193,10 +5330,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -5209,10 +5348,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -5224,6 +5365,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5234,9 +5376,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + - + @@ -5257,10 +5400,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -5272,15 +5417,18 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + false @@ -5296,15 +5444,16 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + false - + + @@ -5315,7 +5464,9 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false - + + + @@ -5339,6 +5490,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5518,8 +5670,16 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + + + + + + false + + arg1 < 'A' || arg1 > 'Z' ? arg1 : arg1 + 32 false @@ -5584,6 +5744,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5596,6 +5757,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5608,6 +5770,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5824,6 +5987,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5838,6 +6002,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5854,6 +6019,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5870,6 +6036,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5886,6 +6053,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5902,6 +6070,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5918,6 +6087,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5935,6 +6105,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5951,6 +6122,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -5987,6 +6159,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun 0: + @@ -6006,6 +6179,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -6025,6 +6199,8 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -6041,6 +6217,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -6061,6 +6238,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -6080,6 +6258,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -6093,6 +6272,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -6102,12 +6282,14 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -6122,6 +6304,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + @@ -6131,11 +6314,13 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + @@ -6144,7 +6329,9 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun false + + @@ -6155,8 +6342,59 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + false + + + + + + + + false + + + + + + + false + + + + + + + false + + + + + + + + + false + + + arg1<arg2?arg2:arg1>arg3?arg3:arg1 + + + + + + + + + + + + + - + false @@ -6170,7 +6408,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + false @@ -6207,6 +6445,38 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + @@ -6230,7 +6500,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + false @@ -6255,38 +6525,29 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun std::istream& std::istream::get (char* s, streamsize n, char delim); stream buffer (3) std::istream& std::istream::get (streambuf& sb); std::istream& std::istream::get (streambuf& sb, char delim);--> - - - - false - - - - - + false - + + + + + + + + 0: + + - - - - + + false - - - - @@ -6324,50 +6585,107 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + - - - - - - + false + + + + + - + false + + + + + + false + - + false - + false - + false - + + + + + false + + + @@ -6381,10 +6699,11 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + - 1: + 0: @@ -6395,10 +6714,36 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + - 1: + 0: + + + + + + + + false + + + + + + @@ -6409,10 +6754,11 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + - 1: + 0: @@ -6423,10 +6769,11 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + - 1: + 0: @@ -6438,25 +6785,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + - - - - false - - - - - - - - - - false - @@ -6473,10 +6805,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + false - + @@ -6494,35 +6826,36 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + - + false - + - + - + false - + - false - + @@ -6531,20 +6864,26 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + + + + false - + - - + false + + + + - + false @@ -6552,10 +6891,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun 0: - - false - - false @@ -6612,15 +6947,44 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + false - - + + + + + + - + + + + + false + + arg1 + + + + + + + + + + + + + false + & arg1 + + + + false - + false @@ -6693,25 +7057,37 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - + false - + - + - + - + - + + + + + + + + + false + + + + @@ -6787,14 +7163,9 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun 0: - - - - - false - + false @@ -6803,10 +7174,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + 0: + false @@ -6815,10 +7188,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + 0: + false @@ -6827,10 +7202,17 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + 0: + + + + + false + - + false @@ -6910,24 +7292,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun - - - - false - - - - - - - - - 0: - - - - - @@ -7125,12 +7489,16 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + false - + + + + @@ -7141,18 +7509,32 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init false - + + + + + + + + + + false + + false - + + + + @@ -7165,6 +7547,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + @@ -7181,6 +7564,34 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init 0: + + + + + + false + + + 0: + + + + 0: + + + + + + false + + + 0: + + + + 0: + + + + + + false + + + + + + + + + @@ -7238,15 +7663,15 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init false - + - + - + @@ -7287,6 +7712,23 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + false + + + + + + + + + + + + @@ -7304,10 +7746,28 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + false + + + + + + + + 0: + + + + + + - + @@ -7322,6 +7782,60 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + @@ -7378,6 +7892,22 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + false + + + + + + + + + + + + + @@ -7699,6 +8229,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + false @@ -7711,11 +8242,36 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + + + + + false + + + + + + + + + + + + + + + + false @@ -7739,7 +8295,11 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init false - + + + + + @@ -7750,11 +8310,55 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init false - + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + @@ -7765,9 +8369,11 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init - + - + + + false @@ -7775,6 +8381,16 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + false + + + + + + @@ -7785,7 +8401,9 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init - + + + @@ -7862,9 +8480,22 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init false + + + + + + + + + false + + + + @@ -7927,6 +8558,13 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + false + + @@ -8057,31 +8695,132 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + + + + false + + + 0: + + + + + + false + 0: + + + + false + + + 0: + + + + 0: + + + + + + false + + + + + + + + false + + + + + + + + false + + + false + + + + + + + false + + + false + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + malloc,std::malloc + calloc,std::calloc + aligned_alloc,std::aligned_alloc + realloc,std::realloc + free,std::free + - malloc - calloc - aligned_alloc - realloc - reallocarray - free + strdup,std::strdup + free,std::free - fopen - tmpfile - freopen - fclose + fopen,std::fopen + tmpfile,std::tmpfile + freopen,std::freopen + fclose,std::fclose - - + + @@ -8106,7 +8845,6 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init - @@ -8119,13 +8857,20 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + + + - + @@ -8139,16 +8884,18 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init - + + - + + @@ -8167,8 +8914,11 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + - @@ -8191,16 +8941,17 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + - + - + @@ -8225,10 +8976,11 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init - + + @@ -8236,28 +8988,99 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init - - - - - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + - + + + - std::insert_iterator + std::fstream + std::wfstream + std::ofstream + std::wofstream + std::basic_fstream + std::basic_ofstream + std::insert_iterator + std::lock_guard + std::scoped_lock + std::unique_lock + std::shared_lock std::pair + std::complex + std::exception + std::logic_error + std::domain_error + std::invalid_argument + std::length_error + std::out_of_range + std::future_error + std::runtime_error + std::range_error + std::overflow_error + std::underflow_error + std::regex_error + std::system_error + std::format_error + std::bad_typeid + std::bad_cast + std::monostate + std::bad_optional_access + std::bad_expected_access + std::bad_weak_ptr + std::bad_function_call + std::bad_alloc + std::bad_array_new_length + std::bad_exception + std::ios_base::failure + std::filesystem::filesystem_error + std::bad_variant_access + std::span + std::stringstream + std::wstringstream + std::istringstream + std::wistringstream + std::ostringstream + std::wostringstream + + std::mutex + std::recursive_mutex + @@ -8290,7 +9113,6 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init - @@ -8362,7 +9184,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + Values are in alignment with posix.cfg --> @@ -8373,4 +9195,11 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init + + + + + + + diff --git a/cfg/tinyxml2.cfg b/cfg/tinyxml2.cfg index 2fdee227bc6..e652fa9c11d 100644 --- a/cfg/tinyxml2.cfg +++ b/cfg/tinyxml2.cfg @@ -1,24 +1,5 @@ - - - - - - - - - - - - - - - - - - - diff --git a/cfg/windows.cfg b/cfg/windows.cfg index 0ca26ec67c3..343e12b3906 100644 --- a/cfg/windows.cfg +++ b/cfg/windows.cfg @@ -1203,6 +1203,12 @@ ExFreePool ExFreePoolWithTag + + _dupenv_s + _wdupenv_s + _tdupenv_s + free + HeapAlloc HeapReAlloc @@ -1349,6 +1355,23 @@ 0: + + + + + + + false + + + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + @@ -1484,6 +1554,7 @@ + @@ -1496,6 +1567,7 @@ + @@ -1508,6 +1580,7 @@ + @@ -1608,6 +1681,24 @@ + + + false + + + + + + + + + + + + + + false @@ -1632,6 +1723,7 @@ + @@ -1643,6 +1735,7 @@ + @@ -1657,6 +1750,7 @@ + @@ -1668,6 +1762,7 @@ + @@ -1679,6 +1774,7 @@ + @@ -1693,13 +1789,14 @@ + false - + @@ -1732,11 +1829,44 @@ + + + arg1 + false + + + + + + + + + + + + + + + arg1 + false + + + + + + + + + + + + false + @@ -1755,8 +1885,9 @@ false - + + @@ -1793,6 +1924,26 @@ + + + + + + + + false + + + + + + + + + + + + false @@ -2038,6 +2189,7 @@ + @@ -2060,6 +2212,7 @@ + @@ -2090,7 +2243,7 @@ false - + @@ -2139,10 +2292,11 @@ - - - - + + + + + false @@ -2150,32 +2304,69 @@ + + - + + + + + false + + + + + + + + + + + + - - - - - + + + false + + + + + + + + + + + + + + + + + + false + It is recommend you use _stricmp instead. + + @@ -2238,7 +2429,7 @@ implemented in Cppcheck. It can not (yet) be configured in the configuration file. See #8381 --> - false @@ -2256,6 +2447,7 @@ + @@ -2287,7 +2479,7 @@ - false @@ -2381,13 +2574,14 @@ HFONT CreateFont( + - @@ -2409,10 +2603,11 @@ HFONT CreateFont( + - false @@ -2439,7 +2634,7 @@ HFONT CreateFont( - false @@ -2456,18 +2651,6 @@ HFONT CreateFont( - - - false - - - These POSIX functions are deprecated. Use the ISO C++ conformant _strdup, _wcsdup, _mbsdup instead. - - - - - - false @@ -2491,7 +2674,7 @@ HFONT CreateFont( - false @@ -2516,7 +2699,25 @@ HFONT CreateFont( false - + strcmp(arg1,arg2) + + + + + + + + + + + + + + + + + false + strcmp(arg1,arg2) @@ -2528,8 +2729,9 @@ HFONT CreateFont( + - false @@ -2549,6 +2751,20 @@ HFONT CreateFont( + + + + false + + + + + + + + + + @@ -2631,10 +2847,12 @@ HFONT CreateFont( + + 0:2 - false @@ -2831,7 +3049,7 @@ HFONT CreateFont( - + @@ -2856,7 +3074,7 @@ HFONT CreateFont( - + @@ -2894,7 +3112,7 @@ HFONT CreateFont( _In_ LPARAM lParam); --> false - + @@ -2915,7 +3133,7 @@ HFONT CreateFont( _In_ LPARAM lParam); --> false - + @@ -3177,7 +3395,7 @@ HFONT CreateFont( false - + @@ -3186,10 +3404,10 @@ HFONT CreateFont( false - + - + @@ -3198,7 +3416,7 @@ HFONT CreateFont( false - + @@ -3210,13 +3428,34 @@ HFONT CreateFont( false + + + + + + + + + + + + + + + + false + + + + + false @@ -3529,7 +3768,7 @@ HFONT CreateFont( false - + @@ -3545,7 +3784,7 @@ HFONT CreateFont( - false @@ -3576,7 +3815,7 @@ HFONT CreateFont( false - + @@ -3613,28 +3852,52 @@ HFONT CreateFont( - - + + false - + + 0 + + + + + + + + + + + + false + + + + + + + + + + - - - @@ -3707,7 +3970,7 @@ HFONT CreateFont( - + @@ -3943,6 +4206,7 @@ HFONT CreateFont( false + @@ -3997,6 +4261,7 @@ HFONT CreateFont( false + @@ -4135,8 +4400,8 @@ HFONT CreateFont( - @@ -4169,8 +4434,8 @@ HFONT CreateFont( - @@ -4283,6 +4548,7 @@ HFONT CreateFont( false + @@ -4325,6 +4591,7 @@ HFONT CreateFont( false + @@ -4370,6 +4637,18 @@ HFONT CreateFont( + + + + false + + + + + + + @@ -4403,6 +4682,108 @@ HFONT CreateFont( + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + + @@ -4516,7 +4897,7 @@ HFONT CreateFont( - + @@ -4562,7 +4943,7 @@ HFONT CreateFont( false - + @@ -4581,7 +4962,7 @@ HFONT CreateFont( - true + false @@ -4590,13 +4971,33 @@ HFONT CreateFont( + + + + + false + + + + + + + + + + + true - + @@ -4611,11 +5012,11 @@ HFONT CreateFont( false - + - + @@ -4674,7 +5075,7 @@ HFONT CreateFont( - + @@ -4731,6 +5132,8 @@ HFONT CreateFont( + + + false + + Due to security concerns it is not recommended to use this function, see MSDN for details. + + + + + + + + + + + + + + + + false + + + Due to security concerns it is not recommended to use this function, see MSDN for details. + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + false + + Due to security concerns it is not recommended to use this function, see MSDN for details. @@ -5098,13 +5557,12 @@ HFONT CreateFont( false - + - + @@ -5114,8 +5572,7 @@ HFONT CreateFont( 0: - + false @@ -5124,9 +5581,9 @@ HFONT CreateFont( 0: + This function is deprecated because a more secure version is available '_malloca'. - + false @@ -5223,6 +5680,17 @@ HFONT CreateFont( + + + + + + + + + + + false @@ -5382,7 +5850,7 @@ HFONT CreateFont( - + @@ -6060,7 +6528,7 @@ HFONT CreateFont( false - + @@ -6147,12 +6615,81 @@ HFONT CreateFont( + + + false + + + + + + + + + + + + + + + + + 0: + + + + + + false + + + + + + + + + + + + + + + + + 0: + + + + + + false + + + + + + + + + + + + + + + + + 0: + + false + @@ -6294,7 +6831,22 @@ HFONT CreateFont( - + + + false + + + This function is obsolete. The ControlTrace function supersedes this function. + + + + + + + + + - + false @@ -6554,25 +7106,6 @@ HFONT CreateFont( - - - - - - - - - - - - - - - - false - - - false @@ -6657,24 +7190,22 @@ HFONT CreateFont( - - - - - - - - - - + + + + + + + + @@ -7350,11 +7881,6 @@ HFONT CreateFont( - - - - - @@ -7453,15 +7979,6 @@ HFONT CreateFont( - - - - - - - - - @@ -8299,9 +8816,6 @@ HFONT CreateFont( - - - @@ -12123,7 +12637,6 @@ HFONT CreateFont( - @@ -12716,6 +13229,7 @@ HFONT CreateFont( + @@ -13517,10 +14031,6 @@ HFONT CreateFont( - - - - @@ -13743,6 +14253,10 @@ HFONT CreateFont( + + + + @@ -14128,57 +14642,6 @@ HFONT CreateFont( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -14186,132 +14649,10 @@ HFONT CreateFont( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -14371,147 +14712,6 @@ HFONT CreateFont( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -16644,4 +16844,394 @@ HFONT CreateFont( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cfg/wxwidgets.cfg b/cfg/wxwidgets.cfg index 9e58d11bbde..e09b19e15af 100644 --- a/cfg/wxwidgets.cfg +++ b/cfg/wxwidgets.cfg @@ -1,5 +1,116 @@ + + + wxAcceleratorEntry + wxAny + wxArchiveIterator + wxArrayDouble + wxArrayInt + wxArrayPtrVoid + wxArrayShort + wxArrayString + wxBitmap + wxBitmapBundle + wxBitmapHandler + wxBoxSizer + wxBrush + wxChar + wxUniChar + wxUniCharRef + wxColour + wxColourDatabase + wxCursor + wxDateSpan + wxDelegateRendererNative + wxHeaderButtonParams + wxRendererNative + wxRendererVersion + wxTextWrapper + wxDCClipper + wxDCBrushChanger + wxDCFontChanger + wxDCPenChanger + wxDCTextColourChanger + wxDCTextBgColourChanger + wxDCTextBgModeChanger + wxFileType + wxFont + wxFlexGridSizer + wxFontEnumerator + wxFontInfo + wxFontList + wxFontMetrics + wxGBPosition + wxGBSizerItem + wxGBSpan + wxGDIObject + wxGraphicsBrush + wxGraphicsFont + wxGraphicsGradientStop + wxGraphicsGradientStops + wxGraphicsMatrix + wxGraphicsPath + wxGridBagSizer + wxGridSizer + wxIcon + wxIconBundle + wxIconLocation + wxIFFHandler + wxImage + wxImageHandler + wxGIFHandler + wxJPEGHandler + wxPCXHandler + wxPNGHandler + wxPNMHandler + wxTGAHandler + wxTIFFHandler + wxXPMHandler + wxMask + wxMetafile + wxNativeFontInfo + wxPalette + wxPen + wxPenList + wxPoint + wxPoint2DDouble + wxPoint2DInt + wxPosition + wxRealPoint + wxRegion + wxRegionContain + wxRegionIterator + wxRegEx + wxRect + wxSize + wxSizer + wxSizerItem + wxSplitterRenderParams + wxStaticBoxSizer + wxStdDialogButtonSizer + wxSystemOptions + wxSystemSettings + wxTarEntry + wxTarInputStream + wxTimeSpan + wxUString + wxVariant + wxVariantData + wxVariantDataCurrency + wxVariantDataErrorCode + wxVariantDataSafeArray + wxVector + wxVersionInfo + wxWrapSizer + wxZipEntry + wxZipInputStream + + + + + + @@ -25,6 +136,7 @@ + @@ -85,12 +197,13 @@ + - - + + @@ -136,7 +249,6 @@ - @@ -205,7 +317,6 @@ - @@ -256,7 +367,6 @@ - @@ -276,6 +386,7 @@ + @@ -283,7 +394,6 @@ - @@ -347,13 +457,11 @@ - - @@ -397,7 +505,6 @@ - @@ -406,7 +513,11 @@ + + + + @@ -578,10 +689,7 @@ - - - @@ -612,7 +720,6 @@ - @@ -675,32 +782,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -775,13 +860,6 @@ - - - - - - - @@ -808,10 +886,6 @@ - - - - @@ -1057,11 +1131,6 @@ - - - - - @@ -3277,9 +3346,6 @@ - - - @@ -3497,13 +3563,6 @@ - - - - - - - @@ -3557,6 +3616,10 @@ + + + + @@ -3718,47 +3781,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3867,23 +3892,7 @@ - - - - - - - - - - - - - - - - @@ -4070,14 +4079,6 @@ - - - - - - - - @@ -4129,7 +4130,7 @@ - + @@ -5126,19 +5127,25 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -5165,9 +5172,6 @@ - - - @@ -5209,10 +5213,18 @@ + + + + - - + + + + + + @@ -5228,10 +5240,10 @@ - - - - + + + + @@ -5296,7 +5308,7 @@ - + @@ -5402,20 +5414,22 @@ - + false + - + false + This is the same as 'wxString::IsEmpty' and is kept for wxWidgets 1.xx compatibility. You should not use it in new code. @@ -5454,16 +5468,6 @@ This is a wxWidgets 1.xx compatibility function; you should not use it in new code. - - - - - false - - - - - @@ -5476,7 +5480,8 @@ - + + false @@ -5679,7 +5684,7 @@ - + @@ -5691,7 +5696,18 @@ - + + + + + + false + + + + + + false @@ -5704,6 +5720,14 @@ + + + false + + + + + @@ -5719,6 +5743,44 @@ + + + false + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + false + + + + + @@ -5837,6 +5899,20 @@ + + + + + + + false + + + + + + + @@ -5848,16 +5924,16 @@ - - - - - - - - - - + + + + + + + + + + false @@ -5865,9 +5941,9 @@ - - - + + + false @@ -5875,15 +5951,15 @@ - + false - - + + false @@ -5891,7 +5967,7 @@ - + @@ -5901,13 +5977,13 @@ - + false - + false @@ -5921,7 +5997,7 @@ - + false @@ -5935,7 +6011,7 @@ - + false @@ -5946,7 +6022,7 @@ - + false @@ -6167,6 +6243,29 @@ + + + false + + + + + + + + false + + + + + + + false + + + + + @@ -6186,6 +6285,22 @@ + + + false + + + + + + + + false + + + + + false @@ -6477,9 +6592,7 @@ false - - - + @@ -6760,7 +6873,7 @@ false - + @@ -7011,31 +7124,422 @@ false + This function is deprecated and kept mostly for backwards compatibility. Please override 'wxApp::MacOpenFiles' method instead in any new code. - + + + false + + + + + This function is deprecated, use 'wxPlatformInfo::GetBitness()' instead. + + + + false + + + + + + + + + This function is deprecated, please use 'ToWChar()' instead. + + + + false + + + + + + + + + This function is deprecated, please use 'FromWChar()' instead. + + + + false + + + + + + + This function has been deprecated in favour of 'wxMenuBar::SetMenuLabel()'. + + + + false + + + + + This function only exists for compatibility, please override FormatTimeMS() in the new code. + + + + false + + + + + This function is deprecated. Please use 'wxMenuItem::GetMenuLabel()' or 'wxMenuItem::GetMenuLabelText()' instead. + + + + false + + + + + This function is deprecated. Please use 'wxMenuItem::GetItemLabel()' or 'wxMenuItem::GetItemLabelText()' instead. + + + + false + + + + + This function is deprecated in favour of 'wxMenuItem::GetItemLabel()'. + + + + false + + + + + + This function is deprecated, use 'wxPlatformInfo::GetBitness()' instead. + + + + false + + + + + + + This function is deprecated, use 'wxPGProperty::AddPrivateChild()' instead. + + + + false + + + + This function is deprecated. Ids generated by it can conflict with the Ids defined by the user code, use wxID_ANY to assign ids which are guaranteed to not conflict with the user-defined ids for the controls and menu items you create instead of using this function. + + + + false + + + + + + + + This function is deprecated, use 'wxPGProperty::GetValueAsString()' instead. + + + + + false + + + + + + + + + + false + + + + + This function is deprecated, use 'wxPlatformInfo::GetBitnessName()' instead. + + + + false + + + + This function is deprecated, use 'wxPlatformInfo::SetBitness()' instead. + + + + false + + + + This function is deprecated in favour of 'wxMenuItem::SetItemLabel()'. + + + + false + + + + + + + This function is deprecated, please use 'wxFileName::SplitPath()' instead. + + + + false + + + + + + + + + + + + This function is deprecated. This is the old way of detecting tool right clicks, although it will still work, you should use the EVT_TOOL_RCLICKED() macro instead. + + + + false + + + + + + The setup dialog is deprecated, though retained for backward compatibility. + + + + false + + + + + + + This function has been deprecated, use 'wxWindow::Close()' instead. + + + + false + + + + + + The setup dialog is deprecated, though retained for backward compatibility. + + + + false + + + + + + + This function is deprecated use 'CreateThread()' instead. + + + + false + + + + This function is deprecated in favour of 'IsShown()'. + false - + + This function is deprecated and kept mostly for backwards compatibility. Please override 'PushBack' method instead in any new code. - - - + + + + false + + + + + + This function should be used instead of changing 'wxCAL_NO_YEAR_CHANGE' style bit directly. It allows or disallows the user to change the year interactively. Only in generic 'wxCalendarCtrl'. + + + + false + + + + + + + This function is deprecated. Construct a wxFileName with wxPATH_UNIX and then use wxFileName::GetFullPath(wxPATH_DOS) instead. + + + + false + + + + + + This function is deprecated. + + + + false + + + + + This function is kept mostly for backwards compatibility. Use 'LastReadCount()' or 'LastWriteCount()' instead. 'LastCount()' is still needed for use with less commonly used functions: 'Discard()', 'Peek()', and 'Unread()'. + + + + + false + + + + + This function is deprecated. + + + + false + + + + This function is deprecated, use GetStream() instead + + + + false + + + + + + This function is deprecated because its name is misleading: notice that the argument is in milliseconds, not microseconds. Please use either 'wxMilliSleep()' or 'wxMicroSleep()' depending on the resolution you need. + + + + false + + + + + + + This function is kept mostly for backwards compatibility. + + + + false + + + + This function is deprecated, use 'wxWindow::SetInitialSize' instead. + + + + false + + + + This function is deprecated, use 'wxTextInputStream::ReadLine()' or 'wxTextInputStream::ReadWord()' instead. + + + + + false + + + + Use 'wxStyledTextEvent::GetString()' instead. + + + + + false + + + + + + + + + + + false + + + + + + + + + false + + + + This function is deprecated. + + + + + + + + + + + + + + + + + false + + + + + + + false - - - - This function should be used instead of changing 'wxCAL_NO_YEAR_CHANGE' style bit directly. It allows or disallows the user to change the year interactively. Only in generic 'wxCalendarCtrl'. + + + This function is deprecated, use 'wxDC::SetPalette' instead. @@ -7043,9 +7547,18 @@ false + This function is deprecated and kept mostly for backwards compatibility. Please override 'GetMargins()' method instead in any new code. + + + false + + + + + @@ -7075,7 +7588,7 @@ This function is deprecated and kept mostly for backwards compatibility. Please override 'SetMargins()' method instead in any new code. - + false @@ -7183,6 +7696,15 @@ This function is deprecated. Please use 'wxFileName::SplitPath()' instead. + + + false + + + + + + @@ -7218,6 +7740,26 @@ This function is deprecated. + + + + + false + + + + + + + + false + + + + + + This function is deprecated. This is exactly the same as 'FitInside()' in wxWidgets 2.9 and later, please replace calls to it with 'FitInside()'. + false @@ -7426,7 +7968,7 @@ - + false @@ -7435,7 +7977,58 @@ This function is deprecated. This function does not free the old sizer which may result in memory leaks, use 'wxSizerItem::AssignSpacer' which does free it instead. - + + + false + + + + + + This function is for backward compatibility only, and applications should use 'wxHelpControllerBase::DisplaySection()' instead. + + + + + + false + + + + + This function is deprecated. + + + + false + + + + + This function is deprecated in favour of 'wxIconizeEvent::IsIconized()'. + + + + false + + + + + This function is deprecated, use 'wxList::GetCount()' instead. Returns the number of elements in the list. + + + + + + false + + + + + + This function is deprecated since version 3.1.2, dimensions and depth can only be set at construction time. + + false @@ -7445,7 +8038,7 @@ - + false @@ -7501,7 +8094,108 @@ - + + + false + + + + + + This function is deprecated, please use 'wxWindow::FindWindowByLabel()' instead. + + + + false + + + + + + This function is deprecated, please use 'wxWindow::FindWindowByName()' instead. + + + + false + + + + + + This function is deprecated, please use 'wxFileName::CreateTempFileName()' instead. + + + + false + + + + + + + + + + This function is deprecated, use 'wxGetUserId()' with no arguments instead. + + + + false + + + + + + + + + + This function is deprecated, use 'wxGetEmailAddress()' with no arguments instead. + + + + false + + + + + + + + + + This function is deprecated, use 'wxGetHostName()' with no arguments instead. + + + + false + + + + + + + + + + This function is deprecated, use 'wxGetUserName()' with no arguments instead. + + + + false + + + + + + + + + + + + This function is deprecated, use 'wxGetCwd()' instead. + false @@ -7837,7 +8531,7 @@ - + false @@ -7878,7 +8572,7 @@ - + false @@ -8088,7 +8782,7 @@ This function is deprecated. Please use 'SetDefaultCellTextColour(colour)' instead. --> - + false @@ -8592,7 +9286,7 @@ - + @@ -8803,7 +9497,7 @@ - + false @@ -8855,6 +9549,26 @@ + + + false + + + + + + + + + + false + + + + + + + false @@ -8896,9 +9610,9 @@ - - - + + + false @@ -9294,8 +10008,8 @@ - - + + false @@ -9383,6 +10097,16 @@ + + + false + + + + + + + false @@ -9415,7 +10139,7 @@ - false @@ -9508,14 +10232,6 @@ - - - false - - - - - false @@ -9662,6 +10378,17 @@ + + + + + + false + + + + + false @@ -10037,7 +10764,7 @@ - + false @@ -10066,6 +10793,35 @@ 0: + + + false + + + + + + + false + + + + + + + + false + + + + + + false + + + + + false @@ -10090,8 +10846,8 @@ - + false @@ -10255,7 +11011,7 @@ - + false @@ -10268,7 +11024,7 @@ - + false @@ -10312,14 +11068,16 @@ - - + + + false + - + false @@ -10366,7 +11124,7 @@ - + false @@ -10474,7 +11232,7 @@ 0: - + false @@ -10486,7 +11244,7 @@ 0: - + false @@ -10892,6 +11650,43 @@ + + + + false + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + false + + + + + @@ -10900,6 +11695,30 @@ + + + false + + + + + + + + false + + + + + + + + false + + + + + @@ -10971,6 +11790,105 @@ + + + false + + + + + + + + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + false + + + + + + + false + + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + @@ -11121,6 +12039,24 @@ + + + + false + + + + + + + + + false + + + + + @@ -13053,8 +13989,8 @@ wxItemKind kind = wxITEM_NORMAL) --> - - + + @@ -13134,7 +14070,7 @@ wxItemKind kind = wxITEM_NORMAL) --> false - + false @@ -13478,10 +14414,76 @@ wxItemKind kind = wxITEM_NORMAL) --> + + + + + + false + + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + + false + + + + + + + + + false + + + + + + + - + + + false @@ -13489,6 +14491,12 @@ wxItemKind kind = wxITEM_NORMAL) --> + + + false + + + @@ -13592,7 +14600,7 @@ wxItemKind kind = wxITEM_NORMAL) --> - + @@ -13899,6 +14907,14 @@ wxItemKind kind = wxITEM_NORMAL) --> + + + false + + + + + false @@ -14260,10 +15276,10 @@ wxItemKind kind = wxITEM_NORMAL) --> - + - + @@ -14291,9 +15307,11 @@ wxItemKind kind = wxITEM_NORMAL) --> + 0: + 1: @@ -14528,6 +15546,45 @@ wxItemKind kind = wxITEM_NORMAL) --> + + + false + + + + + + + + false + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + false @@ -14697,6 +15754,13 @@ wxItemKind kind = wxITEM_NORMAL) --> + + + + false + + + false @@ -14708,13 +15772,65 @@ wxItemKind kind = wxITEM_NORMAL) --> - + + false + + + false + + + + + + + false + + + + + + + + + false + + + + + + + + + + false + + + + + + + + false + + + + + + + + + false + + + + + false @@ -14921,7 +16037,7 @@ wxItemKind kind = wxITEM_NORMAL) --> - + false @@ -14932,7 +16048,7 @@ wxItemKind kind = wxITEM_NORMAL) --> - + false @@ -14974,7 +16090,7 @@ wxItemKind kind = wxITEM_NORMAL) --> - + false @@ -14989,6 +16105,23 @@ wxItemKind kind = wxITEM_NORMAL) --> + + + + false + + + + + + + + false + + + + + @@ -15294,12 +16427,12 @@ wxItemKind kind = wxITEM_NORMAL) --> - false @@ -15535,6 +16668,59 @@ wxItemKind kind = wxITEM_NORMAL) --> 0: + + + + + false + + + + + + + + + + + + false + + + + + + + + + false + + + + + + + + 0: + + + + + 1: + + + + + false + + + + + + 0: + + + false @@ -15680,13 +16866,13 @@ wxItemKind kind = wxITEM_NORMAL) --> - false @@ -15705,7 +16891,7 @@ wxItemKind kind = wxITEM_NORMAL) --> false @@ -15781,4 +16967,279 @@ wxItemKind kind = wxITEM_NORMAL) --> 0: + + + + false + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + false + + + + + + + + + false + + + + + + false + + + + + + + + + false + + + + + + + + + + false + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + + + + false + + + + + diff --git a/cfg/zephyr.cfg b/cfg/zephyr.cfg new file mode 100644 index 00000000000..999de4ea1b5 --- /dev/null +++ b/cfg/zephyr.cfg @@ -0,0 +1,113 @@ + + + + + + + + false + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + + + + + + false + + + 0:2147483647 + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clang-tidy.md b/clang-tidy.md new file mode 100644 index 00000000000..59d28dbaa3d --- /dev/null +++ b/clang-tidy.md @@ -0,0 +1,192 @@ +# clang-tidy + +Below are the reasoning why certain checks are (currently) disabled for out code base + +## Externals + +We do not perform static analysis of the source of the external libraries. `simplecpp` has its own CI with a clang-tidy workflow. + +## Disabled Checks + +`abseil-*`
+`altera-*`
+`android-*`
+`boost-*`
+`darwin-*`
+`fuchsia-*`
+`linuxkernel-*`
+`llvm-*`
+`llvmlibc-*`
+`mpi-*`
+`objc-*`
+`openmp-*`
+`zircon-*`
+ +These are disabled since the platforms/libraries in question are not targeted by us. + +`cert-*`
+`cppcoreguidelines-*`
+`google-*`
+`hicpp-*`
+ +These are coding guidelines we do not follow. Some of the checks might be explicitly enabled though. + +`readability-braces-around-statements`
+`readability-isolate-declaration`
+`modernize-use-trailing-return-type`
+`readability-uppercase-literal-suffix`
+`readability-identifier-length`
+ +These do not reflect the style we are (currently) enforcing. + +`readability-function-size`
+`readability-function-cognitive-complexity`
+ +We are not interested in the size/complexity of a function. + +`readability-magic-numbers`
+ +These do not (always) increase readability. + +`bugprone-macro-parentheses`
+ +To be documented. + +`readability-implicit-bool-conversion`
+ +This does not appear to be useful as it is reported on very common code. + +`bugprone-narrowing-conversions`
+`performance-no-automatic-move`
+ +It was decided not to apply these. + +`modernize-loop-convert`
+ +These might change the behavior of code which might not be intended (need to file an upstream issue) + +`modernize-raw-string-literal`
+ +This leads to a mismatch of raw string literals and regular ones and does reduce the readability. + +`-clang-analyzer-*`
+ +Disabled because of false positives (need to file upstream bug reports). The checks are also quite time consuming. + +`misc-non-private-member-variables-in-classes`
+ +We intentionally use this. + +`misc-no-recursion`
+ +Leads to lots of "false positives". This seem to enforce a coding guidelines of certain codebases. + +`bugprone-easily-swappable-parameters`
+ +This produces a lot of noise and they are not fixable that easily. + +`readability-container-data-pointer`
+ +Disable because of false positives and inconsistent warnings (need to file an upstream bug report). + +`misc-const-correctness`
+ +Work in progress. + +`bugprone-assignment-in-if-condition`
+ +Is reported for valid patterns we are using. + +`readability-suspicious-call-argument`
+ +Produces a lot of false positives since it is too vague in its analysis. + +`performance-inefficient-string-concatenation`
+ +Produces warnings which might be considered false positives starting with C++11 - see https://github.com/llvm/llvm-project/issues/54526. + +`modernize-avoid-c-arrays`
+ +Produces warnings when `const char[]` is being used which is quite common in our code. Does not make sense to enable before C++17 when `std::string_view` becomes available. +Also reports a false positive about templates which deduce the array length: https://github.com/llvm/llvm-project/issues/60053. + +`misc-include-cleaner`
+ +We run this separately via `clang-include-cleaner` in the `iwyu.yml` workflow as the findings of the include checkers still need to be reviewed manually before applying them. + +`bugprone-branch-clone`
+`modernize-return-braced-init-list`
+`misc-throw-by-value-catch-by-reference`
+`bugprone-signed-char-misuse`
+`concurrency-mt-unsafe`
+`misc-use-anonymous-namespace`
+`performance-avoid-endl`
+`bugprone-switch-missing-default-case`
+`bugprone-empty-catch`
+`readability-avoid-nested-conditional-operator`
+`modernize-use-designated-initializers`
+`readability-enum-initial-value`
+ +To be evaluated (need to remove exclusion). + +`cppcoreguidelines-missing-std-forward`
+`cppcoreguidelines-avoid-const-or-ref-data-members`
+`cppcoreguidelines-macro-usage`
+`cppcoreguidelines-pro-type-member-init`
+`cppcoreguidelines-prefer-member-initializer`
+`cppcoreguidelines-misleading-capture-default-by-value`
+`bugprone-argument-comment.CommentBoolLiterals`
+`cert-err33-c`
+`google-readability-namespace-comments`
+`cppcoreguidelines-special-member-functions`
+ +To be evaluated (need to enable explicitly). + +`modernize-type-traits`
+`modernize-use-nodiscard`
+ +These apply to codebases which use later standards then C++11 (C++17 is used when building with Qt6) so we cannot simply apply them. + +### Disabled for performance reasons + +`portability-std-allocator-const`
+ +Only necessary for code which is exclusively compiled with `libc++`. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. + +`modernize-deprecated-ios-base-aliases`
+ +Warns about aliases which are removed in C++20. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. + +`bugprone-unchecked-optional-access`
+ +We are not using any `optional` implementation. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. + +`modernize-replace-auto-ptr`
+ +Still available until C++17. It is unlikely such code will ever be introduced. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. + +`readability-identifier-naming`
+ +We are currently using our own `naming.json` to enforce naming schemes. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. + +`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. + +`modernize-macro-to-enum`
+ +It does not seem to produce any warnings for us (needs to be investigated) and it is one of the more expensive checks. + +`misc-unused-using-decls`
+ +This is the most expensive check for several files and it is providing much in terms of code quality. Reported upstream as https://github.com/llvm/llvm-project/issues/72300. + +### Disabled for GUI only + +`readability-convert-member-functions-to-static`
+ +Disabled because of false positives with Qt `slot` methods (see https://github.com/llvm/llvm-project/issues/57520). + +`readability-redundant-access-specifiers`
+ +Reports warning with the Qt ` slots:` syntax in class declarations - see https://github.com/llvm/llvm-project/issues/60055. diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 49b44316c7e..8ea47196350 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -1,52 +1,98 @@ -include_directories(${PROJECT_SOURCE_DIR}/lib/) -if(USE_BUNDLED_TINYXML2) - include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/externals/tinyxml2/) -endif() -include_directories(${PROJECT_SOURCE_DIR}/externals/simplecpp/) +if (BUILD_CLI) -file(GLOB hdrs "*.h") -file(GLOB srcs "*.cpp") -file(GLOB mainfile "main.cpp") -list(REMOVE_ITEM srcs ${mainfile}) + file(GLOB hdrs "*.h") + file(GLOB srcs "*.cpp") + file(GLOB mainfile "main.cpp") + list(REMOVE_ITEM srcs ${mainfile}) -add_library(cli_objs OBJECT ${hdrs} ${srcs}) + add_library(cli_objs OBJECT ${hdrs} ${srcs}) + target_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/lib/ ${PROJECT_SOURCE_DIR}/frontend/) + if(USE_BUNDLED_TINYXML2) + target_externals_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/) + else() + target_include_directories(cli_objs SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS}) + endif() + target_externals_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/externals/picojson/) + target_externals_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/) + if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS) + target_precompile_headers(cli_objs PRIVATE precompiled.h) + endif() + if (BUILD_CORE_DLL) + target_compile_definitions(cli_objs PRIVATE CPPCHECKLIB_IMPORT TINYXML2_IMPORT) + endif() -list(APPEND cppcheck_SOURCES ${hdrs} ${mainfile} $ $ $) -if(USE_BUNDLED_TINYXML2) - list(APPEND cppcheck_SOURCES $) -endif() + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 13) + # false positive warning in Clang 13 - caused by FD_ZERO macro + set_source_files_properties(processexecutor.cpp PROPERTIES COMPILE_FLAGS -Wno-reserved-identifier) + endif() -add_executable(cppcheck ${cppcheck_SOURCES}) -if (HAVE_RULES) - target_link_libraries(cppcheck ${PCRE_LIBRARY}) -endif() -if (USE_Z3) - target_link_libraries(cppcheck ${Z3_LIBRARIES}) -endif() -if (WIN32 AND NOT BORLAND) - if(NOT MINGW) - target_link_libraries(cppcheck Shlwapi.lib) + list(APPEND cppcheck_SOURCES ${hdrs} ${mainfile} $ $) + if (NOT BUILD_CORE_DLL) + list(APPEND cppcheck_SOURCES $) + list(APPEND cppcheck_SOURCES $) + if(USE_BUNDLED_TINYXML2) + list(APPEND cppcheck_SOURCES $) + endif() + endif() + if (WIN32) + list(APPEND cppcheck_SOURCES version.rc) + endif() + + add_executable(cppcheck ${cppcheck_SOURCES}) + target_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/lib/) + if(USE_BUNDLED_TINYXML2) + target_externals_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/) else() - target_link_libraries(cppcheck shlwapi) + target_include_directories(cppcheck SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS}) + endif() + target_externals_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/) + if (HAVE_RULES) + target_link_libraries(cppcheck ${PCRE_LIBRARY}) + endif() + if (WIN32 AND NOT BORLAND) + if(NOT MINGW) + target_link_libraries(cppcheck Shlwapi.lib) + else() + target_link_libraries(cppcheck shlwapi) + endif() + endif() + if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2) + target_link_libraries(cppcheck ${tinyxml2_LIBRARIES}) + endif() + target_link_libraries(cppcheck ${CMAKE_THREAD_LIBS_INIT}) + if (BUILD_CORE_DLL) + target_link_libraries(cppcheck cppcheck-core) endif() -endif() -if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2) - target_link_libraries(cppcheck tinyxml2) -endif() -install(TARGETS cppcheck - RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} - COMPONENT applications) + add_dependencies(cppcheck copy_cfg) + add_dependencies(cppcheck copy_addons) + add_dependencies(cppcheck copy_platforms) + if (NOT DISABLE_DMAKE) + add_dependencies(cppcheck run-dmake) + endif() + + install(TARGETS cppcheck + RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} + COMPONENT applications) + + install(PROGRAMS ${CMAKE_SOURCE_DIR}/htmlreport/cppcheck-htmlreport + DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} + COMPONENT applications) -install(FILES ${addons} - DESTINATION ${FILESDIR}/addons - COMPONENT headers) + install(FILES ${addons_py} + DESTINATION ${FILESDIR_DEF}/addons + COMPONENT headers) -install(FILES ${cfgs} - DESTINATION ${FILESDIR}/cfg - COMPONENT headers) + install(FILES ${addons_json} + DESTINATION ${FILESDIR_DEF}/addons + COMPONENT headers) -install(FILES ${platforms} - DESTINATION ${FILESDIR}/platforms - COMPONENT headers) + install(FILES ${cfgs} + DESTINATION ${FILESDIR_DEF}/cfg + COMPONENT headers) + install(FILES ${platforms} + DESTINATION ${FILESDIR_DEF}/platforms + COMPONENT headers) + +endif() diff --git a/cli/cli.vcxproj b/cli/cli.vcxproj index 5fb4003e45d..5d4ee25b0e3 100644 --- a/cli/cli.vcxproj +++ b/cli/cli.vcxproj @@ -1,425 +1,262 @@ - - - - - Debug-PCRE - Win32 - - - Debug-PCRE - x64 - - - Debug - Win32 - - - Debug - x64 - - - Release-PCRE - Win32 - - - Release-PCRE - x64 - - - Release - Win32 - - - Release - x64 - - - - {35CBDF51-2456-3EC3-99ED-113C30858883} - cli - 10.0 - - - - Application - Unicode - false - v142 - - - Application - Unicode - false - v142 - - - Application - Unicode - false - v142 - - - Application - Unicode - false - v142 - - - Application - Unicode - false - v142 - - - Application - Unicode - false - v142 - - - Application - Unicode - false - v142 - - - Application - Unicode - false - v142 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(SolutionDir)bin\debug\ - $(SolutionDir)bin\debug\ - $(SolutionDir)bin\debug\ - $(SolutionDir)bin\debug\ - temp\$(Configuration)_$(PlatformName)\ - temp\$(Configuration)_$(PlatformName)\ - temp\$(Configuration)_$(PlatformName)\ - temp\$(Configuration)_$(PlatformName)\ - cppcheck - cppcheck - cppcheck - cppcheck - true - true - true - true - $(SolutionDir)bin\ - $(SolutionDir)bin\ - $(SolutionDir)bin\ - $(SolutionDir)bin\ - temp\$(Configuration)_$(PlatformName)\ - temp\$(Configuration)_$(PlatformName)\ - temp\$(Configuration)_$(PlatformName)\ - temp\$(Configuration)_$(PlatformName)\ - cppcheck - cppcheck - cppcheck - cppcheck - true - true - true - true - true - true - true - true - - - - ..\lib;..\externals;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) - false - true - ProgramDatabase - Disabled - CPPCHECKLIB_IMPORT;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - true - true - stdcpp14 - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - true - Console - true - $(TargetDir)cli.pdb - true - 8000000 - 8000000 - - - - - ..\lib;..\externals;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) - false - true - ProgramDatabase - Disabled - CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;TIXML_USE_STL;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - true - true - stdcpplatest - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - true - Console - true - true - 8000000 - 8000000 - - - - - ..\lib;..\externals;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) - true - ProgramDatabase - Disabled - CPPCHECKLIB_IMPORT;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - true - true - stdcpp14 - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - true - Console - true - 8000000 - 8000000 - - - - - ..\lib;..\externals;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) - true - ProgramDatabase - Disabled - CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level4 - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - true - true - stdcpplatest - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - true - Console - true - 8000000 - 8000000 - - - - - ..\lib;..\externals;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) - false - MaxSpeed - CPPCHECKLIB_IMPORT;NDEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - AnySuitable - true - Speed - true - true - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - - - true - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - true - stdcpp14 - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - false - Console - true - true - true - true - true - 8000000 - 8000000 - - - - - ..\lib;..\externals;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) - false - MaxSpeed - CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;NDEBUG;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;TIXML_USE_STL;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - AnySuitable - true - Speed - true - true - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - - - true - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - true - stdcpplatest - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - false - Console - true - true - true - true - true - 8000000 - 8000000 - - - - - ..\lib;..\externals;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) - false - MaxSpeed - CPPCHECKLIB_IMPORT;NDEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) - MultiThreadedDLL - Level4 - AnySuitable - true - Speed - true - true - true - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - - - true - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - true - stdcpp14 - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - true - Console - true - true - true - true - 8000000 - 8000000 - - - - - ..\lib;..\externals;..\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) - MultiThreadedDLL - Level4 - AnySuitable - true - Speed - true - true - true - 4018;4127;4244;4251;4267;4389;4482;4512;4701;4706;4800 - - - true - /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) - true - stdcpplatest - - - shlwapi.lib;%(AdditionalDependencies) - ../externals;%(AdditionalLibraryDirectories) - false - Console - true - true - true - true - 8000000 - 8000000 - - - - - - - - - - - - - - - {c183db5b-ad6c-423d-80ca-1f9549555a1a} - - - - - - - - - - - + + + + + Debug-PCRE + x64 + + + Debug + x64 + + + Release-PCRE + x64 + + + Release + x64 + + + + {35CBDF51-2456-3EC3-99ED-113C30858883} + cli + 10.0 + + + + Application + Unicode + false + v142 + + + Application + Unicode + false + v142 + + + Application + Unicode + false + v142 + + + Application + Unicode + false + v142 + + + + + + + + + + + + + + + + + + $(SolutionDir)bin\debug\ + $(SolutionDir)bin\debug\ + temp\$(Configuration)_$(PlatformName)\ + temp\$(Configuration)_$(PlatformName)\ + cppcheck + cppcheck + true + true + $(SolutionDir)bin\ + $(SolutionDir)bin\ + temp\$(Configuration)_$(PlatformName)\ + temp\$(Configuration)_$(PlatformName)\ + cppcheck + cppcheck + true + true + true + true + + + + ..\lib;..\frontend;..\externals;..\externals\picojson;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) + true + ProgramDatabase + Disabled + CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level4 + 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 + true + Use + precompiled.h + precompiled.h + true + stdcpp14 + /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) + + + shlwapi.lib;%(AdditionalDependencies) + ../externals;%(AdditionalLibraryDirectories) + true + Console + true + 8000000 + 8000000 + true + + + + + ..\lib;..\frontend;..\externals;..\externals\picojson;..\externals\simplecpp;..\externals\tinyxml2;%(AdditionalIncludeDirectories) + true + ProgramDatabase + Disabled + CPPCHECKLIB_IMPORT;TINYXML2_IMPORT;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level4 + 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 + true + Use + precompiled.h + precompiled.h + true + stdcpp14 + /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) + + + shlwapi.lib;%(AdditionalDependencies) + ../externals;%(AdditionalLibraryDirectories) + true + Console + true + 8000000 + 8000000 + true + + + + + ..\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) + MultiThreadedDLL + Level4 + AnySuitable + true + Speed + true + true + true + 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 + ProgramDatabase + true + Use + precompiled.h + precompiled.h + /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) + true + stdcpp14 + + + shlwapi.lib;%(AdditionalDependencies) + ../externals;%(AdditionalLibraryDirectories) + true + Console + true + true + true + true + 8000000 + 8000000 + true + + + + + ..\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) + MultiThreadedDLL + Level4 + AnySuitable + true + Speed + true + true + true + 4018;4127;4146;4244;4251;4267;4389;4701;4706;4800;4805 + ProgramDatabase + true + Use + precompiled.h + precompiled.h + /Zc:throwingNew /Zc:__cplusplus %(AdditionalOptions) + true + stdcpp14 + + + shlwapi.lib;%(AdditionalDependencies) + ../externals;%(AdditionalLibraryDirectories) + true + Console + true + true + true + true + 8000000 + 8000000 + true + + + + + + + + + + + + + + + + + + + + + {c183db5b-ad6c-423d-80ca-1f9549555a1a} + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + \ No newline at end of file diff --git a/cli/cli.vcxproj.filters b/cli/cli.vcxproj.filters index f95e472bbdc..5d3bd1c86cc 100644 --- a/cli/cli.vcxproj.filters +++ b/cli/cli.vcxproj.filters @@ -1,55 +1,94 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {6d3be647-edb6-43e6-a7eb-3031a2c7b655} - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {6d3be647-edb6-43e6-a7eb-3031a2c7b655} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + \ No newline at end of file diff --git a/cli/cmdlinelogger.h b/cli/cmdlinelogger.h new file mode 100644 index 00000000000..75981c028cd --- /dev/null +++ b/cli/cmdlinelogger.h @@ -0,0 +1,37 @@ +/* -*- C++ -*- + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 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 . + */ + +#ifndef CMD_LINE_LOGGER_H +#define CMD_LINE_LOGGER_H + +#include + +class CmdLineLogger +{ +public: + virtual ~CmdLineLogger() = default; + + /** print a regular message */ + virtual void printMessage(const std::string &message) = 0; + /** print an error message */ + virtual void printError(const std::string &message) = 0; + /** print to the output */ + virtual void printRaw(const std::string &message) = 0; +}; + +#endif // CMD_LINE_LOGGER_H diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index c2e56db3203..608e1844716 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-2021 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 @@ -18,68 +18,89 @@ #include "cmdlineparser.h" +#include "addoninfo.h" #include "check.h" -#include "cppcheckexecutor.h" +#include "checkers.h" +#include "color.h" +#include "config.h" +#include "cppcheck.h" +#include "errorlogger.h" +#include "errortypes.h" #include "filelister.h" +#include "filesettings.h" #include "importproject.h" +#include "library.h" #include "path.h" +#include "pathmatch.h" #include "platform.h" #include "settings.h" #include "standards.h" #include "suppressions.h" -#include "threadexecutor.h" // Threading model #include "timer.h" #include "utils.h" +#include "frontend.h" + #include +#include +#include #include #include // EXIT_FAILURE #include +#include #include +#include #include #include +#include +#include +#include #ifdef HAVE_RULES // xml is used for rules -#include +#include "xml.h" #endif -static void addFilesToList(const std::string& fileList, std::vector& pathNames) +static bool addFilesToList(const std::string& fileList, std::vector& pathNames) { - // To keep things initially simple, if the file can't be opened, just be silent and move on. std::istream *files; std::ifstream infile; if (fileList == "-") { // read from stdin files = &std::cin; } else { infile.open(fileList); + if (!infile.is_open()) + return false; files = &infile; } - if (files && *files) { - std::string fileName; - while (std::getline(*files, fileName)) { // next line - if (!fileName.empty()) { - pathNames.emplace_back(fileName); - } + 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)); } } + + return true; } -static bool addIncludePathsToList(const std::string& fileList, std::list* pathNames) +static bool addIncludePathsToList(const std::string& fileList, std::list& pathNames) { std::ifstream files(fileList); if (files) { std::string pathName; + // cppcheck-suppress accessMoved - FP while (std::getline(files, pathName)) { // next line if (!pathName.empty()) { - pathName = Path::removeQuotationMarks(pathName); - pathName = Path::fromNativeSeparators(pathName); + pathName = Path::removeQuotationMarks(std::move(pathName)); + pathName = Path::fromNativeSeparators(std::move(pathName)); // If path doesn't end with / or \, add it if (!endsWith(pathName, '/')) pathName += '/'; - pathNames->emplace_back(pathName); + pathNames.emplace_back(std::move(pathName)); } } return true; @@ -87,1187 +108,2075 @@ static bool addIncludePathsToList(const std::string& fileList, std::list* set) +static bool addPathsToSet(const std::string& fileName, std::set& set) { std::list templist; - if (!addIncludePathsToList(fileName, &templist)) + if (!addIncludePathsToList(fileName, templist)) return false; - set->insert(templist.begin(), templist.end()); + set.insert(templist.cbegin(), templist.cend()); return true; } -CmdLineParser::CmdLineParser(Settings *settings) - : mSettings(settings) - , mShowHelp(false) - , mShowVersion(false) - , mShowErrorMessages(false) - , mExitAfterPrint(false) -{ -} +namespace { + class XMLErrorMessagesLogger : public ErrorLogger + { + void reportOut(const std::string & outmsg, Color /*c*/ = Color::Reset) override + { + std::cout << outmsg << std::endl; + } -void CmdLineParser::printMessage(const std::string &message) -{ - std::cout << message << std::endl; + void reportErr(const ErrorMessage &msg) override + { + reportOut(msg.toXML()); + } + + void reportMetric(const std::string &metric) override + { + /* Not used here */ + (void) metric; + } + + void reportProgress(const std::string & /*filename*/, const char /*stage*/[], const std::size_t /*value*/) override + {} + }; } -void CmdLineParser::printMessage(const char* message) +CmdLineParser::CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppressions &suppressions) + : mLogger(logger) + , mSettings(settings) + , mSuppressions(suppressions) +{} + +bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) { - std::cout << message << std::endl; + const Result result = parseFromArgs(argc, argv); + + switch (result) { + case Result::Success: + break; + case Result::Exit: + Settings::terminate(); + return true; + case Result::Fail: + return false; + } + + // Libraries must be loaded before FileLister is executed to ensure markup files will be + // listed properly. + if (!loadLibraries(mSettings)) + return false; + + if (!loadAddons(mSettings)) + return false; + + // Check that all include paths exist + { + for (auto iter = mSettings.includePaths.cbegin(); + iter != mSettings.includePaths.cend(); + ) { + const std::string path(Path::toNativeSeparators(*iter)); + if (Path::isDirectory(path)) + ++iter; + else { + // TODO: this bypasses the template format and other settings + // If the include path is not found, warn user and remove the non-existing path from the list. + if (mSettings.severity.isEnabled(Severity::information)) + std::cout << "(information) Couldn't find path given by -I '" << path << '\'' << std::endl; + iter = mSettings.includePaths.erase(iter); + } + } + } + + // Output a warning for the user if he tries to exclude headers + const std::vector& ignored = getIgnoredPaths(); + const bool warn = std::any_of(ignored.cbegin(), ignored.cend(), [](const std::string& i) { + return Path::isHeader(i); + }); + if (warn) { + mLogger.printMessage("filename exclusion does not apply to header (.h and .hpp) files."); + mLogger.printMessage("Please use --suppress for ignoring results from the header files."); + } + + const std::vector& pathnamesRef = getPathNames(); + const std::list& fileSettingsRef = getFileSettings(); + + // the inputs can only be used exclusively - CmdLineParser should already handle this + assert(!(!pathnamesRef.empty() && !fileSettingsRef.empty())); + + if (!fileSettingsRef.empty()) { + // TODO: de-duplicate + + std::list fileSettings; + if (!mSettings.fileFilters.empty()) { + // filter only for the selected filenames from all project files + PathMatch filtermatcher(mSettings.fileFilters, Path::getCurrentPath()); + std::copy_if(fileSettingsRef.cbegin(), fileSettingsRef.cend(), std::back_inserter(fileSettings), [&](const FileSettings &fs) { + return filtermatcher.match(fs.filename()); + }); + if (fileSettings.empty()) { + for (const std::string& f: mSettings.fileFilters) + mLogger.printError("could not find any files matching the filter:" + f); + return false; + } + } + else { + fileSettings = fileSettingsRef; + } + + mFileSettings.clear(); + + frontend::applyLang(fileSettings, mSettings, mEnforcedLang); + + // sort the markup last + std::copy_if(fileSettings.cbegin(), fileSettings.cend(), std::back_inserter(mFileSettings), [&](const FileSettings &fs) { + return !mSettings.library.markupFile(fs.filename()) || !mSettings.library.processMarkupAfterCode(fs.filename()); + }); + + std::copy_if(fileSettings.cbegin(), fileSettings.cend(), std::back_inserter(mFileSettings), [&](const FileSettings &fs) { + return mSettings.library.markupFile(fs.filename()) && mSettings.library.processMarkupAfterCode(fs.filename()); + }); + + if (mFileSettings.empty()) { + mLogger.printError("could not find or open any of the paths given."); + return false; + } + } + + if (!pathnamesRef.empty()) { + std::list filesResolved; + // Execute recursiveAddFiles() to each given file parameter + // TODO: verbose log which files were ignored? + const PathMatch matcher(ignored, Path::getCurrentPath()); + for (const std::string &pathname : pathnamesRef) { + const std::string err = FileLister::recursiveAddFiles(filesResolved, Path::toNativeSeparators(pathname), mSettings.library.markupExtensions(), matcher, mSettings.debugignore); + if (!err.empty()) { + // TODO: bail out? + mLogger.printMessage(err); + } + } + + if (filesResolved.empty()) { + mLogger.printError("could not find or open any of the paths given."); + // TODO: PathMatch should provide the information if files were ignored + if (!ignored.empty()) + mLogger.printMessage("Maybe all paths were ignored?"); + 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); + if (files.empty()) { + for (const std::string& f: mSettings.fileFilters) + mLogger.printError("could not find any files matching the filter:" + f); + return false; + } + } + else { + files = std::move(filesResolved); + } + + frontend::applyLang(files, mSettings, mEnforcedLang); + + // sort the markup last + std::copy_if(files.cbegin(), files.cend(), std::inserter(mFiles, mFiles.end()), [&](const FileWithDetails& entry) { + return !mSettings.library.markupFile(entry.path()) || !mSettings.library.processMarkupAfterCode(entry.path()); + }); + + std::copy_if(files.cbegin(), files.cend(), std::inserter(mFiles, mFiles.end()), [&](const FileWithDetails& entry) { + return mSettings.library.markupFile(entry.path()) && mSettings.library.processMarkupAfterCode(entry.path()); + }); + + if (mFiles.empty()) { + mLogger.printError("could not find or open any of the paths given."); + return false; + } + } + + return true; } -bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) +// TODO: normalize/simplify/native all path parameters +// TODO: error out on all missing given files/paths +CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const argv[]) { + mSettings.exename = Path::getCurrentExecutablePath(argv[0]); + + bool xmlOptionProvided = false; + bool outputFormatOptionProvided = false; + + // default to --check-level=normal from CLI for now + mSettings.setCheckLevel(Settings::CheckLevel::normal); + + if (argc <= 1) { + printHelp(); + return Result::Exit; + } + + // check for exclusive options + for (int i = 1; i < argc; i++) { + // documentation.. + 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()); + if (!name.empty() && !info.empty()) + doc << "## " << name << " ##\n" + << info << "\n"; + } + + mLogger.printRaw(doc.str()); + return Result::Exit; + } + + // print all possible error messages.. + if (std::strcmp(argv[i], "--errorlist") == 0) { + if (!loadCppcheckCfg()) + return Result::Fail; + { + XMLErrorMessagesLogger xmlLogger; + std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName, 2); + CppCheck::getErrorMessages(xmlLogger); + std::cout << ErrorMessage::getXMLFooter(2) << std::endl; + } + return Result::Exit; + } + + // Print help + if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { + printHelp(); + return Result::Exit; + } + + if (std::strcmp(argv[i], "--filesdir") == 0) { +#ifdef FILESDIR + mLogger.printRaw(FILESDIR); // TODO: should not include newline +#endif + return Result::Exit; + } + + if (std::strcmp(argv[i], "--version") == 0) { + if (!loadCppcheckCfg()) + return Result::Fail; + const std::string version = getVersion(); + mLogger.printRaw(version); // TODO: should not include newline + return Result::Exit; + } + } + bool def = false; bool maxconfigs = false; + bool debug = false; + + ImportProject::Type projectType = ImportProject::Type::NONE; + ImportProject project; + std::string vsConfig; + + std::string platform; + char defaultSign = '\0'; + + std::vector lookupPaths{argv[0]}; - mSettings->exename = argv[0]; + bool executorAuto = true; for (int i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - // User define - if (std::strncmp(argv[i], "-D", 2) == 0) { - std::string define; - - // "-D define" - if (std::strcmp(argv[i], "-D") == 0) { - ++i; - if (i >= argc || argv[i][0] == '-') { - printMessage("cppcheck: argument to '-D' is missing."); - return false; - } + if (argv[i][0] != '-') { + mPathNames.emplace_back(Path::fromNativeSeparators(Path::removeQuotationMarks(argv[i]))); + } - define = argv[i]; - } - // "-Ddefine" - else { - define = 2 + argv[i]; + // User define + else if (std::strncmp(argv[i], "-D", 2) == 0) { + std::string define; + + // "-D define" + if (std::strcmp(argv[i], "-D") == 0) { + ++i; + if (i >= argc || argv[i][0] == '-') { + mLogger.printError("argument to '-D' is missing."); + return Result::Fail; } - // No "=", append a "=1" - if (define.find('=') == std::string::npos) - define += "=1"; + define = argv[i]; + } + // "-Ddefine" + else { + define = 2 + argv[i]; + } - if (!mSettings->userDefines.empty()) - mSettings->userDefines += ";"; - mSettings->userDefines += define; + // No "=", append a "=1" + if (define.find('=') == std::string::npos) + define += "=1"; - def = true; - } + if (!mSettings.userDefines.empty()) + mSettings.userDefines += ";"; + mSettings.userDefines += define; - // -E - else if (std::strcmp(argv[i], "-E") == 0) { - mSettings->preprocessOnly = true; - mSettings->quiet = true; - } + def = true; + } - // Include paths - else if (std::strncmp(argv[i], "-I", 2) == 0) { - std::string path; + // -E + else if (std::strcmp(argv[i], "-E") == 0) { + mSettings.preprocessOnly = true; + mSettings.quiet = true; + } - // "-I path/" - if (std::strcmp(argv[i], "-I") == 0) { - ++i; - if (i >= argc || argv[i][0] == '-') { - printMessage("cppcheck: argument to '-I' is missing."); - return false; - } - path = argv[i]; - } + // Include paths + else if (std::strncmp(argv[i], "-I", 2) == 0) { + std::string path; - // "-Ipath/" - else { - path = 2 + argv[i]; + // "-I path/" + if (std::strcmp(argv[i], "-I") == 0) { + ++i; + if (i >= argc || argv[i][0] == '-') { + mLogger.printError("argument to '-I' is missing."); + return Result::Fail; } - path = Path::removeQuotationMarks(path); - path = Path::fromNativeSeparators(path); - - // If path doesn't end with / or \, add it - if (!endsWith(path,'/')) - path += '/'; + path = argv[i]; + } - mSettings->includePaths.emplace_back(path); + // "-Ipath/" + else { + path = 2 + argv[i]; } + path = Path::removeQuotationMarks(std::move(path)); + path = Path::fromNativeSeparators(std::move(path)); - // User undef - else if (std::strncmp(argv[i], "-U", 2) == 0) { - std::string undef; + // If path doesn't end with / or \, add it + if (!endsWith(path,'/')) + path += '/'; - // "-U undef" - if (std::strcmp(argv[i], "-U") == 0) { - ++i; - if (i >= argc || argv[i][0] == '-') { - printMessage("cppcheck: argument to '-U' is missing."); - return false; - } + mSettings.includePaths.emplace_back(std::move(path)); + } - undef = argv[i]; - } - // "-Uundef" - else { - undef = 2 + argv[i]; + // User undef + else if (std::strncmp(argv[i], "-U", 2) == 0) { + std::string undef; + + // "-U undef" + if (std::strcmp(argv[i], "-U") == 0) { + ++i; + if (i >= argc || argv[i][0] == '-') { + mLogger.printError("argument to '-U' is missing."); + return Result::Fail; } - mSettings->userUndefs.insert(undef); + undef = argv[i]; + } + // "-Uundef" + else { + undef = 2 + argv[i]; } - else if (std::strncmp(argv[i], "--addon=", 8) == 0) - mSettings->addons.emplace_back(argv[i]+8); + mSettings.userUndefs.insert(std::move(undef)); + } - else if (std::strncmp(argv[i],"--addon-python=", 15) == 0) - mSettings->addonPython.assign(argv[i]+15); + else if (std::strncmp(argv[i], "--addon=", 8) == 0) + mSettings.addons.emplace(argv[i]+8); - else if (std::strcmp(argv[i], "--bug-hunting") == 0) - mSettings->bugHunting = true; + else if (std::strncmp(argv[i],"--addon-python=", 15) == 0) + mSettings.addonPython.assign(argv[i]+15); - // TODO: Rename or move this parameter? - else if (std::strncmp(argv[i], "--bug-hunting-check-function-max-time=", 38) == 0) - mSettings->bugHuntingCheckFunctionMaxTime = std::atoi(argv[i] + 38); + else if (std::strcmp(argv[i],"--analyze-all-vs-configs") == 0) { + mSettings.analyzeAllVsConfigs = true; + mAnalyzeAllVsConfigsSetOnCmdLine = true; + } - // Check configuration - else if (std::strcmp(argv[i], "--check-config") == 0) - mSettings->checkConfiguration = true; + // Check configuration + else if (std::strcmp(argv[i], "--check-config") == 0) + mSettings.checkConfiguration = true; + + else if (std::strcmp(argv[i], "--check-headers") == 0) + mSettings.checkHeaders = true; + + // Check level + else if (std::strncmp(argv[i], "--check-level=", 14) == 0) { + Settings::CheckLevel level = Settings::CheckLevel::normal; + const std::string level_s(argv[i] + 14); + if (level_s == "reduced") + level = Settings::CheckLevel::reduced; + else if (level_s == "normal") + level = Settings::CheckLevel::normal; + else if (level_s == "exhaustive") + level = Settings::CheckLevel::exhaustive; + else { + mLogger.printError("unknown '--check-level' value '" + level_s + "'."); + return Result::Fail; + } - // Check library definitions - else if (std::strcmp(argv[i], "--check-library") == 0) { - mSettings->checkLibrary = true; - // need to add "information" or no messages will be shown at all - mSettings->addEnabled("information"); + mSettings.setCheckLevel(level); + } + + // Check library definitions + else if (std::strcmp(argv[i], "--check-library") == 0) { + mSettings.checkLibrary = true; + } + + else if (std::strcmp(argv[i], "--check-unused-templates") == 0) + mSettings.checkUnusedTemplates = true; + + else if (std::strncmp(argv[i], "--check-version=", 16) == 0) { + if (!loadCppcheckCfg()) + return Result::Fail; + const std::string actualVersion = getVersion(); + const std::string wantedVersion = argv[i] + 16; + if (actualVersion != wantedVersion) { + mLogger.printError("--check-version check failed. Aborting."); + return Result::Fail; } + } - else if (std::strncmp(argv[i], "--clang", 7) == 0) { - mSettings->clang = true; - if (std::strncmp(argv[i], "--clang=", 8) == 0) { - mSettings->clangExecutable = argv[i] + 8; - } + else if (std::strncmp(argv[i], "--checkers-report=", 18) == 0) + mSettings.checkersReportFilename = argv[i] + 18; + + else if (std::strncmp(argv[i], "--checks-max-time=", 18) == 0) { + if (!parseNumberArg(argv[i], 18, mSettings.checksMaxTime, true)) + return Result::Fail; + } + + else if (std::strcmp(argv[i], "--clang") == 0) { + mSettings.clang = true; + } + + else if (std::strncmp(argv[i], "--clang=", 8) == 0) { + mSettings.clang = true; + mSettings.clangExecutable = argv[i] + 8; + } + + else if (std::strcmp(argv[i], "--clang-tidy") == 0) { + mSettings.clangTidy = true; + } + + else if (std::strncmp(argv[i], "--clang-tidy=", 13) == 0) { + mSettings.clangTidy = true; + mSettings.clangTidyExecutable = argv[i] + 13; + } + + else if (std::strncmp(argv[i], "--config-exclude=",17) ==0) { + mSettings.configExcludePaths.insert(Path::fromNativeSeparators(argv[i] + 17)); + } + + else if (std::strncmp(argv[i], "--config-excludes-file=", 23) == 0) { + // open this file and read every input file (1 file name per line) + const std::string cfgExcludesFile(23 + argv[i]); + if (!addPathsToSet(cfgExcludesFile, mSettings.configExcludePaths)) { + mLogger.printError("unable to open config excludes file at '" + cfgExcludesFile + "'"); + return Result::Fail; } + } - else if (std::strncmp(argv[i], "--config-exclude=",17) ==0) { - mSettings->configExcludePaths.insert(Path::fromNativeSeparators(argv[i] + 17)); + else if (std::strncmp(argv[i], "--cppcheck-build-dir=", 21) == 0) { + std::string path = Path::fromNativeSeparators(argv[i] + 21); + if (path.empty()) { + mLogger.printError("no path has been specified for --cppcheck-build-dir"); + return Result::Fail; } + if (endsWith(path, '/')) + path.pop_back(); + mSettings.buildDir = std::move(path); + } - else if (std::strncmp(argv[i], "--config-excludes-file=", 23) == 0) { - // open this file and read every input file (1 file name per line) - const std::string cfgExcludesFile(23 + argv[i]); - if (!addPathsToSet(cfgExcludesFile, &mSettings->configExcludePaths)) { - printMessage("Cppcheck: unable to open config excludes file at '" + cfgExcludesFile + "'"); - return false; - } + else if (std::strcmp(argv[i], "--cpp-header-probe") == 0) { + mSettings.cppHeaderProbe = true; + } + + else if (std::strcmp(argv[i], "--debug-ast") == 0) + mSettings.debugast = true; + + // Show debug warnings for lookup for configuration files + else if (std::strcmp(argv[i], "--debug-clang-output") == 0) + mSettings.debugClangOutput = true; + + // Show debug messages for ignored files + else if (std::strcmp(argv[i], "--debug-ignore") == 0) + mSettings.debugignore = true; + + // Show --debug output after the first simplifications + else if (std::strcmp(argv[i], "--debug") == 0 || + std::strcmp(argv[i], "--debug-normal") == 0) + debug = true; + + // Show debug warnings for lookup for configuration files + else if (std::strcmp(argv[i], "--debug-lookup") == 0) + mSettings.debuglookup = true; + + else if (std::strncmp(argv[i], "--debug-lookup=", 15) == 0) { + const std::string lookup = argv[i] + 15; + if (lookup == "all") + mSettings.debuglookup = true; + else if (lookup == "addon") + mSettings.debuglookupAddon = true; + else if (lookup == "config") + mSettings.debuglookupConfig = true; + else if (lookup == "library") + mSettings.debuglookupLibrary = true; + else if (lookup == "platform") + mSettings.debuglookupPlatform = true; + else + { + mLogger.printError("unknown lookup '" + lookup + "'"); + return Result::Fail; } + } + + // Flag used for various purposes during debugging + else if (std::strcmp(argv[i], "--debug-simplified") == 0) + mSettings.debugSimplified = true; + + else if (std::strcmp(argv[i], "--debug-symdb") == 0) + mSettings.debugsymdb = true; + + // Show template information + else if (std::strcmp(argv[i], "--debug-template") == 0) + mSettings.debugtemplate = true; + + else if (std::strcmp(argv[i], "--debug-valueflow") == 0) + mSettings.debugvalueflow = true; + + // Show debug warnings + else if (std::strcmp(argv[i], "--debug-warnings") == 0) + mSettings.debugwarnings = true; - else if (std::strncmp(argv[i], "--cppcheck-build-dir=", 21) == 0) { - mSettings->buildDir = Path::fromNativeSeparators(argv[i] + 21); - if (endsWith(mSettings->buildDir, '/')) - mSettings->buildDir.pop_back(); + else if (std::strncmp(argv[i], "--disable=", 10) == 0) { + const std::string errmsg = mSettings.removeEnabled(argv[i] + 10); + if (!errmsg.empty()) { + mLogger.printError(errmsg); + return Result::Fail; } + } - // Show --debug output after the first simplifications - else if (std::strcmp(argv[i], "--debug") == 0 || - std::strcmp(argv[i], "--debug-normal") == 0) - mSettings->debugnormal = true; + // dump cppcheck data + else if (std::strcmp(argv[i], "--dump") == 0) + mSettings.dump = true; - // show bug hunting debug output - else if (std::strcmp(argv[i], "--debug-bug-hunting") == 0) - mSettings->debugBugHunting = true; + else if (std::strcmp(argv[i], "--emit-duplicates") == 0) + mSettings.emitDuplicates = true; - // Flag used for various purposes during debugging - else if (std::strcmp(argv[i], "--debug-simplified") == 0) - mSettings->debugSimplified = true; + else if (std::strncmp(argv[i], "--enable=", 9) == 0) { + const std::string enable_arg = argv[i] + 9; + const std::string errmsg = mSettings.addEnabled(enable_arg); + if (!errmsg.empty()) { + mLogger.printError(errmsg); + return Result::Fail; + } + // when "style" is enabled, also enable "warning", "performance" and "portability" + if (enable_arg.find("style") != std::string::npos) { + mSettings.addEnabled("warning"); + mSettings.addEnabled("performance"); + mSettings.addEnabled("portability"); + } + } - // Show template information - else if (std::strcmp(argv[i], "--debug-template") == 0) - mSettings->debugtemplate = true; + // --error-exitcode=1 + else if (std::strncmp(argv[i], "--error-exitcode=", 17) == 0) { + if (!parseNumberArg(argv[i], 17, mSettings.exitCode)) + return Result::Fail; + } - // Show debug warnings - else if (std::strcmp(argv[i], "--debug-warnings") == 0) - mSettings->debugwarnings = true; + // Exception handling inside cppcheck client + else if (std::strcmp(argv[i], "--exception-handling") == 0) { +#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING) + mSettings.exceptionHandling = true; +#else + mLogger.printError("Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled."); + return Result::Fail; +#endif + } - // documentation.. - else 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()); - if (!name.empty() && !info.empty()) - doc << "## " << name << " ##\n" - << info << "\n"; - } + // Exception handling inside cppcheck client + else if (std::strncmp(argv[i], "--exception-handling=", 21) == 0) { +#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING) + const std::string exceptionOutfilename = argv[i] + 21; + if (exceptionOutfilename != "stderr" && exceptionOutfilename != "stdout") { + mLogger.printError("invalid '--exception-handling' argument"); + return Result::Fail; + } + mSettings.exceptionHandling = true; + mSettings.exceptionOutput = (exceptionOutfilename == "stderr") ? stderr : stdout; +#else + mLogger.printError("Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled."); + return Result::Fail; +#endif + } - std::cout << doc.str(); - mExitAfterPrint = true; - return true; + else if (std::strncmp(argv[i], "--executor=", 11) == 0) { + const std::string type = 11 + argv[i]; + if (type == "auto") { + executorAuto = true; + mSettings.executor = Settings::defaultExecutor(); + } + else if (type == "thread") { +#if defined(HAS_THREADING_MODEL_THREAD) + executorAuto = false; + mSettings.executor = Settings::ExecutorType::Thread; +#else + mLogger.printError("executor type 'thread' cannot be used as Cppcheck has not been built with a respective threading model."); + return Result::Fail; +#endif + } + else if (type == "process") { +#if defined(HAS_THREADING_MODEL_FORK) + executorAuto = false; + mSettings.executor = Settings::ExecutorType::Process; +#else + mLogger.printError("executor type 'process' cannot be used as Cppcheck has not been built with a respective threading model."); + return Result::Fail; +#endif } + else { + mLogger.printError("unknown executor: '" + type + "'."); + return Result::Fail; + } + } - // dump cppcheck data - else if (std::strcmp(argv[i], "--dump") == 0) - mSettings->dump = true; + // Filter errors + else if (std::strncmp(argv[i], "--exitcode-suppressions=", 24) == 0) { + // exitcode-suppressions=filename.txt + std::string filename = 24 + argv[i]; - else if (std::strncmp(argv[i], "--enable=", 9) == 0) { - const std::string errmsg = mSettings->addEnabled(argv[i] + 9); - if (!errmsg.empty()) { - printMessage(errmsg); - return false; - } - // when "style" is enabled, also enable "warning", "performance" and "portability" - if (mSettings->severity.isEnabled(Severity::style)) { - mSettings->addEnabled("warning"); - mSettings->addEnabled("performance"); - mSettings->addEnabled("portability"); + std::ifstream f(filename); + if (!f.is_open()) { + mLogger.printError("couldn't open the file: \"" + filename + "\"."); + return Result::Fail; + } + const std::string errmsg(mSuppressions.nofail.parseFile(f)); + if (!errmsg.empty()) { + mLogger.printError(errmsg); + return Result::Fail; + } + } + + // use a file filter + else if (std::strncmp(argv[i], "--file-filter=", 14) == 0) { + const char *filter = argv[i] + 14; + if (std::strcmp(filter, "-") == 0) { + if (!addFilesToList(filter, mSettings.fileFilters)) { + mLogger.printError("Failed: --file-filter=-"); + return Result::Fail; } + } else { + mSettings.fileFilters.emplace_back(filter); } + } - // print all possible error messages.. - else if (std::strcmp(argv[i], "--errorlist") == 0) { - mShowErrorMessages = true; - mSettings->xml = true; - mExitAfterPrint = true; + // file list specified + else if (std::strncmp(argv[i], "--file-list=", 12) == 0) { + // open this file and read every input file (1 file name per line) + const std::string fileList = argv[i] + 12; + if (!addFilesToList(fileList, mPathNames)) { + mLogger.printError("couldn't open the file: \"" + fileList + "\"."); + return Result::Fail; } + } + + // Force checking of files that have "too many" configurations + else if (std::strcmp(argv[i], "-f") == 0 || std::strcmp(argv[i], "--force") == 0) + mSettings.force = true; + + else if (std::strcmp(argv[i], "--fsigned-char") == 0) + defaultSign = 's'; - // --error-exitcode=1 - else if (std::strncmp(argv[i], "--error-exitcode=", 17) == 0) { - const std::string temp = argv[i]+17; - std::istringstream iss(temp); - if (!(iss >> mSettings->exitCode)) { - mSettings->exitCode = 0; - printMessage("cppcheck: Argument must be an integer. Try something like '--error-exitcode=1'."); - return false; + else if (std::strcmp(argv[i], "--funsigned-char") == 0) + defaultSign = 'u'; + + // Ignored paths + else if (std::strncmp(argv[i], "-i", 2) == 0) { + std::string path; + + // "-i path/" + if (std::strcmp(argv[i], "-i") == 0) { + ++i; + if (i >= argc || argv[i][0] == '-') { + mLogger.printError("argument to '-i' is missing."); + return Result::Fail; } + path = argv[i]; } - // Exception handling inside cppcheck client - else if (std::strcmp(argv[i], "--exception-handling") == 0) - mSettings->exceptionHandling = true; + // "-ipath/" + else { + path = 2 + argv[i]; + } - else if (std::strncmp(argv[i], "--exception-handling=", 21) == 0) { - mSettings->exceptionHandling = true; - const std::string exceptionOutfilename = &(argv[i][21]); - CppCheckExecutor::setExceptionOutput((exceptionOutfilename=="stderr") ? stderr : stdout); + if (!path.empty()) { + mIgnoredPaths.emplace_back(std::move(path)); } + } - // Filter errors - else if (std::strncmp(argv[i], "--exitcode-suppressions=", 24) == 0) { - // exitcode-suppressions=filename.txt - std::string filename = 24 + argv[i]; + else if (std::strncmp(argv[i], "--include=", 10) == 0) { + mSettings.userIncludes.emplace_back(Path::fromNativeSeparators(argv[i] + 10)); + } - std::ifstream f(filename); - if (!f.is_open()) { - printMessage("cppcheck: Couldn't open the file: \"" + filename + "\"."); - return false; - } - const std::string errmsg(mSettings->nofail.parseFile(f)); - if (!errmsg.empty()) { - printMessage(errmsg); - return false; - } + else if (std::strncmp(argv[i], "--includes-file=", 16) == 0) { + // open this file and read every input file (1 file name per line) + const std::string includesFile(16 + argv[i]); + if (!addIncludePathsToList(includesFile, mSettings.includePaths)) { + mLogger.printError("unable to open includes file at '" + includesFile + "'"); + return Result::Fail; } + } - // use a file filter - else if (std::strncmp(argv[i], "--file-filter=", 14) == 0) - mSettings->fileFilter = argv[i] + 14; + // Inconclusive checking + else if (std::strcmp(argv[i], "--inconclusive") == 0) + mSettings.certainty.enable(Certainty::inconclusive); - // file list specified - else if (std::strncmp(argv[i], "--file-list=", 12) == 0) - // open this file and read every input file (1 file name per line) - addFilesToList(12 + argv[i], mPathNames); + // Enables inline suppressions. + else if (std::strcmp(argv[i], "--inline-suppr") == 0) + mSettings.inlineSuppressions = true; - // Force checking of files that have "too many" configurations - else if (std::strcmp(argv[i], "-f") == 0 || std::strcmp(argv[i], "--force") == 0) - mSettings->force = true; + // Checking threads + else if (std::strncmp(argv[i], "-j", 2) == 0) { + std::string numberString; - // Print help - else if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { - mPathNames.clear(); - mShowHelp = true; - mExitAfterPrint = true; - break; + // "-j 3" + if (std::strcmp(argv[i], "-j") == 0) { + ++i; + if (i >= argc || argv[i][0] == '-') { + mLogger.printError("argument to '-j' is missing."); + return Result::Fail; + } + + numberString = argv[i]; } - // Ignored paths - else if (std::strncmp(argv[i], "-i", 2) == 0) { - std::string path; + // "-j3" + else + numberString = argv[i]+2; - // "-i path/" - if (std::strcmp(argv[i], "-i") == 0) { - ++i; - if (i >= argc || argv[i][0] == '-') { - printMessage("cppcheck: argument to '-i' is missing."); - return false; - } - path = argv[i]; - } + unsigned int tmp; + std::string err; + if (!strToInt(numberString, tmp, &err)) { + mLogger.printError("argument to '-j' is not valid - " + err + "."); + return Result::Fail; + } + if (tmp == 0) { + // TODO: implement get CPU logical core count and use that. + // Usually, -j 0 would mean "use all available cores," but + // if we get a 0, we just stall and don't do any work. + mLogger.printError("argument for '-j' must be greater than 0."); + return Result::Fail; + } + if (tmp > 1024) { + // Almost nobody has 1024 logical cores, but somebody out + // there does. + mLogger.printError("argument for '-j' is allowed to be 1024 at max."); + return Result::Fail; + } + mSettings.jobs = tmp; + } - // "-ipath/" - else { - path = 2 + argv[i]; + else if (std::strncmp(argv[i], "-l", 2) == 0) { +#ifdef HAS_THREADING_MODEL_FORK + std::string numberString; + + // "-l 3" + if (std::strcmp(argv[i], "-l") == 0) { + ++i; + if (i >= argc || argv[i][0] == '-') { + mLogger.printError("argument to '-l' is missing."); + return Result::Fail; } - if (!path.empty()) { - path = Path::removeQuotationMarks(path); - path = Path::fromNativeSeparators(path); - path = Path::simplifyPath(path); + numberString = argv[i]; + } - if (FileLister::isDirectory(path)) { - // If directory name doesn't end with / or \, add it - if (!endsWith(path, '/')) - path += '/'; - } - mIgnoredPaths.emplace_back(path); + // "-l3" + else + numberString = argv[i]+2; + + int tmp; + std::string err; + if (!strToInt(numberString, tmp, &err)) { + mLogger.printError("argument to '-l' is not valid - " + err + "."); + return Result::Fail; + } + mSettings.loadAverage = tmp; +#else + mLogger.printError("Option -l cannot be used as Cppcheck has not been built with fork threading model."); + return Result::Fail; +#endif + } + + // Enforce language (--language=, -x) + else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) { + std::string str; + if (argv[i][2]) { + str = argv[i]+11; + } else { + i++; + if (i >= argc || argv[i][0] == '-') { + mLogger.printError("no language given to '-x' option."); + return Result::Fail; } + str = argv[i]; } - else if (std::strncmp(argv[i], "--include=", 10) == 0) { - mSettings->userIncludes.emplace_back(Path::fromNativeSeparators(argv[i] + 10)); + if (str == "c") + mEnforcedLang = Standards::Language::C; + else if (str == "c++") + mEnforcedLang = Standards::Language::CPP; + else { + mLogger.printError("unknown language '" + str + "' enforced."); + return Result::Fail; } + } - else if (std::strncmp(argv[i], "--includes-file=", 16) == 0) { - // open this file and read every input file (1 file name per line) - const std::string includesFile(16 + argv[i]); - if (!addIncludePathsToList(includesFile, &mSettings->includePaths)) { - printMessage("Cppcheck: unable to open includes file at '" + includesFile + "'"); - return false; + // --library + else if (std::strncmp(argv[i], "--library=", 10) == 0) { + std::vector libs = splitString(argv[i] + 10, ','); + for (auto& l : libs) { + if (l.empty()) { + mLogger.printError("empty library specified."); + return Result::Fail; } + mSettings.libraries.emplace_back(std::move(l)); } + } - // Inconclusive checking - else if (std::strcmp(argv[i], "--inconclusive") == 0) - mSettings->certainty.enable(Certainty::inconclusive); + // Set maximum number of #ifdef configurations to check + else if (std::strncmp(argv[i], "--max-configs=", 14) == 0) { + int tmp; + if (!parseNumberArg(argv[i], 14, tmp)) + return Result::Fail; + if (tmp < 1) { + mLogger.printError("argument to '--max-configs=' must be greater than 0."); + return Result::Fail; + } - // Enables inline suppressions. - else if (std::strcmp(argv[i], "--inline-suppr") == 0) - mSettings->inlineSuppressions = true; + mSettings.maxConfigs = tmp; + mSettings.force = false; + maxconfigs = true; + } - // Checking threads - else if (std::strncmp(argv[i], "-j", 2) == 0) { - std::string numberString; + // max ctu depth + else if (std::strncmp(argv[i], "--max-ctu-depth=", 16) == 0) { + int temp = 0; + if (!parseNumberArg(argv[i], 16, temp)) + return Result::Fail; + if (temp > 10) { + mLogger.printMessage("--max-ctu-depth is being capped at 10. This limitation will be removed in a future Cppcheck version."); + temp = 10; + } + mSettings.maxCtuDepth = temp; + } - // "-j 3" - if (std::strcmp(argv[i], "-j") == 0) { - ++i; - if (i >= argc || argv[i][0] == '-') { - printMessage("cppcheck: argument to '-j' is missing."); - return false; - } + else if (std::strncmp(argv[i], "--max-template-recursion=", 25) == 0) { + if (!parseNumberArg(argv[i], 25, mSettings.maxTemplateRecursion)) + return Result::Fail; + } - numberString = argv[i]; - } + else if (std::strcmp(argv[i],"--no-analyze-all-vs-configs") == 0) { + mSettings.analyzeAllVsConfigs = false; + mAnalyzeAllVsConfigsSetOnCmdLine = true; + } - // "-j3" - else - numberString = argv[i]+2; + else if (std::strcmp(argv[i], "--no-check-headers") == 0) + mSettings.checkHeaders = false; - std::istringstream iss(numberString); - if (!(iss >> mSettings->jobs)) { - printMessage("cppcheck: argument to '-j' is not a number."); - return false; - } + else if (std::strcmp(argv[i], "--no-check-unused-templates") == 0) + mSettings.checkUnusedTemplates = false; - if (mSettings->jobs > 10000) { - // This limit is here just to catch typos. If someone has - // need for more jobs, this value should be increased. - printMessage("cppcheck: argument for '-j' is allowed to be 10000 at max."); - return false; - } - } + // undocumented option for usage in Python tests to indicate that no build dir should be injected + else if (std::strcmp(argv[i], "--no-cppcheck-build-dir") == 0) { + mSettings.buildDir.clear(); + } - else if (std::strncmp(argv[i], "-l", 2) == 0) { - std::string numberString; + else if (std::strcmp(argv[i], "--no-cpp-header-probe") == 0) { + mSettings.cppHeaderProbe = false; + } - // "-l 3" - if (std::strcmp(argv[i], "-l") == 0) { - ++i; - if (i >= argc || argv[i][0] == '-') { - printMessage("cppcheck: argument to '-l' is missing."); - return false; - } + // Write results in file + else if (std::strncmp(argv[i], "--output-file=", 14) == 0) + mSettings.outputFile = Path::simplifyPath(argv[i] + 14); - numberString = argv[i]; - } + else if (std::strncmp(argv[i], "--output-format=", 16) == 0) { + if (xmlOptionProvided) { + outputFormatOptionMixingError(); + return Result::Fail; + } + const std::string format = argv[i] + 16; + // plist can not be handled here because it requires additional data + if (format == "text") + mSettings.outputFormat = Settings::OutputFormat::text; + else if (format == "sarif") + mSettings.outputFormat = Settings::OutputFormat::sarif; + else if (format == "xml") + mSettings.outputFormat = Settings::OutputFormat::xml; + else if (format == "xmlv2") { + mSettings.outputFormat = Settings::OutputFormat::xml; + mSettings.xml_version = 2; + } else if (format == "xmlv3") { + mSettings.outputFormat = Settings::OutputFormat::xml; + mSettings.xml_version = 3; + } else { + mLogger.printError("argument to '--output-format=' must be 'text', 'sarif', 'xml' (deprecated), 'xmlv2' or 'xmlv3'."); + return Result::Fail; + } + mSettings.plistOutput = ""; + outputFormatOptionProvided = true; + } - // "-l3" - else - numberString = argv[i]+2; - std::istringstream iss(numberString); - if (!(iss >> mSettings->loadAverage)) { - printMessage("cppcheck: argument to '-l' is not a number."); - return false; - } - } + // Experimental: limit execution time for extended valueflow analysis. basic valueflow analysis + // is always executed. + else if (std::strncmp(argv[i], "--performance-valueflow-max-time=", 33) == 0) { + if (!parseNumberArg(argv[i], 33, mSettings.vfOptions.maxTime, true)) + return Result::Fail; + } - // Enforce language (--language=, -x) - else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) { - std::string str; - if (argv[i][2]) { - str = argv[i]+11; - } else { - i++; - if (i >= argc || argv[i][0] == '-') { - printMessage("cppcheck: No language given to '-x' option."); - return false; - } - str = argv[i]; - } + else if (std::strncmp(argv[i], "--performance-valueflow-max-if-count=", 37) == 0) { + if (!parseNumberArg(argv[i], 37, mSettings.vfOptions.maxIfCount, true)) + return Result::Fail; + } - if (str == "c") - mSettings->enforcedLang = Settings::C; - else if (str == "c++") - mSettings->enforcedLang = Settings::CPP; - else { - printMessage("cppcheck: Unknown language '" + str + "' enforced."); - return false; - } + else if (std::strncmp(argv[i], "--performance-valueflow-max-iterations=", 39) == 0) { + if (!parseNumberArg(argv[i], 39, mSettings.vfOptions.maxIterations, true)) + return Result::Fail; + } + + // Specify platform + else if (std::strncmp(argv[i], "--platform=", 11) == 0) { + std::string p = 11 + argv[i]; + if (p.empty()) { + mLogger.printError("empty platform specified."); + return Result::Fail; } + platform = std::move(p); + } - // --library - else if (std::strncmp(argv[i], "--library=", 10) == 0) { - mSettings->libraries.emplace_back(argv[i] + 10); + // Write results in results.plist + else if (std::strncmp(argv[i], "--plist-output=", 15) == 0) { + std::string path = Path::simplifyPath(argv[i] + 15); + if (path.empty()) + path = "."; + + const std::string plistOutput = Path::toNativeSeparators(path); + if (!Path::isDirectory(plistOutput)) { + std::string message("plist folder does not exist: '"); + message += plistOutput; + message += "'."; + mLogger.printError(message); + return Result::Fail; } - // Set maximum number of #ifdef configurations to check - else if (std::strncmp(argv[i], "--max-configs=", 14) == 0) { - mSettings->force = false; + if (!endsWith(path,'/')) + path += '/'; - std::istringstream iss(14+argv[i]); - if (!(iss >> mSettings->maxConfigs)) { - printMessage("cppcheck: argument to '--max-configs=' is not a number."); - return false; - } + mSettings.outputFormat = Settings::OutputFormat::plist; + mSettings.plistOutput = std::move(path); + } - if (mSettings->maxConfigs < 1) { - printMessage("cppcheck: argument to '--max-configs=' must be greater than 0."); - return false; - } + // Special Cppcheck Premium options + else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && isCppcheckPremium()) { + // valid options --premium=.. + const std::set valid{ + "autosar", + "cert-c-2016", + "cert-c++-2016", + "cert-cpp-2016", + "cert-c", + "cert-c++", + "metrics", + "misra-c-2012", + "misra-c-2023", + "misra-c-2025", + "misra-c++-2008", + "misra-cpp-2008", + "misra-c++-2023", + "misra-cpp-2023", + "bughunting", + "safety", + "debug-progress"}; + // valid options --premium-..= + const std::set valid2{ + "cert-c-int-precision", + "license-file" + }; + + if (std::strcmp(argv[i], "--premium=safety-off") == 0) { + mSettings.safety = false; + continue; + } + if (std::strcmp(argv[i], "--premium=safety") == 0) + mSettings.safety = true; + if (!mSettings.premiumArgs.empty()) + mSettings.premiumArgs += " "; + const std::string p(argv[i] + 10); + const std::string p2(p.find('=') != std::string::npos ? p.substr(0, p.find('=')) : ""); + if (!valid.count(p) && !valid2.count(p2)) { + mLogger.printError("invalid --premium option '" + (p2.empty() ? p : p2) + "'."); + return Result::Fail; + } + mSettings.premiumArgs += "--" + p; + if (startsWith(p, "autosar") || startsWith(p, "cert") || startsWith(p, "misra")) { + // All checkers related to the coding standard should be enabled. The coding standards + // do not all undefined behavior or portability issues. + mSettings.addEnabled("warning"); + mSettings.addEnabled("portability"); + } + } - maxconfigs = true; - } - - // max ctu depth - else if (std::strncmp(argv[i], "--max-ctu-depth=", 16) == 0) - mSettings->maxCtuDepth = std::atoi(argv[i] + 16); - - // Write results in file - else if (std::strncmp(argv[i], "--output-file=", 14) == 0) - mSettings->outputFile = Path::simplifyPath(Path::fromNativeSeparators(argv[i] + 14)); - - // Specify platform - else if (std::strncmp(argv[i], "--platform=", 11) == 0) { - const std::string platform(11+argv[i]); - - if (platform == "win32A") - mSettings->platform(Settings::Win32A); - else if (platform == "win32W") - mSettings->platform(Settings::Win32W); - else if (platform == "win64") - mSettings->platform(Settings::Win64); - else if (platform == "unix32") - mSettings->platform(Settings::Unix32); - else if (platform == "unix64") - mSettings->platform(Settings::Unix64); - else if (platform == "native") - mSettings->platform(Settings::Native); - else if (platform == "unspecified") - mSettings->platform(Settings::Unspecified); - else if (!mSettings->loadPlatformFile(argv[0], platform)) { - std::string message("cppcheck: error: unrecognized platform: \""); - message += platform; - message += "\"."; - printMessage(message); - return false; - } + // --project + else if (std::strncmp(argv[i], "--project=", 10) == 0) { + if (projectType != ImportProject::Type::NONE) + { + mLogger.printError("multiple --project options are not supported."); + return Result::Fail; } - // Write results in results.plist - else if (std::strncmp(argv[i], "--plist-output=", 15) == 0) { - mSettings->plistOutput = Path::simplifyPath(Path::fromNativeSeparators(argv[i] + 15)); - if (mSettings->plistOutput.empty()) - mSettings->plistOutput = "./"; - else if (!endsWith(mSettings->plistOutput,'/')) - mSettings->plistOutput += '/'; - - const std::string plistOutput = Path::toNativeSeparators(mSettings->plistOutput); - if (!FileLister::isDirectory(plistOutput)) { - std::string message("cppcheck: error: plist folder does not exist: \""); - message += plistOutput; - message += "\"."; - printMessage(message); - return false; + mSettings.checkAllConfigurations = false; // Can be overridden with --max-configs or --force + std::string projectFile = argv[i]+10; + projectType = project.import(projectFile, &mSettings, &mSuppressions, isCppcheckPremium()); + if (projectType == ImportProject::Type::CPPCHECK_GUI) { + for (const std::string &lib : project.guiProject.libraries) + mSettings.libraries.emplace_back(lib); + + const auto& excludedPaths = project.guiProject.excludedPaths; + std::copy(excludedPaths.cbegin(), excludedPaths.cend(), std::back_inserter(mIgnoredPaths)); + + if (!project.guiProject.platform.empty()) + platform = project.guiProject.platform; + + // look for external files relative to project first + lookupPaths.insert(lookupPaths.cbegin(), projectFile); + + const auto& projectFileGui = project.guiProject.projectFile; + if (!projectFileGui.empty()) { + // read underlying project + projectFile = projectFileGui; + projectType = project.import(projectFileGui, &mSettings, &mSuppressions); + if (projectType == ImportProject::Type::CPPCHECK_GUI) { + mLogger.printError("nested Cppcheck GUI projects are not supported."); + return Result::Fail; + } } } + if (projectType == ImportProject::Type::VS_SLN || projectType == ImportProject::Type::VS_VCXPROJ) { + mSettings.libraries.emplace_back("windows"); + } + if (projectType == ImportProject::Type::MISSING) { + mLogger.printError("failed to open project '" + projectFile + "'. The file does not exist."); + return Result::Fail; + } + if (projectType == ImportProject::Type::UNKNOWN) { + mLogger.printError("failed to load project '" + projectFile + "'. The format is unknown."); + return Result::Fail; + } + if (projectType == ImportProject::Type::FAILURE) { + mLogger.printError("failed to load project '" + projectFile + "'. An error occurred."); + return Result::Fail; + } + } - // --project - else if (std::strncmp(argv[i], "--project=", 10) == 0) { - mSettings->checkAllConfigurations = false; // Can be overridden with --max-configs or --force - const std::string projectFile = argv[i]+10; - ImportProject::Type projType = mSettings->project.import(projectFile, mSettings); - mSettings->project.projectType = projType; - if (projType == ImportProject::Type::CPPCHECK_GUI) { - mPathNames = mSettings->project.guiProject.pathNames; - for (const std::string &lib : mSettings->project.guiProject.libraries) - mSettings->libraries.emplace_back(lib); - - for (const std::string &ignorePath : mSettings->project.guiProject.excludedPaths) - mIgnoredPaths.emplace_back(ignorePath); - - const std::string platform(mSettings->project.guiProject.platform); - - if (platform == "win32A") - mSettings->platform(Settings::Win32A); - else if (platform == "win32W") - mSettings->platform(Settings::Win32W); - else if (platform == "win64") - mSettings->platform(Settings::Win64); - else if (platform == "unix32") - mSettings->platform(Settings::Unix32); - else if (platform == "unix64") - mSettings->platform(Settings::Unix64); - else if (platform == "native") - mSettings->platform(Settings::Native); - else if (platform == "unspecified" || platform == "Unspecified" || platform == "") - ; - else if (!mSettings->loadPlatformFile(projectFile.c_str(), platform) && !mSettings->loadPlatformFile(argv[0], platform)) { - std::string message("cppcheck: error: unrecognized platform: \""); - message += platform; - message += "\"."; - printMessage(message); - return false; - } + // --project-configuration + else if (std::strncmp(argv[i], "--project-configuration=", 24) == 0) { + vsConfig = argv[i] + 24; + if (vsConfig.empty()) { + mLogger.printError("--project-configuration parameter is empty."); + return Result::Fail; + } + if (projectType != ImportProject::Type::VS_SLN && projectType != ImportProject::Type::VS_VCXPROJ) { + mLogger.printError("--project-configuration has no effect - no Visual Studio project provided."); + return Result::Fail; + } + } - if (!mSettings->project.guiProject.projectFile.empty()) - projType = mSettings->project.import(mSettings->project.guiProject.projectFile, mSettings); - } - if (projType == ImportProject::Type::VS_SLN || projType == ImportProject::Type::VS_VCXPROJ) { - if (mSettings->project.guiProject.analyzeAllVsConfigs == "false") - mSettings->project.selectOneVsConfig(mSettings->platformType); - if (!CppCheckExecutor::tryLoadLibrary(mSettings->library, argv[0], "windows.cfg")) { - // This shouldn't happen normally. - printMessage("cppcheck: Failed to load 'windows.cfg'. Your Cppcheck installation is broken. Please re-install."); - return false; + // Only print something when there are errors + else if (std::strcmp(argv[i], "-q") == 0 || std::strcmp(argv[i], "--quiet") == 0) + mSettings.quiet = true; + + // Output relative paths + else if (std::strcmp(argv[i], "-rp") == 0 || std::strcmp(argv[i], "--relative-paths") == 0) + mSettings.relativePaths = true; + else if (std::strncmp(argv[i], "-rp=", 4) == 0 || std::strncmp(argv[i], "--relative-paths=", 17) == 0) { + mSettings.relativePaths = true; + if (argv[i][argv[i][3]=='='?4:17] != 0) { + std::string paths = argv[i]+(argv[i][3]=='='?4:17); + for (;;) { + const std::string::size_type pos = paths.find(';'); + if (pos == std::string::npos) { + mSettings.basePaths.emplace_back(Path::fromNativeSeparators(std::move(paths))); + break; } + mSettings.basePaths.emplace_back(Path::fromNativeSeparators(paths.substr(0, pos))); + paths.erase(0, pos + 1); } - if (projType == ImportProject::Type::MISSING) { - printMessage("cppcheck: Failed to open project '" + projectFile + "'."); - return false; - } - if (projType == ImportProject::Type::UNKNOWN) { - printMessage("cppcheck: Failed to load project '" + projectFile + "'. The format is unknown."); - return false; - } + } else { + mLogger.printError("no paths specified for the '" + std::string(argv[i]) + "' option."); + return Result::Fail; } + } - // --project-configuration - else if (std::strncmp(argv[i], "--project-configuration=", 24) == 0) { - mVSConfig = argv[i] + 24; - if (!mVSConfig.empty() && (mSettings->project.projectType == ImportProject::Type::VS_SLN || mSettings->project.projectType == ImportProject::Type::VS_VCXPROJ)) - mSettings->project.ignoreOtherConfigs(mVSConfig); - } - - // Only print something when there are errors - else if (std::strcmp(argv[i], "-q") == 0 || std::strcmp(argv[i], "--quiet") == 0) - mSettings->quiet = true; - - // Output relative paths - else if (std::strcmp(argv[i], "-rp") == 0 || std::strcmp(argv[i], "--relative-paths") == 0) - mSettings->relativePaths = true; - else if (std::strncmp(argv[i], "-rp=", 4) == 0 || std::strncmp(argv[i], "--relative-paths=", 17) == 0) { - mSettings->relativePaths = true; - if (argv[i][argv[i][3]=='='?4:17] != 0) { - std::string paths = argv[i]+(argv[i][3]=='='?4:17); - for (;;) { - const std::string::size_type pos = paths.find(';'); - if (pos == std::string::npos) { - mSettings->basePaths.emplace_back(Path::fromNativeSeparators(paths)); - break; - } - mSettings->basePaths.emplace_back(Path::fromNativeSeparators(paths.substr(0, pos))); - paths.erase(0, pos + 1); - } - } else { - printMessage("cppcheck: No paths specified for the '" + std::string(argv[i]) + "' option."); - return false; - } + // Report progress + else if (std::strcmp(argv[i], "--report-progress") == 0) { + mSettings.reportProgress = 10; + } + + else if (std::strncmp(argv[i], "--report-progress=", 18) == 0) { + if (!parseNumberArg(argv[i], 18, mSettings.reportProgress, true)) + return Result::Fail; + } + + else if (std::strncmp(argv[i], "--report-type=", 14) == 0) { + const std::string typeStr = argv[i] + 14; + if (typeStr == "normal") { + mSettings.reportType = ReportType::normal; + } else if (typeStr == "autosar") { + mSettings.reportType = ReportType::autosar; + } else if (typeStr == "cert-c-2016") { + mSettings.reportType = ReportType::certC; + } else if (typeStr == "cert-cpp-2016") { + mSettings.reportType = ReportType::certCpp; + } else if (typeStr == "misra-c-2012") { + mSettings.reportType = ReportType::misraC2012; + } else if (typeStr == "misra-c-2023") { + mSettings.reportType = ReportType::misraC2023; + } else if (typeStr == "misra-c-2025") { + mSettings.reportType = ReportType::misraC2025; + } else if (typeStr == "misra-cpp-2008") { + mSettings.reportType = ReportType::misraCpp2008; + } else if (typeStr == "misra-cpp-2023") { + mSettings.reportType = ReportType::misraCpp2023; + } else { + mLogger.printError("Unknown report type \'" + typeStr + "\'"); + return Result::Fail; } + } + + // Rule given at command line + else if (std::strncmp(argv[i], "--rule=", 7) == 0) { +#ifdef HAVE_RULES + Settings::Rule rule; + rule.pattern = 7 + argv[i]; - // Report progress - else if (std::strcmp(argv[i], "--report-progress") == 0) { - mSettings->reportProgress = true; + if (rule.pattern.empty()) { + mLogger.printError("no rule pattern provided."); + return Result::Fail; } + mSettings.rules.emplace_back(std::move(rule)); +#else + mLogger.printError("Option --rule cannot be used as Cppcheck has not been built with rules support."); + return Result::Fail; +#endif + } + + // Rule file + else if (std::strncmp(argv[i], "--rule-file=", 12) == 0) { #ifdef HAVE_RULES - // Rule given at command line - else if (std::strncmp(argv[i], "--rule=", 7) == 0) { - Settings::Rule rule; - rule.pattern = 7 + argv[i]; - mSettings->rules.emplace_back(rule); - } - - // Rule file - else if (std::strncmp(argv[i], "--rule-file=", 12) == 0) { - tinyxml2::XMLDocument doc; - if (doc.LoadFile(12+argv[i]) == tinyxml2::XML_SUCCESS) { - tinyxml2::XMLElement *node = doc.FirstChildElement(); - for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) { - Settings::Rule rule; - - tinyxml2::XMLElement *tokenlist = node->FirstChildElement("tokenlist"); - if (tokenlist) - rule.tokenlist = tokenlist->GetText(); - - tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern"); - if (pattern) { - rule.pattern = pattern->GetText(); + // TODO: improved error handling - wrong root node, etc. + // TODO: consume unused "version" attribute + const std::string ruleFile = argv[i] + 12; + tinyxml2::XMLDocument doc; + const tinyxml2::XMLError err = doc.LoadFile(ruleFile.c_str()); + if (err == tinyxml2::XML_SUCCESS) { + const tinyxml2::XMLElement *node = doc.FirstChildElement(); + // check if it is a single or multi rule configuration + if (node && strcmp(node->Value(), "rules") == 0) + node = node->FirstChildElement("rule"); + for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) { + Settings::Rule rule; + + for (const tinyxml2::XMLElement *subnode = node->FirstChildElement(); subnode; subnode = subnode->NextSiblingElement()) { + const char * const subname = subnode->Name(); + const char * const subtext = subnode->GetText(); + if (std::strcmp(subname, "tokenlist") == 0) { + rule.tokenlist = empty_if_null(subtext); } + else if (std::strcmp(subname, "pattern") == 0) { + rule.pattern = empty_if_null(subtext); + } + else if (std::strcmp(subname, "message") == 0) { + for (const tinyxml2::XMLElement *msgnode = subnode->FirstChildElement(); msgnode; msgnode = msgnode->NextSiblingElement()) { + const char * const msgname = msgnode->Name(); + const char * const msgtext = msgnode->GetText(); + if (std::strcmp(msgname, "severity") == 0) { + rule.severity = severityFromString(empty_if_null(msgtext)); + } + else if (std::strcmp(msgname, "id") == 0) { + rule.id = empty_if_null(msgtext); + } + else if (std::strcmp(msgname, "summary") == 0) { + rule.summary = empty_if_null(msgtext); + } + else { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - unknown element '" + msgname + "' encountered in 'message'."); + return Result::Fail; + } + } + } + else { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - unknown element '" + subname + "' encountered in 'rule'."); + return Result::Fail; + } + } - tinyxml2::XMLElement *message = node->FirstChildElement("message"); - if (message) { - tinyxml2::XMLElement *severity = message->FirstChildElement("severity"); - if (severity) - rule.severity = Severity::fromString(severity->GetText()); + if (rule.pattern.empty()) { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - a rule is lacking a pattern."); + return Result::Fail; + } - tinyxml2::XMLElement *id = message->FirstChildElement("id"); - if (id) - rule.id = id->GetText(); + if (rule.id.empty()) { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - a rule is lacking an id."); + return Result::Fail; + } - tinyxml2::XMLElement *summary = message->FirstChildElement("summary"); - if (summary) - rule.summary = summary->GetText() ? summary->GetText() : ""; - } + if (rule.tokenlist.empty()) { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - a rule is lacking a tokenlist."); + return Result::Fail; + } + + if (rule.tokenlist != "normal" && rule.tokenlist != "define" && rule.tokenlist != "raw") { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - a rule is using the unsupported tokenlist '" + rule.tokenlist + "'."); + return Result::Fail; + } - if (!rule.pattern.empty()) - mSettings->rules.emplace_back(rule); + if (rule.severity == Severity::none) { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - a rule has an invalid severity."); + return Result::Fail; } - } else { - printMessage("cppcheck: error: unable to load rule-file: " + std::string(12+argv[i])); - return false; + + mSettings.rules.emplace_back(std::move(rule)); } + } else { + mLogger.printError("unable to load rule-file '" + ruleFile + "' (" + tinyxml2::XMLDocument::ErrorIDToName(err) + ")."); + return Result::Fail; } +#else + mLogger.printError("Option --rule-file cannot be used as Cppcheck has not been built with rules support."); + return Result::Fail; #endif + } - // show timing information.. - 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; - else if (showtimeMode == "summary") - mSettings->showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY; - else if (showtimeMode == "top5") - mSettings->showtime = SHOWTIME_MODES::SHOWTIME_TOP5; - else if (showtimeMode.empty()) - mSettings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; - else { - printMessage("cppcheck: error: unrecognized showtime mode: \"" + showtimeMode + "\". Supported modes: file, summary, top5."); - return false; - } + // Safety certified behavior + else if (std::strcmp(argv[i], "--safety") == 0) + mSettings.safety = true; + + // show timing information.. + 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; + else if (showtimeMode == "file-total") + mSettings.showtime = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL; + else if (showtimeMode == "summary") + mSettings.showtime = SHOWTIME_MODES::SHOWTIME_SUMMARY; + else if (showtimeMode == "top5_file") + mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_FILE; + else if (showtimeMode == "top5_summary") + mSettings.showtime = SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY; + else if (showtimeMode == "none") + mSettings.showtime = SHOWTIME_MODES::SHOWTIME_NONE; + else if (showtimeMode.empty()) { + mLogger.printError("no mode provided for --showtime"); + return Result::Fail; } - - // --std - else if (std::strcmp(argv[i], "--std=posix") == 0) { - printMessage("cppcheck: Option --std=posix is deprecated and will be removed in 2.05."); - } else if (std::strcmp(argv[i], "--std=c89") == 0) { - mSettings->standards.c = Standards::C89; - } else if (std::strcmp(argv[i], "--std=c99") == 0) { - mSettings->standards.c = Standards::C99; - } else if (std::strcmp(argv[i], "--std=c11") == 0) { - mSettings->standards.c = Standards::C11; - } else if (std::strcmp(argv[i], "--std=c++03") == 0) { - mSettings->standards.cpp = Standards::CPP03; - } else if (std::strcmp(argv[i], "--std=c++11") == 0) { - mSettings->standards.cpp = Standards::CPP11; - } else if (std::strcmp(argv[i], "--std=c++14") == 0) { - mSettings->standards.cpp = Standards::CPP14; - } else if (std::strcmp(argv[i], "--std=c++17") == 0) { - mSettings->standards.cpp = Standards::CPP17; - } else if (std::strcmp(argv[i], "--std=c++20") == 0) { - mSettings->standards.cpp = Standards::CPP20; - } - - else if (std::strncmp(argv[i], "--suppress=", 11) == 0) { - const std::string suppression = argv[i]+11; - const std::string errmsg(mSettings->nomsg.addSuppressionLine(suppression)); - if (!errmsg.empty()) { - printMessage(errmsg); - return false; - } + else { + mLogger.printError("unrecognized --showtime mode: '" + showtimeMode + "'. Supported modes: file, file-total, summary, top5_file, top5_summary."); + return Result::Fail; } + } - // Filter errors - else if (std::strncmp(argv[i], "--suppressions-list=", 20) == 0) { - std::string filename = argv[i]+20; - std::ifstream f(filename); - if (!f.is_open()) { - std::string message("cppcheck: Couldn't open the file: \""); - message += filename; - message += "\"."; - if (std::count(filename.begin(), filename.end(), ',') > 0 || - std::count(filename.begin(), filename.end(), '.') > 1) { - // If user tried to pass multiple files (we can only guess that) - // e.g. like this: --suppressions-list=a.txt,b.txt - // print more detailed error message to tell user how he can solve the problem - message += "\nIf you want to pass two files, you can do it e.g. like this:"; - message += "\n cppcheck --suppressions-list=a.txt --suppressions-list=b.txt file.cpp"; - } - - printMessage(message); - return false; - } - const std::string errmsg(mSettings->nomsg.parseFile(f)); - if (!errmsg.empty()) { - printMessage(errmsg); - return false; - } + // --std + else if (std::strncmp(argv[i], "--std=", 6) == 0) { + const std::string std = argv[i] + 6; + if (!mSettings.standards.setStd(std)) { + mLogger.printError("unknown --std value '" + std + "'"); + return Result::Fail; } + } - else if (std::strncmp(argv[i], "--suppress-xml=", 15) == 0) { - const char * filename = argv[i] + 15; - const std::string errmsg(mSettings->nomsg.parseXmlFile(filename)); - if (!errmsg.empty()) { - printMessage(errmsg); - return false; - } + else if (std::strncmp(argv[i], "--suppress=", 11) == 0) { + const std::string suppression = argv[i]+11; + const std::string errmsg(mSuppressions.nomsg.addSuppressionLine(suppression)); + if (!errmsg.empty()) { + mLogger.printError(errmsg); + return Result::Fail; } + } - // Output formatter - else if (std::strcmp(argv[i], "--template") == 0 || - std::strncmp(argv[i], "--template=", 11) == 0) { - // "--template format" - if (argv[i][10] == '=') - mSettings->templateFormat = argv[i] + 11; - else if ((i+1) < argc && argv[i+1][0] != '-') { - ++i; - mSettings->templateFormat = argv[i]; - } else { - printMessage("cppcheck: argument to '--template' is missing."); - return false; + // Filter errors + else if (std::strncmp(argv[i], "--suppressions-list=", 20) == 0) { + std::string filename = argv[i]+20; + std::ifstream f(filename); + if (!f.is_open()) { + std::string message("couldn't open the file: \""); + message += filename; + message += "\"."; + if (std::count(filename.cbegin(), filename.cend(), ',') > 0 || + std::count(filename.cbegin(), filename.cend(), '.') > 1) { + // If user tried to pass multiple files (we can only guess that) + // e.g. like this: --suppressions-list=a.txt,b.txt + // print more detailed error message to tell user how he can solve the problem + message += "\nIf you want to pass two files, you can do it e.g. like this:"; + message += "\n cppcheck --suppressions-list=a.txt --suppressions-list=b.txt file.cpp"; } - if (mSettings->templateFormat == "gcc") { - mSettings->templateFormat = "{file}:{line}:{column}: warning: {message} [{id}]\\n{code}"; - mSettings->templateLocation = "{file}:{line}:{column}: note: {info}\\n{code}"; - } else if (mSettings->templateFormat == "daca2") { - mSettings->daca = true; - mSettings->templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]"; - mSettings->templateLocation = "{file}:{line}:{column}: note: {info}"; - } else if (mSettings->templateFormat == "vs") - mSettings->templateFormat = "{file}({line}): {severity}: {message}"; - else if (mSettings->templateFormat == "edit") - mSettings->templateFormat = "{file} +{line}: {severity}: {message}"; - else if (mSettings->templateFormat == "cppcheck1") - mSettings->templateFormat = "{callstack}: ({severity}{inconclusive:, inconclusive}) {message}"; - else if (mSettings->templateFormat == "selfcheck") { - mSettings->templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}"; - mSettings->templateLocation = "{file}:{line}:{column}: note: {info}\\n{code}"; - mSettings->daca = true; - } + mLogger.printError(message); + return Result::Fail; } - - else if (std::strcmp(argv[i], "--template-location") == 0 || - std::strncmp(argv[i], "--template-location=", 20) == 0) { - // "--template-location format" - if (argv[i][19] == '=') - mSettings->templateLocation = argv[i] + 20; - else if ((i+1) < argc && argv[i+1][0] != '-') { - ++i; - mSettings->templateLocation = argv[i]; - } else { - printMessage("cppcheck: argument to '--template' is missing."); - return false; - } + const std::string errmsg(mSuppressions.nomsg.parseFile(f)); + if (!errmsg.empty()) { + mLogger.printError(errmsg); + return Result::Fail; } + } - else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0) - mSettings->verbose = true; + else if (std::strncmp(argv[i], "--suppress-xml=", 15) == 0) { + const char * filename = argv[i] + 15; + const std::string errmsg(mSuppressions.nomsg.parseXmlFile(filename)); + if (!errmsg.empty()) { + mLogger.printError(errmsg); + return Result::Fail; + } + } - else if (std::strcmp(argv[i], "--version") == 0) { - mShowVersion = true; - mExitAfterPrint = true; - return true; + // Output formatter + else if (std::strncmp(argv[i], "--template=", 11) == 0) { + mSettings.templateFormat = argv[i] + 11; + // TODO: bail out when no template is provided? + + if (mSettings.templateFormat == "gcc") { + mSettings.templateFormat = "{bold}{file}:{line}:{column}: {magenta}warning:{default} {message} [{id}]{reset}\\n{code}"; + mSettings.templateLocation = "{bold}{file}:{line}:{column}: {dim}note:{reset} {info}\\n{code}"; + } else if (mSettings.templateFormat == "daca2") { + mSettings.daca = true; + mSettings.templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]"; + mSettings.templateLocation = "{file}:{line}:{column}: note: {info}"; + } else if (mSettings.templateFormat == "vs") + mSettings.templateFormat = "{file}({line}): {severity}: {message}"; + else if (mSettings.templateFormat == "edit") + mSettings.templateFormat = "{file} +{line}: {severity}: {message}"; + else if (mSettings.templateFormat == "cppcheck1") + mSettings.templateFormat = "{callstack}: ({severity}{inconclusive:, inconclusive}) {message}"; + else if (mSettings.templateFormat == "selfcheck") { + mSettings.templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}"; + mSettings.templateLocation = "{file}:{line}:{column}: note: {info}\\n{code}"; + mSettings.daca = true; + } else if (mSettings.templateFormat == "simple") { + mSettings.templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]"; + mSettings.templateLocation = ""; } + // TODO: bail out when no placeholders are found? + } - // Write results in results.xml - else if (std::strcmp(argv[i], "--xml") == 0) - mSettings->xml = true; + else if (std::strncmp(argv[i], "--template-location=", 20) == 0) { + mSettings.templateLocation = argv[i] + 20; + // TODO: bail out when no template is provided? + // TODO: bail out when no placeholders are found? + } - // Define the XML file version (and enable XML output) - else if (std::strncmp(argv[i], "--xml-version=", 14) == 0) { - const std::string numberString(argv[i]+14); + else if (std::strncmp(argv[i], "--template-max-time=", 20) == 0) { + if (!parseNumberArg(argv[i], 20, mSettings.templateMaxTime)) + return Result::Fail; + } - std::istringstream iss(numberString); - if (!(iss >> mSettings->xml_version)) { - printMessage("cppcheck: argument to '--xml-version' is not a number."); - return false; - } + else if (std::strncmp(argv[i], "--typedef-max-time=", 19) == 0) { + if (!parseNumberArg(argv[i], 19, mSettings.typedefMaxTime)) + return Result::Fail; + } - if (mSettings->xml_version != 2) { - // We only have xml version 2 - printMessage("cppcheck: '--xml-version' can only be 2."); - return false; - } + else if (std::strncmp(argv[i], "--valueflow-max-iterations=", 27) == 0) { + if (!parseNumberArg(argv[i], 27, mSettings.vfOptions.maxIterations)) + return Result::Fail; + } - // Enable also XML if version is set - mSettings->xml = true; + else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0) + mSettings.verbose = true; + + // Write results in results.xml + else if (std::strcmp(argv[i], "--xml") == 0) { + if (outputFormatOptionProvided) { + outputFormatOptionMixingError(); + return Result::Fail; } + mSettings.outputFormat = Settings::OutputFormat::xml; + xmlOptionProvided = true; + } - else { - std::string message("cppcheck: error: unrecognized command line option: \""); - message += argv[i]; - message += "\"."; - printMessage(message); - return false; + // Define the XML file version (and enable XML output) + else if (std::strncmp(argv[i], "--xml-version=", 14) == 0) { + if (outputFormatOptionProvided) { + outputFormatOptionMixingError(); + return Result::Fail; + } + int tmp; + if (!parseNumberArg(argv[i], 14, tmp)) + return Result::Fail; + if (tmp != 2 && tmp != 3) { + // We only have xml version 2 and 3 + mLogger.printError("'--xml-version' can only be 2 or 3."); + return Result::Fail; } + + mSettings.xml_version = tmp; + // Enable also XML if version is set + mSettings.outputFormat = Settings::OutputFormat::xml; + xmlOptionProvided = true; } else { - mPathNames.emplace_back(Path::fromNativeSeparators(Path::removeQuotationMarks(argv[i]))); + std::string message("unrecognized command line option: \""); + message += argv[i]; + message += "\"."; + mLogger.printError(message); + return Result::Fail; } } + if (!loadCppcheckCfg()) + return Result::Fail; + + // TODO: bail out? + if (!executorAuto && mSettings.useSingleJob()) + mLogger.printMessage("'--executor' has no effect as only a single job will be used."); + // Default template format.. - if (mSettings->templateFormat.empty()) { - mSettings->templateFormat = "{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}"; - if (mSettings->templateLocation.empty()) - mSettings->templateLocation = "{file}:{line}:{column}: note: {info}\\n{code}"; + if (mSettings.templateFormat.empty()) { + mSettings.templateFormat = "{bold}{file}:{line}:{column}: {red}{inconclusive:{magenta}}{severity}:{inconclusive: inconclusive:}{default} {message} [{id}]{reset}\\n{code}"; + if (mSettings.templateLocation.empty()) + mSettings.templateLocation = "{bold}{file}:{line}:{column}: {dim}note:{reset} {info}\\n{code}"; + } + // replace static parts of the templates + substituteTemplateFormatStatic(mSettings.templateFormat); + substituteTemplateLocationStatic(mSettings.templateLocation); + + 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; + if (mSettings.verbose) { + mSettings.debugast = true; + mSettings.debugsymdb = true; + } } - mSettings->project.ignorePaths(mIgnoredPaths); + if (mSettings.jobs > 1 && mSettings.buildDir.empty()) { + // TODO: bail out instead? + if (mSettings.checks.isEnabled(Checks::unusedFunction)) + mLogger.printMessage("unusedFunction check requires --cppcheck-build-dir to be active with -j."); + // TODO: enable + //mLogger.printMessage("whole program analysis requires --cppcheck-build-dir to be active with -j."); + } - if (mSettings->force || maxconfigs) - mSettings->checkAllConfigurations = true; + if (!mPathNames.empty() && projectType != ImportProject::Type::NONE) { + mLogger.printError("--project cannot be used in conjunction with source files."); + return Result::Fail; + } - if (mSettings->force) - mSettings->maxConfigs = INT_MAX; + // TODO: conflicts with analyzeAllVsConfigs + if (!vsConfig.empty()) { + // TODO: bail out when this does nothing + project.ignoreOtherConfigs(vsConfig); + } - else if ((def || mSettings->preprocessOnly) && !maxconfigs) - mSettings->maxConfigs = 1U; + if (!platform.empty()) + { + std::string errstr; + if (!mSettings.platform.set(platform, errstr, lookupPaths, mSettings.debuglookup || mSettings.debuglookupPlatform)) { + mLogger.printError(errstr); + return Result::Fail; + } - if (mSettings->checks.isEnabled(Checks::unusedFunction) && mSettings->jobs > 1) { - printMessage("cppcheck: unusedFunction check can't be used with '-j' option. Disabling unusedFunction check."); + // TODO: remove + // these are loaded via external files and thus have Settings::PlatformFile set instead. + // override the type so they behave like the regular platforms. + if (platform == "unix32-unsigned") { + mSettings.platform.type = Platform::Type::Unix32; + mLogger.printMessage("The platform 'unix32-unsigned' has been deprecated and will be removed in Cppcheck 2.19. Please use '--platform=unix32 --funsigned-char' instead"); + } + else if (platform == "unix64-unsigned") { + mSettings.platform.type = Platform::Type::Unix64; + mLogger.printMessage("The platform 'unix64-unsigned' has been deprecated and will be removed in Cppcheck 2.19. Please use '--platform=unix64 --funsigned-char' instead"); + } } - if (argc <= 1) { - mShowHelp = true; - mExitAfterPrint = true; + if (defaultSign != '\0') + mSettings.platform.defaultSign = defaultSign; + + if (!mSettings.analyzeAllVsConfigs) { + if (projectType != ImportProject::Type::VS_SLN && 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; + } + } else { + // TODO: bail out when this does nothing + project.selectOneVsConfig(mSettings.platform.type); + } } - if (mShowHelp) { - printHelp(); - return true; + if (!mSettings.buildDir.empty() && !Path::isDirectory(mSettings.buildDir)) { + mLogger.printError("Directory '" + mSettings.buildDir + "' specified by --cppcheck-build-dir argument has to be existent."); + return Result::Fail; } // Print error only if we have "real" command and expect files - if (!mExitAfterPrint && mPathNames.empty() && mSettings->project.fileSettings.empty()) { - printMessage("cppcheck: No C or C++ source files found."); - return false; + if (mPathNames.empty() && project.guiProject.pathNames.empty() && project.fileSettings.empty()) { + // TODO: this message differs from the one reported in fillSettingsFromArgs() + mLogger.printError("no C or C++ source files found."); + return Result::Fail; + } + + for (auto& path : mIgnoredPaths) + { + path = Path::removeQuotationMarks(std::move(path)); + path = Path::fromNativeSeparators(std::move(path)); + } + + if (!project.guiProject.pathNames.empty()) + mPathNames = project.guiProject.pathNames; + + if (!project.fileSettings.empty()) { + project.ignorePaths(mIgnoredPaths, mSettings.debugignore); + if (project.fileSettings.empty()) { + mLogger.printError("no C or C++ source files found."); + mLogger.printMessage("all paths were ignored"); // TODO: log this differently? + return Result::Fail; + } + mFileSettings = project.fileSettings; + } + + if (mSettings.debugnormal && mSettings.outputFormat == Settings::OutputFormat::xml && (mPathNames.size() > 1 || mFileSettings.size() > 1)) + { + mLogger.printError("printing debug output in XML format does not support multiple input files."); + return Result::Fail; } // Use paths _pathnames if no base paths for relative path output are given - if (mSettings->basePaths.empty() && mSettings->relativePaths) - mSettings->basePaths = mPathNames; + if (mSettings.basePaths.empty() && mSettings.relativePaths) + mSettings.basePaths = mPathNames; + + return Result::Success; +} + +void CmdLineParser::printHelp() const +{ + const std::string manualUrl(isCppcheckPremium() ? + "https://cppcheck.sourceforge.io/manual.pdf" : + "https://files.cppchecksolutions.com/manual.pdf"); + + std::ostringstream oss; + oss << "Cppcheck - A tool for static C/C++ code analysis\n" + "\n" + "Syntax:\n" + " cppcheck [OPTIONS] [files or paths]\n" + "\n" + "If a directory is given instead of a filename, *.cpp, *.cxx, *.cc, *.c++, *.c, *.ipp,\n" + "*.ixx, *.tpp, and *.txx files are checked recursively from the given directory.\n\n" + "Options:\n" + " --addon=\n" + " Execute addon. i.e. --addon=misra. If options must be\n" + " provided a json configuration is needed.\n" + " --addon-python=\n" + " You can specify the python interpreter either in the\n" + " addon json files or through this command line option.\n" + " If not present, Cppcheck will try \"python3\" first and\n" + " then \"python\".\n" + " --cppcheck-build-dir=\n" + " Cppcheck work folder. Advantages:\n" + " * whole program analysis\n" + " * faster analysis; Cppcheck will reuse the results if\n" + " the hash for a file is unchanged.\n" + " * some useful debug information, i.e. commands used to\n" + " execute clang/clang-tidy/addons.\n" + " --check-config Check cppcheck configuration. The normal code\n" + " analysis is disabled by this flag.\n" + " --check-level=\n" + " Configure how much valueflow analysis you want:\n" + " * reduced: Reduce valueflow to finish checking quickly.\n" + " * normal: Cppcheck uses some compromises in the analysis so\n" + " the checking will finish in reasonable time.\n" + " * exhaustive: deeper analysis that you choose when you can\n" + " wait.\n" + " The default choice is 'normal'.\n" + " --check-library Show information messages when library files have\n" + " incomplete info.\n" + " --checkers-report=\n" + " Write a report of all the active checkers to the given file.\n" + " --clang= Experimental: Use Clang parser instead of the builtin Cppcheck\n" + " parser. Takes the executable as optional parameter and\n" + " defaults to `clang`. Cppcheck will run the given Clang\n" + " executable, import the Clang AST and convert it into\n" + " Cppcheck data. After that the normal Cppcheck analysis is\n" + " used. You must have the executable in PATH if no path is\n" + " given.\n" + " --config-exclude=\n" + " Path (prefix) to be excluded from configuration\n" + " checking. Preprocessor configurations defined in\n" + " headers (but not sources) matching the prefix will not\n" + " be considered for evaluation.\n" + " --config-excludes-file=\n" + " A file that contains a list of config-excludes\n" + " --disable= Disable individual checks.\n" + " Please refer to the documentation of --enable=\n" + " for further details.\n" + " --dump Dump xml data for each translation unit. The dump\n" + " files have the extension .dump and contain ast,\n" + " tokenlist, symboldatabase, valueflow.\n" + " -D Define preprocessor symbol. Unless --max-configs or\n" + " --force is used, Cppcheck will only check the given\n" + " configuration when -D is used.\n" + " Example: '-DDEBUG=1 -D__cplusplus'.\n" + " -E Print preprocessor output on stdout and don't do any\n" + " further processing.\n" + " --enable= Enable additional checks. The available ids are:\n" + " * all\n" + " Enable all checks. It is recommended to only\n" + " use --enable=all when the whole program is\n" + " scanned, because this enables unusedFunction.\n" + " * warning\n" + " Enable warning messages\n" + " * style\n" + " Enable all coding style checks. All messages\n" + " with the severities 'style', 'warning',\n" + " 'performance' and 'portability' are enabled.\n" + " * performance\n" + " Enable performance messages\n" + " * portability\n" + " Enable portability messages\n" + " * information\n" + " Enable information messages\n" + " * unusedFunction\n" + " Check for unused functions. It is recommended\n" + " to only enable this when the whole program is\n" + " scanned.\n" + " * missingInclude\n" + " Warn if there are missing includes.\n" + " Several ids can be given if you separate them with\n" + " commas. See also --std\n" + " --error-exitcode= If errors are found, integer [n] is returned instead of\n" + " the default '0'. '" << EXIT_FAILURE << "' is returned\n" + " if arguments are not valid or if no input files are\n" + " 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-suppressions=\n" + " Used when certain messages should be displayed but\n" + " should not cause a non-zero exitcode.\n" + " --file-filter= Analyze only those files matching the given filter str\n" + " Can be used multiple times\n" + " Example: --file-filter=*bar.cpp analyzes only files\n" + " that end with bar.cpp.\n" + " --file-list= Specify the files to check in a text file. Add one\n" + " filename per line. When file is '-,' the file list will\n" + " be read from standard input.\n" + " -f, --force Force checking of all configurations in files. If used\n" + " together with '--max-configs=', the last option is the\n" + " one that is effective.\n" + " --fsigned-char Treat char type as signed.\n" + " --funsigned-char Treat char type as unsigned.\n" + " -h, --help Print this help.\n" + " -I Give path to search for include files. Give several -I\n" + " parameters to give several paths. First given path is\n" + " searched for contained header files first. If paths are\n" + " relative to source files, this is not needed.\n" + " --includes-file=\n" + " Specify directory paths to search for included header\n" + " files in a text file. Add one include path per line.\n" + " First given path is searched for contained header\n" + " files first. If paths are relative to source files,\n" + " 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" + " --inconclusive Allow that Cppcheck reports even though the analysis is\n" + " inconclusive.\n" + " There are false positives with this option. Each result\n" + " must be carefully investigated before you know if it is\n" + " good or bad.\n" + " --inline-suppr Enable inline suppressions. Use them by placing one or\n" + " more comments, like: '// cppcheck-suppress warningId'\n" + " on the lines before the warning to suppress.\n" + " -j Start threads to do the checking simultaneously.\n" + " -l Specifies that no new threads should be started if\n" + " there are other threads running and the load average is\n" + " at least .\n" + " --language=, -x \n" + " Forces cppcheck to check all files as the given\n" + " language. Valid values are: c, c++\n" + " --library= Load file that contains information about types\n" + " and functions. With such information Cppcheck\n" + " understands your code better and therefore you\n" + " get better results. The std.cfg file that is\n" + " distributed with Cppcheck is loaded automatically.\n" + " For more information about library files, read the\n" + " manual.\n" + " --max-configs=\n" + " Maximum number of configurations to check in a file\n" + " before skipping it. Default is '12'. If used together\n" + " with '--force', the last option is the one that is\n" + " effective.\n" + " --max-ctu-depth=N Max depth in whole program analysis. The default value\n" + " is 2. A larger value will mean more errors can be found\n" + " but also means the analysis will be slower.\n" + " --output-file= Write results to file, rather than standard error.\n" + " --output-format=\n" + " Specify the output format. The available formats are:\n" + " * text\n" + " * sarif\n" + " * xml (deprecated)\n" + " * xmlv2\n" + " * xmlv3\n" + " --platform=, --platform=\n" + " Specifies platform specific types and sizes. The\n" + " available builtin platforms are:\n" + " * unix32\n" + " 32 bit unix variant\n" + " * unix64\n" + " 64 bit unix variant\n" + " * win32A\n" + " 32 bit Windows ASCII character encoding\n" + " * win32W\n" + " 32 bit Windows UNICODE character encoding\n" + " * win64\n" + " 64 bit Windows\n" + " * avr8\n" + " 8 bit AVR microcontrollers\n" + " * elbrus-e1cp\n" + " Elbrus e1c+ architecture\n" + " * pic8\n" + " 8 bit PIC microcontrollers\n" + " Baseline and mid-range architectures\n" + " * pic8-enhanced\n" + " 8 bit PIC microcontrollers\n" + " Enhanced mid-range and high end (PIC18) architectures\n" + " * pic16\n" + " 16 bit PIC microcontrollers\n" + " * mips32\n" + " 32 bit MIPS microcontrollers\n" + " * native\n" + " Type sizes of host system are assumed, but no\n" + " further assumptions.\n" + " * unspecified\n" + " Unknown type sizes\n" + " --plist-output=\n" + " Generate Clang-plist output files in folder.\n"; + + if (isCppcheckPremium()) { + oss << + " --premium=