Compare commits
69 Commits
Author | SHA1 | Date |
---|---|---|
chrchr-github | 30397f0d53 | |
chrchr-github | 9fceba4fbc | |
chrchr-github | c21166565f | |
Daniel Marjamäki | 8903f0e4b1 | |
Oliver Stöneberg | 08d754d536 | |
Oliver Stöneberg | 30ca8e11b5 | |
Oliver Stöneberg | bbd2b2aa83 | |
Oliver Stöneberg | 81700b481d | |
Maarten van der Schrieck | 328f98b35a | |
Oliver Stöneberg | e3b3048d00 | |
orbitcowboy | 71212c7d66 | |
orbitcowboy | 32cabecca9 | |
chrchr-github | fde7ea6d17 | |
Oliver Stöneberg | 44ed53319e | |
Oliver Stöneberg | bd9700b848 | |
Oliver Stöneberg | 028596f100 | |
orbitcowboy | 950b285608 | |
Oliver Stöneberg | 42c3aebda9 | |
chrchr-github | c7cd091a93 | |
chrchr-github | f9134a69d2 | |
Oliver Stöneberg | 02f474bc19 | |
Oliver Stöneberg | 957096417e | |
orbitcowboy | 3241cf5966 | |
Philip Chimento | 8ca93c983b | |
Oliver Stöneberg | 6ef3224bd4 | |
Oliver Stöneberg | 93a53af168 | |
Daniel Marjamäki | fc1d4d6f7d | |
chrchr-github | 1eee68f039 | |
chrchr-github | efa8a08407 | |
Oliver Stöneberg | 87540e6ca6 | |
Oliver Stöneberg | b2e0b3b425 | |
Oliver Stöneberg | 615e4c01c4 | |
chrchr-github | f24c7fdae9 | |
chrchr-github | 73187e6e12 | |
Daniel Marjamäki | 9aae9aeb25 | |
Maarten van der Schrieck | 21a9de7d42 | |
chrchr-github | 481d4578ab | |
thingsconnected | 8261ded475 | |
chrchr-github | 5e59652fd3 | |
Oliver Stöneberg | dd869cf808 | |
chrchr-github | 8d64d12e5d | |
chrchr-github | 14627ca6d2 | |
thingsconnected | 98b9244bcb | |
chrchr-github | d9d23d979d | |
Daniel Marjamäki | 0c8ee7895d | |
thingsconnected | 24133d4a59 | |
Daniel Marjamäki | b7c5505550 | |
Swasti Shrivastava | 681b15f5c9 | |
thingsconnected | 4c7aae3a16 | |
Paul Fultz II | 4d9e69e42c | |
Daniel Marjamäki | b6e157408c | |
Christoph Grüninger | 4a9b921ccf | |
thingsconnected | 403e7f1f7d | |
chrchr-github | a7baf88d4f | |
olabetskyi | e553940e23 | |
Tomo Dote | c02d0786ad | |
thingsconnected | d506e7e937 | |
chrchr-github | 9118d330d3 | |
orbitcowboy | 06e6c3eba4 | |
chrchr-github | 17ee4093fa | |
Paul Fultz II | 7f0234e7d5 | |
Paul Fultz II | 77157a678a | |
Daniel Marjamäki | 2af3b7bf44 | |
Daniel Marjamäki | c9401a576d | |
Daniel Marjamäki | 0fec74d867 | |
Daniel Marjamäki | 79fb57e756 | |
Daniel Marjamäki | 5a222b80a1 | |
Daniel Marjamäki | 36b8e54b71 | |
Daniel Marjamäki | d81c69682c |
|
@ -19,7 +19,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
image: ["centos:7", "ubuntu:14.04", "ubuntu:16.04", "ubuntu:18.04", "ubuntu:23.10"]
|
image: ["ubuntu:16.04", "ubuntu:18.04", "ubuntu:23.10"]
|
||||||
include:
|
include:
|
||||||
- build_gui: false
|
- build_gui: false
|
||||||
- image: "ubuntu:23.10"
|
- image: "ubuntu:23.10"
|
||||||
|
@ -39,13 +39,6 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install missing software on CentOS 7
|
|
||||||
if: matrix.image == 'centos:7'
|
|
||||||
run: |
|
|
||||||
yum install -y cmake gcc-c++ make pcre-devel
|
|
||||||
yum --enablerepo=extras install -y epel-release
|
|
||||||
yum install -y ccache
|
|
||||||
|
|
||||||
- name: Install missing software on ubuntu
|
- name: Install missing software on ubuntu
|
||||||
if: contains(matrix.image, 'ubuntu')
|
if: contains(matrix.image, 'ubuntu')
|
||||||
run: |
|
run: |
|
||||||
|
@ -62,22 +55,12 @@ jobs:
|
||||||
# - it doesn't support centos
|
# - it doesn't support centos
|
||||||
- name: ccache
|
- name: ccache
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
uses: hendrikmuhs/ccache-action@v1.2
|
||||||
if: matrix.image != 'ubuntu:14.04' # no support for --set-config
|
|
||||||
with:
|
with:
|
||||||
key: ${{ github.workflow }}-${{ matrix.image }}
|
key: ${{ github.workflow }}-${{ matrix.image }}
|
||||||
|
|
||||||
# tests require CMake 3.9 - no ccache available
|
|
||||||
- name: CMake build (no tests / no ccache)
|
|
||||||
if: matrix.image == 'ubuntu:14.04'
|
|
||||||
run: |
|
|
||||||
mkdir cmake.output
|
|
||||||
cd cmake.output
|
|
||||||
cmake -G "Unix Makefiles" -DHAVE_RULES=On ..
|
|
||||||
cmake --build . -- -j$(nproc)
|
|
||||||
|
|
||||||
# tests require CMake 3.9 - ccache available
|
# tests require CMake 3.9 - ccache available
|
||||||
- name: CMake build (no tests)
|
- name: CMake build (no tests)
|
||||||
if: matrix.image == 'centos:7' || matrix.image == 'ubuntu:16.04'
|
if: matrix.image == 'ubuntu:16.04'
|
||||||
run: |
|
run: |
|
||||||
mkdir cmake.output
|
mkdir cmake.output
|
||||||
cd cmake.output
|
cd cmake.output
|
||||||
|
@ -85,7 +68,7 @@ jobs:
|
||||||
cmake --build . -- -j$(nproc)
|
cmake --build . -- -j$(nproc)
|
||||||
|
|
||||||
- name: CMake build
|
- name: CMake build
|
||||||
if: ${{ !matrix.build_gui && matrix.image != 'centos:7' && matrix.image != 'ubuntu:14.04' && matrix.image != 'ubuntu:16.04' }}
|
if: ${{ !matrix.build_gui && matrix.image != 'ubuntu:16.04' }}
|
||||||
run: |
|
run: |
|
||||||
mkdir cmake.output
|
mkdir cmake.output
|
||||||
cd cmake.output
|
cd cmake.output
|
||||||
|
@ -99,7 +82,7 @@ jobs:
|
||||||
cmake --build cmake.output -- -j$(nproc)
|
cmake --build cmake.output -- -j$(nproc)
|
||||||
|
|
||||||
- name: Run CMake test
|
- name: Run CMake test
|
||||||
if: matrix.image != 'centos:7' && matrix.image != 'ubuntu:14.04' && matrix.image != 'ubuntu:16.04'
|
if: matrix.image != 'ubuntu:16.04'
|
||||||
run: |
|
run: |
|
||||||
cmake --build cmake.output --target check -- -j$(nproc)
|
cmake --build cmake.output --target check -- -j$(nproc)
|
||||||
|
|
||||||
|
@ -107,7 +90,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
image: ["centos:7", "ubuntu:14.04", "ubuntu:16.04", "ubuntu:18.04", "ubuntu:23.10"]
|
image: ["ubuntu:16.04", "ubuntu:18.04", "ubuntu:23.10"]
|
||||||
fail-fast: false # Prefer quick result
|
fail-fast: false # Prefer quick result
|
||||||
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
@ -118,13 +101,6 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install missing software on CentOS 7
|
|
||||||
if: matrix.image == 'centos:7'
|
|
||||||
run: |
|
|
||||||
yum install -y gcc-c++ make which python3 pcre-devel
|
|
||||||
yum --enablerepo=extras install -y epel-release
|
|
||||||
yum install -y ccache
|
|
||||||
|
|
||||||
- name: Install missing software on ubuntu
|
- name: Install missing software on ubuntu
|
||||||
if: contains(matrix.image, 'ubuntu')
|
if: contains(matrix.image, 'ubuntu')
|
||||||
run: |
|
run: |
|
||||||
|
@ -136,7 +112,6 @@ jobs:
|
||||||
# - it doesn't support centos
|
# - it doesn't support centos
|
||||||
- name: ccache
|
- name: ccache
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
uses: hendrikmuhs/ccache-action@v1.2
|
||||||
if: matrix.image != 'ubuntu:14.04' # no support for --set-config
|
|
||||||
with:
|
with:
|
||||||
key: ${{ github.workflow }}-${{ matrix.image }}
|
key: ${{ github.workflow }}-${{ matrix.image }}
|
||||||
|
|
||||||
|
|
|
@ -446,8 +446,6 @@ jobs:
|
||||||
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump
|
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump
|
||||||
../../cppcheck --dump naming_test.cpp
|
../../cppcheck --dump naming_test.cpp
|
||||||
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump
|
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump
|
||||||
../../cppcheck --dump namingng_test.c
|
|
||||||
python3 ../namingng.py --configfile ../naming.json --verify namingng_test.c.dump
|
|
||||||
|
|
||||||
- name: Build democlient
|
- name: Build democlient
|
||||||
if: matrix.os == 'ubuntu-22.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
|
|
@ -202,6 +202,4 @@ jobs:
|
||||||
rem python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump || exit /b !errorlevel!
|
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!
|
..\..\cppcheck --dump naming_test.cpp || exit /b !errorlevel!
|
||||||
python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump || exit /b !errorlevel!
|
python3 ..\naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump || exit /b !errorlevel!
|
||||||
..\..\cppcheck --dump namingng_test.c || exit /b !errorlevel!
|
|
||||||
python3 ..\namingng.py --configfile ..\naming.json --verify namingng_test.c.dump || exit /b !errorlevel!
|
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,23 @@ jobs:
|
||||||
runs-on: ubuntu-22.04 # run on the latest image only
|
runs-on: ubuntu-22.04 # run on the latest image only
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PREMIUM_VERSION: devdrop-20231105
|
PREMIUM_VERSION: 23.12.0
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Download cppcheckpremium
|
- name: Download cppcheckpremium
|
||||||
run: |
|
run: |
|
||||||
wget https://files.cppchecksolutions.com/cppcheckpremium-${{ env.PREMIUM_VERSION }}-amd64.tar.gz
|
wget https://files.cppchecksolutions.com/${{ env.PREMIUM_VERSION }}/ubuntu-22.04/cppcheckpremium-${{ env.PREMIUM_VERSION }}-amd64.tar.gz
|
||||||
|
#wget https://files.cppchecksolutions.com/cppcheckpremium-${{ env.PREMIUM_VERSION }}-amd64.tar.gz
|
||||||
tar xzf cppcheckpremium-${{ env.PREMIUM_VERSION }}-amd64.tar.gz
|
tar xzf cppcheckpremium-${{ env.PREMIUM_VERSION }}-amd64.tar.gz
|
||||||
|
|
||||||
- name: Generate a license file
|
- name: Generate a license file
|
||||||
run: |
|
run: |
|
||||||
echo cppcheck > cppcheck.lic
|
echo cppcheck > cppcheck.lic
|
||||||
echo 231231 >> cppcheck.lic
|
echo 241231 >> cppcheck.lic
|
||||||
echo 80000 >> cppcheck.lic
|
echo 80000 >> cppcheck.lic
|
||||||
echo 57e08c39523ab54d >> cppcheck.lic
|
echo 53b72a908d7aeeee >> cppcheck.lic
|
||||||
echo path:lib >> cppcheck.lic
|
echo path:lib >> cppcheck.lic
|
||||||
|
|
||||||
- name: Check
|
- name: Check
|
||||||
|
|
|
@ -63,7 +63,7 @@ jobs:
|
||||||
# TODO: switch to Qt 6 after we enabled the Qt mappings again
|
# TODO: switch to Qt 6 after we enabled the Qt mappings again
|
||||||
- name: Prepare CMake
|
- name: Prepare CMake
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCPPCHK_GLIBCXX_DEBUG=Off -DUSE_MATCHCOMPILER=Off
|
cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=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
|
||||||
|
|
||||||
- name: Prepare CMake dependencies
|
- name: Prepare CMake dependencies
|
||||||
run: |
|
run: |
|
||||||
|
@ -140,7 +140,7 @@ jobs:
|
||||||
|
|
||||||
- name: Prepare CMake
|
- name: Prepare CMake
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCPPCHK_GLIBCXX_DEBUG=Off -DUSE_MATCHCOMPILER=Off
|
cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=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
|
||||||
env:
|
env:
|
||||||
CC: clang-17
|
CC: clang-17
|
||||||
CXX: clang++-17
|
CXX: clang++-17
|
||||||
|
|
1
AUTHORS
1
AUTHORS
|
@ -221,6 +221,7 @@ Lukas Grützmacher
|
||||||
Lukasz Czajczyk
|
Lukasz Czajczyk
|
||||||
Łukasz Jankowski
|
Łukasz Jankowski
|
||||||
Luxon Jean-Pierre
|
Luxon Jean-Pierre
|
||||||
|
Maarten van der Schrieck
|
||||||
Maksim Derbasov
|
Maksim Derbasov
|
||||||
Malcolm Parsons
|
Malcolm Parsons
|
||||||
Marc-Antoine Perennou
|
Marc-Antoine Perennou
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
project(Cppcheck)
|
if (MSVC)
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
endif()
|
||||||
|
cmake_policy(SET CMP0048 NEW) # allow VERSION in project()
|
||||||
|
project(Cppcheck VERSION 2.13.99 LANGUAGES CXX)
|
||||||
|
|
||||||
include(cmake/cxx11.cmake)
|
include(cmake/cxx11.cmake)
|
||||||
use_cxx11()
|
use_cxx11()
|
||||||
|
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
include(cmake/ccache.cmake)
|
|
||||||
include(cmake/compilerCheck.cmake)
|
include(cmake/compilerCheck.cmake)
|
||||||
include(cmake/versions.cmake)
|
include(cmake/versions.cmake)
|
||||||
include(cmake/options.cmake)
|
include(cmake/options.cmake)
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -626,7 +626,7 @@ $(libcppdir)/settings.o: lib/settings.cpp externals/picojson/picojson.h lib/addo
|
||||||
$(libcppdir)/summaries.o: lib/summaries.cpp lib/addoninfo.h lib/analyzerinfo.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/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
|
$(libcppdir)/summaries.o: lib/summaries.cpp lib/addoninfo.h lib/analyzerinfo.h lib/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/suppressions.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
|
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/summaries.cpp
|
||||||
|
|
||||||
$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/path.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h
|
$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/path.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
|
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/suppressions.cpp
|
||||||
|
|
||||||
$(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/addoninfo.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/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
|
$(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/addoninfo.h lib/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/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
|
||||||
|
|
|
@ -33,8 +33,10 @@ Addons are scripts that analyses Cppcheck dump files to check compatibility with
|
||||||
Helper class for reading Cppcheck dump files within an addon.
|
Helper class for reading Cppcheck dump files within an addon.
|
||||||
- misra_9.py
|
- misra_9.py
|
||||||
Implementation of the MISRA 9.x rules used by `misra` addon.
|
Implementation of the MISRA 9.x rules used by `misra` addon.
|
||||||
- naming.json
|
- namingng.config.json
|
||||||
Example configuration for `namingng` addon.
|
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
|
- ROS_naming.json
|
||||||
Example configuration for the `namingng` addon enforcing the [ROS naming convention for C++ ](http://wiki.ros.org/CppStyleGuide#Files).
|
Example configuration for the `namingng` addon enforcing the [ROS naming convention for C++ ](http://wiki.ros.org/CppStyleGuide#Files).
|
||||||
- runaddon.py
|
- runaddon.py
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"RE_FILE": {".*[A-Z]": [true, "under_scored"]},
|
"RE_FILE": [".*[A-Z]"],
|
||||||
"RE_NAMESPACE": {".*[A-Z]": [true, "under_scored"],
|
"RE_NAMESPACE": {".*[A-Z]": [true, "under_scored"],
|
||||||
".*\\_$": [true, "under_scored"]},
|
".*\\_$": [true, "under_scored"]},
|
||||||
"RE_FUNCTIONNAME": {".*\\_": [true, "camelCase"],
|
"RE_FUNCTIONNAME": {".*\\_": [true, "camelCase"],
|
||||||
|
|
|
@ -1619,11 +1619,11 @@ def is_suppressed(location, message, errorId):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def reportError(location, severity, message, addon, errorId, extra=''):
|
def reportError(location, severity, message, addon, errorId, extra='', columnOverride=None):
|
||||||
if '--cli' in sys.argv:
|
if '--cli' in sys.argv:
|
||||||
msg = { 'file': location.file,
|
msg = { 'file': location.file,
|
||||||
'linenr': location.linenr,
|
'linenr': location.linenr,
|
||||||
'column': location.column,
|
'column': location.column if columnOverride is None else columnOverride,
|
||||||
'severity': severity,
|
'severity': severity,
|
||||||
'message': message,
|
'message': message,
|
||||||
'addon': addon,
|
'addon': addon,
|
||||||
|
|
|
@ -311,8 +311,7 @@ class InitializerParser:
|
||||||
if self.ed and self.ed.isValue:
|
if self.ed and self.ed.isValue:
|
||||||
if not isDesignated and len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root:
|
if not isDesignated and len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root:
|
||||||
self.rootStack[-1][0].markStuctureViolation(self.token)
|
self.rootStack[-1][0].markStuctureViolation(self.token)
|
||||||
|
if isFirstElement and self.token.isInt and self.token.getKnownIntValue() == 0 and self.token.next.str == '}':
|
||||||
if isFirstElement and self.token.str == '0' and self.token.next.str == '}':
|
|
||||||
# Zero initializer causes recursive initialization
|
# Zero initializer causes recursive initialization
|
||||||
self.root.initializeChildren()
|
self.root.initializeChildren()
|
||||||
elif self.token.isString and self.ed.valueType and self.ed.valueType.pointer > 0:
|
elif self.token.isString and self.ed.valueType and self.ed.valueType.pointer > 0:
|
||||||
|
|
|
@ -2,6 +2,15 @@
|
||||||
"RE_VARNAME": ["[a-z]*[a-zA-Z0-9_]*\\Z"],
|
"RE_VARNAME": ["[a-z]*[a-zA-Z0-9_]*\\Z"],
|
||||||
"RE_PRIVATE_MEMBER_VARIABLE": null,
|
"RE_PRIVATE_MEMBER_VARIABLE": null,
|
||||||
"RE_FUNCTIONNAME": ["[a-z0-9A-Z]*\\Z"],
|
"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",
|
"var_prefixes": {"uint32_t": "ui32",
|
||||||
"int*": "intp"},
|
"int*": "intp"},
|
||||||
"function_prefixes": {"uint16_t": "ui16",
|
"function_prefixes": {"uint16_t": "ui16",
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"script":"namingng.py",
|
||||||
|
"args":[
|
||||||
|
"--configfile=namingng.config.json"
|
||||||
|
]
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
# cppcheck addon for naming conventions
|
# cppcheck addon for naming conventions
|
||||||
# An enhanced version. Configuration is taken from a json file
|
# An enhanced version. Configuration is taken from a json file
|
||||||
# It supports to check for type-based prefixes in function or variable names.
|
# 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):
|
# Example usage (variable name must start with lowercase, function name must start with uppercase):
|
||||||
# $ cppcheck --dump path-to-src/
|
# $ cppcheck --dump path-to-src/
|
||||||
|
@ -11,9 +12,18 @@
|
||||||
# JSON format:
|
# 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_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"},
|
# "var_prefixes": {"uint32_t": "ui32"},
|
||||||
# "function_prefixes": {"uint16_t": "ui16",
|
# "function_prefixes": {"uint16_t": "ui16",
|
||||||
# "uint32_t": "ui32"}
|
# "uint32_t": "ui32"}
|
||||||
|
@ -24,230 +34,386 @@
|
||||||
|
|
||||||
import cppcheckdata
|
import cppcheckdata
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
# Auxiliary class
|
# Auxiliary class
|
||||||
class DataStruct:
|
class DataStruct:
|
||||||
def __init__(self, file, linenr, string):
|
def __init__(self, file, linenr, string, column=0):
|
||||||
self.file = file
|
self.file = file
|
||||||
self.linenr = linenr
|
self.linenr = linenr
|
||||||
self.str = string
|
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 reportError(filename, linenr, severity, msg):
|
def configError(error,fatal=True):
|
||||||
message = "[{filename}:{linenr}] ( {severity} ) naming.py: {msg}\n".format(
|
print('config error: %s'%error)
|
||||||
filename=filename,
|
if fatal:
|
||||||
linenr=linenr,
|
sys.exit(1)
|
||||||
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):
|
def loadConfig(configfile):
|
||||||
with open(configfile) as fh:
|
if not os.path.exists(configfile):
|
||||||
data = json.load(fh)
|
configError("cannot find config file '%s'"%configfile)
|
||||||
return data
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if have_error:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def checkTrueRegex(data, expr, msg, errors):
|
def evalExpr(conf, exp, mockToken, msgType):
|
||||||
res = re.match(expr, data.str)
|
report_as_error = False
|
||||||
if res:
|
msg = msgType + ' ' + mockToken.str + ' violates naming convention'
|
||||||
errors.append(reportError(data.file, data.linenr, 'style', msg))
|
|
||||||
|
|
||||||
|
|
||||||
def checkFalseRegex(data, expr, msg, errors):
|
|
||||||
res = re.match(expr, data.str)
|
|
||||||
if not res:
|
|
||||||
errors.append(reportError(data.file, data.linenr, 'style', msg))
|
|
||||||
|
|
||||||
|
|
||||||
def evalExpr(conf, exp, mockToken, msgType, errors):
|
|
||||||
if isinstance(conf, dict):
|
if isinstance(conf, dict):
|
||||||
if conf[exp][0]:
|
report_as_error = conf[exp][0]
|
||||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
|
msg += ': ' + conf[exp][1]
|
||||||
checkTrueRegex(mockToken, exp, msg, errors)
|
|
||||||
elif ~conf[exp][0]:
|
res = re.match(exp,mockToken.str)
|
||||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
|
if bool(res) == report_as_error:
|
||||||
checkFalseRegex(mockToken, exp, msg, errors)
|
reportNamingError(mockToken,msg)
|
||||||
else:
|
|
||||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][0]
|
def check_include_guard_name(conf,directive):
|
||||||
checkFalseRegex(mockToken, exp, msg, errors)
|
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:
|
else:
|
||||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention'
|
print("invalid config value for 'case': '%s'"%use_case,file=sys.stderr)
|
||||||
checkFalseRegex(mockToken, exp, msg, errors)
|
sys.exit(1)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
def process(dumpfiles, configfile, debugprint=False):
|
return guard_name,guard_column
|
||||||
|
|
||||||
errors = []
|
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,column=0):
|
||||||
|
reportNamingError(directive,msg,errorId,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
|
||||||
|
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(include_guard_header_re,directive.file):
|
||||||
|
phase = -1
|
||||||
|
continue
|
||||||
|
|
||||||
|
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 == 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):
|
||||||
conf = loadConfig(configfile)
|
conf = loadConfig(configfile)
|
||||||
|
|
||||||
|
if conf.include_guard:
|
||||||
|
global include_guard_header_re
|
||||||
|
include_guard_header_re = conf.include_guard.get('RE_HEADERFILE',"[^/].*\\.h\\Z")
|
||||||
|
|
||||||
for afile in dumpfiles:
|
for afile in dumpfiles:
|
||||||
if not afile[-5:] == '.dump':
|
if not afile[-5:] == '.dump':
|
||||||
continue
|
continue
|
||||||
print('Checking ' + afile + '...')
|
if not args.cli:
|
||||||
|
print('Checking ' + afile + '...')
|
||||||
data = cppcheckdata.CppcheckData(afile)
|
data = cppcheckdata.CppcheckData(afile)
|
||||||
|
process_data(conf,data)
|
||||||
|
|
||||||
# Check File naming
|
def check_file_naming(conf,data):
|
||||||
if "RE_FILE" in conf and conf["RE_FILE"]:
|
for source_file in data.files:
|
||||||
mockToken = DataStruct(afile[:-5], "0", afile[afile.rfind('/') + 1:-5])
|
basename = os.path.basename(source_file)
|
||||||
msgType = 'File name'
|
good = False
|
||||||
for exp in conf["RE_FILE"]:
|
for exp in conf.file:
|
||||||
evalExpr(conf["RE_FILE"], exp, mockToken, msgType, errors)
|
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')
|
||||||
|
|
||||||
# Check Namespace naming
|
def check_namespace_naming(conf,data):
|
||||||
if "RE_NAMESPACE" in conf and conf["RE_NAMESPACE"]:
|
for tk in data.rawTokens:
|
||||||
for tk in data.rawTokens:
|
if tk.str != 'namespace':
|
||||||
if tk.str == 'namespace':
|
continue
|
||||||
mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str)
|
mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str, tk.next.column)
|
||||||
msgType = 'Namespace'
|
for exp in conf.namespace:
|
||||||
for exp in conf["RE_NAMESPACE"]:
|
evalExpr(conf.namespace, exp, mockToken, 'Namespace')
|
||||||
evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors)
|
|
||||||
|
|
||||||
for cfg in data.configurations:
|
def check_variable_naming(conf,cfg):
|
||||||
print('Checking %s, config %s...' % (afile, cfg.name))
|
for var in cfg.variables:
|
||||||
if "RE_VARNAME" in conf and conf["RE_VARNAME"]:
|
if not var.nameToken:
|
||||||
for var in cfg.variables:
|
continue
|
||||||
if var.nameToken and var.access != 'Global' and var.access != 'Public' and var.access != 'Private':
|
if var.access in ('Global','Public','Private'):
|
||||||
prev = var.nameToken.previous
|
continue
|
||||||
varType = prev.str
|
prev = var.nameToken.previous
|
||||||
while "*" in varType and len(varType.replace("*", "")) == 0:
|
varType = prev.str
|
||||||
prev = prev.previous
|
while "*" in varType and len(varType.replace("*", "")) == 0:
|
||||||
varType = prev.str + varType
|
prev = prev.previous
|
||||||
|
varType = prev.str + varType
|
||||||
|
|
||||||
if debugprint:
|
if args.debugprint:
|
||||||
print("Variable Name: " + str(var.nameToken.str))
|
print("Variable Name: " + str(var.nameToken.str))
|
||||||
print("original Type Name: " + str(var.nameToken.valueType.originalTypeName))
|
print("original Type Name: " + str(var.nameToken.valueType.originalTypeName))
|
||||||
print("Type Name: " + var.nameToken.valueType.type)
|
print("Type Name: " + var.nameToken.valueType.type)
|
||||||
print("Sign: " + str(var.nameToken.valueType.sign))
|
print("Sign: " + str(var.nameToken.valueType.sign))
|
||||||
print("variable type: " + varType)
|
print("variable type: " + varType)
|
||||||
print("\n")
|
print("\n")
|
||||||
print("\t-- {} {}".format(varType, str(var.nameToken.str)))
|
print("\t-- {} {}".format(varType, str(var.nameToken.str)))
|
||||||
|
|
||||||
if conf["skip_one_char_variables"] and len(var.nameToken.str) == 1:
|
if conf.skip_one_char_variables and len(var.nameToken.str) == 1:
|
||||||
continue
|
continue
|
||||||
if varType in conf["var_prefixes"]:
|
if varType in conf.variable_prefixes:
|
||||||
if not var.nameToken.str.startswith(conf["var_prefixes"][varType]):
|
prefix = conf.variable_prefixes[varType]
|
||||||
errors.append(reportError(
|
if not var.nameToken.str.startswith(prefix):
|
||||||
var.typeStartToken.file,
|
reportNamingError(var.typeStartToken,
|
||||||
var.typeStartToken.linenr,
|
'Variable ' +
|
||||||
'style',
|
var.nameToken.str +
|
||||||
'Variable ' +
|
' violates naming convention',
|
||||||
var.nameToken.str +
|
column=var.nameToken.column)
|
||||||
' violates naming convention'))
|
|
||||||
|
|
||||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column)
|
||||||
msgType = 'Variable'
|
for exp in conf.variable:
|
||||||
for exp in conf["RE_VARNAME"]:
|
evalExpr(conf.variable, exp, mockToken, 'Variable')
|
||||||
evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType, errors)
|
|
||||||
|
|
||||||
# Check Private Variable naming
|
# Naming check for Global, Private and Public member variables
|
||||||
if "RE_PRIVATE_MEMBER_VARIABLE" in conf and conf["RE_PRIVATE_MEMBER_VARIABLE"]:
|
def check_gpp_naming(conf_list,cfg,access,message):
|
||||||
# TODO: Not converted yet
|
for var in cfg.variables:
|
||||||
for var in cfg.variables:
|
if var.access != access:
|
||||||
if (var.access is None) or var.access != 'Private':
|
continue
|
||||||
continue
|
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column)
|
||||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
for exp in conf_list:
|
||||||
msgType = 'Private member variable'
|
evalExpr(conf_list, exp, mockToken, message)
|
||||||
for exp in conf["RE_PRIVATE_MEMBER_VARIABLE"]:
|
|
||||||
evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
|
|
||||||
|
|
||||||
# Check Public Member Variable naming
|
def check_function_naming(conf,cfg):
|
||||||
if "RE_PUBLIC_MEMBER_VARIABLE" in conf and conf["RE_PUBLIC_MEMBER_VARIABLE"]:
|
for token in cfg.tokenlist:
|
||||||
for var in cfg.variables:
|
if not token.function:
|
||||||
if (var.access is None) or var.access != 'Public':
|
continue
|
||||||
continue
|
if token.function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
|
||||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
continue
|
||||||
msgType = 'Public member variable'
|
retval = token.previous.str
|
||||||
for exp in conf["RE_PUBLIC_MEMBER_VARIABLE"]:
|
prev = token.previous
|
||||||
evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
|
while "*" in retval and len(retval.replace("*", "")) == 0:
|
||||||
|
prev = prev.previous
|
||||||
|
retval = prev.str + retval
|
||||||
|
if args.debugprint:
|
||||||
|
print("\t:: {} {}".format(retval, token.function.name))
|
||||||
|
|
||||||
# Check Global Variable naming
|
if retval and retval in conf.function_prefixes:
|
||||||
if "RE_GLOBAL_VARNAME" in conf and conf["RE_GLOBAL_VARNAME"]:
|
if not token.function.name.startswith(conf.function_prefixes[retval]):
|
||||||
for var in cfg.variables:
|
reportNamingError(token, 'Function ' + token.function.name + ' violates naming convention', column=token.column)
|
||||||
if (var.access is None) or var.access != 'Global':
|
mockToken = DataStruct(token.file, token.linenr, token.function.name, token.column)
|
||||||
continue
|
msgType = 'Function'
|
||||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
for exp in conf.function_name:
|
||||||
msgType = 'Public member variable'
|
evalExpr(conf.function_name, exp, mockToken, msgType)
|
||||||
for exp in conf["RE_GLOBAL_VARNAME"]:
|
|
||||||
evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType, errors)
|
|
||||||
|
|
||||||
# Check Functions naming
|
def check_class_naming(conf,cfg):
|
||||||
if "RE_FUNCTIONNAME" in conf and conf["RE_FUNCTIONNAME"]:
|
for fnc in cfg.functions:
|
||||||
for token in cfg.tokenlist:
|
if fnc.type not in ('Constructor','Destructor'):
|
||||||
if token.function:
|
continue
|
||||||
if token.function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
|
mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name, fnc.tokenDef.column)
|
||||||
continue
|
msgType = 'Class ' + fnc.type
|
||||||
retval = token.previous.str
|
for exp in conf.class_name:
|
||||||
prev = token.previous
|
evalExpr(conf.class_name, exp, mockToken, msgType)
|
||||||
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"]:
|
def process_data(conf,data):
|
||||||
if not token.function.name.startswith(conf["function_prefixes"][retval]):
|
if conf.file:
|
||||||
errors.append(reportError(
|
check_file_naming(conf,data)
|
||||||
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 conf.namespace:
|
||||||
if "RE_CLASS_NAME" in conf and conf["RE_CLASS_NAME"]:
|
check_namespace_naming(conf,data)
|
||||||
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
|
|
||||||
|
|
||||||
|
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(include_guard_header_re,fn)]
|
||||||
|
|
||||||
|
for cfg in data.configurations:
|
||||||
|
if not args.cli:
|
||||||
|
print('Checking config %s...' % cfg.name)
|
||||||
|
if conf.variable:
|
||||||
|
check_variable_naming(conf,cfg)
|
||||||
|
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)
|
||||||
|
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__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description='Naming verification')
|
parser = cppcheckdata.ArgumentParser()
|
||||||
parser.add_argument('dumpfiles', type=str, nargs='+',
|
|
||||||
help='A set of dumpfiles to process')
|
|
||||||
parser.add_argument("--debugprint", action="store_true", default=False,
|
parser.add_argument("--debugprint", action="store_true", default=False,
|
||||||
help="Add debug prints")
|
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")
|
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()
|
args = parser.parse_args()
|
||||||
errors = process(args.dumpfiles, args.configfile, args.debugprint)
|
process(args.dumpfile, args.configfile)
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
|
@ -441,6 +441,7 @@ static void misra_9_empty_or_zero_initializers(void) {
|
||||||
int e[2][2] = { { 1 , 2 }, {} }; // 9.2
|
int e[2][2] = { { 1 , 2 }, {} }; // 9.2
|
||||||
|
|
||||||
int f[5] = { 0 };
|
int f[5] = { 0 };
|
||||||
|
int f1[5] = { 0u }; // no-warning #11298
|
||||||
int g[5][2] = { 0 };
|
int g[5][2] = { 0 };
|
||||||
int h[2][2] = { { 0 } }; // 9.3
|
int h[2][2] = { { 0 } }; // 9.3
|
||||||
int i[2][2] = { { 0 }, { 0 } };
|
int i[2][2] = { { 0 }, { 0 } };
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -6,6 +6,7 @@
|
||||||
<define name="cairo_bool_t" value="int"/>
|
<define name="cairo_bool_t" value="int"/>
|
||||||
<!-- TODO: Configure cairo_status_t as an enum when this is implemented in Cppcheck -->
|
<!-- TODO: Configure cairo_status_t as an enum when this is implemented in Cppcheck -->
|
||||||
<podtype name="cairo_status_t"/>
|
<podtype name="cairo_status_t"/>
|
||||||
|
<define name="CAIRO_STATUS_READ_ERROR" value="10"/>
|
||||||
<!-- ########## cairo Macros / Defines ########## -->
|
<!-- ########## cairo Macros / Defines ########## -->
|
||||||
<define name="CAIRO_HAS_MIME_SURFACE" value="1"/>
|
<define name="CAIRO_HAS_MIME_SURFACE" value="1"/>
|
||||||
<define name="CAIRO_MIME_TYPE_CCITT_FAX" value=""image/g3fax""/>
|
<define name="CAIRO_MIME_TYPE_CCITT_FAX" value=""image/g3fax""/>
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
<!-- This file once has been generated automatically. See https://github.com/scriptum/cppcheck-libs -->
|
<!-- This file once has been generated automatically. See https://github.com/scriptum/cppcheck-libs -->
|
||||||
<!-- Now it is maintained and extended manually. -->
|
<!-- Now it is maintained and extended manually. -->
|
||||||
<def format="2">
|
<def format="2">
|
||||||
|
<define name="TRUE" value="(!FALSE)"/>
|
||||||
|
<define name="FALSE" value="(0)"/>
|
||||||
<define name="g_return_if_fail(expr)" value="do{if(!(expr)){return;}}while(0)"/>
|
<define name="g_return_if_fail(expr)" value="do{if(!(expr)){return;}}while(0)"/>
|
||||||
<define name="g_return_val_if_fail(expr, val)" value="do{if(!(expr)){return val;}}while(0)"/>
|
<define name="g_return_val_if_fail(expr, val)" value="do{if(!(expr)){return val;}}while(0)"/>
|
||||||
<define name="g_return_if_reached()" value="do{return;}while(0)"/>
|
<define name="g_return_if_reached()" value="do{return;}while(0)"/>
|
||||||
|
@ -178,11 +180,14 @@
|
||||||
<define name="g_assert(expr)" value="assert(expr)"/>
|
<define name="g_assert(expr)" value="assert(expr)"/>
|
||||||
<define name="g_assert_not_reached()" value="assert(NULL)"/>
|
<define name="g_assert_not_reached()" value="assert(NULL)"/>
|
||||||
<define name="g_assert_true(expr)" value="g_assert(expr)"/>
|
<define name="g_assert_true(expr)" value="g_assert(expr)"/>
|
||||||
|
<define name="g_assert_false(expr)" value="g_assert(!(expr))"/>
|
||||||
<define name="g_assert_cmpstr(s1, cmp, s2)" value="g_assert_true(g_strcmp0 ((s1), (s2)) cmp 0)"/>
|
<define name="g_assert_cmpstr(s1, cmp, s2)" value="g_assert_true(g_strcmp0 ((s1), (s2)) cmp 0)"/>
|
||||||
<define name="g_assert_cmpint(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
<define name="g_assert_cmpint(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
||||||
<define name="g_assert_cmpuint(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
<define name="g_assert_cmpuint(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
||||||
<define name="g_assert_cmphex(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
<define name="g_assert_cmphex(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
||||||
<define name="g_assert_cmpfloat(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
<define name="g_assert_cmpfloat(n1, cmp, n2)" value="g_assert_true((n1) cmp (n2))"/>
|
||||||
|
<define name="g_assert_null(expr)" value="g_assert_true((expr) == NULL)"/>
|
||||||
|
<define name="g_assert_nonnull(expr)" value="g_assert_true((expr) != NULL)"/>
|
||||||
<define name="g_signal_connect(instance, detailed_signal, c_handler, data)" value="g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0)"/>
|
<define name="g_signal_connect(instance, detailed_signal, c_handler, data)" value="g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0)"/>
|
||||||
<define name="g_signal_connect_after(instance, detailed_signal, c_handler, data)" value="g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, G_CONNECT_AFTER)"/>
|
<define name="g_signal_connect_after(instance, detailed_signal, c_handler, data)" value="g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, G_CONNECT_AFTER)"/>
|
||||||
<define name="g_signal_connect_swapped(instance, detailed_signal, c_handler, data)" value="g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, G_CONNECT_SWAPPED)"/>
|
<define name="g_signal_connect_swapped(instance, detailed_signal, c_handler, data)" value="g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, G_CONNECT_SWAPPED)"/>
|
||||||
|
|
|
@ -4179,6 +4179,30 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
|
||||||
<valid>0:</valid>
|
<valid>0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
<!-- https://pubs.opengroup.org/onlinepubs/9699919799/functions/strxfrm_l.html -->
|
||||||
|
<!-- size_t strxfrm_l(char *restrict s1, const char *restrict s2, size_t n, locale_t locale) -->
|
||||||
|
<function name="strxfrm_l">
|
||||||
|
<returnValue type="size_t"/>
|
||||||
|
<noreturn>false</noreturn>
|
||||||
|
<leak-ignore/>
|
||||||
|
<!-- In case the 3rd argument is 0, the 1st argument is permitted to be a null pointer. (#6306) -->
|
||||||
|
<arg nr="1" direction="out">
|
||||||
|
<minsize type="argvalue" arg="3"/>
|
||||||
|
</arg>
|
||||||
|
<arg nr="2" direction="in">
|
||||||
|
<not-null/>
|
||||||
|
<not-uninit/>
|
||||||
|
<strz/>
|
||||||
|
<minsize type="argvalue" arg="3"/>
|
||||||
|
</arg>
|
||||||
|
<arg nr="3" direction="in">
|
||||||
|
<not-uninit/>
|
||||||
|
<valid>0:</valid>
|
||||||
|
</arg>
|
||||||
|
<arg nr="4" direction="in">
|
||||||
|
<not-uninit/>
|
||||||
|
</arg>
|
||||||
|
</function>
|
||||||
<!-- https://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html -->
|
<!-- https://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html -->
|
||||||
<!-- char *asctime_r(const struct tm *tm, char *buf); -->
|
<!-- char *asctime_r(const struct tm *tm, char *buf); -->
|
||||||
<function name="asctime_r">
|
<function name="asctime_r">
|
||||||
|
|
18
cfg/std.cfg
18
cfg/std.cfg
|
@ -737,6 +737,7 @@
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
<!-- https://en.cppreference.com/w/cpp/numeric/math/tgamma -->
|
||||||
<!-- double tgamma(double x); -->
|
<!-- double tgamma(double x); -->
|
||||||
<function name="tgamma,std::tgamma">
|
<function name="tgamma,std::tgamma">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
|
@ -746,8 +747,11 @@
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<!-- If x is zero or a negative integer for which the function is asymptotic, it may cause a pole error (depending on implementation).-->
|
||||||
|
<valid>!0.0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
<!-- https://en.cppreference.com/w/cpp/numeric/math/tgamma -->
|
||||||
<!-- float tgammaf(float x); -->
|
<!-- float tgammaf(float x); -->
|
||||||
<function name="tgammaf,std::tgammaf">
|
<function name="tgammaf,std::tgammaf">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
|
@ -757,8 +761,11 @@
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<!-- If x is zero or a negative integer for which the function is asymptotic, it may cause a pole error (depending on implementation).-->
|
||||||
|
<valid>!0.0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
<!-- https://en.cppreference.com/w/cpp/numeric/math/tgamma -->
|
||||||
<!-- long double tgammal(long double x); -->
|
<!-- long double tgammal(long double x); -->
|
||||||
<function name="tgammal,std::tgammal">
|
<function name="tgammal,std::tgammal">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
|
@ -768,6 +775,8 @@
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<!-- If x is zero or a negative integer for which the function is asymptotic, it may cause a pole error (depending on implementation).-->
|
||||||
|
<valid>!0.0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<!-- double trunc(double x); -->
|
<!-- double trunc(double x); -->
|
||||||
|
@ -3035,6 +3044,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
<!-- https://cplusplus.com/reference/cmath/lgamma/ -->
|
||||||
<!-- double lgamma(double x); -->
|
<!-- double lgamma(double x); -->
|
||||||
<function name="lgamma,std::lgamma">
|
<function name="lgamma,std::lgamma">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
|
@ -3044,8 +3054,11 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<!-- If x is zero or a negative integer for which the function is asymptotic, it may cause a pole error (depending on implementation).-->
|
||||||
|
<valid>!0.0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
<!-- https://cplusplus.com/reference/cmath/lgamma/ -->
|
||||||
<!-- float lgammaf(float x); -->
|
<!-- float lgammaf(float x); -->
|
||||||
<function name="lgammaf,std::lgammaf">
|
<function name="lgammaf,std::lgammaf">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
|
@ -3055,8 +3068,11 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<!-- If x is zero or a negative integer for which the function is asymptotic, it may cause a pole error (depending on implementation).-->
|
||||||
|
<valid>!0.0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
<!-- https://cplusplus.com/reference/cmath/lgamma/ -->
|
||||||
<!-- long double lgammal(long double x); -->
|
<!-- long double lgammal(long double x); -->
|
||||||
<function name="lgammal,std::lgammal">
|
<function name="lgammal,std::lgammal">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
|
@ -3066,6 +3082,8 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1" direction="in">
|
<arg nr="1" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<!-- If x is zero or a negative integer for which the function is asymptotic, it may cause a pole error (depending on implementation).-->
|
||||||
|
<valid>!0.0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<!-- double rint(double x); -->
|
<!-- double rint(double x); -->
|
||||||
|
|
|
@ -6,11 +6,11 @@ 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/)
|
target_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
||||||
if(USE_BUNDLED_TINYXML2)
|
if(USE_BUNDLED_TINYXML2)
|
||||||
target_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
target_externals_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
||||||
else()
|
else()
|
||||||
target_include_directories(cli_objs SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
target_include_directories(cli_objs SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/)
|
target_externals_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/)
|
||||||
if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS)
|
if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS)
|
||||||
target_precompile_headers(cli_objs PRIVATE precompiled.h)
|
target_precompile_headers(cli_objs PRIVATE precompiled.h)
|
||||||
endif()
|
endif()
|
||||||
|
@ -38,11 +38,11 @@ endif()
|
||||||
add_executable(cppcheck ${cppcheck_SOURCES})
|
add_executable(cppcheck ${cppcheck_SOURCES})
|
||||||
target_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
target_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
||||||
if(USE_BUNDLED_TINYXML2)
|
if(USE_BUNDLED_TINYXML2)
|
||||||
target_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
target_externals_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
||||||
else()
|
else()
|
||||||
target_include_directories(cppcheck SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
target_include_directories(cppcheck SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/)
|
target_externals_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/)
|
||||||
if (HAVE_RULES)
|
if (HAVE_RULES)
|
||||||
target_link_libraries(cppcheck ${PCRE_LIBRARY})
|
target_link_libraries(cppcheck ${PCRE_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib> // EXIT_FAILURE
|
#include <cstdlib> // EXIT_FAILURE
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -797,9 +798,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str == "c")
|
if (str == "c")
|
||||||
mSettings.enforcedLang = Settings::Language::C;
|
mSettings.enforcedLang = Standards::Language::C;
|
||||||
else if (str == "c++")
|
else if (str == "c++")
|
||||||
mSettings.enforcedLang = Settings::Language::CPP;
|
mSettings.enforcedLang = Standards::Language::CPP;
|
||||||
else {
|
else {
|
||||||
mLogger.printError("unknown language '" + str + "' enforced.");
|
mLogger.printError("unknown language '" + str + "' enforced.");
|
||||||
return Result::Fail;
|
return Result::Fail;
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib> // EXIT_SUCCESS and EXIT_FAILURE
|
#include <cstdlib> // EXIT_SUCCESS and EXIT_FAILURE
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream> // IWYU pragma: keep
|
#include <sstream> // IWYU pragma: keep
|
||||||
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -217,21 +219,29 @@ int CppCheckExecutor::check_wrapper(CppCheck& cppcheck)
|
||||||
return check_internal(cppcheck);
|
return check_internal(cppcheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppCheckExecutor::reportSuppressions(const Settings &settings, bool unusedFunctionCheckEnabled, const std::list<std::pair<std::string, std::size_t>> &files, ErrorLogger& errorLogger) {
|
bool CppCheckExecutor::reportSuppressions(const Settings &settings, const Suppressions& suppressions, bool unusedFunctionCheckEnabled, const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, ErrorLogger& errorLogger) {
|
||||||
const auto& suppressions = settings.nomsg.getSuppressions();
|
const auto& suppr = suppressions.getSuppressions();
|
||||||
if (std::any_of(suppressions.begin(), suppressions.end(), [](const Suppressions::Suppression& s) {
|
if (std::any_of(suppr.begin(), suppr.end(), [](const Suppressions::Suppression& s) {
|
||||||
return s.errorId == "unmatchedSuppression" && s.fileName.empty() && s.lineNumber == Suppressions::Suppression::NO_LINE;
|
return s.errorId == "unmatchedSuppression" && s.fileName.empty() && s.lineNumber == Suppressions::Suppression::NO_LINE;
|
||||||
}))
|
}))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool err = false;
|
bool err = false;
|
||||||
if (settings.useSingleJob()) {
|
if (settings.useSingleJob()) {
|
||||||
|
// the two inputs may only be used exclusively
|
||||||
|
assert(!(!files.empty() && !fileSettings.empty()));
|
||||||
|
|
||||||
for (std::list<std::pair<std::string, std::size_t>>::const_iterator i = files.cbegin(); i != files.cend(); ++i) {
|
for (std::list<std::pair<std::string, std::size_t>>::const_iterator i = files.cbegin(); i != files.cend(); ++i) {
|
||||||
err |= Suppressions::reportUnmatchedSuppressions(
|
err |= Suppressions::reportUnmatchedSuppressions(
|
||||||
settings.nomsg.getUnmatchedLocalSuppressions(i->first, unusedFunctionCheckEnabled), errorLogger);
|
suppressions.getUnmatchedLocalSuppressions(i->first, unusedFunctionCheckEnabled), errorLogger);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::list<FileSettings>::const_iterator i = fileSettings.cbegin(); i != fileSettings.cend(); ++i) {
|
||||||
|
err |= Suppressions::reportUnmatchedSuppressions(
|
||||||
|
suppressions.getUnmatchedLocalSuppressions(i->filename, unusedFunctionCheckEnabled), errorLogger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err |= Suppressions::reportUnmatchedSuppressions(settings.nomsg.getUnmatchedGlobalSuppressions(unusedFunctionCheckEnabled), errorLogger);
|
err |= Suppressions::reportUnmatchedSuppressions(suppressions.getUnmatchedGlobalSuppressions(unusedFunctionCheckEnabled), errorLogger);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +287,7 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) const
|
||||||
cppcheck.analyseWholeProgram(settings.buildDir, mFiles, mFileSettings);
|
cppcheck.analyseWholeProgram(settings.buildDir, mFiles, mFileSettings);
|
||||||
|
|
||||||
if (settings.severity.isEnabled(Severity::information) || settings.checkConfiguration) {
|
if (settings.severity.isEnabled(Severity::information) || settings.checkConfiguration) {
|
||||||
const bool err = reportSuppressions(settings, cppcheck.isUnusedFunctionCheckEnabled(), mFiles, *mStdLogger);
|
const bool err = reportSuppressions(settings, settings.nomsg, cppcheck.isUnusedFunctionCheckEnabled(), mFiles, mFileSettings, *mStdLogger);
|
||||||
if (err && returnValue == 0)
|
if (err && returnValue == 0)
|
||||||
returnValue = settings.exitCode;
|
returnValue = settings.exitCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
class CppCheck;
|
class CppCheck;
|
||||||
class Settings;
|
class Settings;
|
||||||
class ErrorLogger;
|
class ErrorLogger;
|
||||||
|
class Suppressions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class works as an example of how CppCheck can be used in external
|
* This class works as an example of how CppCheck can be used in external
|
||||||
|
@ -48,7 +49,7 @@ public:
|
||||||
*/
|
*/
|
||||||
CppCheckExecutor() = default;
|
CppCheckExecutor() = default;
|
||||||
CppCheckExecutor(const CppCheckExecutor &) = delete;
|
CppCheckExecutor(const CppCheckExecutor &) = delete;
|
||||||
void operator=(const CppCheckExecutor&) = delete;
|
CppCheckExecutor& operator=(const CppCheckExecutor&) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the checking.
|
* Starts the checking.
|
||||||
|
@ -81,7 +82,7 @@ private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
static bool reportSuppressions(const Settings &settings, bool unusedFunctionCheckEnabled, const std::list<std::pair<std::string, std::size_t>> &files, ErrorLogger& errorLogger);
|
static bool reportSuppressions(const Settings &settings, const Suppressions& suppressions, bool unusedFunctionCheckEnabled, const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, ErrorLogger& errorLogger);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around check_internal
|
* Wrapper around check_internal
|
||||||
|
|
|
@ -109,7 +109,7 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
||||||
pid_t killid;
|
pid_t killid;
|
||||||
// TODO: separate these two defines
|
// TODO: separate these two defines
|
||||||
#if defined(__linux__) && defined(REG_ERR)
|
#if defined(__linux__) && defined(REG_ERR)
|
||||||
const ucontext_t* const uc = reinterpret_cast<const ucontext_t*>(context);
|
const auto* const uc = reinterpret_cast<const ucontext_t*>(context);
|
||||||
killid = (pid_t) syscall(SYS_gettid);
|
killid = (pid_t) syscall(SYS_gettid);
|
||||||
if (uc) {
|
if (uc) {
|
||||||
type = (int)uc->uc_mcontext.gregs[REG_ERR] & 2;
|
type = (int)uc->uc_mcontext.gregs[REG_ERR] & 2;
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
#include "library.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "suppressions.h"
|
#include "suppressions.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <sstream> // IWYU pragma: keep
|
#include <sstream> // IWYU pragma: keep
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
virtual ~Executor() = default;
|
virtual ~Executor() = default;
|
||||||
|
|
||||||
Executor(const Executor &) = delete;
|
Executor(const Executor &) = delete;
|
||||||
void operator=(const Executor &) = delete;
|
Executor& operator=(const Executor &) = delete;
|
||||||
|
|
||||||
virtual unsigned int check() = 0;
|
virtual unsigned int check() = 0;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @mainpage Cppcheck
|
* @mainpage Cppcheck
|
||||||
* @version 2.12.99
|
* @version 2.13.99
|
||||||
*
|
*
|
||||||
* @section overview_sec Overview
|
* @section overview_sec Overview
|
||||||
* Cppcheck is a simple tool for static analysis of C/C++ code.
|
* Cppcheck is a simple tool for static analysis of C/C++ code.
|
||||||
|
|
|
@ -107,11 +107,11 @@ namespace {
|
||||||
void writeToPipe(PipeSignal type, const std::string &data) const
|
void writeToPipe(PipeSignal type, const std::string &data) const
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const char t = static_cast<char>(type);
|
const auto t = static_cast<char>(type);
|
||||||
writeToPipeInternal(type, &t, 1);
|
writeToPipeInternal(type, &t, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int len = static_cast<unsigned int>(data.length());
|
const auto len = static_cast<unsigned int>(data.length());
|
||||||
{
|
{
|
||||||
static constexpr std::size_t l_size = sizeof(unsigned int);
|
static constexpr std::size_t l_size = sizeof(unsigned int);
|
||||||
writeToPipeInternal(type, &len, l_size);
|
writeToPipeInternal(type, &len, l_size);
|
||||||
|
|
|
@ -43,7 +43,7 @@ class ProcessExecutor : public Executor {
|
||||||
public:
|
public:
|
||||||
ProcessExecutor(const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand);
|
ProcessExecutor(const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand);
|
||||||
ProcessExecutor(const ProcessExecutor &) = delete;
|
ProcessExecutor(const ProcessExecutor &) = delete;
|
||||||
void operator=(const ProcessExecutor &) = delete;
|
ProcessExecutor& operator=(const ProcessExecutor &) = delete;
|
||||||
|
|
||||||
unsigned int check() override;
|
unsigned int check() override;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class SingleExecutor : public Executor
|
||||||
public:
|
public:
|
||||||
SingleExecutor(CppCheck &cppcheck, const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger);
|
SingleExecutor(CppCheck &cppcheck, const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger);
|
||||||
SingleExecutor(const SingleExecutor &) = delete;
|
SingleExecutor(const SingleExecutor &) = delete;
|
||||||
void operator=(const SingleExecutor &) = delete;
|
SingleExecutor& operator=(const SingleExecutor &) = delete;
|
||||||
|
|
||||||
unsigned int check() override;
|
unsigned int check() override;
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ThreadExecutor : public Executor {
|
||||||
public:
|
public:
|
||||||
ThreadExecutor(const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand);
|
ThreadExecutor(const std::list<std::pair<std::string, std::size_t>> &files, const std::list<FileSettings>& fileSettings, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger, CppCheck::ExecuteCmdFn executeCommand);
|
||||||
ThreadExecutor(const ThreadExecutor &) = delete;
|
ThreadExecutor(const ThreadExecutor &) = delete;
|
||||||
void operator=(const ThreadExecutor &) = delete;
|
ThreadExecutor& operator=(const ThreadExecutor &) = delete;
|
||||||
|
|
||||||
unsigned int check() override;
|
unsigned int check() override;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
if (CMAKE_VERSION VERSION_LESS "3.0")
|
|
||||||
if (CMAKE_CXX_COMPILER_LAUNCHER)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_CXX_COMPILER_LAUNCHER}")
|
|
||||||
elseif (CMAKE_C_COMPILER_LAUNCHER)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_C_COMPILER_LAUNCHER}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
|
@ -1,14 +1,13 @@
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1)
|
||||||
message(ERROR "GCC >= 4.8 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
message(ERROR "GCC >= 5.1 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
||||||
endif ()
|
endif ()
|
||||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
# TODO: verify this
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.9)
|
message(ERROR "Clang >= 3.5 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
||||||
message(ERROR "Clang >= 2.9 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
|
||||||
endif ()
|
endif ()
|
||||||
elseif(MSVC)
|
elseif(MSVC)
|
||||||
if (MSVC_VERSION VERSION_LESS 1800)
|
if (MSVC_VERSION VERSION_LESS 1900)
|
||||||
message(ERROR "Visual Studio >= 2013 (1800) required - detected ${MSVC_VERSION} not supported")
|
message(ERROR "Visual Studio >= 2015 (19.0) required - detected ${MSVC_VERSION} not supported")
|
||||||
endif ()
|
endif ()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
# add_compile_definitions() requires CMake 3.12
|
||||||
|
|
||||||
# Visual Studio only sets _DEBUG
|
# Visual Studio only sets _DEBUG
|
||||||
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
|
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,14 @@ function(target_compile_options_safe TARGET FLAG)
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(target_externals_include_directories TARGET)
|
||||||
|
if (EXTERNALS_AS_SYSTEM)
|
||||||
|
target_include_directories(${TARGET} SYSTEM ${ARGN})
|
||||||
|
else()
|
||||||
|
target_include_directories(${TARGET} ${ARGN})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
add_compile_options(-Weverything)
|
add_compile_options(-Weverything)
|
||||||
endif()
|
endif()
|
||||||
|
@ -77,7 +85,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
|
||||||
if (USE_LIBCXX)
|
if (USE_LIBCXX)
|
||||||
add_compile_options(-stdlib=libc++)
|
add_compile_options(-stdlib=libc++)
|
||||||
add_link_options(-lc++)
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# TODO: fix and enable these warnings - or move to suppression list below
|
# TODO: fix and enable these warnings - or move to suppression list below
|
||||||
|
@ -125,6 +133,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
# add_link_options() requires CMake 3.13
|
||||||
|
|
||||||
# General
|
# General
|
||||||
add_compile_options(/W4) # Warning Level
|
add_compile_options(/W4) # Warning Level
|
||||||
add_compile_options(/Zi) # Debug Information Format - Program Database
|
add_compile_options(/Zi) # Debug Information Format - Program Database
|
||||||
|
|
|
@ -1,20 +1,9 @@
|
||||||
macro(use_cxx11)
|
macro(use_cxx11)
|
||||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
# some GitHub Action Windows runners randomly fail with a complaint that Qt6 requires a C++17 compiler
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if (MSVC AND USE_QT6)
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
# CMAKE_CXX_STANDARD 17 was added in CMake 3.8
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
set (CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to use")
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
endif ()
|
|
||||||
else ()
|
else ()
|
||||||
# some GitHub Action windows runners randomly fail with a complaint that Qt6 requires a C++17 compiler
|
set (CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to use")
|
||||||
if (MSVC)
|
endif()
|
||||||
set (CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to use")
|
|
||||||
else ()
|
|
||||||
set (CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to use")
|
|
||||||
endif()
|
|
||||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
if (POLICY CMP0025)
|
|
||||||
cmake_policy(SET CMP0025 NEW)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
endmacro(use_cxx11)
|
endmacro(use_cxx11)
|
||||||
|
|
|
@ -17,7 +17,9 @@ option(ANALYZE_ADDRESS "Clang dynamic analyzer: fast memory error detector.
|
||||||
option(ANALYZE_THREAD "Clang dynamic analyzer: tool that detects data races. " OFF)
|
option(ANALYZE_THREAD "Clang dynamic analyzer: tool that detects data races. " OFF)
|
||||||
option(ANALYZE_UNDEFINED "Clang dynamic analyzer: undefined behavior checker. " OFF)
|
option(ANALYZE_UNDEFINED "Clang dynamic analyzer: undefined behavior checker. " OFF)
|
||||||
option(ANALYZE_DATAFLOW "Clang dynamic analyzer: general dynamic dataflow analysis." OFF)
|
option(ANALYZE_DATAFLOW "Clang dynamic analyzer: general dynamic dataflow analysis." OFF)
|
||||||
|
|
||||||
option(WARNINGS_ARE_ERRORS "Treat warnings as errors" OFF)
|
option(WARNINGS_ARE_ERRORS "Treat warnings as errors" OFF)
|
||||||
|
option(EXTERNALS_AS_SYSTEM "Treat externals as system includes" OFF)
|
||||||
|
|
||||||
set(USE_MATCHCOMPILER "Auto" CACHE STRING "Usage of match compiler")
|
set(USE_MATCHCOMPILER "Auto" CACHE STRING "Usage of match compiler")
|
||||||
set_property(CACHE USE_MATCHCOMPILER PROPERTY STRINGS Auto Off On Verify)
|
set_property(CACHE USE_MATCHCOMPILER PROPERTY STRINGS Auto Off On Verify)
|
||||||
|
@ -70,6 +72,10 @@ else()
|
||||||
set(CMAKE_DISABLE_PRECOMPILE_HEADERS On CACHE BOOL "Disable precompiled headers")
|
set(CMAKE_DISABLE_PRECOMPILE_HEADERS On CACHE BOOL "Disable precompiled headers")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (BUILD_TESTS AND REGISTER_TESTS AND CMAKE_VERSION VERSION_LESS "3.9")
|
||||||
|
message(FATAL_ERROR "Registering tests with CTest requires at least CMake 3.9. Use REGISTER_TESTS=OFF to disable this.")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_DIRS_CONFIGCMAKE ${CMAKE_INSTALL_PREFIX}/include CACHE PATH "Output directory for headers")
|
set(CMAKE_INCLUDE_DIRS_CONFIGCMAKE ${CMAKE_INSTALL_PREFIX}/include CACHE PATH "Output directory for headers")
|
||||||
set(CMAKE_LIB_DIRS_CONFIGCMAKE ${CMAKE_INSTALL_PREFIX}/lib CACHE PATH "Output directory for libraries")
|
set(CMAKE_LIB_DIRS_CONFIGCMAKE ${CMAKE_INSTALL_PREFIX}/lib CACHE PATH "Output directory for libraries")
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
message( STATUS "------------------ General configuration for ${PROJECT_NAME} ${VERSION} -----------------")
|
message( STATUS "------------------ General configuration for ${PROJECT_NAME} ${PROJECT_VERSION} -----------------")
|
||||||
message( STATUS )
|
message( STATUS )
|
||||||
message( STATUS "CMake Version = ${CMAKE_VERSION}")
|
message( STATUS "CMake Version = ${CMAKE_VERSION}")
|
||||||
message( STATUS "CMake Generator = ${CMAKE_GENERATOR}")
|
message( STATUS "CMake Generator = ${CMAKE_GENERATOR}")
|
||||||
|
@ -25,7 +25,9 @@ message( STATUS "ANALYZE_ADDRESS = ${ANALYZE_ADDRESS}" )
|
||||||
message( STATUS "ANALYZE_THREAD = ${ANALYZE_THREAD}" )
|
message( STATUS "ANALYZE_THREAD = ${ANALYZE_THREAD}" )
|
||||||
message( STATUS "ANALYZE_UNDEFINED = ${ANALYZE_UNDEFINED}" )
|
message( STATUS "ANALYZE_UNDEFINED = ${ANALYZE_UNDEFINED}" )
|
||||||
message( STATUS "ANALYZE_DATAFLOW = ${ANALYZE_DATAFLOW}" )
|
message( STATUS "ANALYZE_DATAFLOW = ${ANALYZE_DATAFLOW}" )
|
||||||
|
message( STATUS )
|
||||||
message( STATUS "WARNINGS_ARE_ERRORS = ${WARNINGS_ARE_ERRORS}" )
|
message( STATUS "WARNINGS_ARE_ERRORS = ${WARNINGS_ARE_ERRORS}" )
|
||||||
|
message( STATUS "EXTERNALS_AS_SYSTEM = ${EXTERNALS_AS_SYSTEM}" )
|
||||||
message( STATUS )
|
message( STATUS )
|
||||||
message( STATUS "USE_MATCHCOMPILER = ${USE_MATCHCOMPILER}" )
|
message( STATUS "USE_MATCHCOMPILER = ${USE_MATCHCOMPILER}" )
|
||||||
message( STATUS "USE_MATCHCOMPILER_OPT = ${USE_MATCHCOMPILER_OPT}" )
|
message( STATUS "USE_MATCHCOMPILER_OPT = ${USE_MATCHCOMPILER_OPT}" )
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
# Version for libraries CPP
|
# Version for libraries CPP
|
||||||
# Version string must have 3 "parts". https://sourceforge.net/p/cppcheck/discussion/development/thread/e57efb2b62/
|
# Version string must have 3 "parts". https://sourceforge.net/p/cppcheck/discussion/development/thread/e57efb2b62/
|
||||||
SET(VERSION "2.12.99")
|
SET(SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
STRING(REGEX MATCHALL "[0-9]+" VERSION_PARTS "${VERSION}")
|
|
||||||
LIST(GET VERSION_PARTS 0 VERSION_MAJOR)
|
|
||||||
LIST(GET VERSION_PARTS 1 VERSION_MINOR)
|
|
||||||
LIST(GET VERSION_PARTS 2 VERSION_PATCH)
|
|
||||||
SET(SOVERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
|
||||||
|
|
||||||
# Postfix of so's:
|
# Postfix of so's:
|
||||||
SET(DLLVERSION "")
|
SET(DLLVERSION "")
|
||||||
|
|
|
@ -37,11 +37,11 @@
|
||||||
# - empty the releasenotes.txt in main branch
|
# - empty the releasenotes.txt in main branch
|
||||||
#
|
#
|
||||||
# Update version numbers in:
|
# Update version numbers in:
|
||||||
# sed -i -r "s/version 2[.][0-9]+([.]99)*/version 2.9/" cli/main.cpp
|
# sed -i -r "s/version 2[.][0-9]+([.]99)*/version 2.13.0/" cli/main.cpp
|
||||||
# sed -i -r "s|2[.][0-9]+([.]99)*|2.9.0|" cmake/versions.cmake # version must have 3 parts.
|
# sed -i -r "s|2[.][0-9]+([.]99)*|2.13.0|" cmake/versions.cmake # version must have 3 parts.
|
||||||
# sed -i -r "s/MINOR [0-9]+/MINOR 9/" lib/version.h
|
# sed -i -r "s/CPPCHECK_MINOR_VERSION [0-9]+/CPPCHECK_MINOR_VERSION 13/" lib/version.h
|
||||||
# sed -i -r "s/2[.][0-9]+([.]99)*/2.9/" win_installer/productInfo.wxi
|
# sed -i -r "s/2[.][0-9]+([.]99)*( dev)*/2.13.0/" win_installer/productInfo.wxi
|
||||||
# sed -i -r "s/subtitle: Version 2\.[0-9]+/subtitle: Version 2.9/" man/*.md
|
# sed -i -r "s/subtitle: Version 2\.[0-9]+.*/subtitle: Version 2.13/" man/*.md
|
||||||
# Ensure that "-rc1" is added in productInfo.wxi and lib/version.h
|
# Ensure that "-rc1" is added in productInfo.wxi and lib/version.h
|
||||||
# Verify:
|
# Verify:
|
||||||
# grep '\.99' */*.[ch]* && grep '[0-9][0-9] dev' */*.[ch]*
|
# grep '\.99' */*.[ch]* && grep '[0-9][0-9] dev' */*.[ch]*
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
# git tag 2.8 ; git push --tags
|
# git tag 2.8 ; git push --tags
|
||||||
# ./createrelease 2.8
|
# ./createrelease 2.8
|
||||||
#
|
#
|
||||||
# copy msi from release-windows
|
# copy msi from release-windows, install and test cppcheck
|
||||||
# copy manual from build-manual
|
# copy manual from build-manual
|
||||||
#
|
#
|
||||||
# Update download link on index.php main page
|
# Update download link on index.php main page
|
||||||
|
@ -96,13 +96,14 @@
|
||||||
# ./build-cppcheck.sh
|
# ./build-cppcheck.sh
|
||||||
#
|
#
|
||||||
# run daca with new release
|
# run daca with new release
|
||||||
# 1. edit tools/donate-cpu-server.py. Update OLD_VERSION and VERSION
|
# 1. edit tools/donate-cpu-server.py. Update OLD_VERSION and SERVER_VERSION
|
||||||
# 2. scp -i ../.ssh/osuosl_id_rsa tools/donate-cpu-server.py danielmarjamaki@cppcheck1.osuosl.org:/var/daca@home/
|
# 2. scp -i ~/.ssh/osuosl_id_rsa tools/donate-cpu-server.py danielmarjamaki@cppcheck1.osuosl.org:/var/daca@home/
|
||||||
#
|
#
|
||||||
# Backup:
|
# Backup:
|
||||||
# * trac: cd /var && nice tar -zcf /home/danielmarjamaki/trac.tar.gz trac-cppcheck
|
# * trac: cd /var && nice tar -cJf trac.tar.xz trac-cppcheck
|
||||||
# * git: git checkout -f && git checkout main && git pull && tar -zcf ~/cppchecksolutions/backups/2.12.0-git.tar.gz .git
|
# * git: git checkout -f && git checkout main && git pull && tar -cJf git.tar.xz .git
|
||||||
# * Changelog
|
# * Changelog
|
||||||
|
# * ci status: screenshot(s) showing that all tests pass for tagged commit
|
||||||
|
|
||||||
# Folder/tag to use
|
# Folder/tag to use
|
||||||
folder=$1
|
folder=$1
|
||||||
|
@ -132,8 +133,8 @@ rm $releasename.*
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# Generate version.txt
|
# Generate version.txt
|
||||||
make -j4
|
make -j12
|
||||||
rm cppcheck.cfg
|
rm -f cppcheck.cfg
|
||||||
./cppcheck --version > upload/version.txt
|
./cppcheck --version > upload/version.txt
|
||||||
|
|
||||||
cd ~/cppcheck/upload
|
cd ~/cppcheck/upload
|
||||||
|
@ -149,7 +150,7 @@ cp -R ~/cppcheck/cfg .
|
||||||
cp -R ~/cppcheck/addons .
|
cp -R ~/cppcheck/addons .
|
||||||
cp -R ~/cppcheck/platforms .
|
cp -R ~/cppcheck/platforms .
|
||||||
cd ~/cppcheck
|
cd ~/cppcheck
|
||||||
make clean ; make -j4 FILESDIR=~/.cppcheck/$tag MATCHCOMPILER=yes
|
make clean ; make -j12 FILESDIR=~/.cppcheck/$tag MATCHCOMPILER=yes CXXFLAGS=-O2
|
||||||
mv cppcheck ~/.cppcheck/cppcheck-$tag
|
mv cppcheck ~/.cppcheck/cppcheck-$tag
|
||||||
|
|
||||||
git checkout main
|
git checkout main
|
||||||
|
|
|
@ -38,7 +38,7 @@ CheckOptions:
|
||||||
set_target_properties(cppcheck-gui PROPERTIES WIN32_EXECUTABLE ON)
|
set_target_properties(cppcheck-gui PROPERTIES WIN32_EXECUTABLE ON)
|
||||||
target_include_directories(cppcheck-gui PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
target_include_directories(cppcheck-gui PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
||||||
if(USE_BUNDLED_TINYXML2)
|
if(USE_BUNDLED_TINYXML2)
|
||||||
target_include_directories(cppcheck-gui PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
target_externals_include_directories(cppcheck-gui PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
||||||
else()
|
else()
|
||||||
target_include_directories(cppcheck-gui SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
target_include_directories(cppcheck-gui SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -112,7 +112,7 @@ of the GNU General Public License version 3</string>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="mUsedLibs">
|
<widget class="QLabel" name="mUsedLibs">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p>Many thanks to these libraries that we use:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">pcre</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">picojson</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">qt</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tinyxml2</li></ul></body></html></string>
|
<string><html><head/><body><p>Many thanks to these libraries that we use:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">PCRE</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">PicoJSON</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">TinyXML2</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Boost</li></ul></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <QChar>
|
#include <QChar>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include <QCryptographicHash>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
#include <QKeySequence>
|
#include <QKeySequence>
|
||||||
|
@ -37,7 +38,6 @@
|
||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
#include <QTextFormat>
|
#include <QTextFormat>
|
||||||
#include <QtCore>
|
|
||||||
|
|
||||||
class QTextDocument;
|
class QTextDocument;
|
||||||
|
|
||||||
|
@ -287,11 +287,11 @@ CodeEditor::CodeEditor(QWidget *parent) :
|
||||||
setStyleSheet(generateStyleString());
|
setStyleSheet(generateStyleString());
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
QShortcut *copyText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_C),this);
|
auto *copyText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_C),this);
|
||||||
QShortcut *allText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_A),this);
|
auto *allText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_A),this);
|
||||||
#else
|
#else
|
||||||
const QShortcut *copyText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C),this);
|
const auto *copyText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C),this);
|
||||||
const QShortcut *allText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A),this);
|
const auto *allText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A),this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
||||||
|
@ -448,15 +448,14 @@ void CodeEditor::lineNumberAreaPaintEvent(const QPaintEvent *event)
|
||||||
QString CodeEditor::generateStyleString()
|
QString CodeEditor::generateStyleString()
|
||||||
{
|
{
|
||||||
QString bgcolor = QString("background:rgb(%1,%2,%3);")
|
QString bgcolor = QString("background:rgb(%1,%2,%3);")
|
||||||
.arg(mWidgetStyle->widgetBGColor.red())
|
.arg(mWidgetStyle->widgetBGColor.red(),
|
||||||
.arg(mWidgetStyle->widgetBGColor.green())
|
mWidgetStyle->widgetBGColor.green(),
|
||||||
.arg(mWidgetStyle->widgetBGColor.blue());
|
mWidgetStyle->widgetBGColor.blue());
|
||||||
QString fgcolor = QString("color:rgb(%1,%2,%3);")
|
QString fgcolor = QString("color:rgb(%1,%2,%3);")
|
||||||
.arg(mWidgetStyle->widgetFGColor.red())
|
.arg(mWidgetStyle->widgetFGColor.red(),
|
||||||
.arg(mWidgetStyle->widgetFGColor.green())
|
mWidgetStyle->widgetFGColor.green(),
|
||||||
.arg(mWidgetStyle->widgetFGColor.blue());
|
mWidgetStyle->widgetFGColor.blue());
|
||||||
QString style = QString("%1 %2")
|
QString style = QString("%1 %2")
|
||||||
.arg(bgcolor)
|
.arg(bgcolor, fgcolor);
|
||||||
.arg(fgcolor);
|
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,10 +72,10 @@ StyleEditDialog::StyleEditDialog(const CodeEditorStyle& newStyle,
|
||||||
mStyleIncoming(newStyle),
|
mStyleIncoming(newStyle),
|
||||||
mStyleOutgoing(newStyle)
|
mStyleOutgoing(newStyle)
|
||||||
{
|
{
|
||||||
QVBoxLayout *vboxMain = new QVBoxLayout(this);
|
auto *vboxMain = new QVBoxLayout(this);
|
||||||
QHBoxLayout *hboxEdit = new QHBoxLayout();
|
auto *hboxEdit = new QHBoxLayout();
|
||||||
// Color/Weight controls
|
// Color/Weight controls
|
||||||
QFormLayout *flEditControls = new QFormLayout();
|
auto *flEditControls = new QFormLayout();
|
||||||
mBtnWidgetColorFG = new SelectColorButton(this);
|
mBtnWidgetColorFG = new SelectColorButton(this);
|
||||||
flEditControls->addRow(QObject::tr("Editor Foreground Color"),
|
flEditControls->addRow(QObject::tr("Editor Foreground Color"),
|
||||||
mBtnWidgetColorFG);
|
mBtnWidgetColorFG);
|
||||||
|
@ -141,7 +141,7 @@ StyleEditDialog::StyleEditDialog(const CodeEditorStyle& newStyle,
|
||||||
vboxMain->addLayout(hboxEdit);
|
vboxMain->addLayout(hboxEdit);
|
||||||
|
|
||||||
// Default Controls
|
// Default Controls
|
||||||
QHBoxLayout *hboxDefaultControls = new QHBoxLayout();
|
auto *hboxDefaultControls = new QHBoxLayout();
|
||||||
mBtnDefaultLight = new QPushButton(QObject::tr("Set to Default Light"),
|
mBtnDefaultLight = new QPushButton(QObject::tr("Set to Default Light"),
|
||||||
this);
|
this);
|
||||||
mBtnDefaultDark = new QPushButton(QObject::tr("Set to Default Dark"),
|
mBtnDefaultDark = new QPushButton(QObject::tr("Set to Default Dark"),
|
||||||
|
@ -153,7 +153,7 @@ StyleEditDialog::StyleEditDialog(const CodeEditorStyle& newStyle,
|
||||||
vboxMain->addLayout(hboxDefaultControls);
|
vboxMain->addLayout(hboxDefaultControls);
|
||||||
vboxMain->addStretch(2);
|
vboxMain->addStretch(2);
|
||||||
// dialog controls
|
// dialog controls
|
||||||
QDialogButtonBox *dBtnBox = new QDialogButtonBox(
|
auto *dBtnBox = new QDialogButtonBox(
|
||||||
QDialogButtonBox::Cancel |
|
QDialogButtonBox::Cancel |
|
||||||
QDialogButtonBox::Ok |
|
QDialogButtonBox::Ok |
|
||||||
QDialogButtonBox::Reset);
|
QDialogButtonBox::Reset);
|
||||||
|
|
|
@ -66,7 +66,7 @@ QString toFilterString(const QMap<QString,QString>& filters, bool addAllSupporte
|
||||||
// name patterns are our values. The generated filter string list will
|
// name patterns are our values. The generated filter string list will
|
||||||
// thus be sorted alphabetically over the descriptions.
|
// thus be sorted alphabetically over the descriptions.
|
||||||
for (const auto& k: filters.keys()) {
|
for (const auto& k: filters.keys()) {
|
||||||
entries << QString("%1 (%2)").arg(k).arg(filters.value(k));
|
entries << QString("%1 (%2)").arg(k, filters.value(k));
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries.join(";;");
|
return entries.join(";;");
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QCryptographicHash>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
@ -52,7 +53,6 @@
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QtCore>
|
|
||||||
|
|
||||||
static void addHeaders(const QString& file1, QSet<QString> &allFiles) {
|
static void addHeaders(const QString& file1, QSet<QString> &allFiles) {
|
||||||
if (allFiles.contains(file1))
|
if (allFiles.contains(file1))
|
||||||
|
@ -170,7 +170,7 @@ void ComplianceReportDialog::save()
|
||||||
} catch (InternalError &e) {
|
} catch (InternalError &e) {
|
||||||
QMessageBox msg(QMessageBox::Critical,
|
QMessageBox msg(QMessageBox::Critical,
|
||||||
tr("Save compliance report"),
|
tr("Save compliance report"),
|
||||||
tr("Failed to import '%1' (%2), can not show files in compliance report").arg(prjfile).arg(QString::fromStdString(e.errorMessage)),
|
tr("Failed to import '%1' (%2), can not show files in compliance report").arg(prjfile, QString::fromStdString(e.errorMessage)),
|
||||||
QMessageBox::Ok,
|
QMessageBox::Ok,
|
||||||
this);
|
this);
|
||||||
msg.exec();
|
msg.exec();
|
||||||
|
|
|
@ -176,7 +176,7 @@ Parameters: -l(line) (file)</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="compliancereportdialog.cpp" line="173"/>
|
<location filename="compliancereportdialog.cpp" line="173"/>
|
||||||
<source>Failed to import '%1' (%2), can not show files in compliance report</source>
|
<source>Failed to import '%1' (%2), can not show files in compliance report</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>'%1' (%2)のインポートに失敗しました。コンプライアンスレポートに表示できません</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Failed to import '%1', can not show files in compliance report</source>
|
<source>Failed to import '%1', can not show files in compliance report</source>
|
||||||
|
@ -1153,7 +1153,7 @@ Do you want to load this project file instead?</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainwindow.cpp" line="961"/>
|
<location filename="mainwindow.cpp" line="961"/>
|
||||||
<source>Failed to load %1 - %2</source>
|
<source>Failed to load %1 - %2</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>%1 - %2 の読み込みに失敗</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainwindow.cpp" line="1313"/>
|
<location filename="mainwindow.cpp" line="1313"/>
|
||||||
|
@ -1233,7 +1233,7 @@ Analysis is stopped.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainwindow.cpp" line="1799"/>
|
<location filename="mainwindow.cpp" line="1799"/>
|
||||||
<source>Failed to import '%1' (%2), analysis is stopped</source>
|
<source>Failed to import '%1' (%2), analysis is stopped</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>'%1' (%2) のインポートに失敗しました。解析は停止</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainwindow.cpp" line="2099"/>
|
<location filename="mainwindow.cpp" line="2099"/>
|
||||||
|
@ -2213,7 +2213,7 @@ Options:
|
||||||
<message>
|
<message>
|
||||||
<location filename="resultstree.cpp" line="347"/>
|
<location filename="resultstree.cpp" line="347"/>
|
||||||
<source>internal</source>
|
<source>internal</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>内部</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="resultstree.cpp" line="692"/>
|
<location filename="resultstree.cpp" line="692"/>
|
||||||
|
@ -2435,7 +2435,7 @@ To toggle what kind of errors are shown, open view menu.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="resultsview.cpp" line="575"/>
|
<location filename="resultsview.cpp" line="575"/>
|
||||||
<source>when checking a file</source>
|
<source>when checking a file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>ファイルをチェックするとき</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="resultsview.cpp" line="576"/>
|
<location filename="resultsview.cpp" line="576"/>
|
||||||
|
|
|
@ -46,8 +46,8 @@ static std::string mandatoryAttibuteMissing(const QXmlStreamReader &xmlReader, c
|
||||||
{
|
{
|
||||||
throw std::runtime_error(QObject::tr("line %1: Mandatory attribute '%2' missing in '%3'")
|
throw std::runtime_error(QObject::tr("line %1: Mandatory attribute '%2' missing in '%3'")
|
||||||
.arg(xmlReader.lineNumber())
|
.arg(xmlReader.lineNumber())
|
||||||
.arg(attributeName)
|
.arg(attributeName, xmlReader.name().toString())
|
||||||
.arg(xmlReader.name().toString()).toStdString());
|
.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
|
static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
|
||||||
|
|
|
@ -62,8 +62,8 @@ void CsvReport::writeError(const ErrorItem &error)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const QString file = QDir::toNativeSeparators(error.errorPath.back().file);
|
const QString file = QDir::toNativeSeparators(error.errorPath.back().file);
|
||||||
QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line);
|
QString line = QString("%1,%2,").arg(file, error.errorPath.back().line);
|
||||||
line += QString("%1,%2,%3").arg(GuiSeverity::toString(error.severity)).arg(error.errorId).arg(error.summary);
|
line += QString("%1,%2,%3").arg(GuiSeverity::toString(error.severity), error.errorId, error.summary);
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||||
mTxtWriter << line << Qt::endl;
|
mTxtWriter << line << Qt::endl;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -121,7 +121,7 @@ void LibraryDialog::openCfg()
|
||||||
if (!errmsg.isNull()) {
|
if (!errmsg.isNull()) {
|
||||||
QMessageBox msg(QMessageBox::Critical,
|
QMessageBox msg(QMessageBox::Critical,
|
||||||
tr("Cppcheck"),
|
tr("Cppcheck"),
|
||||||
tr("Failed to load %1. %2.").arg(selectedFile).arg(errmsg),
|
tr("Failed to load %1. %2.").arg(selectedFile, errmsg),
|
||||||
QMessageBox::Ok,
|
QMessageBox::Ok,
|
||||||
this);
|
this);
|
||||||
msg.exec();
|
msg.exec();
|
||||||
|
@ -185,7 +185,7 @@ void LibraryDialog::saveCfgAs()
|
||||||
|
|
||||||
void LibraryDialog::addFunction()
|
void LibraryDialog::addFunction()
|
||||||
{
|
{
|
||||||
LibraryAddFunctionDialog *d = new LibraryAddFunctionDialog;
|
auto *d = new LibraryAddFunctionDialog;
|
||||||
if (d->exec() == QDialog::Accepted && !d->functionName().isEmpty()) {
|
if (d->exec() == QDialog::Accepted && !d->functionName().isEmpty()) {
|
||||||
|
|
||||||
CppcheckLibraryData::Function f;
|
CppcheckLibraryData::Function f;
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QtCore>
|
|
||||||
|
|
||||||
|
|
||||||
static void ShowUsage();
|
static void ShowUsage();
|
||||||
|
@ -59,7 +58,7 @@ int main(int argc, char *argv[])
|
||||||
QCoreApplication::setOrganizationName("Cppcheck");
|
QCoreApplication::setOrganizationName("Cppcheck");
|
||||||
QCoreApplication::setApplicationName("Cppcheck-GUI");
|
QCoreApplication::setApplicationName("Cppcheck-GUI");
|
||||||
|
|
||||||
QSettings* settings = new QSettings("Cppcheck", "Cppcheck-GUI", &app);
|
auto* settings = new QSettings("Cppcheck", "Cppcheck-GUI", &app);
|
||||||
|
|
||||||
// Set data dir..
|
// Set data dir..
|
||||||
const QStringList args = QApplication::arguments();
|
const QStringList args = QApplication::arguments();
|
||||||
|
@ -71,7 +70,7 @@ int main(int argc, char *argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationHandler* th = new TranslationHandler(&app);
|
auto* th = new TranslationHandler(&app);
|
||||||
th->setLanguage(settings->value(SETTINGS_LANGUAGE, th->suggestLanguage()).toString());
|
th->setLanguage(settings->value(SETTINGS_LANGUAGE, th->suggestLanguage()).toString());
|
||||||
|
|
||||||
if (!CheckArgs(QApplication::arguments()))
|
if (!CheckArgs(QApplication::arguments()))
|
||||||
|
|
|
@ -247,7 +247,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
|
||||||
|
|
||||||
for (int i = 0; i < mPlatforms.getCount(); i++) {
|
for (int i = 0; i < mPlatforms.getCount(); i++) {
|
||||||
PlatformData platform = mPlatforms.mPlatforms[i];
|
PlatformData platform = mPlatforms.mPlatforms[i];
|
||||||
QAction *action = new QAction(this);
|
auto *action = new QAction(this);
|
||||||
platform.mActMainWindow = action;
|
platform.mActMainWindow = action;
|
||||||
mPlatforms.mPlatforms[i] = platform;
|
mPlatforms.mPlatforms[i] = platform;
|
||||||
action->setText(platform.mTitle);
|
action->setText(platform.mTitle);
|
||||||
|
@ -392,10 +392,10 @@ void MainWindow::loadSettings()
|
||||||
mUI->mActionToolBarFilter->setChecked(showFilterToolbar);
|
mUI->mActionToolBarFilter->setChecked(showFilterToolbar);
|
||||||
mUI->mToolBarFilter->setVisible(showFilterToolbar);
|
mUI->mToolBarFilter->setVisible(showFilterToolbar);
|
||||||
|
|
||||||
const Settings::Language enforcedLanguage = (Settings::Language)mSettings->value(SETTINGS_ENFORCED_LANGUAGE, 0).toInt();
|
const Standards::Language enforcedLanguage = (Standards::Language)mSettings->value(SETTINGS_ENFORCED_LANGUAGE, 0).toInt();
|
||||||
if (enforcedLanguage == Settings::CPP)
|
if (enforcedLanguage == Standards::Language::CPP)
|
||||||
mUI->mActionEnforceCpp->setChecked(true);
|
mUI->mActionEnforceCpp->setChecked(true);
|
||||||
else if (enforcedLanguage == Settings::C)
|
else if (enforcedLanguage == Standards::Language::C)
|
||||||
mUI->mActionEnforceC->setChecked(true);
|
mUI->mActionEnforceC->setChecked(true);
|
||||||
else
|
else
|
||||||
mUI->mActionAutoDetectLanguage->setChecked(true);
|
mUI->mActionAutoDetectLanguage->setChecked(true);
|
||||||
|
@ -469,11 +469,11 @@ void MainWindow::saveSettings() const
|
||||||
mSettings->setValue(SETTINGS_TOOLBARS_FILTER_SHOW, mUI->mToolBarFilter->isVisible());
|
mSettings->setValue(SETTINGS_TOOLBARS_FILTER_SHOW, mUI->mToolBarFilter->isVisible());
|
||||||
|
|
||||||
if (mUI->mActionEnforceCpp->isChecked())
|
if (mUI->mActionEnforceCpp->isChecked())
|
||||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Settings::CPP);
|
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::CPP);
|
||||||
else if (mUI->mActionEnforceC->isChecked())
|
else if (mUI->mActionEnforceC->isChecked())
|
||||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Settings::C);
|
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::C);
|
||||||
else
|
else
|
||||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Settings::None);
|
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::None);
|
||||||
|
|
||||||
mApplications->saveSettings();
|
mApplications->saveSettings();
|
||||||
|
|
||||||
|
@ -861,7 +861,7 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename)
|
||||||
const Library::Error error = loadLibrary(library, filename);
|
const Library::Error error = loadLibrary(library, filename);
|
||||||
if (error.errorcode != Library::ErrorCode::OK) {
|
if (error.errorcode != Library::ErrorCode::OK) {
|
||||||
if (error.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT) {
|
if (error.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT) {
|
||||||
QMessageBox::information(this, tr("Information"), tr("The library '%1' contains unknown elements:\n%2").arg(filename).arg(error.reason.c_str()));
|
QMessageBox::information(this, tr("Information"), tr("The library '%1' contains unknown elements:\n%2").arg(filename, error.reason.c_str()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,7 +899,7 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename)
|
||||||
}
|
}
|
||||||
if (!error.reason.empty())
|
if (!error.reason.empty())
|
||||||
errmsg += " '" + QString::fromStdString(error.reason) + "'";
|
errmsg += " '" + QString::fromStdString(error.reason) + "'";
|
||||||
QMessageBox::information(this, tr("Information"), tr("Failed to load the selected library '%1'.\n%2").arg(filename).arg(errmsg));
|
QMessageBox::information(this, tr("Information"), tr("Failed to load the selected library '%1'.\n%2").arg(filename, errmsg));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -958,7 +958,7 @@ Settings MainWindow::getCppcheckSettings()
|
||||||
{
|
{
|
||||||
const QString cfgErr = QString::fromStdString(result.loadCppcheckCfg());
|
const QString cfgErr = QString::fromStdString(result.loadCppcheckCfg());
|
||||||
if (!cfgErr.isEmpty())
|
if (!cfgErr.isEmpty())
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1 - %2").arg("cppcheck.cfg").arg(cfgErr));
|
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1 - %2").arg("cppcheck.cfg", cfgErr));
|
||||||
|
|
||||||
const auto cfgAddons = result.addons;
|
const auto cfgAddons = result.addons;
|
||||||
result.addons.clear();
|
result.addons.clear();
|
||||||
|
@ -1021,7 +1021,7 @@ Settings MainWindow::getCppcheckSettings()
|
||||||
result.platform.loadFromFile(applicationFilePath.toStdString().c_str(), platform.toStdString());
|
result.platform.loadFromFile(applicationFilePath.toStdString().c_str(), platform.toStdString());
|
||||||
} else {
|
} else {
|
||||||
for (int i = Platform::Type::Native; i <= Platform::Type::Unix64; i++) {
|
for (int i = Platform::Type::Native; i <= Platform::Type::Unix64; i++) {
|
||||||
const Platform::Type p = (Platform::Type)i;
|
const auto p = (Platform::Type)i;
|
||||||
if (platform == Platform::toString(p)) {
|
if (platform == Platform::toString(p)) {
|
||||||
result.platform.set(p);
|
result.platform.set(p);
|
||||||
break;
|
break;
|
||||||
|
@ -1091,7 +1091,7 @@ Settings MainWindow::getCppcheckSettings()
|
||||||
result.platform.set((Platform::Type) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt());
|
result.platform.set((Platform::Type) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt());
|
||||||
result.standards.setCPP(mSettings->value(SETTINGS_STD_CPP, QString()).toString().toStdString());
|
result.standards.setCPP(mSettings->value(SETTINGS_STD_CPP, QString()).toString().toStdString());
|
||||||
result.standards.setC(mSettings->value(SETTINGS_STD_C, QString()).toString().toStdString());
|
result.standards.setC(mSettings->value(SETTINGS_STD_C, QString()).toString().toStdString());
|
||||||
result.enforcedLang = (Settings::Language)mSettings->value(SETTINGS_ENFORCED_LANGUAGE, 0).toInt();
|
result.enforcedLang = (Standards::Language)mSettings->value(SETTINGS_ENFORCED_LANGUAGE, 0).toInt();
|
||||||
|
|
||||||
if (result.jobs <= 1) {
|
if (result.jobs <= 1) {
|
||||||
result.jobs = 1;
|
result.jobs = 1;
|
||||||
|
@ -1468,21 +1468,21 @@ void MainWindow::about()
|
||||||
msg.exec();
|
msg.exec();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this);
|
auto *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this);
|
||||||
dlg->exec();
|
dlg->exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showLicense()
|
void MainWindow::showLicense()
|
||||||
{
|
{
|
||||||
FileViewDialog *dlg = new FileViewDialog(":COPYING", tr("License"), this);
|
auto *dlg = new FileViewDialog(":COPYING", tr("License"), this);
|
||||||
dlg->resize(570, 400);
|
dlg->resize(570, 400);
|
||||||
dlg->exec();
|
dlg->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showAuthors()
|
void MainWindow::showAuthors()
|
||||||
{
|
{
|
||||||
FileViewDialog *dlg = new FileViewDialog(":AUTHORS", tr("Authors"), this);
|
auto *dlg = new FileViewDialog(":AUTHORS", tr("Authors"), this);
|
||||||
dlg->resize(350, 400);
|
dlg->resize(350, 400);
|
||||||
dlg->exec();
|
dlg->exec();
|
||||||
}
|
}
|
||||||
|
@ -1634,7 +1634,7 @@ void MainWindow::openHelpContents()
|
||||||
|
|
||||||
void MainWindow::openOnlineHelp()
|
void MainWindow::openOnlineHelp()
|
||||||
{
|
{
|
||||||
HelpDialog *helpDialog = new HelpDialog;
|
auto *helpDialog = new HelpDialog;
|
||||||
helpDialog->showMaximized();
|
helpDialog->showMaximized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1787,7 +1787,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile, const bool check
|
||||||
if (!errorMessage.isEmpty()) {
|
if (!errorMessage.isEmpty()) {
|
||||||
QMessageBox msg(QMessageBox::Critical,
|
QMessageBox msg(QMessageBox::Critical,
|
||||||
tr("Cppcheck"),
|
tr("Cppcheck"),
|
||||||
tr("Failed to import '%1': %2\n\nAnalysis is stopped.").arg(prjfile).arg(errorMessage),
|
tr("Failed to import '%1': %2\n\nAnalysis is stopped.").arg(prjfile, errorMessage),
|
||||||
QMessageBox::Ok,
|
QMessageBox::Ok,
|
||||||
this);
|
this);
|
||||||
msg.exec();
|
msg.exec();
|
||||||
|
@ -1796,7 +1796,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile, const bool check
|
||||||
} catch (InternalError &e) {
|
} catch (InternalError &e) {
|
||||||
QMessageBox msg(QMessageBox::Critical,
|
QMessageBox msg(QMessageBox::Critical,
|
||||||
tr("Cppcheck"),
|
tr("Cppcheck"),
|
||||||
tr("Failed to import '%1' (%2), analysis is stopped").arg(prjfile).arg(QString::fromStdString(e.errorMessage)),
|
tr("Failed to import '%1' (%2), analysis is stopped").arg(prjfile, QString::fromStdString(e.errorMessage)),
|
||||||
QMessageBox::Ok,
|
QMessageBox::Ok,
|
||||||
this);
|
this);
|
||||||
msg.exec();
|
msg.exec();
|
||||||
|
@ -1923,7 +1923,7 @@ void MainWindow::enableProjectOpenActions(bool enable)
|
||||||
|
|
||||||
void MainWindow::openRecentProject()
|
void MainWindow::openRecentProject()
|
||||||
{
|
{
|
||||||
QAction *action = qobject_cast<QAction *>(sender());
|
auto *action = qobject_cast<QAction *>(sender());
|
||||||
if (!action)
|
if (!action)
|
||||||
return;
|
return;
|
||||||
const QString project = action->data().toString();
|
const QString project = action->data().toString();
|
||||||
|
@ -2012,7 +2012,7 @@ void MainWindow::removeProjectMRU(const QString &project)
|
||||||
|
|
||||||
void MainWindow::selectPlatform()
|
void MainWindow::selectPlatform()
|
||||||
{
|
{
|
||||||
QAction *action = qobject_cast<QAction *>(sender());
|
auto *action = qobject_cast<QAction *>(sender());
|
||||||
if (action) {
|
if (action) {
|
||||||
const Platform::Type platform = (Platform::Type) action->data().toInt();
|
const Platform::Type platform = (Platform::Type) action->data().toInt();
|
||||||
mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform);
|
mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform);
|
||||||
|
@ -2100,7 +2100,7 @@ void MainWindow::replyFinished(QNetworkReply *reply) {
|
||||||
}
|
}
|
||||||
mUI->mButtonHideInformation->setVisible(true);
|
mUI->mButtonHideInformation->setVisible(true);
|
||||||
mUI->mLabelInformation->setVisible(true);
|
mUI->mLabelInformation->setVisible(true);
|
||||||
mUI->mLabelInformation->setText(tr("New version available: %1. %2").arg(str.trimmed()).arg(install));
|
mUI->mLabelInformation->setText(tr("New version available: %1. %2").arg(str.trimmed(), install));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ void PrintableReport::writeError(const ErrorItem &error)
|
||||||
{
|
{
|
||||||
const QString file = QDir::toNativeSeparators(error.errorPath.back().file);
|
const QString file = QDir::toNativeSeparators(error.errorPath.back().file);
|
||||||
QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line);
|
QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line);
|
||||||
line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary);
|
line += QString("%1,%2").arg(GuiSeverity::toString(error.severity), error.summary);
|
||||||
|
|
||||||
mFormattedReport += line;
|
mFormattedReport += line;
|
||||||
mFormattedReport += "\n";
|
mFormattedReport += "\n";
|
||||||
|
|
|
@ -55,7 +55,6 @@
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QtCore>
|
|
||||||
|
|
||||||
static constexpr char ADDON_MISRA[] = "misra";
|
static constexpr char ADDON_MISRA[] = "misra";
|
||||||
static constexpr char CODING_STANDARD_MISRA_C_2023[] = "misra-c-2023";
|
static constexpr char CODING_STANDARD_MISRA_C_2023[] = "misra-c-2023";
|
||||||
|
@ -183,7 +182,7 @@ ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, bool premium, QWi
|
||||||
libs.sort();
|
libs.sort();
|
||||||
mUI->mLibraries->clear();
|
mUI->mLibraries->clear();
|
||||||
for (const QString &lib : libs) {
|
for (const QString &lib : libs) {
|
||||||
QListWidgetItem* item = new QListWidgetItem(lib, mUI->mLibraries);
|
auto* item = new QListWidgetItem(lib, mUI->mLibraries);
|
||||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag
|
||||||
item->setCheckState(Qt::Unchecked); // AND initialize check state
|
item->setCheckState(Qt::Unchecked); // AND initialize check state
|
||||||
}
|
}
|
||||||
|
@ -605,7 +604,7 @@ void ProjectFileDialog::setProjectConfigurations(const QStringList &configs)
|
||||||
mUI->mListVsConfigs->clear();
|
mUI->mListVsConfigs->clear();
|
||||||
mUI->mListVsConfigs->setEnabled(!configs.isEmpty() && !mUI->mChkAllVsConfigs->isChecked());
|
mUI->mListVsConfigs->setEnabled(!configs.isEmpty() && !mUI->mChkAllVsConfigs->isChecked());
|
||||||
for (const QString &cfg : configs) {
|
for (const QString &cfg : configs) {
|
||||||
QListWidgetItem* item = new QListWidgetItem(cfg, mUI->mListVsConfigs);
|
auto* item = new QListWidgetItem(cfg, mUI->mListVsConfigs);
|
||||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag
|
||||||
item->setCheckState(Qt::Unchecked);
|
item->setCheckState(Qt::Unchecked);
|
||||||
}
|
}
|
||||||
|
@ -622,7 +621,7 @@ void ProjectFileDialog::addIncludeDir(const QString &dir)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QString newdir = QDir::toNativeSeparators(dir);
|
const QString newdir = QDir::toNativeSeparators(dir);
|
||||||
QListWidgetItem *item = new QListWidgetItem(newdir);
|
auto *item = new QListWidgetItem(newdir);
|
||||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||||
mUI->mListIncludeDirs->addItem(item);
|
mUI->mListIncludeDirs->addItem(item);
|
||||||
}
|
}
|
||||||
|
@ -633,7 +632,7 @@ void ProjectFileDialog::addCheckPath(const QString &path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QString newpath = QDir::toNativeSeparators(path);
|
const QString newpath = QDir::toNativeSeparators(path);
|
||||||
QListWidgetItem *item = new QListWidgetItem(newpath);
|
auto *item = new QListWidgetItem(newpath);
|
||||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||||
mUI->mListCheckPaths->addItem(item);
|
mUI->mListCheckPaths->addItem(item);
|
||||||
}
|
}
|
||||||
|
@ -644,7 +643,7 @@ void ProjectFileDialog::addExcludePath(const QString &path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QString newpath = QDir::toNativeSeparators(path);
|
const QString newpath = QDir::toNativeSeparators(path);
|
||||||
QListWidgetItem *item = new QListWidgetItem(newpath);
|
auto *item = new QListWidgetItem(newpath);
|
||||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||||
mUI->mListExcludedPaths->addItem(item);
|
mUI->mListExcludedPaths->addItem(item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ void ResultsTree::initialize(QSettings *settings, ApplicationList *list, ThreadH
|
||||||
|
|
||||||
QStandardItem *ResultsTree::createNormalItem(const QString &name)
|
QStandardItem *ResultsTree::createNormalItem(const QString &name)
|
||||||
{
|
{
|
||||||
QStandardItem *item = new QStandardItem(name);
|
auto *item = new QStandardItem(name);
|
||||||
item->setData(name, Qt::ToolTipRole);
|
item->setData(name, Qt::ToolTipRole);
|
||||||
item->setEditable(false);
|
item->setEditable(false);
|
||||||
return item;
|
return item;
|
||||||
|
@ -118,7 +118,7 @@ QStandardItem *ResultsTree::createNormalItem(const QString &name)
|
||||||
|
|
||||||
QStandardItem *ResultsTree::createCheckboxItem(bool checked)
|
QStandardItem *ResultsTree::createCheckboxItem(bool checked)
|
||||||
{
|
{
|
||||||
QStandardItem *item = new QStandardItem;
|
auto *item = new QStandardItem;
|
||||||
item->setCheckable(true);
|
item->setCheckable(true);
|
||||||
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
|
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
|
||||||
item->setEnabled(false);
|
item->setEnabled(false);
|
||||||
|
@ -127,7 +127,7 @@ QStandardItem *ResultsTree::createCheckboxItem(bool checked)
|
||||||
|
|
||||||
QStandardItem *ResultsTree::createLineNumberItem(const QString &linenumber)
|
QStandardItem *ResultsTree::createLineNumberItem(const QString &linenumber)
|
||||||
{
|
{
|
||||||
QStandardItem *item = new QStandardItem();
|
auto *item = new QStandardItem();
|
||||||
item->setData(QVariant(linenumber.toInt()), Qt::DisplayRole);
|
item->setData(QVariant(linenumber.toInt()), Qt::DisplayRole);
|
||||||
item->setToolTip(linenumber);
|
item->setToolTip(linenumber);
|
||||||
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
@ -611,7 +611,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
||||||
|
|
||||||
//Create a signal mapper so we don't have to store data to class
|
//Create a signal mapper so we don't have to store data to class
|
||||||
//member variables
|
//member variables
|
||||||
QSignalMapper *signalMapper = new QSignalMapper(this);
|
auto *signalMapper = new QSignalMapper(this);
|
||||||
|
|
||||||
if (mContextItem && mApplications->getApplicationCount() > 0 && mContextItem->parent()) {
|
if (mContextItem && mApplications->getApplicationCount() > 0 && mContextItem->parent()) {
|
||||||
//Create an action for the application
|
//Create an action for the application
|
||||||
|
@ -619,7 +619,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
||||||
if (defaultApplicationIndex < 0)
|
if (defaultApplicationIndex < 0)
|
||||||
defaultApplicationIndex = 0;
|
defaultApplicationIndex = 0;
|
||||||
const Application& app = mApplications->getApplication(defaultApplicationIndex);
|
const Application& app = mApplications->getApplication(defaultApplicationIndex);
|
||||||
QAction *start = new QAction(app.getName(), &menu);
|
auto *start = new QAction(app.getName(), &menu);
|
||||||
if (multipleSelection)
|
if (multipleSelection)
|
||||||
start->setDisabled(true);
|
start->setDisabled(true);
|
||||||
|
|
||||||
|
@ -646,11 +646,11 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create an action for the application
|
//Create an action for the application
|
||||||
QAction *recheckAction = new QAction(tr("Recheck"), &menu);
|
auto *recheckAction = new QAction(tr("Recheck"), &menu);
|
||||||
QAction *copyAction = new QAction(tr("Copy"), &menu);
|
auto *copyAction = new QAction(tr("Copy"), &menu);
|
||||||
QAction *hide = new QAction(tr("Hide"), &menu);
|
auto *hide = new QAction(tr("Hide"), &menu);
|
||||||
QAction *hideallid = new QAction(tr("Hide all with id"), &menu);
|
auto *hideallid = new QAction(tr("Hide all with id"), &menu);
|
||||||
QAction *opencontainingfolder = new QAction(tr("Open containing folder"), &menu);
|
auto *opencontainingfolder = new QAction(tr("Open containing folder"), &menu);
|
||||||
|
|
||||||
if (multipleSelection) {
|
if (multipleSelection) {
|
||||||
hideallid->setDisabled(true);
|
hideallid->setDisabled(true);
|
||||||
|
@ -668,7 +668,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
||||||
menu.addAction(hide);
|
menu.addAction(hide);
|
||||||
menu.addAction(hideallid);
|
menu.addAction(hideallid);
|
||||||
|
|
||||||
QAction *suppress = new QAction(tr("Suppress selected id(s)"), &menu);
|
auto *suppress = new QAction(tr("Suppress selected id(s)"), &menu);
|
||||||
{
|
{
|
||||||
QVariantMap data = mContextItem->data().toMap();
|
QVariantMap data = mContextItem->data().toMap();
|
||||||
const QString messageId = data[ERRORID].toString();
|
const QString messageId = data[ERRORID].toString();
|
||||||
|
@ -691,7 +691,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
QMenu *tagMenu = menu.addMenu(tr("Tag"));
|
QMenu *tagMenu = menu.addMenu(tr("Tag"));
|
||||||
{
|
{
|
||||||
QAction *action = new QAction(tr("No tag"), tagMenu);
|
auto *action = new QAction(tr("No tag"), tagMenu);
|
||||||
tagMenu->addAction(action);
|
tagMenu->addAction(action);
|
||||||
connect(action, &QAction::triggered, [=]() {
|
connect(action, &QAction::triggered, [=]() {
|
||||||
tagSelectedItems(QString());
|
tagSelectedItems(QString());
|
||||||
|
@ -699,7 +699,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QString& tagstr : currentProject->getTags()) {
|
for (const QString& tagstr : currentProject->getTags()) {
|
||||||
QAction *action = new QAction(tagstr, tagMenu);
|
auto *action = new QAction(tagstr, tagMenu);
|
||||||
tagMenu->addAction(action);
|
tagMenu->addAction(action);
|
||||||
connect(action, &QAction::triggered, [=]() {
|
connect(action, &QAction::triggered, [=]() {
|
||||||
tagSelectedItems(tagstr);
|
tagSelectedItems(tagstr);
|
||||||
|
@ -816,7 +816,7 @@ void ResultsTree::startApplication(const QStandardItem *target, int application)
|
||||||
}
|
}
|
||||||
#endif // Q_OS_WIN
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
const QString cmdLine = QString("%1 %2").arg(program).arg(params);
|
const QString cmdLine = QString("%1 %2").arg(program, params);
|
||||||
|
|
||||||
// this is reported as deprecated in Qt 5.15.2 but no longer in Qt 6
|
// this is reported as deprecated in Qt 5.15.2 but no longer in Qt 6
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
|
|
@ -436,7 +436,7 @@ void ResultsView::readErrorsXml(const QString &filename)
|
||||||
|
|
||||||
void ResultsView::updateDetails(const QModelIndex &index)
|
void ResultsView::updateDetails(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
const QStandardItemModel *model = qobject_cast<const QStandardItemModel*>(mUI->mTree->model());
|
const auto *model = qobject_cast<const QStandardItemModel*>(mUI->mTree->model());
|
||||||
QStandardItem *item = model->itemFromIndex(index);
|
QStandardItem *item = model->itemFromIndex(index);
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
|
@ -463,7 +463,7 @@ void ResultsView::updateDetails(const QModelIndex &index)
|
||||||
|
|
||||||
const QString file0 = data["file0"].toString();
|
const QString file0 = data["file0"].toString();
|
||||||
if (!file0.isEmpty() && Path::isHeader(data["file"].toString().toStdString()))
|
if (!file0.isEmpty() && Path::isHeader(data["file"].toString().toStdString()))
|
||||||
formattedMsg += QString("\n\n%1: %2").arg(tr("First included by")).arg(QDir::toNativeSeparators(file0));
|
formattedMsg += QString("\n\n%1: %2").arg(tr("First included by"), QDir::toNativeSeparators(file0));
|
||||||
|
|
||||||
if (data["cwe"].toInt() > 0)
|
if (data["cwe"].toInt() > 0)
|
||||||
formattedMsg.prepend("CWE: " + QString::number(data["cwe"].toInt()) + "\n");
|
formattedMsg.prepend("CWE: " + QString::number(data["cwe"].toInt()) + "\n");
|
||||||
|
|
|
@ -140,7 +140,7 @@ void SettingsDialog::initTranslationsList()
|
||||||
{
|
{
|
||||||
const QString current = mTranslator->getCurrentLanguage();
|
const QString current = mTranslator->getCurrentLanguage();
|
||||||
for (const TranslationInfo& translation : mTranslator->getTranslations()) {
|
for (const TranslationInfo& translation : mTranslator->getTranslations()) {
|
||||||
QListWidgetItem *item = new QListWidgetItem;
|
auto *item = new QListWidgetItem;
|
||||||
item->setText(translation.mName);
|
item->setText(translation.mName);
|
||||||
item->setData(mLangCodeRole, QVariant(translation.mCode));
|
item->setData(mLangCodeRole, QVariant(translation.mCode));
|
||||||
mUI->mListLanguages->addItem(item);
|
mUI->mListLanguages->addItem(item);
|
||||||
|
|
|
@ -182,9 +182,9 @@ void StatsDialog::pdfExport()
|
||||||
"<font color=\"blue\"><h3>%9 : %10</h3></font>\n"
|
"<font color=\"blue\"><h3>%9 : %10</h3></font>\n"
|
||||||
"<font color=\"blue\"><h3>%11 : %12</h3></font>\n"
|
"<font color=\"blue\"><h3>%11 : %12</h3></font>\n"
|
||||||
"<font color=\"purple\"><h3>%13 : %14</h3></font>\n")
|
"<font color=\"purple\"><h3>%13 : %14</h3></font>\n")
|
||||||
.arg(tr("Statistics"))
|
.arg(tr("Statistics"),
|
||||||
.arg(QDate::currentDate().toString("dd.MM.yyyy"))
|
QDate::currentDate().toString("dd.MM.yyyy"),
|
||||||
.arg(tr("Errors"))
|
tr("Errors"))
|
||||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
||||||
.arg(tr("Warnings"))
|
.arg(tr("Warnings"))
|
||||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
||||||
|
@ -246,17 +246,17 @@ void StatsDialog::copyToClipboard()
|
||||||
"\t%8:\t%9\n"
|
"\t%8:\t%9\n"
|
||||||
"\t%10:\t%11\n"
|
"\t%10:\t%11\n"
|
||||||
)
|
)
|
||||||
.arg(projSettings)
|
.arg(projSettings,
|
||||||
.arg(project)
|
project,
|
||||||
.arg(mUI->mProject->text())
|
mUI->mProject->text(),
|
||||||
.arg(paths)
|
paths,
|
||||||
.arg(mUI->mPaths->text())
|
mUI->mPaths->text(),
|
||||||
.arg(incPaths)
|
incPaths,
|
||||||
.arg(mUI->mIncludePaths->text())
|
mUI->mIncludePaths->text(),
|
||||||
.arg(defines)
|
defines)
|
||||||
.arg(mUI->mDefines->text())
|
.arg(mUI->mDefines->text(),
|
||||||
.arg(undefines)
|
undefines,
|
||||||
.arg(mUI->mUndefines->text());
|
mUI->mUndefines->text());
|
||||||
|
|
||||||
const QString previous = QString(
|
const QString previous = QString(
|
||||||
"%1\n"
|
"%1\n"
|
||||||
|
@ -264,13 +264,13 @@ void StatsDialog::copyToClipboard()
|
||||||
"\t%4:\t%5\n"
|
"\t%4:\t%5\n"
|
||||||
"\t%6:\t%7\n"
|
"\t%6:\t%7\n"
|
||||||
)
|
)
|
||||||
.arg(prevScan)
|
.arg(prevScan,
|
||||||
.arg(selPath)
|
selPath,
|
||||||
.arg(mUI->mPath->text())
|
mUI->mPath->text(),
|
||||||
.arg(numFiles)
|
numFiles,
|
||||||
.arg(mUI->mNumberOfFilesScanned->text())
|
mUI->mNumberOfFilesScanned->text(),
|
||||||
.arg(duration)
|
duration,
|
||||||
.arg(mUI->mScanDuration->text());
|
mUI->mScanDuration->text());
|
||||||
|
|
||||||
const QString statistics = QString(
|
const QString statistics = QString(
|
||||||
"%1\n"
|
"%1\n"
|
||||||
|
@ -281,8 +281,8 @@ void StatsDialog::copyToClipboard()
|
||||||
"\t%10:\t%11\n"
|
"\t%10:\t%11\n"
|
||||||
"\t%12:\t%13\n"
|
"\t%12:\t%13\n"
|
||||||
)
|
)
|
||||||
.arg(stats)
|
.arg(stats,
|
||||||
.arg(errors)
|
errors)
|
||||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
||||||
.arg(warnings)
|
.arg(warnings)
|
||||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
||||||
|
@ -308,17 +308,17 @@ void StatsDialog::copyToClipboard()
|
||||||
" <tr><th>%10:</th><td>%11</td></tr>\n"
|
" <tr><th>%10:</th><td>%11</td></tr>\n"
|
||||||
"</table>\n"
|
"</table>\n"
|
||||||
)
|
)
|
||||||
.arg(projSettings)
|
.arg(projSettings,
|
||||||
.arg(project)
|
project,
|
||||||
.arg(mUI->mProject->text())
|
mUI->mProject->text(),
|
||||||
.arg(paths)
|
paths,
|
||||||
.arg(mUI->mPaths->text())
|
mUI->mPaths->text(),
|
||||||
.arg(incPaths)
|
incPaths,
|
||||||
.arg(mUI->mIncludePaths->text())
|
mUI->mIncludePaths->text(),
|
||||||
.arg(defines)
|
defines)
|
||||||
.arg(mUI->mDefines->text())
|
.arg(mUI->mDefines->text(),
|
||||||
.arg(undefines)
|
undefines,
|
||||||
.arg(mUI->mUndefines->text());
|
mUI->mUndefines->text());
|
||||||
|
|
||||||
const QString htmlPrevious = QString(
|
const QString htmlPrevious = QString(
|
||||||
"<h3>%1</h3>\n"
|
"<h3>%1</h3>\n"
|
||||||
|
@ -328,13 +328,13 @@ void StatsDialog::copyToClipboard()
|
||||||
" <tr><th>%6:</th><td>%7</td></tr>\n"
|
" <tr><th>%6:</th><td>%7</td></tr>\n"
|
||||||
"</table>\n"
|
"</table>\n"
|
||||||
)
|
)
|
||||||
.arg(prevScan)
|
.arg(prevScan,
|
||||||
.arg(selPath)
|
selPath,
|
||||||
.arg(mUI->mPath->text())
|
mUI->mPath->text(),
|
||||||
.arg(numFiles)
|
numFiles,
|
||||||
.arg(mUI->mNumberOfFilesScanned->text())
|
mUI->mNumberOfFilesScanned->text(),
|
||||||
.arg(duration)
|
duration,
|
||||||
.arg(mUI->mScanDuration->text());
|
mUI->mScanDuration->text());
|
||||||
|
|
||||||
const QString htmlStatistics = QString(
|
const QString htmlStatistics = QString(
|
||||||
"<h3>%1</h3>\n"
|
"<h3>%1</h3>\n"
|
||||||
|
@ -346,8 +346,8 @@ void StatsDialog::copyToClipboard()
|
||||||
" <tr><th>%12:</th><td>%13</td></tr>\n"
|
" <tr><th>%12:</th><td>%13</td></tr>\n"
|
||||||
"</table>\n"
|
"</table>\n"
|
||||||
)
|
)
|
||||||
.arg(stats)
|
.arg(stats,
|
||||||
.arg(errors)
|
errors)
|
||||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
||||||
.arg(warnings)
|
.arg(warnings)
|
||||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
||||||
|
@ -362,7 +362,7 @@ void StatsDialog::copyToClipboard()
|
||||||
|
|
||||||
const QString htmlSummary = htmlSettings + htmlPrevious + htmlStatistics;
|
const QString htmlSummary = htmlSettings + htmlPrevious + htmlStatistics;
|
||||||
|
|
||||||
QMimeData *mimeData = new QMimeData();
|
auto *mimeData = new QMimeData();
|
||||||
mimeData->setText(textSummary);
|
mimeData->setText(textSummary);
|
||||||
mimeData->setHtml(htmlSummary);
|
mimeData->setHtml(htmlSummary);
|
||||||
clipboard->setMimeData(mimeData);
|
clipboard->setMimeData(mimeData);
|
||||||
|
@ -384,14 +384,14 @@ void StatsDialog::setStatistics(const CheckStatistics *stats)
|
||||||
#ifdef QT_CHARTS_LIB
|
#ifdef QT_CHARTS_LIB
|
||||||
QChartView *createChart(const QString &statsFile, const QString &tool)
|
QChartView *createChart(const QString &statsFile, const QString &tool)
|
||||||
{
|
{
|
||||||
QChart *chart = new QChart;
|
auto *chart = new QChart;
|
||||||
chart->addSeries(numberOfReports(statsFile, tool + "-error"));
|
chart->addSeries(numberOfReports(statsFile, tool + "-error"));
|
||||||
chart->addSeries(numberOfReports(statsFile, tool + "-warning"));
|
chart->addSeries(numberOfReports(statsFile, tool + "-warning"));
|
||||||
chart->addSeries(numberOfReports(statsFile, tool + "-style"));
|
chart->addSeries(numberOfReports(statsFile, tool + "-style"));
|
||||||
chart->addSeries(numberOfReports(statsFile, tool + "-performance"));
|
chart->addSeries(numberOfReports(statsFile, tool + "-performance"));
|
||||||
chart->addSeries(numberOfReports(statsFile, tool + "-portability"));
|
chart->addSeries(numberOfReports(statsFile, tool + "-portability"));
|
||||||
|
|
||||||
QDateTimeAxis *axisX = new QDateTimeAxis;
|
auto *axisX = new QDateTimeAxis;
|
||||||
axisX->setTitleText("Date");
|
axisX->setTitleText("Date");
|
||||||
chart->addAxis(axisX, Qt::AlignBottom);
|
chart->addAxis(axisX, Qt::AlignBottom);
|
||||||
|
|
||||||
|
@ -399,7 +399,7 @@ QChartView *createChart(const QString &statsFile, const QString &tool)
|
||||||
s->attachAxis(axisX);
|
s->attachAxis(axisX);
|
||||||
}
|
}
|
||||||
|
|
||||||
QValueAxis *axisY = new QValueAxis;
|
auto *axisY = new QValueAxis;
|
||||||
axisY->setLabelFormat("%i");
|
axisY->setLabelFormat("%i");
|
||||||
axisY->setTitleText("Count");
|
axisY->setTitleText("Count");
|
||||||
chart->addAxis(axisY, Qt::AlignLeft);
|
chart->addAxis(axisY, Qt::AlignLeft);
|
||||||
|
@ -407,7 +407,7 @@ QChartView *createChart(const QString &statsFile, const QString &tool)
|
||||||
qreal maxY = 0;
|
qreal maxY = 0;
|
||||||
for (QAbstractSeries *s : chart->series()) {
|
for (QAbstractSeries *s : chart->series()) {
|
||||||
s->attachAxis(axisY);
|
s->attachAxis(axisY);
|
||||||
if (const QLineSeries *ls = dynamic_cast<const QLineSeries*>(s)) {
|
if (const auto *ls = dynamic_cast<const QLineSeries*>(s)) {
|
||||||
for (QPointF p : ls->points()) {
|
for (QPointF p : ls->points()) {
|
||||||
if (p.y() > maxY)
|
if (p.y() > maxY)
|
||||||
maxY = p.y();
|
maxY = p.y();
|
||||||
|
@ -419,14 +419,14 @@ QChartView *createChart(const QString &statsFile, const QString &tool)
|
||||||
//chart->createDefaultAxes();
|
//chart->createDefaultAxes();
|
||||||
chart->setTitle(tool);
|
chart->setTitle(tool);
|
||||||
|
|
||||||
QChartView *chartView = new QChartView(chart);
|
auto *chartView = new QChartView(chart);
|
||||||
chartView->setRenderHint(QPainter::Antialiasing);
|
chartView->setRenderHint(QPainter::Antialiasing);
|
||||||
return chartView;
|
return chartView;
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineSeries *numberOfReports(const QString &fileName, const QString &severity)
|
QLineSeries *numberOfReports(const QString &fileName, const QString &severity)
|
||||||
{
|
{
|
||||||
QLineSeries *series = new QLineSeries();
|
auto *series = new QLineSeries();
|
||||||
series->setName(severity);
|
series->setName(severity);
|
||||||
QFile f(fileName);
|
QFile f(fileName);
|
||||||
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
|
|
@ -10,7 +10,8 @@ add_executable(test-filelist
|
||||||
${CMAKE_SOURCE_DIR}/lib/utils.cpp
|
${CMAKE_SOURCE_DIR}/lib/utils.cpp
|
||||||
$<TARGET_OBJECTS:simplecpp_objs>
|
$<TARGET_OBJECTS:simplecpp_objs>
|
||||||
)
|
)
|
||||||
target_include_directories(test-filelist PRIVATE ${CMAKE_SOURCE_DIR}/gui ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/externals/simplecpp)
|
target_include_directories(test-filelist PRIVATE ${CMAKE_SOURCE_DIR}/gui ${CMAKE_SOURCE_DIR}/lib)
|
||||||
|
target_externals_include_directories(test-filelist PRIVATE ${CMAKE_SOURCE_DIR}/externals/simplecpp)
|
||||||
target_compile_definitions(test-filelist PRIVATE SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
target_compile_definitions(test-filelist PRIVATE SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
target_link_libraries(test-filelist ${QT_CORE_LIB} ${QT_TEST_LIB})
|
target_link_libraries(test-filelist ${QT_CORE_LIB} ${QT_TEST_LIB})
|
||||||
|
|
||||||
|
|
|
@ -408,8 +408,8 @@ def filter_bar(enabled):
|
||||||
,'\n | '
|
,'\n | '
|
||||||
,''.join([filter_button(enabled, tool, 'toggleTool') for tool in ['cppcheck', 'clang-tidy']])
|
,''.join([filter_button(enabled, tool, 'toggleTool') for tool in ['cppcheck', 'clang-tidy']])
|
||||||
,'\n | '
|
,'\n | '
|
||||||
,'\n <label class="severityHeader">File: <input type="text" oninput="filterFile(this.value)"/></label>'
|
,'\n <label class="severityHeader">File: <input type="search" oninput="filterFile(this.value)"/></label>'
|
||||||
,'\n <label class="severityHeader">Filter: <input type="text" oninput="filterText(this.value)"/></label>'
|
,'\n <label class="severityHeader">Filter: <input type="search" oninput="filterText(this.value)"/></label>'
|
||||||
,'\n </div>\n'])
|
,'\n </div>\n'])
|
||||||
|
|
||||||
def git_blame(errors, path, file, blame_options):
|
def git_blame(errors, path, file, blame_options):
|
||||||
|
|
|
@ -43,14 +43,14 @@ if (BUILD_CORE_DLL)
|
||||||
else()
|
else()
|
||||||
add_library(cppcheck-core OBJECT ${srcs_lib} ${hdrs})
|
add_library(cppcheck-core OBJECT ${srcs_lib} ${hdrs})
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/)
|
target_externals_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/)
|
||||||
if(USE_BUNDLED_TINYXML2)
|
if(USE_BUNDLED_TINYXML2)
|
||||||
target_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
target_externals_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
||||||
else()
|
else()
|
||||||
target_include_directories(cppcheck-core SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
target_include_directories(cppcheck-core SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/picojson/)
|
target_externals_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/picojson/)
|
||||||
target_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/)
|
target_externals_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/)
|
||||||
if (HAVE_RULES)
|
if (HAVE_RULES)
|
||||||
target_include_directories(cppcheck-core SYSTEM PRIVATE ${PCRE_INCLUDE})
|
target_include_directories(cppcheck-core SYSTEM PRIVATE ${PCRE_INCLUDE})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -52,42 +52,73 @@ static std::string parseAddonInfo(AddonInfo& addoninfo, const picojson::value &j
|
||||||
return "Loading " + fileName + " failed. " + json_error;
|
return "Loading " + fileName + " failed. " + json_error;
|
||||||
}
|
}
|
||||||
if (!json.is<picojson::object>())
|
if (!json.is<picojson::object>())
|
||||||
return "Loading " + fileName + " failed. Bad json.";
|
return "Loading " + fileName + " failed. JSON is not an object.";
|
||||||
picojson::object obj = json.get<picojson::object>();
|
|
||||||
if (obj.count("args")) {
|
|
||||||
if (!obj["args"].is<picojson::array>())
|
|
||||||
return "Loading " + fileName + " failed. args must be array.";
|
|
||||||
for (const picojson::value &v : obj["args"].get<picojson::array>())
|
|
||||||
addoninfo.args += " " + v.get<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj.count("ctu")) {
|
// TODO: remove/complete default value handling for missing fields
|
||||||
// ctu is specified in the config file
|
const picojson::object& obj = json.get<picojson::object>();
|
||||||
if (!obj["ctu"].is<bool>())
|
{
|
||||||
return "Loading " + fileName + " failed. ctu must be boolean.";
|
const auto it = obj.find("args");
|
||||||
addoninfo.ctu = obj["ctu"].get<bool>();
|
if (it != obj.cend()) {
|
||||||
} else {
|
const auto& val = it->second;
|
||||||
addoninfo.ctu = false;
|
if (!val.is<picojson::array>())
|
||||||
}
|
return "Loading " + fileName + " failed. 'args' must be an array.";
|
||||||
|
for (const picojson::value &v : val.get<picojson::array>()) {
|
||||||
if (obj.count("python")) {
|
if (!v.is<std::string>())
|
||||||
// Python was defined in the config file
|
return "Loading " + fileName + " failed. 'args' entry is not a string.";
|
||||||
if (obj["python"].is<picojson::array>()) {
|
addoninfo.args += " " + v.get<std::string>();
|
||||||
return "Loading " + fileName +" failed. python must not be an array.";
|
}
|
||||||
}
|
}
|
||||||
addoninfo.python = obj["python"].get<std::string>();
|
|
||||||
} else {
|
|
||||||
addoninfo.python = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj.count("executable")) {
|
{
|
||||||
if (!obj["executable"].is<std::string>())
|
const auto it = obj.find("ctu");
|
||||||
return "Loading " + fileName + " failed. executable must be a string.";
|
if (it != obj.cend()) {
|
||||||
addoninfo.executable = getFullPath(obj["executable"].get<std::string>(), fileName);
|
const auto& val = it->second;
|
||||||
return "";
|
// ctu is specified in the config file
|
||||||
|
if (!val.is<bool>())
|
||||||
|
return "Loading " + fileName + " failed. 'ctu' must be a boolean.";
|
||||||
|
addoninfo.ctu = val.get<bool>();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addoninfo.ctu = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return addoninfo.getAddonInfo(obj["script"].get<std::string>(), exename);
|
{
|
||||||
|
const auto it = obj.find("python");
|
||||||
|
if (it != obj.cend()) {
|
||||||
|
const auto& val = it->second;
|
||||||
|
// Python was defined in the config file
|
||||||
|
if (!val.is<std::string>()) {
|
||||||
|
return "Loading " + fileName +" failed. 'python' must be a string.";
|
||||||
|
}
|
||||||
|
addoninfo.python = val.get<std::string>();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addoninfo.python = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto it = obj.find("executable");
|
||||||
|
if (it != obj.cend()) {
|
||||||
|
const auto& val = it->second;
|
||||||
|
if (!val.is<std::string>())
|
||||||
|
return "Loading " + fileName + " failed. 'executable' must be a string.";
|
||||||
|
addoninfo.executable = getFullPath(val.get<std::string>(), fileName);
|
||||||
|
return ""; // TODO: why bail out?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto it = obj.find("script");
|
||||||
|
if (it == obj.cend())
|
||||||
|
return "Loading " + fileName + " failed. 'script' is missing.";
|
||||||
|
|
||||||
|
const auto& val = it->second;
|
||||||
|
if (!val.is<std::string>())
|
||||||
|
return "Loading " + fileName + " failed. 'script' must be a string.";
|
||||||
|
|
||||||
|
return addoninfo.getAddonInfo(val.get<std::string>(), exename);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AddonInfo::getAddonInfo(const std::string &fileName, const std::string &exename) {
|
std::string AddonInfo::getAddonInfo(const std::string &fileName, const std::string &exename) {
|
||||||
|
|
|
@ -181,6 +181,8 @@ struct Analyzer {
|
||||||
virtual bool stopOnCondition(const Token* condTok) const = 0;
|
virtual bool stopOnCondition(const Token* condTok) const = 0;
|
||||||
/// The condition that will be assumed during analysis
|
/// The condition that will be assumed during analysis
|
||||||
virtual void assume(const Token* tok, bool state, unsigned int flags = 0) = 0;
|
virtual void assume(const Token* tok, bool state, unsigned int flags = 0) = 0;
|
||||||
|
/// Update the state of the program at the token
|
||||||
|
virtual void updateState(const Token* tok) = 0;
|
||||||
/// Return analyzer for expression at token
|
/// Return analyzer for expression at token
|
||||||
virtual ValuePtr<Analyzer> reanalyze(Token* tok, const std::string& msg = emptyString) const = 0;
|
virtual ValuePtr<Analyzer> reanalyze(Token* tok, const std::string& msg = emptyString) const = 0;
|
||||||
virtual bool invalid() const {
|
virtual bool invalid() const {
|
||||||
|
|
|
@ -1020,7 +1020,7 @@ bool isAliasOf(const Token* tok, const Token* expr, int* indirect, bool* inconcl
|
||||||
if (val.isLocalLifetimeValue() || (pointer && val.isSymbolicValue() && val.intvalue == 0)) {
|
if (val.isLocalLifetimeValue() || (pointer && val.isSymbolicValue() && val.intvalue == 0)) {
|
||||||
if (findAstNode(val.tokvalue,
|
if (findAstNode(val.tokvalue,
|
||||||
[&](const Token* aliasTok) {
|
[&](const Token* aliasTok) {
|
||||||
return aliasTok->exprId() == childTok->exprId();
|
return aliasTok != childTok && aliasTok->exprId() == childTok->exprId();
|
||||||
})) {
|
})) {
|
||||||
if (val.isInconclusive() && inconclusive != nullptr) {
|
if (val.isInconclusive() && inconclusive != nullptr) {
|
||||||
value = &val;
|
value = &val;
|
||||||
|
@ -2651,8 +2651,11 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings,
|
||||||
const Token * ptok = tok2;
|
const Token * ptok = tok2;
|
||||||
while (Token::Match(ptok->astParent(), ".|::|["))
|
while (Token::Match(ptok->astParent(), ".|::|["))
|
||||||
ptok = ptok->astParent();
|
ptok = ptok->astParent();
|
||||||
|
int pindirect = indirect;
|
||||||
|
if (indirect == 0 && astIsLHS(tok2) && Token::Match(ptok, ". %var%") && astIsPointer(ptok->next()))
|
||||||
|
pindirect = 1;
|
||||||
bool inconclusive = false;
|
bool inconclusive = false;
|
||||||
bool isChanged = isVariableChangedByFunctionCall(ptok, indirect, settings, &inconclusive);
|
bool isChanged = isVariableChangedByFunctionCall(ptok, pindirect, settings, &inconclusive);
|
||||||
isChanged |= inconclusive;
|
isChanged |= inconclusive;
|
||||||
if (isChanged)
|
if (isChanged)
|
||||||
return true;
|
return true;
|
||||||
|
@ -3257,6 +3260,8 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
|
||||||
continue;
|
continue;
|
||||||
if (arg->isReference())
|
if (arg->isReference())
|
||||||
return ExprUsage::PassedByReference;
|
return ExprUsage::PassedByReference;
|
||||||
|
if (arg->isPointer() && indirect == 1)
|
||||||
|
return ExprUsage::PassedByReference;
|
||||||
}
|
}
|
||||||
if (!args.empty() && indirect == 0 && !addressOf)
|
if (!args.empty() && indirect == 0 && !addressOf)
|
||||||
return ExprUsage::Used;
|
return ExprUsage::Used;
|
||||||
|
@ -3301,6 +3306,8 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings,
|
||||||
parent = parent->astParent();
|
parent = parent->astParent();
|
||||||
if (Token::Match(parent, "%assign%") && (astIsRHS(tok) || astIsLHS(parent->astOperand1())))
|
if (Token::Match(parent, "%assign%") && (astIsRHS(tok) || astIsLHS(parent->astOperand1())))
|
||||||
return ExprUsage::NotUsed;
|
return ExprUsage::NotUsed;
|
||||||
|
if (Token::Match(parent, "++|--"))
|
||||||
|
return ExprUsage::NotUsed;
|
||||||
if (parent->isConstOp())
|
if (parent->isConstOp())
|
||||||
return ExprUsage::NotUsed;
|
return ExprUsage::NotUsed;
|
||||||
if (parent->isCast())
|
if (parent->isCast())
|
||||||
|
|
|
@ -948,7 +948,7 @@ bool CheckBufferOverrun::isCtuUnsafePointerArith(const Settings *settings, const
|
||||||
/** @brief Parse current TU and extract file info */
|
/** @brief Parse current TU and extract file info */
|
||||||
Check::FileInfo *CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const
|
Check::FileInfo *CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const
|
||||||
{
|
{
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
fileInfo->unsafeArrayIndex = CTU::getUnsafeUsage(tokenizer, settings, isCtuUnsafeArrayIndex);
|
fileInfo->unsafeArrayIndex = CTU::getUnsafeUsage(tokenizer, settings, isCtuUnsafeArrayIndex);
|
||||||
fileInfo->unsafePointerArith = CTU::getUnsafeUsage(tokenizer, settings, isCtuUnsafePointerArith);
|
fileInfo->unsafePointerArith = CTU::getUnsafeUsage(tokenizer, settings, isCtuUnsafePointerArith);
|
||||||
if (fileInfo->unsafeArrayIndex.empty() && fileInfo->unsafePointerArith.empty()) {
|
if (fileInfo->unsafeArrayIndex.empty() && fileInfo->unsafePointerArith.empty()) {
|
||||||
|
@ -964,7 +964,7 @@ Check::FileInfo * CheckBufferOverrun::loadFileInfoFromXml(const tinyxml2::XMLEle
|
||||||
const std::string arrayIndex("array-index");
|
const std::string arrayIndex("array-index");
|
||||||
const std::string pointerArith("pointer-arith");
|
const std::string pointerArith("pointer-arith");
|
||||||
|
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
||||||
if (e->Name() == arrayIndex)
|
if (e->Name() == arrayIndex)
|
||||||
fileInfo->unsafeArrayIndex = CTU::loadUnsafeUsageListFromXml(e);
|
fileInfo->unsafeArrayIndex = CTU::loadUnsafeUsageListFromXml(e);
|
||||||
|
|
|
@ -2633,6 +2633,7 @@ namespace { // avoid one-definition-rule violation
|
||||||
|
|
||||||
const Variable *var;
|
const Variable *var;
|
||||||
const Token *tok;
|
const Token *tok;
|
||||||
|
std::vector<const Variable*> initArgs;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2663,25 +2664,44 @@ void CheckClass::initializerListOrder()
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
// find all variable initializations in list
|
// find all variable initializations in list
|
||||||
while (tok && tok != func->functionScope->bodyStart) {
|
for (; tok && tok != func->functionScope->bodyStart; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "%name% (|{")) {
|
if (Token::Match(tok, "%name% (|{")) {
|
||||||
const Variable *var = scope->getVariable(tok->str());
|
const Variable *var = scope->getVariable(tok->str());
|
||||||
if (var)
|
if (var)
|
||||||
vars.emplace_back(var, tok);
|
vars.emplace_back(var, tok);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
if (Token::Match(tok->tokAt(2), "%name% =")) {
|
const Token* const end = tok->next()->link();
|
||||||
var = scope->getVariable(tok->strAt(2));
|
for (; tok != end; tok = tok->next()) {
|
||||||
|
if (const Variable* argVar = scope->getVariable(tok->str())) {
|
||||||
if (var)
|
if (scope != argVar->scope())
|
||||||
vars.emplace_back(var, tok->tokAt(2));
|
continue;
|
||||||
|
if (argVar->isStatic())
|
||||||
|
continue;
|
||||||
|
if (tok->variable() && tok->variable()->isArgument())
|
||||||
|
continue;
|
||||||
|
if (var->isPointer() && (argVar->isArray() || Token::simpleMatch(tok->astParent(), "&")))
|
||||||
|
continue;
|
||||||
|
if (var->isReference())
|
||||||
|
continue;
|
||||||
|
if (Token::simpleMatch(tok->astParent(), "="))
|
||||||
|
continue;
|
||||||
|
vars.back().initArgs.emplace_back(argVar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tok = tok->next()->link()->next();
|
}
|
||||||
} else
|
|
||||||
tok = tok->next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// need at least 2 members to have out of order initialization
|
for (int j = 0; j < vars.size(); j++) {
|
||||||
for (int j = 1; j < vars.size(); j++) {
|
// check for use of uninitialized arguments
|
||||||
|
for (const auto& arg : vars[j].initArgs)
|
||||||
|
if (vars[j].var->index() < arg->index())
|
||||||
|
initializerListError(vars[j].tok, vars[j].var->nameToken(), scope->className, vars[j].var->name(), /*isArgument*/ true);
|
||||||
|
|
||||||
|
// need at least 2 members to have out of order initialization
|
||||||
|
if (j == 0)
|
||||||
|
continue;
|
||||||
// check for out of order initialization
|
// check for out of order initialization
|
||||||
if (vars[j].var->index() < vars[j - 1].var->index())
|
if (vars[j].var->index() < vars[j - 1].var->index())
|
||||||
initializerListError(vars[j].tok,vars[j].var->nameToken(), scope->className, vars[j].var->name());
|
initializerListError(vars[j].tok,vars[j].var->nameToken(), scope->className, vars[j].var->name());
|
||||||
|
@ -2692,15 +2712,18 @@ void CheckClass::initializerListOrder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname)
|
void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname, bool isArgument)
|
||||||
{
|
{
|
||||||
std::list<const Token *> toks = { tok1, tok2 };
|
std::list<const Token *> toks = { tok1, tok2 };
|
||||||
|
const std::string msg = isArgument ?
|
||||||
|
"Member variable '$symbol' uses an uninitialized argument due to the order of declarations." :
|
||||||
|
"Member variable '$symbol' is in the wrong place in the initializer list.";
|
||||||
reportError(toks, Severity::style, "initializerList",
|
reportError(toks, Severity::style, "initializerList",
|
||||||
"$symbol:" + classname + "::" + varname +"\n"
|
"$symbol:" + classname + "::" + varname + '\n' +
|
||||||
"Member variable '$symbol' is in the wrong place in the initializer list.\n"
|
msg + '\n' +
|
||||||
"Member variable '$symbol' is in the wrong place in the initializer list. "
|
msg + ' ' +
|
||||||
"Members are initialized in the order they are declared, not in the "
|
"Members are initialized in the order they are declared, not in the "
|
||||||
"order they are in the initializer list. Keeping the initializer list "
|
"order they are in the initializer list. Keeping the initializer list "
|
||||||
"in the same order that the members were declared prevents order dependent "
|
"in the same order that the members were declared prevents order dependent "
|
||||||
"initialization errors.", CWE398, Certainty::inconclusive);
|
"initialization errors.", CWE398, Certainty::inconclusive);
|
||||||
}
|
}
|
||||||
|
@ -2988,7 +3011,8 @@ static std::vector<DuplMemberFuncInfo> getDuplInheritedMemberFunctionsRecursive(
|
||||||
if (classFuncIt.name() == parentClassFuncIt.name() &&
|
if (classFuncIt.name() == parentClassFuncIt.name() &&
|
||||||
(parentClassFuncIt.access != AccessControl::Private || !skipPrivate) &&
|
(parentClassFuncIt.access != AccessControl::Private || !skipPrivate) &&
|
||||||
!classFuncIt.isConstructor() && !classFuncIt.isDestructor() &&
|
!classFuncIt.isConstructor() && !classFuncIt.isDestructor() &&
|
||||||
classFuncIt.argsMatch(parentClassIt.type->classScope, parentClassFuncIt.argDef, classFuncIt.argDef, emptyString, 0))
|
classFuncIt.argsMatch(parentClassIt.type->classScope, parentClassFuncIt.argDef, classFuncIt.argDef, emptyString, 0) &&
|
||||||
|
(classFuncIt.isConst() == parentClassFuncIt.isConst() || Function::returnsConst(&classFuncIt) == Function::returnsConst(&parentClassFuncIt)))
|
||||||
results.emplace_back(&classFuncIt, &parentClassFuncIt, &parentClassIt);
|
results.emplace_back(&classFuncIt, &parentClassFuncIt, &parentClassIt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3509,14 +3533,14 @@ Check::FileInfo *CheckClass::getFileInfo(const Tokenizer *tokenizer, const Setti
|
||||||
if (classDefinitions.empty())
|
if (classDefinitions.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
fileInfo->classDefinitions.swap(classDefinitions);
|
fileInfo->classDefinitions.swap(classDefinitions);
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
Check::FileInfo * CheckClass::loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const
|
Check::FileInfo * CheckClass::loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const
|
||||||
{
|
{
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
||||||
if (std::strcmp(e->Name(), "class") != 0)
|
if (std::strcmp(e->Name(), "class") != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -199,7 +199,7 @@ private:
|
||||||
void operatorEqToSelfError(const Token *tok);
|
void operatorEqToSelfError(const Token *tok);
|
||||||
void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic);
|
void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic);
|
||||||
void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic);
|
void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic);
|
||||||
void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname);
|
void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname, bool isArgument = false);
|
||||||
void suggestInitializationList(const Token *tok, const std::string& varname);
|
void suggestInitializationList(const Token *tok, const std::string& varname);
|
||||||
void selfInitializationError(const Token* tok, const std::string& varname);
|
void selfInitializationError(const Token* tok, const std::string& varname);
|
||||||
void pureVirtualFunctionCallInConstructorError(const Function * scopeFunction, const std::list<const Token *> & tokStack, const std::string &purefuncname);
|
void pureVirtualFunctionCallInConstructorError(const Function * scopeFunction, const std::list<const Token *> & tokStack, const std::string &purefuncname);
|
||||||
|
|
|
@ -417,8 +417,6 @@ void CheckCondition::comparison()
|
||||||
|
|
||||||
void CheckCondition::comparisonError(const Token *tok, const std::string &bitop, MathLib::bigint value1, const std::string &op, MathLib::bigint value2, bool result)
|
void CheckCondition::comparisonError(const Token *tok, const std::string &bitop, MathLib::bigint value1, const std::string &op, MathLib::bigint value2, bool result)
|
||||||
{
|
{
|
||||||
if (tok && (diag(tok) | diag(tok->astParent())))
|
|
||||||
return;
|
|
||||||
std::ostringstream expression;
|
std::ostringstream expression;
|
||||||
expression << std::hex << "(X " << bitop << " 0x" << value1 << ") " << op << " 0x" << value2;
|
expression << std::hex << "(X " << bitop << " 0x" << value1 << ") " << op << " 0x" << value2;
|
||||||
|
|
||||||
|
@ -1287,15 +1285,15 @@ void CheckCondition::checkIncorrectLogicOperator()
|
||||||
// 5 => testvalue is larger than both value1 and value2
|
// 5 => testvalue is larger than both value1 and value2
|
||||||
bool result1, result2;
|
bool result1, result2;
|
||||||
if (isfloat) {
|
if (isfloat) {
|
||||||
const double testvalue = getvalue<double>(test, d1, d2);
|
const auto testvalue = getvalue<double>(test, d1, d2);
|
||||||
result1 = checkFloatRelation(op1, testvalue, d1);
|
result1 = checkFloatRelation(op1, testvalue, d1);
|
||||||
result2 = checkFloatRelation(op2, testvalue, d2);
|
result2 = checkFloatRelation(op2, testvalue, d2);
|
||||||
} else if (useUnsignedInt) {
|
} else if (useUnsignedInt) {
|
||||||
const MathLib::biguint testvalue = getvalue<MathLib::biguint>(test, u1, u2);
|
const auto testvalue = getvalue<MathLib::biguint>(test, u1, u2);
|
||||||
result1 = checkIntRelation(op1, testvalue, u1);
|
result1 = checkIntRelation(op1, testvalue, u1);
|
||||||
result2 = checkIntRelation(op2, testvalue, u2);
|
result2 = checkIntRelation(op2, testvalue, u2);
|
||||||
} else {
|
} else {
|
||||||
const MathLib::bigint testvalue = getvalue<MathLib::bigint>(test, i1, i2);
|
const auto testvalue = getvalue<MathLib::bigint>(test, i1, i2);
|
||||||
result1 = checkIntRelation(op1, testvalue, i1);
|
result1 = checkIntRelation(op1, testvalue, i1);
|
||||||
result2 = checkIntRelation(op2, testvalue, i2);
|
result2 = checkIntRelation(op2, testvalue, i2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
|
#include "tokenlist.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "vfvalue.h"
|
#include "vfvalue.h"
|
||||||
|
|
||||||
|
@ -466,6 +467,9 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
const Token * closingParenthesis = tok->linkAt(1);
|
const Token * closingParenthesis = tok->linkAt(1);
|
||||||
for (const Token *innerTok = tok->tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->next()) {
|
for (const Token *innerTok = tok->tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->next()) {
|
||||||
// TODO: replace with checkTokenInsideExpression()
|
// TODO: replace with checkTokenInsideExpression()
|
||||||
|
const Token* const openingPar = isFunctionCall(innerTok);
|
||||||
|
if (!openingPar)
|
||||||
|
checkTokenInsideExpression(innerTok, varInfo);
|
||||||
|
|
||||||
if (!isLocalVarNoAutoDealloc(innerTok, mTokenizer->isCPP()))
|
if (!isLocalVarNoAutoDealloc(innerTok, mTokenizer->isCPP()))
|
||||||
continue;
|
continue;
|
||||||
|
@ -502,7 +506,6 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for function call
|
// check for function call
|
||||||
const Token * const openingPar = isFunctionCall(innerTok);
|
|
||||||
if (openingPar) {
|
if (openingPar) {
|
||||||
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(innerTok);
|
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(innerTok);
|
||||||
// innerTok is a function name
|
// innerTok is a function name
|
||||||
|
@ -805,14 +808,15 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
const Token * vtok = typeEndTok->tokAt(3);
|
const Token * vtok = typeEndTok->tokAt(3);
|
||||||
const VarInfo::AllocInfo allocation(af ? af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, ftok);
|
const VarInfo::AllocInfo allocation(af ? af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, ftok);
|
||||||
changeAllocStatus(varInfo, allocation, vtok, vtok);
|
changeAllocStatus(varInfo, allocation, vtok, vtok);
|
||||||
}
|
} else if (Token::Match(tok, "%var% ."))
|
||||||
|
checkTokenInsideExpression(tok, varInfo);
|
||||||
}
|
}
|
||||||
ret(endToken, varInfo, true);
|
ret(endToken, varInfo, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo)
|
const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo, bool inFuncCall)
|
||||||
{
|
{
|
||||||
// Deallocation and then dereferencing pointer..
|
// Deallocation and then dereferencing pointer..
|
||||||
if (tok->varId() > 0) {
|
if (tok->varId() > 0) {
|
||||||
|
@ -838,7 +842,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
|
||||||
if (rhs->varId() == tok->varId()) {
|
if (rhs->varId() == tok->varId()) {
|
||||||
// simple assignment
|
// simple assignment
|
||||||
varInfo.erase(tok->varId());
|
varInfo.erase(tok->varId());
|
||||||
} else if (rhs->str() == "(" && !mSettings->library.returnValue(rhs->astOperand1()).empty()) {
|
} else if (rhs->astParent() && rhs->str() == "(" && !mSettings->library.returnValue(rhs->astOperand1()).empty()) {
|
||||||
// #9298, assignment through return value of a function
|
// #9298, assignment through return value of a function
|
||||||
const std::string &returnValue = mSettings->library.returnValue(rhs->astOperand1());
|
const std::string &returnValue = mSettings->library.returnValue(rhs->astOperand1());
|
||||||
if (startsWith(returnValue, "arg")) {
|
if (startsWith(returnValue, "arg")) {
|
||||||
|
@ -859,7 +863,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for function call
|
// check for function call
|
||||||
const Token * const openingPar = isFunctionCall(tok);
|
const Token * const openingPar = inFuncCall ? nullptr : isFunctionCall(tok);
|
||||||
if (openingPar) {
|
if (openingPar) {
|
||||||
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(tok);
|
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(tok);
|
||||||
VarInfo::AllocInfo alloc(allocFunc ? allocFunc->groupId : 0, VarInfo::DEALLOC, tok);
|
VarInfo::AllocInfo alloc(allocFunc ? allocFunc->groupId : 0, VarInfo::DEALLOC, tok);
|
||||||
|
@ -930,8 +934,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI
|
||||||
void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af)
|
void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af)
|
||||||
{
|
{
|
||||||
// Ignore function call?
|
// Ignore function call?
|
||||||
if (mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)))
|
const bool isLeakIgnore = mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName));
|
||||||
return;
|
|
||||||
if (mSettings->library.getReallocFuncInfo(tokName))
|
if (mSettings->library.getReallocFuncInfo(tokName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -990,6 +993,8 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
|
||||||
varAlloc.allocTok = arg;
|
varAlloc.allocTok = arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (isLeakIgnore)
|
||||||
|
checkTokenInsideExpression(arg, varInfo);
|
||||||
else
|
else
|
||||||
changeAllocStatus(varInfo, dealloc.type == 0 ? allocation : dealloc, tokName, arg);
|
changeAllocStatus(varInfo, dealloc.type == 0 ? allocation : dealloc, tokName, arg);
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1046,14 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
|
||||||
const VarInfo::AllocInfo sp_allocation(sp_af ? sp_af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, allocTok);
|
const VarInfo::AllocInfo sp_allocation(sp_af ? sp_af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, allocTok);
|
||||||
changeAllocStatus(varInfo, sp_allocation, vtok, vtok);
|
changeAllocStatus(varInfo, sp_allocation, vtok, vtok);
|
||||||
} else {
|
} else {
|
||||||
checkTokenInsideExpression(arg, varInfo);
|
const Token* const nextArg = funcArg->nextArgument();
|
||||||
|
while (arg && ((nextArg && arg != nextArg) || (!nextArg && arg != tokOpeningPar->link()))) {
|
||||||
|
checkTokenInsideExpression(arg, varInfo, /*inFuncCall*/ isLeakIgnore);
|
||||||
|
|
||||||
|
if (isLambdaCaptureList(arg))
|
||||||
|
break;
|
||||||
|
arg = arg->next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO: check each token in argument expression (could contain multiple variables)
|
// TODO: check each token in argument expression (could contain multiple variables)
|
||||||
argNr++;
|
argNr++;
|
||||||
|
@ -1107,7 +1119,7 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO
|
||||||
for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) {
|
||||||
if (tok2->str() == ";")
|
if (tok2->str() == ";")
|
||||||
break;
|
break;
|
||||||
if (!Token::Match(tok2, "return|(|{|,"))
|
if (!Token::Match(tok2, "return|(|{|,|*"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token* tok3 = tok2->next();
|
const Token* tok3 = tok2->next();
|
||||||
|
|
|
@ -135,7 +135,7 @@ private:
|
||||||
* @param varInfo Variable info
|
* @param varInfo Variable info
|
||||||
* @return next token to process (if no other checks needed for this token). NULL if other checks could be performed.
|
* @return next token to process (if no other checks needed for this token). NULL if other checks could be performed.
|
||||||
*/
|
*/
|
||||||
const Token * checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo);
|
const Token * checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo, bool inFuncCall = false);
|
||||||
|
|
||||||
/** parse function call */
|
/** parse function call */
|
||||||
void functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af);
|
void functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af);
|
||||||
|
|
|
@ -86,7 +86,7 @@ private:
|
||||||
public:
|
public:
|
||||||
CheckMemoryLeak() = delete;
|
CheckMemoryLeak() = delete;
|
||||||
CheckMemoryLeak(const CheckMemoryLeak &) = delete;
|
CheckMemoryLeak(const CheckMemoryLeak &) = delete;
|
||||||
void operator=(const CheckMemoryLeak &) = delete;
|
CheckMemoryLeak& operator=(const CheckMemoryLeak &) = delete;
|
||||||
|
|
||||||
CheckMemoryLeak(const Tokenizer *t, ErrorLogger *e, const Settings *s)
|
CheckMemoryLeak(const Tokenizer *t, ErrorLogger *e, const Settings *s)
|
||||||
: mTokenizer_(t), mErrorLogger_(e), mSettings_(s) {}
|
: mTokenizer_(t), mErrorLogger_(e), mSettings_(s) {}
|
||||||
|
|
|
@ -586,7 +586,7 @@ Check::FileInfo *CheckNullPointer::getFileInfo(const Tokenizer *tokenizer, const
|
||||||
if (unsafeUsage.empty())
|
if (unsafeUsage.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
fileInfo->unsafeUsage = unsafeUsage;
|
fileInfo->unsafeUsage = unsafeUsage;
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
|
@ -597,7 +597,7 @@ Check::FileInfo * CheckNullPointer::loadFileInfoFromXml(const tinyxml2::XMLEleme
|
||||||
if (unsafeUsage.empty())
|
if (unsafeUsage.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
fileInfo->unsafeUsage = unsafeUsage;
|
fileInfo->unsafeUsage = unsafeUsage;
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -995,16 +995,7 @@ void CheckOther::checkVariableScope()
|
||||||
|
|
||||||
// parse else if blocks..
|
// parse else if blocks..
|
||||||
} else if (Token::simpleMatch(tok, "else { if (") && Token::simpleMatch(tok->linkAt(3), ") {")) {
|
} else if (Token::simpleMatch(tok, "else { if (") && Token::simpleMatch(tok->linkAt(3), ") {")) {
|
||||||
const Token *endif = tok->linkAt(3)->linkAt(1);
|
tok = tok->next();
|
||||||
bool elseif = false;
|
|
||||||
if (Token::simpleMatch(endif, "} }"))
|
|
||||||
elseif = true;
|
|
||||||
else if (Token::simpleMatch(endif, "} else {") && Token::simpleMatch(endif->linkAt(2),"} }"))
|
|
||||||
elseif = true;
|
|
||||||
if (elseif && Token::findmatch(tok->next(), "%varid%", tok->linkAt(1), var->declarationId())) {
|
|
||||||
reduce = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (tok->varId() == var->declarationId() || tok->str() == "goto") {
|
} else if (tok->varId() == var->declarationId() || tok->str() == "goto") {
|
||||||
reduce = false;
|
reduce = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1642,12 +1642,7 @@ void CheckUninitVar::valueFlowUninit()
|
||||||
const bool isarray = tok->variable()->isArray();
|
const bool isarray = tok->variable()->isArray();
|
||||||
if (isarray && tok->variable()->isMember())
|
if (isarray && tok->variable()->isMember())
|
||||||
continue; // Todo: this is a bailout
|
continue; // Todo: this is a bailout
|
||||||
const bool ispointer = astIsPointer(tok) && !isarray;
|
|
||||||
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
||||||
if (ispointer && v->indirect == 1 && !deref)
|
|
||||||
continue;
|
|
||||||
if (isarray && !deref)
|
|
||||||
continue;
|
|
||||||
uninitderef = deref && v->indirect == 0;
|
uninitderef = deref && v->indirect == 0;
|
||||||
const bool isleaf = isLeafDot(tok) || uninitderef;
|
const bool isleaf = isLeafDot(tok) || uninitderef;
|
||||||
if (!isleaf && Token::Match(tok->astParent(), ". %name%") && (tok->astParent()->next()->varId() || tok->astParent()->next()->isEnumerator()))
|
if (!isleaf && Token::Match(tok->astParent(), ". %name%") && (tok->astParent()->next()->varId() || tok->astParent()->next()->isEnumerator()))
|
||||||
|
@ -1710,7 +1705,7 @@ Check::FileInfo *CheckUninitVar::getFileInfo(const Tokenizer *tokenizer, const S
|
||||||
if (unsafeUsage.empty())
|
if (unsafeUsage.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
fileInfo->unsafeUsage = unsafeUsage;
|
fileInfo->unsafeUsage = unsafeUsage;
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
|
@ -1721,7 +1716,7 @@ Check::FileInfo * CheckUninitVar::loadFileInfoFromXml(const tinyxml2::XMLElement
|
||||||
if (unsafeUsage.empty())
|
if (unsafeUsage.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
MyFileInfo *fileInfo = new MyFileInfo;
|
auto *fileInfo = new MyFileInfo;
|
||||||
fileInfo->unsafeUsage = unsafeUsage;
|
fileInfo->unsafeUsage = unsafeUsage;
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -325,15 +325,15 @@ namespace clangimport {
|
||||||
std::string nodeType;
|
std::string nodeType;
|
||||||
std::vector<AstNodePtr> children;
|
std::vector<AstNodePtr> children;
|
||||||
|
|
||||||
void setLocations(TokenList *tokenList, int file, int line, int col);
|
void setLocations(TokenList &tokenList, int file, int line, int col);
|
||||||
|
|
||||||
void dumpAst(int num = 0, int indent = 0) const;
|
void dumpAst(int num = 0, int indent = 0) const;
|
||||||
void createTokens1(TokenList *tokenList) {
|
void createTokens1(TokenList &tokenList) {
|
||||||
//dumpAst();
|
//dumpAst();
|
||||||
if (!tokenList->back())
|
if (!tokenList.back())
|
||||||
setLocations(tokenList, 0, 1, 1);
|
setLocations(tokenList, 0, 1, 1);
|
||||||
else
|
else
|
||||||
setLocations(tokenList, tokenList->back()->fileIndex(), tokenList->back()->linenr(), 1);
|
setLocations(tokenList, tokenList.back()->fileIndex(), tokenList.back()->linenr(), 1);
|
||||||
createTokens(tokenList);
|
createTokens(tokenList);
|
||||||
if (nodeType == VarDecl || nodeType == RecordDecl || nodeType == TypedefDecl)
|
if (nodeType == VarDecl || nodeType == RecordDecl || nodeType == TypedefDecl)
|
||||||
addtoken(tokenList, ";");
|
addtoken(tokenList, ";");
|
||||||
|
@ -351,22 +351,22 @@ namespace clangimport {
|
||||||
return children[c];
|
return children[c];
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Token *createTokens(TokenList *tokenList);
|
Token *createTokens(TokenList &tokenList);
|
||||||
Token *addtoken(TokenList *tokenList, const std::string &str, bool valueType=true);
|
Token *addtoken(TokenList &tokenList, const std::string &str, bool valueType=true);
|
||||||
const ::Type *addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope = nullptr);
|
const ::Type *addTypeTokens(TokenList &tokenList, const std::string &str, const Scope *scope = nullptr);
|
||||||
void addFullScopeNameTokens(TokenList *tokenList, const Scope *recordScope);
|
void addFullScopeNameTokens(TokenList &tokenList, const Scope *recordScope);
|
||||||
Scope *createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def);
|
Scope *createScope(TokenList &tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def);
|
||||||
Scope *createScope(TokenList *tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> &children2, const Token *def);
|
Scope *createScope(TokenList &tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> &children2, const Token *def);
|
||||||
Token *createTokensCall(TokenList *tokenList);
|
Token *createTokensCall(TokenList &tokenList);
|
||||||
void createTokensFunctionDecl(TokenList *tokenList);
|
void createTokensFunctionDecl(TokenList &tokenList);
|
||||||
void createTokensForCXXRecord(TokenList *tokenList);
|
void createTokensForCXXRecord(TokenList &tokenList);
|
||||||
Token *createTokensVarDecl(TokenList *tokenList);
|
Token *createTokensVarDecl(TokenList &tokenList);
|
||||||
std::string getSpelling() const;
|
std::string getSpelling() const;
|
||||||
std::string getType(int index = 0) const;
|
std::string getType(int index = 0) const;
|
||||||
std::string getFullType(int index = 0) const;
|
std::string getFullType(int index = 0) const;
|
||||||
bool isDefinition() const;
|
bool isDefinition() const;
|
||||||
std::string getTemplateParameters() const;
|
std::string getTemplateParameters() const;
|
||||||
const Scope *getNestedInScope(TokenList *tokenList);
|
const Scope *getNestedInScope(TokenList &tokenList);
|
||||||
void setValueType(Token *tok);
|
void setValueType(Token *tok);
|
||||||
|
|
||||||
int mFile = 0;
|
int mFile = 0;
|
||||||
|
@ -496,7 +496,7 @@ void clangimport::AstNode::dumpAst(int num, int indent) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clangimport::AstNode::setLocations(TokenList *tokenList, int file, int line, int col)
|
void clangimport::AstNode::setLocations(TokenList &tokenList, int file, int line, int col)
|
||||||
{
|
{
|
||||||
for (const std::string &ext: mExtTokens) {
|
for (const std::string &ext: mExtTokens) {
|
||||||
if (startsWith(ext, "<col:"))
|
if (startsWith(ext, "<col:"))
|
||||||
|
@ -512,7 +512,7 @@ void clangimport::AstNode::setLocations(TokenList *tokenList, int file, int line
|
||||||
const bool windowsPath = colon == 2 && ext.size() > 3 && ext[2] == ':';
|
const bool windowsPath = colon == 2 && ext.size() > 3 && ext[2] == ':';
|
||||||
const std::string::size_type sep1 = windowsPath ? ext.find(':', 4) : colon;
|
const std::string::size_type sep1 = windowsPath ? ext.find(':', 4) : colon;
|
||||||
const std::string::size_type sep2 = ext.find(':', sep1 + 1);
|
const std::string::size_type sep2 = ext.find(':', sep1 + 1);
|
||||||
file = tokenList->appendFileIfNew(ext.substr(1, sep1 - 1));
|
file = tokenList.appendFileIfNew(ext.substr(1, sep1 - 1));
|
||||||
line = strToInt<int>(ext.substr(sep1 + 1, sep2 - sep1 - 1));
|
line = strToInt<int>(ext.substr(sep1 + 1, sep2 - sep1 - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,17 +526,17 @@ void clangimport::AstNode::setLocations(TokenList *tokenList, int file, int line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token *clangimport::AstNode::addtoken(TokenList *tokenList, const std::string &str, bool valueType)
|
Token *clangimport::AstNode::addtoken(TokenList &tokenList, const std::string &str, bool valueType)
|
||||||
{
|
{
|
||||||
const Scope *scope = getNestedInScope(tokenList);
|
const Scope *scope = getNestedInScope(tokenList);
|
||||||
tokenList->addtoken(str, mLine, mCol, mFile);
|
tokenList.addtoken(str, mLine, mCol, mFile);
|
||||||
tokenList->back()->scope(scope);
|
tokenList.back()->scope(scope);
|
||||||
if (valueType)
|
if (valueType)
|
||||||
setValueType(tokenList->back());
|
setValueType(tokenList.back());
|
||||||
return tokenList->back();
|
return tokenList.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope)
|
const ::Type * clangimport::AstNode::addTypeTokens(TokenList &tokenList, const std::string &str, const Scope *scope)
|
||||||
{
|
{
|
||||||
if (str.find("\':\'") != std::string::npos) {
|
if (str.find("\':\'") != std::string::npos) {
|
||||||
return addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1), scope);
|
return addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1), scope);
|
||||||
|
@ -574,11 +574,11 @@ const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const s
|
||||||
|
|
||||||
// Set Type
|
// Set Type
|
||||||
if (!scope) {
|
if (!scope) {
|
||||||
scope = tokenList->back() ? tokenList->back()->scope() : nullptr;
|
scope = tokenList.back() ? tokenList.back()->scope() : nullptr;
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
for (const Token *typeToken = tokenList->back(); Token::Match(typeToken, "&|*|%name%"); typeToken = typeToken->previous()) {
|
for (const Token *typeToken = tokenList.back(); Token::Match(typeToken, "&|*|%name%"); typeToken = typeToken->previous()) {
|
||||||
if (!typeToken->isName())
|
if (!typeToken->isName())
|
||||||
continue;
|
continue;
|
||||||
const ::Type *recordType = scope->check->findVariableType(scope, typeToken);
|
const ::Type *recordType = scope->check->findVariableType(scope, typeToken);
|
||||||
|
@ -590,12 +590,12 @@ const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const s
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clangimport::AstNode::addFullScopeNameTokens(TokenList *tokenList, const Scope *recordScope)
|
void clangimport::AstNode::addFullScopeNameTokens(TokenList &tokenList, const Scope *recordScope)
|
||||||
{
|
{
|
||||||
if (!recordScope)
|
if (!recordScope)
|
||||||
return;
|
return;
|
||||||
std::list<const Scope *> scopes;
|
std::list<const Scope *> scopes;
|
||||||
while (recordScope && recordScope != tokenList->back()->scope() && !recordScope->isExecutable()) {
|
while (recordScope && recordScope != tokenList.back()->scope() && !recordScope->isExecutable()) {
|
||||||
scopes.push_front(recordScope);
|
scopes.push_front(recordScope);
|
||||||
recordScope = recordScope->nestedIn;
|
recordScope = recordScope->nestedIn;
|
||||||
}
|
}
|
||||||
|
@ -607,13 +607,13 @@ void clangimport::AstNode::addFullScopeNameTokens(TokenList *tokenList, const Sc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Scope *clangimport::AstNode::getNestedInScope(TokenList *tokenList)
|
const Scope *clangimport::AstNode::getNestedInScope(TokenList &tokenList)
|
||||||
{
|
{
|
||||||
if (!tokenList->back())
|
if (!tokenList.back())
|
||||||
return &mData->mSymbolDatabase->scopeList.front();
|
return &mData->mSymbolDatabase->scopeList.front();
|
||||||
if (tokenList->back()->str() == "}" && mData->mNotScope.find(tokenList->back()) == mData->mNotScope.end())
|
if (tokenList.back()->str() == "}" && mData->mNotScope.find(tokenList.back()) == mData->mNotScope.end())
|
||||||
return tokenList->back()->scope()->nestedIn;
|
return tokenList.back()->scope()->nestedIn;
|
||||||
return tokenList->back()->scope();
|
return tokenList.back()->scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clangimport::AstNode::setValueType(Token *tok)
|
void clangimport::AstNode::setValueType(Token *tok)
|
||||||
|
@ -626,7 +626,7 @@ void clangimport::AstNode::setValueType(Token *tok)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TokenList decl(nullptr);
|
TokenList decl(nullptr);
|
||||||
addTypeTokens(&decl, type, tok->scope());
|
addTypeTokens(decl, type, tok->scope());
|
||||||
if (!decl.front())
|
if (!decl.front())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -638,17 +638,17 @@ void clangimport::AstNode::setValueType(Token *tok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def)
|
Scope *clangimport::AstNode::createScope(TokenList &tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def)
|
||||||
{
|
{
|
||||||
std::vector<AstNodePtr> children2{std::move(astNode)};
|
std::vector<AstNodePtr> children2{std::move(astNode)};
|
||||||
return createScope(tokenList, scopeType, children2, def);
|
return createScope(tokenList, scopeType, children2, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> & children2, const Token *def)
|
Scope *clangimport::AstNode::createScope(TokenList &tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> & children2, const Token *def)
|
||||||
{
|
{
|
||||||
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
|
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
|
||||||
|
|
||||||
Scope *nestedIn = const_cast<Scope *>(getNestedInScope(tokenList));
|
auto *nestedIn = const_cast<Scope *>(getNestedInScope(tokenList));
|
||||||
|
|
||||||
symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nestedIn);
|
symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nestedIn);
|
||||||
Scope *scope = &symbolDatabase->scopeList.back();
|
Scope *scope = &symbolDatabase->scopeList.back();
|
||||||
|
@ -682,7 +682,7 @@ Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope->bodyStart = addtoken(tokenList, "{");
|
scope->bodyStart = addtoken(tokenList, "{");
|
||||||
tokenList->back()->scope(scope);
|
tokenList.back()->scope(scope);
|
||||||
mData->scopeAccessControl[scope] = scope->defaultAccess();
|
mData->scopeAccessControl[scope] = scope->defaultAccess();
|
||||||
if (!children2.empty()) {
|
if (!children2.empty()) {
|
||||||
for (const AstNodePtr &astNode: children2) {
|
for (const AstNodePtr &astNode: children2) {
|
||||||
|
@ -700,7 +700,7 @@ Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType
|
||||||
astNode->createTokens(tokenList);
|
astNode->createTokens(tokenList);
|
||||||
if (scopeType == Scope::ScopeType::eEnum)
|
if (scopeType == Scope::ScopeType::eEnum)
|
||||||
astNode->addtoken(tokenList, ",");
|
astNode->addtoken(tokenList, ",");
|
||||||
else if (!Token::Match(tokenList->back(), "[;{}]"))
|
else if (!Token::Match(tokenList.back(), "[;{}]"))
|
||||||
astNode->addtoken(tokenList, ";");
|
astNode->addtoken(tokenList, ";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -710,7 +710,7 @@ Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
Token *clangimport::AstNode::createTokens(TokenList &tokenList)
|
||||||
{
|
{
|
||||||
if (nodeType == ArraySubscriptExpr) {
|
if (nodeType == ArraySubscriptExpr) {
|
||||||
Token *array = getChild(0)->createTokens(tokenList);
|
Token *array = getChild(0)->createTokens(tokenList);
|
||||||
|
@ -796,7 +796,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
if (nodeType == CompoundStmt) {
|
if (nodeType == CompoundStmt) {
|
||||||
for (const AstNodePtr& child: children) {
|
for (const AstNodePtr& child: children) {
|
||||||
child->createTokens(tokenList);
|
child->createTokens(tokenList);
|
||||||
if (!Token::Match(tokenList->back(), "[;{}]"))
|
if (!Token::Match(tokenList.back(), "[;{}]"))
|
||||||
child->addtoken(tokenList, ";");
|
child->addtoken(tokenList, ";");
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -818,14 +818,14 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
return getChild(0)->createTokens(tokenList);
|
return getChild(0)->createTokens(tokenList);
|
||||||
if (nodeType == CXXBoolLiteralExpr) {
|
if (nodeType == CXXBoolLiteralExpr) {
|
||||||
addtoken(tokenList, mExtTokens.back());
|
addtoken(tokenList, mExtTokens.back());
|
||||||
tokenList->back()->setValueType(new ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0));
|
tokenList.back()->setValueType(new ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0));
|
||||||
return tokenList->back();
|
return tokenList.back();
|
||||||
}
|
}
|
||||||
if (nodeType == CXXConstructExpr) {
|
if (nodeType == CXXConstructExpr) {
|
||||||
if (!children.empty())
|
if (!children.empty())
|
||||||
return getChild(0)->createTokens(tokenList);
|
return getChild(0)->createTokens(tokenList);
|
||||||
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
||||||
Token *type = tokenList->back();
|
Token *type = tokenList.back();
|
||||||
Token *par1 = addtoken(tokenList, "(");
|
Token *par1 = addtoken(tokenList, "(");
|
||||||
Token *par2 = addtoken(tokenList, ")");
|
Token *par2 = addtoken(tokenList, ")");
|
||||||
par1->link(par2);
|
par1->link(par2);
|
||||||
|
@ -866,7 +866,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!range)
|
if (!range)
|
||||||
throw InternalError(tokenList->back(), "Failed to import CXXForRangeStmt. Range?");
|
throw InternalError(tokenList.back(), "Failed to import CXXForRangeStmt. Range?");
|
||||||
Token *expr2 = range->createTokens(tokenList);
|
Token *expr2 = range->createTokens(tokenList);
|
||||||
Token *par2 = addtoken(tokenList, ")");
|
Token *par2 = addtoken(tokenList, ")");
|
||||||
|
|
||||||
|
@ -961,7 +961,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
}
|
}
|
||||||
if (nodeType == DoStmt) {
|
if (nodeType == DoStmt) {
|
||||||
addtoken(tokenList, "do");
|
addtoken(tokenList, "do");
|
||||||
createScope(tokenList, Scope::ScopeType::eDo, getChild(0), tokenList->back());
|
createScope(tokenList, Scope::ScopeType::eDo, getChild(0), tokenList.back());
|
||||||
Token *tok1 = addtoken(tokenList, "while");
|
Token *tok1 = addtoken(tokenList, "while");
|
||||||
Token *par1 = addtoken(tokenList, "(");
|
Token *par1 = addtoken(tokenList, "(");
|
||||||
Token *expr = children[1]->createTokens(tokenList);
|
Token *expr = children[1]->createTokens(tokenList);
|
||||||
|
@ -974,7 +974,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
}
|
}
|
||||||
if (nodeType == EnumConstantDecl) {
|
if (nodeType == EnumConstantDecl) {
|
||||||
Token *nameToken = addtoken(tokenList, getSpelling());
|
Token *nameToken = addtoken(tokenList, getSpelling());
|
||||||
Scope *scope = const_cast<Scope *>(nameToken->scope());
|
auto *scope = const_cast<Scope *>(nameToken->scope());
|
||||||
scope->enumeratorList.emplace_back(nameToken->scope());
|
scope->enumeratorList.emplace_back(nameToken->scope());
|
||||||
Enumerator *e = &scope->enumeratorList.back();
|
Enumerator *e = &scope->enumeratorList.back();
|
||||||
e->name = nameToken;
|
e->name = nameToken;
|
||||||
|
@ -1088,7 +1088,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
createScope(tokenList, Scope::ScopeType::eIf, thenCode, iftok);
|
createScope(tokenList, Scope::ScopeType::eIf, thenCode, iftok);
|
||||||
if (elseCode) {
|
if (elseCode) {
|
||||||
elseCode->addtoken(tokenList, "else");
|
elseCode->addtoken(tokenList, "else");
|
||||||
createScope(tokenList, Scope::ScopeType::eElse, elseCode, tokenList->back());
|
createScope(tokenList, Scope::ScopeType::eElse, elseCode, tokenList.back());
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1099,11 +1099,11 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
if (nodeType == InitListExpr) {
|
if (nodeType == InitListExpr) {
|
||||||
const Scope *scope = tokenList->back()->scope();
|
const Scope *scope = tokenList.back()->scope();
|
||||||
Token *start = addtoken(tokenList, "{");
|
Token *start = addtoken(tokenList, "{");
|
||||||
start->scope(scope);
|
start->scope(scope);
|
||||||
for (const AstNodePtr& child: children) {
|
for (const AstNodePtr& child: children) {
|
||||||
if (tokenList->back()->str() != "{")
|
if (tokenList.back()->str() != "{")
|
||||||
addtoken(tokenList, ",");
|
addtoken(tokenList, ",");
|
||||||
child->createTokens(tokenList);
|
child->createTokens(tokenList);
|
||||||
}
|
}
|
||||||
|
@ -1261,7 +1261,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
return addtoken(tokenList, "?" + nodeType + "?");
|
return addtoken(tokenList, "?" + nodeType + "?");
|
||||||
}
|
}
|
||||||
|
|
||||||
Token * clangimport::AstNode::createTokensCall(TokenList *tokenList)
|
Token * clangimport::AstNode::createTokensCall(TokenList &tokenList)
|
||||||
{
|
{
|
||||||
int firstParam;
|
int firstParam;
|
||||||
Token *f;
|
Token *f;
|
||||||
|
@ -1302,7 +1302,7 @@ Token * clangimport::AstNode::createTokensCall(TokenList *tokenList)
|
||||||
return par1;
|
return par1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
void clangimport::AstNode::createTokensFunctionDecl(TokenList &tokenList)
|
||||||
{
|
{
|
||||||
const bool prev = contains(mExtTokens, "prev");
|
const bool prev = contains(mExtTokens, "prev");
|
||||||
const bool hasBody = !children.empty() && children.back()->nodeType == CompoundStmt;
|
const bool hasBody = !children.empty() && children.back()->nodeType == CompoundStmt;
|
||||||
|
@ -1317,16 +1317,16 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
||||||
addtoken(tokenList, "static");
|
addtoken(tokenList, "static");
|
||||||
if (isInline)
|
if (isInline)
|
||||||
addtoken(tokenList, "inline");
|
addtoken(tokenList, "inline");
|
||||||
const Token * const before = tokenList->back();
|
const Token * const before = tokenList.back();
|
||||||
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
||||||
startToken = before ? before->next() : tokenList->front();
|
startToken = before ? before->next() : tokenList.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExtTokens.size() > 4 && mExtTokens[1] == "parent")
|
if (mExtTokens.size() > 4 && mExtTokens[1] == "parent")
|
||||||
addFullScopeNameTokens(tokenList, mData->getScope(mExtTokens[2]));
|
addFullScopeNameTokens(tokenList, mData->getScope(mExtTokens[2]));
|
||||||
|
|
||||||
Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
|
Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
|
||||||
Scope *nestedIn = const_cast<Scope *>(nameToken->scope());
|
auto *nestedIn = const_cast<Scope *>(nameToken->scope());
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
const std::string addr = *(std::find(mExtTokens.cbegin(), mExtTokens.cend(), "prev") + 1);
|
const std::string addr = *(std::find(mExtTokens.cbegin(), mExtTokens.cend(), "prev") + 1);
|
||||||
|
@ -1343,10 +1343,10 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
||||||
nestedIn->functionList.back().retDef = startToken;
|
nestedIn->functionList.back().retDef = startToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
Function * const function = const_cast<Function*>(nameToken->function());
|
auto * const function = const_cast<Function*>(nameToken->function());
|
||||||
|
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
auto accessControl = mData->scopeAccessControl.find(tokenList->back()->scope());
|
auto accessControl = mData->scopeAccessControl.find(tokenList.back()->scope());
|
||||||
if (accessControl != mData->scopeAccessControl.end())
|
if (accessControl != mData->scopeAccessControl.end())
|
||||||
function->access = accessControl->second;
|
function->access = accessControl->second;
|
||||||
}
|
}
|
||||||
|
@ -1377,10 +1377,10 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
||||||
AstNodePtr child = children[i];
|
AstNodePtr child = children[i];
|
||||||
if (child->nodeType != ParmVarDecl)
|
if (child->nodeType != ParmVarDecl)
|
||||||
continue;
|
continue;
|
||||||
if (tokenList->back() != par1)
|
if (tokenList.back() != par1)
|
||||||
addtoken(tokenList, ",");
|
addtoken(tokenList, ",");
|
||||||
const Type *recordType = addTypeTokens(tokenList, child->mExtTokens.back(), nestedIn);
|
const Type *recordType = addTypeTokens(tokenList, child->mExtTokens.back(), nestedIn);
|
||||||
const Token *typeEndToken = tokenList->back();
|
const Token *typeEndToken = tokenList.back();
|
||||||
const std::string spelling = child->getSpelling();
|
const std::string spelling = child->getSpelling();
|
||||||
Token *vartok = nullptr;
|
Token *vartok = nullptr;
|
||||||
if (!spelling.empty())
|
if (!spelling.empty())
|
||||||
|
@ -1424,7 +1424,7 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clangimport::AstNode::createTokensForCXXRecord(TokenList *tokenList)
|
void clangimport::AstNode::createTokensForCXXRecord(TokenList &tokenList)
|
||||||
{
|
{
|
||||||
const bool isStruct = contains(mExtTokens, "struct");
|
const bool isStruct = contains(mExtTokens, "struct");
|
||||||
Token * const classToken = addtoken(tokenList, isStruct ? "struct" : "class");
|
Token * const classToken = addtoken(tokenList, isStruct ? "struct" : "class");
|
||||||
|
@ -1466,10 +1466,10 @@ void clangimport::AstNode::createTokensForCXXRecord(TokenList *tokenList)
|
||||||
const_cast<Scope *>(classToken->scope())->definedTypesMap[className] = scope->definedType;
|
const_cast<Scope *>(classToken->scope())->definedTypesMap[className] = scope->definedType;
|
||||||
}
|
}
|
||||||
addtoken(tokenList, ";");
|
addtoken(tokenList, ";");
|
||||||
const_cast<Token *>(tokenList->back())->scope(classToken->scope());
|
const_cast<Token *>(tokenList.back())->scope(classToken->scope());
|
||||||
}
|
}
|
||||||
|
|
||||||
Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
|
Token * clangimport::AstNode::createTokensVarDecl(TokenList &tokenList)
|
||||||
{
|
{
|
||||||
const std::string addr = mExtTokens.front();
|
const std::string addr = mExtTokens.front();
|
||||||
if (contains(mExtTokens, "static"))
|
if (contains(mExtTokens, "static"))
|
||||||
|
@ -1479,14 +1479,14 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
|
||||||
typeIndex--;
|
typeIndex--;
|
||||||
const std::string type = mExtTokens[typeIndex];
|
const std::string type = mExtTokens[typeIndex];
|
||||||
const std::string name = mExtTokens[typeIndex - 1];
|
const std::string name = mExtTokens[typeIndex - 1];
|
||||||
const Token *startToken = tokenList->back();
|
const Token *startToken = tokenList.back();
|
||||||
const ::Type *recordType = addTypeTokens(tokenList, type);
|
const ::Type *recordType = addTypeTokens(tokenList, type);
|
||||||
if (!startToken)
|
if (!startToken)
|
||||||
startToken = tokenList->front();
|
startToken = tokenList.front();
|
||||||
else if (startToken->str() != "static")
|
else if (startToken->str() != "static")
|
||||||
startToken = startToken->next();
|
startToken = startToken->next();
|
||||||
Token *vartok1 = addtoken(tokenList, name);
|
Token *vartok1 = addtoken(tokenList, name);
|
||||||
Scope *scope = const_cast<Scope *>(tokenList->back()->scope());
|
auto *scope = const_cast<Scope *>(tokenList.back()->scope());
|
||||||
scope->varlist.emplace_back(vartok1, unquote(type), startToken, vartok1->previous(), 0, scope->defaultAccess(), recordType, scope);
|
scope->varlist.emplace_back(vartok1, unquote(type), startToken, vartok1->previous(), 0, scope->defaultAccess(), recordType, scope);
|
||||||
mData->varDecl(addr, vartok1, &scope->varlist.back());
|
mData->varDecl(addr, vartok1, &scope->varlist.back());
|
||||||
if (mExtTokens.back() == "cinit" && !children.empty()) {
|
if (mExtTokens.back() == "cinit" && !children.empty()) {
|
||||||
|
@ -1510,9 +1510,9 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
|
||||||
return vartok1;
|
return vartok1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setTypes(TokenList *tokenList)
|
static void setTypes(TokenList &tokenList)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenList->front(); tok; tok = tok->next()) {
|
for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "sizeof (")) {
|
if (Token::simpleMatch(tok, "sizeof (")) {
|
||||||
for (Token *typeToken = tok->tokAt(2); typeToken->str() != ")"; typeToken = typeToken->next()) {
|
for (Token *typeToken = tok->tokAt(2); typeToken->str() != ")"; typeToken = typeToken->next()) {
|
||||||
if (typeToken->type())
|
if (typeToken->type())
|
||||||
|
@ -1523,9 +1523,9 @@ static void setTypes(TokenList *tokenList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setValues(const Tokenizer *tokenizer, const SymbolDatabase *symbolDatabase)
|
static void setValues(const Tokenizer &tokenizer, const SymbolDatabase *symbolDatabase)
|
||||||
{
|
{
|
||||||
const Settings * const settings = tokenizer->getSettings();
|
const Settings * const settings = tokenizer.getSettings();
|
||||||
|
|
||||||
for (const Scope& scope : symbolDatabase->scopeList) {
|
for (const Scope& scope : symbolDatabase->scopeList) {
|
||||||
if (!scope.definedType)
|
if (!scope.definedType)
|
||||||
|
@ -1542,7 +1542,7 @@ static void setValues(const Tokenizer *tokenizer, const SymbolDatabase *symbolDa
|
||||||
scope.definedType->sizeOf = typeSize;
|
scope.definedType->sizeOf = typeSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Token *tok = const_cast<Token*>(tokenizer->tokens()); tok; tok = tok->next()) {
|
for (auto *tok = const_cast<Token*>(tokenizer.tokens()); tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "sizeof (")) {
|
if (Token::simpleMatch(tok, "sizeof (")) {
|
||||||
ValueType vt = ValueType::parseDecl(tok->tokAt(2), *settings);
|
ValueType vt = ValueType::parseDecl(tok->tokAt(2), *settings);
|
||||||
const int sz = vt.typeSize(settings->platform, true);
|
const int sz = vt.typeSize(settings->platform, true);
|
||||||
|
@ -1563,18 +1563,18 @@ static void setValues(const Tokenizer *tokenizer, const SymbolDatabase *symbolDa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
void clangimport::parseClangAstDump(Tokenizer &tokenizer, std::istream &f)
|
||||||
{
|
{
|
||||||
TokenList *tokenList = &tokenizer->list;
|
TokenList &tokenList = tokenizer.list;
|
||||||
|
|
||||||
tokenizer->createSymbolDatabase();
|
tokenizer.createSymbolDatabase();
|
||||||
SymbolDatabase *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer->getSymbolDatabase());
|
auto *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer.getSymbolDatabase());
|
||||||
symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nullptr);
|
symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nullptr);
|
||||||
symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
|
symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
|
||||||
symbolDatabase->scopeList.back().check = symbolDatabase;
|
symbolDatabase->scopeList.back().check = symbolDatabase;
|
||||||
|
|
||||||
clangimport::Data data;
|
clangimport::Data data;
|
||||||
data.mSettings = tokenizer->getSettings();
|
data.mSettings = tokenizer.getSettings();
|
||||||
data.mSymbolDatabase = symbolDatabase;
|
data.mSymbolDatabase = symbolDatabase;
|
||||||
std::string line;
|
std::string line;
|
||||||
std::vector<AstNodePtr> tree;
|
std::vector<AstNodePtr> tree;
|
||||||
|
@ -1617,16 +1617,16 @@ void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
||||||
tree[0]->createTokens1(tokenList);
|
tree[0]->createTokens1(tokenList);
|
||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
for (const Token *tok = tokenList->front(); tok; tok = tok->next()) {
|
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "(|)|[|]|{|}") && !tok->link())
|
if (Token::Match(tok, "(|)|[|]|{|}") && !tok->link())
|
||||||
throw InternalError(tok, "Token::link() is not set properly");
|
throw InternalError(tok, "Token::link() is not set properly");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenList->front())
|
if (tokenList.front())
|
||||||
tokenList->front()->assignIndexes();
|
tokenList.front()->assignIndexes();
|
||||||
symbolDatabase->clangSetVariables(data.getVariableList());
|
symbolDatabase->clangSetVariables(data.getVariableList());
|
||||||
symbolDatabase->createSymbolDatabaseExprIds();
|
symbolDatabase->createSymbolDatabaseExprIds();
|
||||||
tokenList->clangSetOrigFiles();
|
tokenList.clangSetOrigFiles();
|
||||||
setTypes(tokenList);
|
setTypes(tokenList);
|
||||||
setValues(tokenizer, symbolDatabase);
|
setValues(tokenizer, symbolDatabase);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
class Tokenizer;
|
class Tokenizer;
|
||||||
|
|
||||||
namespace clangimport {
|
namespace clangimport {
|
||||||
void CPPCHECKLIB parseClangAstDump(Tokenizer *tokenizer, std::istream &f);
|
void CPPCHECKLIB parseClangAstDump(Tokenizer &tokenizer, std::istream &f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
227
lib/cppcheck.cpp
227
lib/cppcheck.cpp
|
@ -188,13 +188,13 @@ static void createDumpFile(const Settings& settings,
|
||||||
|
|
||||||
std::string language;
|
std::string language;
|
||||||
switch (settings.enforcedLang) {
|
switch (settings.enforcedLang) {
|
||||||
case Settings::Language::C:
|
case Standards::Language::C:
|
||||||
language = " language=\"c\"";
|
language = " language=\"c\"";
|
||||||
break;
|
break;
|
||||||
case Settings::Language::CPP:
|
case Standards::Language::CPP:
|
||||||
language = " language=\"cpp\"";
|
language = " language=\"cpp\"";
|
||||||
break;
|
break;
|
||||||
case Settings::Language::None:
|
case Standards::Language::None:
|
||||||
if (Path::isCPP(filename))
|
if (Path::isCPP(filename))
|
||||||
language = " language=\"cpp\"";
|
language = " language=\"cpp\"";
|
||||||
else if (Path::isC(filename))
|
else if (Path::isC(filename))
|
||||||
|
@ -423,120 +423,127 @@ static bool reportClangErrors(std::istream &is, const std::function<void(const E
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CppCheck::check(const std::string &path)
|
unsigned int CppCheck::checkClang(const std::string &path)
|
||||||
{
|
{
|
||||||
if (mSettings.clang) {
|
if (!mSettings.quiet)
|
||||||
if (!mSettings.quiet)
|
mErrorLogger.reportOut(std::string("Checking ") + path + " ...", Color::FgGreen);
|
||||||
mErrorLogger.reportOut(std::string("Checking ") + path + " ...", Color::FgGreen);
|
|
||||||
|
|
||||||
const std::string lang = Path::isCPP(path) ? "-x c++" : "-x c";
|
// TODO: this ignores the configured language
|
||||||
const std::string analyzerInfo = mSettings.buildDir.empty() ? std::string() : AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, path, emptyString);
|
const std::string lang = Path::isCPP(path) ? "-x c++" : "-x c";
|
||||||
const std::string clangcmd = analyzerInfo + ".clang-cmd";
|
const std::string analyzerInfo = mSettings.buildDir.empty() ? std::string() : AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, path, emptyString);
|
||||||
const std::string clangStderr = analyzerInfo + ".clang-stderr";
|
const std::string clangcmd = analyzerInfo + ".clang-cmd";
|
||||||
const std::string clangAst = analyzerInfo + ".clang-ast";
|
const std::string clangStderr = analyzerInfo + ".clang-stderr";
|
||||||
std::string exe = mSettings.clangExecutable;
|
const std::string clangAst = analyzerInfo + ".clang-ast";
|
||||||
|
std::string exe = mSettings.clangExecutable;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// append .exe if it is not a path
|
// append .exe if it is not a path
|
||||||
if (Path::fromNativeSeparators(mSettings.clangExecutable).find('/') == std::string::npos) {
|
if (Path::fromNativeSeparators(mSettings.clangExecutable).find('/') == std::string::npos) {
|
||||||
exe += ".exe";
|
exe += ".exe";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string flags(lang + " ");
|
std::string flags(lang + " ");
|
||||||
if (Path::isCPP(path) && !mSettings.standards.stdValue.empty())
|
// TODO: does not apply C standard
|
||||||
flags += "-std=" + mSettings.standards.stdValue + " ";
|
if (Path::isCPP(path) && !mSettings.standards.stdValue.empty())
|
||||||
|
flags += "-std=" + mSettings.standards.stdValue + " ";
|
||||||
|
|
||||||
for (const std::string &i: mSettings.includePaths)
|
for (const std::string &i: mSettings.includePaths)
|
||||||
flags += "-I" + i + " ";
|
flags += "-I" + i + " ";
|
||||||
|
|
||||||
flags += getDefinesFlags(mSettings.userDefines);
|
flags += getDefinesFlags(mSettings.userDefines);
|
||||||
|
|
||||||
const std::string args2 = "-fsyntax-only -Xclang -ast-dump -fno-color-diagnostics " + flags + path;
|
const std::string args2 = "-fsyntax-only -Xclang -ast-dump -fno-color-diagnostics " + flags + path;
|
||||||
const std::string redirect2 = analyzerInfo.empty() ? std::string("2>&1") : ("2> " + clangStderr);
|
const std::string redirect2 = analyzerInfo.empty() ? std::string("2>&1") : ("2> " + clangStderr);
|
||||||
if (!mSettings.buildDir.empty()) {
|
if (!mSettings.buildDir.empty()) {
|
||||||
std::ofstream fout(clangcmd);
|
std::ofstream fout(clangcmd);
|
||||||
fout << exe << " " << args2 << " " << redirect2 << std::endl;
|
fout << exe << " " << args2 << " " << redirect2 << std::endl;
|
||||||
} else if (mSettings.verbose && !mSettings.quiet) {
|
} else if (mSettings.verbose && !mSettings.quiet) {
|
||||||
mErrorLogger.reportOut(exe + " " + args2);
|
mErrorLogger.reportOut(exe + " " + args2);
|
||||||
}
|
|
||||||
|
|
||||||
std::string output2;
|
|
||||||
if (mExecuteCommand(exe,split(args2),redirect2,output2) != EXIT_SUCCESS || output2.find("TranslationUnitDecl") == std::string::npos) {
|
|
||||||
std::cerr << "Failed to execute '" << exe << " " << args2 << " " << redirect2 << "'" << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure there are not syntax errors...
|
|
||||||
std::vector<ErrorMessage> compilerWarnings;
|
|
||||||
if (!mSettings.buildDir.empty()) {
|
|
||||||
std::ifstream fin(clangStderr);
|
|
||||||
auto reportError = [this](const ErrorMessage& errorMessage) {
|
|
||||||
reportErr(errorMessage);
|
|
||||||
};
|
|
||||||
if (reportClangErrors(fin, reportError, compilerWarnings))
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
std::istringstream istr(output2);
|
|
||||||
auto reportError = [this](const ErrorMessage& errorMessage) {
|
|
||||||
reportErr(errorMessage);
|
|
||||||
};
|
|
||||||
if (reportClangErrors(istr, reportError, compilerWarnings))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mSettings.buildDir.empty()) {
|
|
||||||
std::ofstream fout(clangAst);
|
|
||||||
fout << output2 << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
std::istringstream ast(output2);
|
|
||||||
Tokenizer tokenizer(&mSettings, this);
|
|
||||||
tokenizer.list.appendFileIfNew(path);
|
|
||||||
clangimport::parseClangAstDump(&tokenizer, ast);
|
|
||||||
ValueFlow::setValues(tokenizer.list,
|
|
||||||
const_cast<SymbolDatabase&>(*tokenizer.getSymbolDatabase()),
|
|
||||||
this,
|
|
||||||
&mSettings,
|
|
||||||
&s_timerResults);
|
|
||||||
if (mSettings.debugnormal)
|
|
||||||
tokenizer.printDebugOutput(1);
|
|
||||||
checkNormalTokens(tokenizer);
|
|
||||||
|
|
||||||
// create dumpfile
|
|
||||||
std::ofstream fdump;
|
|
||||||
std::string dumpFile;
|
|
||||||
createDumpFile(mSettings, path, fdump, dumpFile);
|
|
||||||
if (fdump.is_open()) {
|
|
||||||
fdump << "<dump cfg=\"\">\n";
|
|
||||||
for (const ErrorMessage& errmsg: compilerWarnings)
|
|
||||||
fdump << " <clang-warning file=\"" << toxml(errmsg.callStack.front().getfile()) << "\" line=\"" << errmsg.callStack.front().line << "\" column=\"" << errmsg.callStack.front().column << "\" message=\"" << toxml(errmsg.shortMessage()) << "\"/>\n";
|
|
||||||
fdump << " <standards>\n";
|
|
||||||
fdump << " <c version=\"" << mSettings.standards.getC() << "\"/>\n";
|
|
||||||
fdump << " <cpp version=\"" << mSettings.standards.getCPP() << "\"/>\n";
|
|
||||||
fdump << " </standards>\n";
|
|
||||||
tokenizer.dump(fdump);
|
|
||||||
fdump << "</dump>\n";
|
|
||||||
fdump << "</dumps>\n";
|
|
||||||
fdump.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// run addons
|
|
||||||
executeAddons(dumpFile, path);
|
|
||||||
|
|
||||||
} catch (const InternalError &e) {
|
|
||||||
const ErrorMessage errmsg = ErrorMessage::fromInternalError(e, nullptr, path, "Bailing out from analysis: Processing Clang AST dump failed");
|
|
||||||
reportErr(errmsg);
|
|
||||||
} catch (const TerminateException &) {
|
|
||||||
// Analysis is terminated
|
|
||||||
return mExitCode;
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
internalError(path, std::string("Processing Clang AST dump failed: ") + e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
return mExitCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string output2;
|
||||||
|
if (mExecuteCommand(exe,split(args2),redirect2,output2) != EXIT_SUCCESS || output2.find("TranslationUnitDecl") == std::string::npos) {
|
||||||
|
std::cerr << "Failed to execute '" << exe << " " << args2 << " " << redirect2 << "'" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure there are not syntax errors...
|
||||||
|
std::vector<ErrorMessage> compilerWarnings;
|
||||||
|
if (!mSettings.buildDir.empty()) {
|
||||||
|
std::ifstream fin(clangStderr);
|
||||||
|
auto reportError = [this](const ErrorMessage& errorMessage) {
|
||||||
|
reportErr(errorMessage);
|
||||||
|
};
|
||||||
|
if (reportClangErrors(fin, reportError, compilerWarnings))
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
std::istringstream istr(output2);
|
||||||
|
auto reportError = [this](const ErrorMessage& errorMessage) {
|
||||||
|
reportErr(errorMessage);
|
||||||
|
};
|
||||||
|
if (reportClangErrors(istr, reportError, compilerWarnings))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSettings.buildDir.empty()) {
|
||||||
|
std::ofstream fout(clangAst);
|
||||||
|
fout << output2 << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::istringstream ast(output2);
|
||||||
|
Tokenizer tokenizer(&mSettings, this);
|
||||||
|
tokenizer.list.appendFileIfNew(path);
|
||||||
|
clangimport::parseClangAstDump(tokenizer, ast);
|
||||||
|
ValueFlow::setValues(tokenizer.list,
|
||||||
|
const_cast<SymbolDatabase&>(*tokenizer.getSymbolDatabase()),
|
||||||
|
this,
|
||||||
|
&mSettings,
|
||||||
|
&s_timerResults);
|
||||||
|
if (mSettings.debugnormal)
|
||||||
|
tokenizer.printDebugOutput(1);
|
||||||
|
checkNormalTokens(tokenizer);
|
||||||
|
|
||||||
|
// create dumpfile
|
||||||
|
std::ofstream fdump;
|
||||||
|
std::string dumpFile;
|
||||||
|
createDumpFile(mSettings, path, fdump, dumpFile);
|
||||||
|
if (fdump.is_open()) {
|
||||||
|
// TODO: use tinyxml2 to create XML
|
||||||
|
fdump << "<dump cfg=\"\">\n";
|
||||||
|
for (const ErrorMessage& errmsg: compilerWarnings)
|
||||||
|
fdump << " <clang-warning file=\"" << toxml(errmsg.callStack.front().getfile()) << "\" line=\"" << errmsg.callStack.front().line << "\" column=\"" << errmsg.callStack.front().column << "\" message=\"" << toxml(errmsg.shortMessage()) << "\"/>\n";
|
||||||
|
fdump << " <standards>\n";
|
||||||
|
fdump << " <c version=\"" << mSettings.standards.getC() << "\"/>\n";
|
||||||
|
fdump << " <cpp version=\"" << mSettings.standards.getCPP() << "\"/>\n";
|
||||||
|
fdump << " </standards>\n";
|
||||||
|
tokenizer.dump(fdump);
|
||||||
|
fdump << "</dump>\n";
|
||||||
|
fdump << "</dumps>\n";
|
||||||
|
fdump.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// run addons
|
||||||
|
executeAddons(dumpFile, path);
|
||||||
|
|
||||||
|
} catch (const InternalError &e) {
|
||||||
|
const ErrorMessage errmsg = ErrorMessage::fromInternalError(e, nullptr, path, "Bailing out from analysis: Processing Clang AST dump failed");
|
||||||
|
reportErr(errmsg);
|
||||||
|
} catch (const TerminateException &) {
|
||||||
|
// Analysis is terminated
|
||||||
|
return mExitCode;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
internalError(path, std::string("Processing Clang AST dump failed: ") + e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return mExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CppCheck::check(const std::string &path)
|
||||||
|
{
|
||||||
|
if (mSettings.clang)
|
||||||
|
return checkClang(path);
|
||||||
|
|
||||||
return checkFile(Path::simplifyPath(path), emptyString);
|
return checkFile(Path::simplifyPath(path), emptyString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1347,8 +1354,8 @@ void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &token
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const unsigned int pos1 = (unsigned int)ovector[0];
|
const auto pos1 = (unsigned int)ovector[0];
|
||||||
const unsigned int pos2 = (unsigned int)ovector[1];
|
const auto pos2 = (unsigned int)ovector[1];
|
||||||
|
|
||||||
// jump to the end of the match for the next pcre_exec
|
// jump to the end of the match for the next pcre_exec
|
||||||
pos = (int)pos2;
|
pos = (int)pos2;
|
||||||
|
@ -1751,7 +1758,7 @@ bool CppCheck::analyseWholeProgram()
|
||||||
// Analyse the tokens
|
// Analyse the tokens
|
||||||
CTU::FileInfo ctu;
|
CTU::FileInfo ctu;
|
||||||
for (const Check::FileInfo *fi : mFileInfo) {
|
for (const Check::FileInfo *fi : mFileInfo) {
|
||||||
const CTU::FileInfo *fi2 = dynamic_cast<const CTU::FileInfo *>(fi);
|
const auto *fi2 = dynamic_cast<const CTU::FileInfo *>(fi);
|
||||||
if (fi2) {
|
if (fi2) {
|
||||||
ctu.functionCalls.insert(ctu.functionCalls.end(), fi2->functionCalls.cbegin(), fi2->functionCalls.cend());
|
ctu.functionCalls.insert(ctu.functionCalls.end(), fi2->functionCalls.cbegin(), fi2->functionCalls.cend());
|
||||||
ctu.nestedCalls.insert(ctu.nestedCalls.end(), fi2->nestedCalls.cbegin(), fi2->nestedCalls.cend());
|
ctu.nestedCalls.insert(ctu.nestedCalls.end(), fi2->nestedCalls.cbegin(), fi2->nestedCalls.cend());
|
||||||
|
|
|
@ -200,6 +200,8 @@ private:
|
||||||
void executeRules(const std::string &tokenlist, const Tokenizer &tokenizer);
|
void executeRules(const std::string &tokenlist, const Tokenizer &tokenizer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned int checkClang(const std::string &path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Errors and warnings are directed here.
|
* @brief Errors and warnings are directed here.
|
||||||
*
|
*
|
||||||
|
|
|
@ -309,7 +309,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer)
|
||||||
{
|
{
|
||||||
const SymbolDatabase * const symbolDatabase = tokenizer->getSymbolDatabase();
|
const SymbolDatabase * const symbolDatabase = tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
FileInfo *fileInfo = new FileInfo;
|
auto *fileInfo = new FileInfo;
|
||||||
|
|
||||||
// Parse all functions in TU
|
// Parse all functions in TU
|
||||||
for (const Scope &scope : symbolDatabase->scopeList) {
|
for (const Scope &scope : symbolDatabase->scopeList) {
|
||||||
|
@ -513,7 +513,7 @@ static bool findPath(const std::string &callId,
|
||||||
if (c->callArgNr != callArgNr)
|
if (c->callArgNr != callArgNr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const CTU::FileInfo::FunctionCall *functionCall = dynamic_cast<const CTU::FileInfo::FunctionCall *>(c);
|
const auto *functionCall = dynamic_cast<const CTU::FileInfo::FunctionCall *>(c);
|
||||||
if (functionCall) {
|
if (functionCall) {
|
||||||
if (!warning && functionCall->warning)
|
if (!warning && functionCall->warning)
|
||||||
continue;
|
continue;
|
||||||
|
@ -537,7 +537,7 @@ static bool findPath(const std::string &callId,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CTU::FileInfo::NestedCall *nestedCall = dynamic_cast<const CTU::FileInfo::NestedCall *>(c);
|
const auto *nestedCall = dynamic_cast<const CTU::FileInfo::NestedCall *>(c);
|
||||||
if (!nestedCall)
|
if (!nestedCall)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ std::list<ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(InvalidValueTy
|
||||||
if (!path[index])
|
if (!path[index])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const CTU::FileInfo::FunctionCall *functionCall = dynamic_cast<const CTU::FileInfo::FunctionCall *>(path[index]);
|
const auto *functionCall = dynamic_cast<const CTU::FileInfo::FunctionCall *>(path[index]);
|
||||||
|
|
||||||
if (functionCall) {
|
if (functionCall) {
|
||||||
if (functionCallPtr)
|
if (functionCallPtr)
|
||||||
|
|
|
@ -31,14 +31,17 @@ struct CPPCHECKLIB FileSettings {
|
||||||
std::string cfg;
|
std::string cfg;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string defines;
|
std::string defines;
|
||||||
|
// TODO: handle differently
|
||||||
std::string cppcheckDefines() const {
|
std::string cppcheckDefines() const {
|
||||||
return defines + (msc ? ";_MSC_VER=1900" : "") + (useMfc ? ";__AFXWIN_H__=1" : "");
|
return defines + (msc ? ";_MSC_VER=1900" : "") + (useMfc ? ";__AFXWIN_H__=1" : "");
|
||||||
}
|
}
|
||||||
std::set<std::string> undefs;
|
std::set<std::string> undefs;
|
||||||
std::list<std::string> includePaths;
|
std::list<std::string> includePaths;
|
||||||
|
// only used by clang mode
|
||||||
std::list<std::string> systemIncludePaths;
|
std::list<std::string> systemIncludePaths;
|
||||||
std::string standard;
|
std::string standard;
|
||||||
Platform::Type platformType = Platform::Type::Unspecified;
|
Platform::Type platformType = Platform::Type::Unspecified;
|
||||||
|
// TODO: get rid of these
|
||||||
bool msc{};
|
bool msc{};
|
||||||
bool useMfc{};
|
bool useMfc{};
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,10 +26,12 @@
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "valueptr.h"
|
#include "valueptr.h"
|
||||||
#include "vfvalue.h"
|
#include "vfvalue.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -443,7 +445,7 @@ namespace {
|
||||||
if (checkElse && isDoWhile &&
|
if (checkElse && isDoWhile &&
|
||||||
(condTok->hasKnownIntValue() ||
|
(condTok->hasKnownIntValue() ||
|
||||||
(!bodyAnalysis.isModified() && !condAnalysis.isModified() && condAnalysis.isRead()))) {
|
(!bodyAnalysis.isModified() && !condAnalysis.isModified() && condAnalysis.isRead()))) {
|
||||||
if (updateRange(endBlock->link(), endBlock) == Progress::Break)
|
if (updateScope(endBlock) == Progress::Break)
|
||||||
return Break();
|
return Break();
|
||||||
return updateRecursive(condTok);
|
return updateRecursive(condTok);
|
||||||
}
|
}
|
||||||
|
@ -519,8 +521,17 @@ namespace {
|
||||||
return updateLoop(endToken, endBlock, condTok, initTok, stepTok, true);
|
return updateLoop(endToken, endBlock, condTok, initTok, stepTok, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Progress updateScope(Token* endBlock) {
|
Progress updateScope(Token* endBlock, int depth = 20)
|
||||||
return updateRange(endBlock->link(), endBlock);
|
{
|
||||||
|
if (!endBlock)
|
||||||
|
return Break();
|
||||||
|
assert(endBlock->link());
|
||||||
|
Token* ctx = endBlock->link()->previous();
|
||||||
|
if (Token::simpleMatch(ctx, ")"))
|
||||||
|
ctx = ctx->link()->previous();
|
||||||
|
if (ctx)
|
||||||
|
analyzer->updateState(ctx);
|
||||||
|
return updateRange(endBlock->link(), endBlock, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Progress updateRange(Token* start, const Token* end, int depth = 20) {
|
Progress updateRange(Token* start, const Token* end, int depth = 20) {
|
||||||
|
@ -682,7 +693,7 @@ namespace {
|
||||||
thenBranch.escape = isEscapeScope(endBlock, thenBranch.escapeUnknown);
|
thenBranch.escape = isEscapeScope(endBlock, thenBranch.escapeUnknown);
|
||||||
if (thenBranch.check) {
|
if (thenBranch.check) {
|
||||||
thenBranch.active = true;
|
thenBranch.active = true;
|
||||||
if (updateRange(endCond->next(), endBlock, depth - 1) == Progress::Break)
|
if (updateScope(endBlock, depth - 1) == Progress::Break)
|
||||||
return Break();
|
return Break();
|
||||||
} else if (!elseBranch.check) {
|
} else if (!elseBranch.check) {
|
||||||
thenBranch.active = true;
|
thenBranch.active = true;
|
||||||
|
@ -694,7 +705,7 @@ namespace {
|
||||||
elseBranch.escape = isEscapeScope(endBlock->linkAt(2), elseBranch.escapeUnknown);
|
elseBranch.escape = isEscapeScope(endBlock->linkAt(2), elseBranch.escapeUnknown);
|
||||||
if (elseBranch.check) {
|
if (elseBranch.check) {
|
||||||
elseBranch.active = true;
|
elseBranch.active = true;
|
||||||
const Progress result = updateRange(endBlock->tokAt(2), endBlock->linkAt(2), depth - 1);
|
const Progress result = updateScope(endBlock->linkAt(2), depth - 1);
|
||||||
if (result == Progress::Break)
|
if (result == Progress::Break)
|
||||||
return Break();
|
return Break();
|
||||||
} else if (!thenBranch.check) {
|
} else if (!thenBranch.check) {
|
||||||
|
@ -746,7 +757,7 @@ namespace {
|
||||||
} else if (Token::simpleMatch(tok, "try {")) {
|
} else if (Token::simpleMatch(tok, "try {")) {
|
||||||
Token* endBlock = tok->next()->link();
|
Token* endBlock = tok->next()->link();
|
||||||
ForwardTraversal tryTraversal = fork();
|
ForwardTraversal tryTraversal = fork();
|
||||||
tryTraversal.updateRange(tok->next(), endBlock, depth - 1);
|
tryTraversal.updateScope(endBlock, depth - 1);
|
||||||
bool bail = tryTraversal.actions.isModified();
|
bool bail = tryTraversal.actions.isModified();
|
||||||
if (bail) {
|
if (bail) {
|
||||||
actions = tryTraversal.actions;
|
actions = tryTraversal.actions;
|
||||||
|
@ -760,7 +771,7 @@ namespace {
|
||||||
return Break();
|
return Break();
|
||||||
endBlock = endCatch->linkAt(1);
|
endBlock = endCatch->linkAt(1);
|
||||||
ForwardTraversal ft = fork();
|
ForwardTraversal ft = fork();
|
||||||
ft.updateRange(endBlock->link(), endBlock, depth - 1);
|
ft.updateScope(endBlock, depth - 1);
|
||||||
bail |= ft.terminate != Analyzer::Terminate::None || ft.actions.isModified();
|
bail |= ft.terminate != Analyzer::Terminate::None || ft.actions.isModified();
|
||||||
}
|
}
|
||||||
if (bail)
|
if (bail)
|
||||||
|
@ -880,6 +891,8 @@ Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const V
|
||||||
if (a->invalid())
|
if (a->invalid())
|
||||||
return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail};
|
return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail};
|
||||||
ForwardTraversal ft{a, settings};
|
ForwardTraversal ft{a, settings};
|
||||||
|
if (start)
|
||||||
|
ft.analyzer->updateState(start);
|
||||||
ft.updateRange(start, end);
|
ft.updateRange(start, end);
|
||||||
return Analyzer::Result{ ft.actions, ft.terminate };
|
return Analyzer::Result{ ft.actions, ft.terminate };
|
||||||
}
|
}
|
||||||
|
|
|
@ -757,6 +757,7 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
|
||||||
FileSettings fs;
|
FileSettings fs;
|
||||||
fs.filename = cfilename;
|
fs.filename = cfilename;
|
||||||
fs.cfg = p.name;
|
fs.cfg = p.name;
|
||||||
|
// TODO: detect actual MSC version
|
||||||
fs.msc = true;
|
fs.msc = true;
|
||||||
fs.useMfc = useOfMfc;
|
fs.useMfc = useOfMfc;
|
||||||
fs.defines = "_WIN32=1";
|
fs.defines = "_WIN32=1";
|
||||||
|
|
|
@ -34,14 +34,13 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
ExprIdToken::ExprIdToken(const Token* tok) : tok(tok), exprid(tok ? tok->exprId() : 0) {}
|
ExprIdToken::ExprIdToken(const Token* tok) : tok(tok), exprid(tok ? tok->exprId() : 0) {}
|
||||||
|
|
||||||
nonneg int ExprIdToken::getExpressionId() const {
|
nonneg int ExprIdToken::getExpressionId() const {
|
||||||
|
@ -1640,6 +1639,14 @@ namespace {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool updateValue(ValueFlow::Value& v, ValueFlow::Value x)
|
||||||
|
{
|
||||||
|
const bool returnValue = !x.isUninitValue() && !x.isImpossible();
|
||||||
|
if (v.isUninitValue() || returnValue)
|
||||||
|
v = std::move(x);
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
ValueFlow::Value execute(const Token* expr)
|
ValueFlow::Value execute(const Token* expr)
|
||||||
{
|
{
|
||||||
depth--;
|
depth--;
|
||||||
|
@ -1648,13 +1655,29 @@ namespace {
|
||||||
}};
|
}};
|
||||||
if (depth < 0)
|
if (depth < 0)
|
||||||
return unknown();
|
return unknown();
|
||||||
ValueFlow::Value v = executeImpl(expr);
|
ValueFlow::Value v = unknown();
|
||||||
if (!v.isUninitValue())
|
if (updateValue(v, executeImpl(expr)))
|
||||||
return v;
|
return v;
|
||||||
if (!expr)
|
if (!expr)
|
||||||
return v;
|
return v;
|
||||||
if (expr->exprId() > 0 && pm->hasValue(expr->exprId()))
|
if (expr->exprId() > 0 && pm->hasValue(expr->exprId())) {
|
||||||
return pm->at(expr->exprId());
|
if (updateValue(v, pm->at(expr->exprId())))
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
// Find symbolic values
|
||||||
|
for (const ValueFlow::Value& value : expr->values()) {
|
||||||
|
if (!value.isSymbolicValue())
|
||||||
|
continue;
|
||||||
|
if (!value.isKnown())
|
||||||
|
continue;
|
||||||
|
if (value.tokvalue->exprId() > 0 && !pm->hasValue(value.tokvalue->exprId()))
|
||||||
|
continue;
|
||||||
|
ValueFlow::Value v2 = pm->at(value.tokvalue->exprId());
|
||||||
|
if (!v2.isIntValue() && value.intvalue != 0)
|
||||||
|
continue;
|
||||||
|
v2.intvalue += value.intvalue;
|
||||||
|
return v2;
|
||||||
|
}
|
||||||
if (const ValueFlow::Value* value = getImpossibleValue(expr))
|
if (const ValueFlow::Value* value = getImpossibleValue(expr))
|
||||||
return *value;
|
return *value;
|
||||||
return v;
|
return v;
|
||||||
|
|
|
@ -182,12 +182,8 @@ public:
|
||||||
bool dump{};
|
bool dump{};
|
||||||
std::string dumpFile;
|
std::string dumpFile;
|
||||||
|
|
||||||
enum Language {
|
|
||||||
None, C, CPP
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @brief Name of the language that is enforced. Empty per default. */
|
/** @brief Name of the language that is enforced. Empty per default. */
|
||||||
Language enforcedLang{};
|
Standards::Language enforcedLang{};
|
||||||
|
|
||||||
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
|
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
|
||||||
/** @brief Is --exception-handling given */
|
/** @brief Is --exception-handling given */
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
* This struct contains all possible standards that cppcheck recognize.
|
* This struct contains all possible standards that cppcheck recognize.
|
||||||
*/
|
*/
|
||||||
struct Standards {
|
struct Standards {
|
||||||
|
enum Language { None, C, CPP };
|
||||||
|
|
||||||
/** C code standard */
|
/** C code standard */
|
||||||
enum cstd_t { C89, C99, C11, CLatest = C11 } c = CLatest;
|
enum cstd_t { C89, C99, C11, CLatest = C11 } c = CLatest;
|
||||||
|
|
||||||
|
|
|
@ -43,11 +43,11 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
|
||||||
#include <sstream> // IWYU pragma: keep
|
#include <sstream> // IWYU pragma: keep
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -1052,7 +1052,7 @@ void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
||||||
|
|
||||||
const_cast<Token *>(bodyEnd)->scope(&scope);
|
const_cast<Token *>(bodyEnd)->scope(&scope);
|
||||||
|
|
||||||
for (Token* tok = const_cast<Token *>(bodyStart); tok != bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token *>(bodyStart); tok != bodyEnd; tok = tok->next()) {
|
||||||
if (bodyStart != bodyEnd && tok->str() == "{") {
|
if (bodyStart != bodyEnd && tok->str() == "{") {
|
||||||
bool isEndOfScope = false;
|
bool isEndOfScope = false;
|
||||||
for (Scope* innerScope: scope.nestedList) {
|
for (Scope* innerScope: scope.nestedList) {
|
||||||
|
@ -1702,7 +1702,7 @@ void SymbolDatabase::createSymbolDatabaseExprIds()
|
||||||
std::unordered_map<std::string, nonneg int> unknownIds;
|
std::unordered_map<std::string, nonneg int> unknownIds;
|
||||||
// Assign IDs to incomplete vars which are part of an expression
|
// Assign IDs to incomplete vars which are part of an expression
|
||||||
// Such variables should be assumed global
|
// Such variables should be assumed global
|
||||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (!tok->isIncompleteVar())
|
if (!tok->isIncompleteVar())
|
||||||
continue;
|
continue;
|
||||||
if (!isExpression(tok->astParent()))
|
if (!isExpression(tok->astParent()))
|
||||||
|
@ -1725,7 +1725,7 @@ void SymbolDatabase::createSymbolDatabaseExprIds()
|
||||||
// Assign IDs
|
// Assign IDs
|
||||||
ExprIdMap exprIdMap;
|
ExprIdMap exprIdMap;
|
||||||
std::map<std::string, nonneg int> baseIds;
|
std::map<std::string, nonneg int> baseIds;
|
||||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (tok->varId() > 0) {
|
if (tok->varId() > 0) {
|
||||||
tok->exprId(tok->varId());
|
tok->exprId(tok->varId());
|
||||||
if (tok->astParent() && tok->astParent()->exprId() == 0)
|
if (tok->astParent() && tok->astParent()->exprId() == 0)
|
||||||
|
@ -1794,7 +1794,7 @@ void SymbolDatabase::setArrayDimensionsUsingValueFlow()
|
||||||
continue;
|
continue;
|
||||||
// check each array dimension
|
// check each array dimension
|
||||||
for (const Dimension &const_dimension : var->dimensions()) {
|
for (const Dimension &const_dimension : var->dimensions()) {
|
||||||
Dimension &dimension = const_cast<Dimension &>(const_dimension);
|
auto &dimension = const_cast<Dimension &>(const_dimension);
|
||||||
if (dimension.num != 0 || !dimension.tok)
|
if (dimension.num != 0 || !dimension.tok)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -3383,7 +3383,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
||||||
if (match) {
|
if (match) {
|
||||||
auto range = scope1->functionMap.equal_range((*tok)->str());
|
auto range = scope1->functionMap.equal_range((*tok)->str());
|
||||||
for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
|
for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
|
||||||
Function * func = const_cast<Function *>(it->second);
|
auto * func = const_cast<Function *>(it->second);
|
||||||
if (!func->hasBody()) {
|
if (!func->hasBody()) {
|
||||||
if (func->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
if (func->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
||||||
const Token *closeParen = (*tok)->next()->link();
|
const Token *closeParen = (*tok)->next()->link();
|
||||||
|
@ -6502,7 +6502,7 @@ static bool isContainerYieldPointer(Library::Container::Yield yield)
|
||||||
|
|
||||||
void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, SourceLocation loc)
|
void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, SourceLocation loc)
|
||||||
{
|
{
|
||||||
ValueType* valuetypePtr = new ValueType(valuetype);
|
auto* valuetypePtr = new ValueType(valuetype);
|
||||||
if (mSettings.debugnormal || mSettings.debugwarnings)
|
if (mSettings.debugnormal || mSettings.debugwarnings)
|
||||||
valuetypePtr->setDebugPath(tok, loc);
|
valuetypePtr->setDebugPath(tok, loc);
|
||||||
tok->setValueType(valuetypePtr);
|
tok->setValueType(valuetypePtr);
|
||||||
|
@ -6584,7 +6584,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
|
||||||
setValueType(var1Tok, vt);
|
setValueType(var1Tok, vt);
|
||||||
if (var1Tok != parent->previous())
|
if (var1Tok != parent->previous())
|
||||||
setValueType(parent->previous(), vt);
|
setValueType(parent->previous(), vt);
|
||||||
Variable *var = const_cast<Variable *>(parent->previous()->variable());
|
auto *var = const_cast<Variable *>(parent->previous()->variable());
|
||||||
if (var) {
|
if (var) {
|
||||||
ValueType vt2_(*vt2);
|
ValueType vt2_(*vt2);
|
||||||
if (vt2_.pointer == 0 && autoTok->strAt(1) == "*")
|
if (vt2_.pointer == 0 && autoTok->strAt(1) == "*")
|
||||||
|
@ -6737,7 +6737,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
|
||||||
varvt.constness |= 1;
|
varvt.constness |= 1;
|
||||||
}
|
}
|
||||||
setValueType(parent->previous(), varvt);
|
setValueType(parent->previous(), varvt);
|
||||||
Variable *var = const_cast<Variable *>(parent->previous()->variable());
|
auto *var = const_cast<Variable *>(parent->previous()->variable());
|
||||||
if (var) {
|
if (var) {
|
||||||
var->setValueType(varvt);
|
var->setValueType(varvt);
|
||||||
if (vt2->typeScope && vt2->typeScope->definedType) {
|
if (vt2->typeScope && vt2->typeScope->definedType) {
|
||||||
|
@ -6803,7 +6803,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
|
||||||
if (isconst)
|
if (isconst)
|
||||||
varvt.constness |= (1 << autovt.pointer);
|
varvt.constness |= (1 << autovt.pointer);
|
||||||
setValueType(parent->previous(), varvt);
|
setValueType(parent->previous(), varvt);
|
||||||
Variable * var = const_cast<Variable *>(parent->previous()->variable());
|
auto * var = const_cast<Variable *>(parent->previous()->variable());
|
||||||
if (var) {
|
if (var) {
|
||||||
var->setValueType(varvt);
|
var->setValueType(varvt);
|
||||||
if (templateArgType && templateArgType->classScope && templateArgType->classScope->definedType) {
|
if (templateArgType && templateArgType->classScope && templateArgType->classScope->definedType) {
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
static Token *skipRequires(Token *tok)
|
static Token *skipRequires(Token *tok)
|
||||||
|
@ -1376,7 +1377,7 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
Token *end = const_cast<Token *>(aliasDeclaration.aliasEndToken());
|
auto *end = const_cast<Token *>(aliasDeclaration.aliasEndToken());
|
||||||
|
|
||||||
// remove declaration tokens
|
// remove declaration tokens
|
||||||
if (aliasDeclaration.token()->previous())
|
if (aliasDeclaration.token()->previous())
|
||||||
|
@ -3227,7 +3228,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
// process uninstantiated templates
|
// process uninstantiated templates
|
||||||
// TODO: remove the specialized check and handle all uninstantiated templates someday.
|
// TODO: remove the specialized check and handle all uninstantiated templates someday.
|
||||||
if (!instantiated && specialized) {
|
if (!instantiated && specialized) {
|
||||||
Token * tok2 = const_cast<Token *>(templateDeclaration.nameToken());
|
auto * tok2 = const_cast<Token *>(templateDeclaration.nameToken());
|
||||||
if (mErrorLogger && !mTokenList.getFiles().empty())
|
if (mErrorLogger && !mTokenList.getFiles().empty())
|
||||||
mErrorLogger->reportProgress(mTokenList.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue());
|
mErrorLogger->reportProgress(mTokenList.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue());
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream> // IWYU pragma: keep
|
#include <sstream> // IWYU pragma: keep
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <type_traits>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
|
@ -821,7 +821,14 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* const tok2 = insertTokens(tok, mRangeType);
|
// don't add class|struct|union in inheritance list
|
||||||
|
auto rangeType = mRangeType;
|
||||||
|
if (Token::Match(tok->previous(), "public|private|protected")) {
|
||||||
|
while (Token::Match(rangeType.first, "const|class|struct|union"))
|
||||||
|
rangeType.first = rangeType.first->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* const tok2 = insertTokens(tok, rangeType);
|
||||||
Token* const tok3 = insertTokens(tok2, mRangeTypeQualifiers);
|
Token* const tok3 = insertTokens(tok2, mRangeTypeQualifiers);
|
||||||
|
|
||||||
Token *after = tok3;
|
Token *after = tok3;
|
||||||
|
@ -3354,10 +3361,10 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration)
|
||||||
if (mTimerResults) {
|
if (mTimerResults) {
|
||||||
Timer t("Tokenizer::simplifyTokens1::createAst", mSettings->showtime, mTimerResults);
|
Timer t("Tokenizer::simplifyTokens1::createAst", mSettings->showtime, mTimerResults);
|
||||||
list.createAst();
|
list.createAst();
|
||||||
list.validateAst();
|
list.validateAst(mSettings->debugnormal);
|
||||||
} else {
|
} else {
|
||||||
list.createAst();
|
list.createAst();
|
||||||
list.validateAst();
|
list.validateAst(mSettings->debugnormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTimerResults) {
|
if (mTimerResults) {
|
||||||
|
@ -3915,7 +3922,7 @@ void Tokenizer::simplifyLabelsCaseDefault()
|
||||||
int indentLevel = 0;
|
int indentLevel = 0;
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
// Simplify labels in the executable scope..
|
// Simplify labels in the executable scope..
|
||||||
Token *start = const_cast<Token *>(startOfExecutableScope(tok));
|
auto *start = const_cast<Token *>(startOfExecutableScope(tok));
|
||||||
if (start) {
|
if (start) {
|
||||||
tok = start;
|
tok = start;
|
||||||
executablescope = true;
|
executablescope = true;
|
||||||
|
|
|
@ -50,6 +50,9 @@ TokenList::TokenList(const Settings* settings) :
|
||||||
mSettings(settings)
|
mSettings(settings)
|
||||||
{
|
{
|
||||||
mTokensFrontBack.list = this;
|
mTokensFrontBack.list = this;
|
||||||
|
if (mSettings && (mSettings->enforcedLang != Standards::Language::None)) {
|
||||||
|
mLang = mSettings->enforcedLang;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenList::~TokenList()
|
TokenList::~TokenList()
|
||||||
|
@ -80,12 +83,12 @@ void TokenList::deallocateTokens()
|
||||||
|
|
||||||
void TokenList::determineCppC()
|
void TokenList::determineCppC()
|
||||||
{
|
{
|
||||||
if (!mSettings) {
|
// only try to determine it if it wasn't enforced
|
||||||
mIsC = Path::isC(getSourceFilePath());
|
if (mLang == Standards::Language::None) {
|
||||||
mIsCpp = Path::isCPP(getSourceFilePath());
|
if (Path::isC(getSourceFilePath()))
|
||||||
} else {
|
mLang = Standards::Language::C;
|
||||||
mIsC = mSettings->enforcedLang == Settings::Language::C || (mSettings->enforcedLang == Settings::Language::None && Path::isC(getSourceFilePath()));
|
else if (Path::isCPP(getSourceFilePath()))
|
||||||
mIsCpp = mSettings->enforcedLang == Settings::Language::CPP || (mSettings->enforcedLang == Settings::Language::None && Path::isCPP(getSourceFilePath()));
|
mLang = Standards::Language::CPP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,8 +576,12 @@ static bool iscpp11init_impl(const Token * const tok)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto isCaseStmt = [](const Token* colonTok) {
|
auto isCaseStmt = [](const Token* colonTok) {
|
||||||
if (!Token::Match(colonTok->tokAt(-1), "%name%|%num%|%char% :"))
|
if (!Token::Match(colonTok->tokAt(-1), "%name%|%num%|%char%|) :"))
|
||||||
return false;
|
return false;
|
||||||
|
if (const Token* castTok = colonTok->linkAt(-1)) {
|
||||||
|
if (Token::simpleMatch(castTok->astParent(), "case"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const Token* caseTok = colonTok->tokAt(-2);
|
const Token* caseTok = colonTok->tokAt(-2);
|
||||||
while (caseTok && Token::Match(caseTok->tokAt(-1), "::|%name%"))
|
while (caseTok && Token::Match(caseTok->tokAt(-1), "::|%name%"))
|
||||||
caseTok = caseTok->tokAt(-1);
|
caseTok = caseTok->tokAt(-1);
|
||||||
|
@ -1718,10 +1725,10 @@ namespace {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TokenList::validateAst() const
|
void TokenList::validateAst(bool print) const
|
||||||
{
|
{
|
||||||
OnException oe{[&] {
|
OnException oe{[&] {
|
||||||
if (mSettings && mSettings->debugnormal)
|
if (print)
|
||||||
mTokensFrontBack.front->printOut();
|
mTokensFrontBack.front->printOut();
|
||||||
}};
|
}};
|
||||||
// Check for some known issues in AST to avoid crash/hang later on
|
// Check for some known issues in AST to avoid crash/hang later on
|
||||||
|
@ -1850,7 +1857,7 @@ void TokenList::simplifyPlatformTypes()
|
||||||
if (!mSettings)
|
if (!mSettings)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const bool isCPP11 = mSettings->standards.cpp >= Standards::CPP11;
|
const bool isCPP11 = isCPP() && (mSettings->standards.cpp >= Standards::CPP11);
|
||||||
|
|
||||||
enum { isLongLong, isLong, isInt } type;
|
enum { isLongLong, isLong, isInt } type;
|
||||||
|
|
||||||
|
@ -1992,7 +1999,7 @@ void TokenList::simplifyStdType()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok, "char|short|int|long|unsigned|signed|double|float") || (mSettings->standards.c >= Standards::C99 && Token::Match(tok, "complex|_Complex"))) {
|
if (Token::Match(tok, "char|short|int|long|unsigned|signed|double|float") || (isC() && (!mSettings || (mSettings->standards.c >= Standards::C99)) && Token::Match(tok, "complex|_Complex"))) {
|
||||||
bool isFloat= false;
|
bool isFloat= false;
|
||||||
bool isSigned = false;
|
bool isSigned = false;
|
||||||
bool isUnsigned = false;
|
bool isUnsigned = false;
|
||||||
|
@ -2015,7 +2022,7 @@ void TokenList::simplifyStdType()
|
||||||
else if (Token::Match(tok2, "float|double")) {
|
else if (Token::Match(tok2, "float|double")) {
|
||||||
isFloat = true;
|
isFloat = true;
|
||||||
typeSpec = tok2;
|
typeSpec = tok2;
|
||||||
} else if (mSettings->standards.c >= Standards::C99 && Token::Match(tok2, "complex|_Complex"))
|
} else if (isC() && (!mSettings || (mSettings->standards.c >= Standards::C99)) && Token::Match(tok2, "complex|_Complex"))
|
||||||
isComplex = !isFloat || tok2->str() == "_Complex" || Token::Match(tok2->next(), "*|&|%name%"); // Ensure that "complex" is not the variables name
|
isComplex = !isFloat || tok2->str() == "_Complex" || Token::Match(tok2->next(), "*|&|%name%"); // Ensure that "complex" is not the variables name
|
||||||
else if (Token::Match(tok2, "char|int")) {
|
else if (Token::Match(tok2, "char|int")) {
|
||||||
if (!typeSpec)
|
if (!typeSpec)
|
||||||
|
@ -2053,7 +2060,7 @@ void TokenList::simplifyStdType()
|
||||||
|
|
||||||
bool TokenList::isKeyword(const std::string &str) const
|
bool TokenList::isKeyword(const std::string &str) const
|
||||||
{
|
{
|
||||||
if (mIsCpp) {
|
if (isCPP()) {
|
||||||
// TODO: integrate into keywords?
|
// TODO: integrate into keywords?
|
||||||
// types and literals are not handled as keywords
|
// types and literals are not handled as keywords
|
||||||
static const std::unordered_set<std::string> cpp_types = {"bool", "false", "true"};
|
static const std::unordered_set<std::string> cpp_types = {"bool", "false", "true"};
|
||||||
|
|
|
@ -22,15 +22,16 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "standards.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Settings;
|
|
||||||
class Token;
|
class Token;
|
||||||
class TokenList;
|
class TokenList;
|
||||||
|
class Settings;
|
||||||
|
|
||||||
namespace simplecpp {
|
namespace simplecpp {
|
||||||
class TokenList;
|
class TokenList;
|
||||||
|
@ -61,12 +62,12 @@ public:
|
||||||
|
|
||||||
/** Is the code C. Used for bailouts */
|
/** Is the code C. Used for bailouts */
|
||||||
bool isC() const {
|
bool isC() const {
|
||||||
return mIsC;
|
return mLang == Standards::Language::C;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Is the code CPP. Used for bailouts */
|
/** Is the code CPP. Used for bailouts */
|
||||||
bool isCPP() const {
|
bool isCPP() const {
|
||||||
return mIsCpp;
|
return mLang == Standards::Language::CPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,7 +172,7 @@ public:
|
||||||
* Check abstract syntax tree.
|
* Check abstract syntax tree.
|
||||||
* Throws InternalError on failure
|
* Throws InternalError on failure
|
||||||
*/
|
*/
|
||||||
void validateAst() const;
|
void validateAst(bool print) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that the given token is an element of the tokenlist.
|
* Verify that the given token is an element of the tokenlist.
|
||||||
|
@ -214,8 +215,7 @@ private:
|
||||||
const Settings* const mSettings{};
|
const Settings* const mSettings{};
|
||||||
|
|
||||||
/** File is known to be C/C++ code */
|
/** File is known to be C/C++ code */
|
||||||
bool mIsC{};
|
Standards::Language mLang{Standards::Language::None};
|
||||||
bool mIsCpp{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -2969,6 +2969,13 @@ struct ValueFlowAnalyzer : Analyzer {
|
||||||
makeConditional();
|
makeConditional();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateState(const Token* tok) override
|
||||||
|
{
|
||||||
|
// Update program state
|
||||||
|
pms.removeModifiedVars(tok);
|
||||||
|
pms.addState(tok, getProgramState());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void internalUpdate(Token* /*tok*/, const ValueFlow::Value& /*v*/, Direction /*d*/)
|
virtual void internalUpdate(Token* /*tok*/, const ValueFlow::Value& /*v*/, Direction /*d*/)
|
||||||
{
|
{
|
||||||
assert(false && "Internal update unimplemented.");
|
assert(false && "Internal update unimplemented.");
|
||||||
|
@ -5113,7 +5120,7 @@ static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symbo
|
||||||
start = memberInitializationTok;
|
start = memberInitializationTok;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Token* tok = const_cast<Token*>(start); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(start); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
Token * varTok;
|
Token * varTok;
|
||||||
if (Token::Match(tok, "%var% . reset|clear (") && tok->next()->originalName().empty()) {
|
if (Token::Match(tok, "%var% . reset|clear (") && tok->next()->originalName().empty()) {
|
||||||
varTok = tok;
|
varTok = tok;
|
||||||
|
@ -5369,7 +5376,7 @@ static std::set<nonneg int> getVarIds(const Token* tok)
|
||||||
static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings)
|
static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings)
|
||||||
{
|
{
|
||||||
for (const Scope* scope : symboldatabase.functionScopes) {
|
for (const Scope* scope : symboldatabase.functionScopes) {
|
||||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (!Token::simpleMatch(tok, "="))
|
if (!Token::simpleMatch(tok, "="))
|
||||||
continue;
|
continue;
|
||||||
if (tok->astParent())
|
if (tok->astParent())
|
||||||
|
@ -5462,7 +5469,7 @@ static ValueFlow::Value inferCondition(const std::string& op, const Token* varTo
|
||||||
static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, const Settings* settings)
|
static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, const Settings* settings)
|
||||||
{
|
{
|
||||||
for (const Scope* scope : symboldatabase.functionScopes) {
|
for (const Scope* scope : symboldatabase.functionScopes) {
|
||||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (tok->hasKnownIntValue())
|
if (tok->hasKnownIntValue())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -5575,7 +5582,7 @@ struct SymbolicInferModel : InferModel {
|
||||||
static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings* settings)
|
static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings* settings)
|
||||||
{
|
{
|
||||||
for (const Scope* scope : symboldatabase.functionScopes) {
|
for (const Scope* scope : symboldatabase.functionScopes) {
|
||||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (!Token::Match(tok, "-|%comp%"))
|
if (!Token::Match(tok, "-|%comp%"))
|
||||||
continue;
|
continue;
|
||||||
if (tok->hasKnownIntValue())
|
if (tok->hasKnownIntValue())
|
||||||
|
@ -5923,7 +5930,7 @@ static void valueFlowAfterAssign(TokenList &tokenlist,
|
||||||
if (skippedFunctions.count(scope))
|
if (skippedFunctions.count(scope))
|
||||||
continue;
|
continue;
|
||||||
std::unordered_map<nonneg int, std::unordered_set<nonneg int>> backAssigns;
|
std::unordered_map<nonneg int, std::unordered_set<nonneg int>> backAssigns;
|
||||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
// Assignment
|
// Assignment
|
||||||
bool isInit = false;
|
bool isInit = false;
|
||||||
if (tok->str() != "=" && !(isInit = isVariableInit(tok)))
|
if (tok->str() != "=" && !(isInit = isVariableInit(tok)))
|
||||||
|
@ -6056,7 +6063,7 @@ static void valueFlowAfterSwap(TokenList& tokenlist,
|
||||||
const Settings* settings)
|
const Settings* settings)
|
||||||
{
|
{
|
||||||
for (const Scope* scope : symboldatabase.functionScopes) {
|
for (const Scope* scope : symboldatabase.functionScopes) {
|
||||||
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (!Token::simpleMatch(tok, "swap ("))
|
if (!Token::simpleMatch(tok, "swap ("))
|
||||||
continue;
|
continue;
|
||||||
if (!Token::simpleMatch(tok->next()->astOperand2(), ","))
|
if (!Token::simpleMatch(tok->next()->astOperand2(), ","))
|
||||||
|
@ -6231,7 +6238,7 @@ struct ConditionHandler {
|
||||||
for (const Scope *scope : symboldatabase.functionScopes) {
|
for (const Scope *scope : symboldatabase.functionScopes) {
|
||||||
if (skippedFunctions.count(scope))
|
if (skippedFunctions.count(scope))
|
||||||
continue;
|
continue;
|
||||||
for (Token *tok = const_cast<Token *>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
for (auto *tok = const_cast<Token *>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "if|while|for ("))
|
if (Token::Match(tok, "if|while|for ("))
|
||||||
continue;
|
continue;
|
||||||
if (Token::Match(tok, ":|;|,"))
|
if (Token::Match(tok, ":|;|,"))
|
||||||
|
@ -6720,7 +6727,7 @@ struct ConditionHandler {
|
||||||
return;
|
return;
|
||||||
if (r.action.isModified())
|
if (r.action.isModified())
|
||||||
return;
|
return;
|
||||||
Token* start = const_cast<Token*>(loopScope->bodyEnd);
|
auto* start = const_cast<Token*>(loopScope->bodyEnd);
|
||||||
if (Token::simpleMatch(start, "} while (")) {
|
if (Token::simpleMatch(start, "} while (")) {
|
||||||
start = start->tokAt(2);
|
start = start->tokAt(2);
|
||||||
forward(start, start->link(), cond.vartok, values, tokenlist, settings);
|
forward(start, start->link(), cond.vartok, values, tokenlist, settings);
|
||||||
|
@ -7173,8 +7180,8 @@ static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symbold
|
||||||
if (scope.type != Scope::eFor)
|
if (scope.type != Scope::eFor)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Token* tok = const_cast<Token*>(scope.classDef);
|
auto* tok = const_cast<Token*>(scope.classDef);
|
||||||
Token* const bodyStart = const_cast<Token*>(scope.bodyStart);
|
auto* const bodyStart = const_cast<Token*>(scope.bodyStart);
|
||||||
|
|
||||||
if (!Token::simpleMatch(tok->next()->astOperand2(), ";") ||
|
if (!Token::simpleMatch(tok->next()->astOperand2(), ";") ||
|
||||||
!Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";"))
|
!Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";"))
|
||||||
|
@ -8772,7 +8779,7 @@ static void valueFlowContainerSize(TokenList& tokenlist,
|
||||||
|
|
||||||
// after assignment
|
// after assignment
|
||||||
for (const Scope *functionScope : symboldatabase.functionScopes) {
|
for (const Scope *functionScope : symboldatabase.functionScopes) {
|
||||||
for (Token* tok = const_cast<Token*>(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) {
|
for (auto* tok = const_cast<Token*>(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "%name%|;|{|} %var% = %str% ;")) {
|
if (Token::Match(tok, "%name%|;|{|} %var% = %str% ;")) {
|
||||||
Token* containerTok = tok->next();
|
Token* containerTok = tok->next();
|
||||||
if (containerTok->exprId() == 0)
|
if (containerTok->exprId() == 0)
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
#define versionH
|
#define versionH
|
||||||
|
|
||||||
#define CPPCHECK_MAJOR_VERSION 2
|
#define CPPCHECK_MAJOR_VERSION 2
|
||||||
#define CPPCHECK_MINOR_VERSION 12
|
#define CPPCHECK_MINOR_VERSION 13
|
||||||
#define CPPCHECK_DEVMINOR_VERSION 13
|
#define CPPCHECK_DEVMINOR_VERSION 14
|
||||||
#define CPPCHECK_FIX_VERSION 0
|
#define CPPCHECK_BUGFIX_VERSION 99
|
||||||
|
|
||||||
#define STRINGIFY(x) STRING(x)
|
#define STRINGIFY(x) STRING(x)
|
||||||
#define STRING(VER) #VER
|
#define STRING(VER) #VER
|
||||||
#if CPPCHECK_MINOR_VERSION == CPPCHECK_DEVMINOR_VERSION
|
#if CPPCHECK_BUGFIX_VERSION < 99
|
||||||
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR_VERSION) "." STRINGIFY(CPPCHECK_MINOR_VERSION) "." STRINGIFY(CPPCHECK_FIX_VERSION)
|
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR_VERSION) "." STRINGIFY(CPPCHECK_MINOR_VERSION) "." STRINGIFY(CPPCHECK_BUGFIX_VERSION)
|
||||||
#define CPPCHECK_VERSION CPPCHECK_MAJOR_VERSION,CPPCHECK_MINOR_VERSION,CPPCHECK_FIX_VERSION,0
|
#define CPPCHECK_VERSION CPPCHECK_MAJOR_VERSION,CPPCHECK_MINOR_VERSION,CPPCHECK_BUGFIX_VERSION,0
|
||||||
#else
|
#else
|
||||||
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR_VERSION) "." STRINGIFY(CPPCHECK_DEVMINOR_VERSION) " dev"
|
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR_VERSION) "." STRINGIFY(CPPCHECK_DEVMINOR_VERSION) " dev"
|
||||||
#define CPPCHECK_VERSION CPPCHECK_MAJOR_VERSION,CPPCHECK_MINOR_VERSION,99,0
|
#define CPPCHECK_VERSION CPPCHECK_MAJOR_VERSION,CPPCHECK_MINOR_VERSION,99,0
|
||||||
|
|
|
@ -26,7 +26,7 @@ SUPPRESS_WARNING_CLANG_PUSH("-Wextra-semi-stmt")
|
||||||
SUPPRESS_WARNING_CLANG_PUSH("-Wsuggest-override")
|
SUPPRESS_WARNING_CLANG_PUSH("-Wsuggest-override")
|
||||||
SUPPRESS_WARNING_CLANG_PUSH("-Wsuggest-destructor-override")
|
SUPPRESS_WARNING_CLANG_PUSH("-Wsuggest-destructor-override")
|
||||||
|
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h> // IWYU pragma: export
|
||||||
|
|
||||||
SUPPRESS_WARNING_CLANG_POP
|
SUPPRESS_WARNING_CLANG_POP
|
||||||
SUPPRESS_WARNING_CLANG_POP
|
SUPPRESS_WARNING_CLANG_POP
|
||||||
|
|
|
@ -320,7 +320,7 @@ If you can generate a compile database, then it is possible to import that in Cp
|
||||||
|
|
||||||
In Linux you can use for instance the `bear` (build ear) utility to generate a compile database from arbitrary build tools:
|
In Linux you can use for instance the `bear` (build ear) utility to generate a compile database from arbitrary build tools:
|
||||||
|
|
||||||
bear make
|
bear -- make
|
||||||
|
|
||||||
# Preprocessor Settings
|
# Preprocessor Settings
|
||||||
|
|
||||||
|
@ -450,10 +450,10 @@ The format for an error suppression is one of:
|
||||||
[error id]:[filename2]
|
[error id]:[filename2]
|
||||||
[error id]
|
[error id]
|
||||||
|
|
||||||
The `error id` is the id that you want to suppress. The easiest way to get it is to use the --template=gcc command line flag. The id is shown in brackets.
|
The `error id` is the id that you want to suppress. The id of a warning is shown in brackets in the normal cppcheck text output. The suppression `error id` may contain \* to match any sequence of tokens.
|
||||||
|
|
||||||
The filename may include the wildcard characters \* or ?, which matches any sequence of characters or any single character respectively.
|
The filename may include the wildcard characters \* or ?, which matches any sequence of characters or any single character respectively.
|
||||||
It is recommended to use "/" as path separator on all operating systems. The filename must match the filename in the reported warning exactly.
|
It is recommended to use forward-slash `/` as path separator on all operating systems. The filename must match the filename in the reported warning exactly.
|
||||||
For instance, if the warning contains a relative path, then the suppression must match that relative path.
|
For instance, if the warning contains a relative path, then the suppression must match that relative path.
|
||||||
|
|
||||||
## Command line suppression
|
## Command line suppression
|
||||||
|
@ -929,13 +929,87 @@ Addons could be run through Cppcheck command line utility as follows:
|
||||||
|
|
||||||
This will launch all Cppcheck checks and additionally calls specific checks provided by selected addon.
|
This will launch all Cppcheck checks and additionally calls specific checks provided by selected addon.
|
||||||
|
|
||||||
|
Some addons need extra arguments. You can configure how you want to execute an addon in a json file. For example put this in misra.json:
|
||||||
|
|
||||||
|
{
|
||||||
|
"script": "misra.py",
|
||||||
|
"args": [
|
||||||
|
"--rule-texts=misra.txt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
And then the configuration can be executed on the Cppcheck command line:
|
||||||
|
|
||||||
|
cppcheck --addon=misra.json somefile.c
|
||||||
|
|
||||||
|
By default Cppcheck would search addon at the standard path which was specified
|
||||||
|
during the installation process. You also can set this path directly, for example:
|
||||||
|
|
||||||
|
cppcheck --addon=/opt/cppcheck/configurations/my_misra.json somefile.c
|
||||||
|
|
||||||
|
This allows you to create and manage multiple configuration files for different projects.
|
||||||
|
|
||||||
# Library configuration
|
# Library configuration
|
||||||
|
|
||||||
When external libraries are used, such as WinAPI, POSIX, gtk, Qt, etc, Cppcheck doesn't know how the external functions behave. Cppcheck then fails to detect various problems such as memory leaks, buffer overflows, possible null pointer dereferences, etc. But this can be fixed with configuration files.
|
When external libraries are used, such as WinAPI, POSIX, gtk, Qt, etc, Cppcheck has no information about functions, types, or macros contained in those libraries. Cppcheck then fails to detect various problems in the code, or might even abort the analysis. But this can be fixed by using the appropriate configuration files.
|
||||||
|
|
||||||
Cppcheck already contains configurations for several libraries. They can be loaded as described below. Note that the configuration for the standard libraries of C and C++, std.cfg, is always loaded by cppcheck. If you create or update a configuration file for a popular library, we would appreciate if you upload it to us.
|
Cppcheck already contains configurations for several libraries. They can be loaded as described below. Note that the configuration for the standard libraries of C and C++, std.cfg, is always loaded by cppcheck. If you create or update a configuration file for a popular library, we would appreciate if you supplied it to the cppcheck project.
|
||||||
|
|
||||||
## Using your own custom .cfg file
|
## Using a .cfg file
|
||||||
|
|
||||||
|
To use a .cfg file shipped with cppcheck, pass the `--library=<lib>` option. The table below shows the currently existing libraries:
|
||||||
|
| .cfg file | Library | Comment |
|
||||||
|
| ------------- | ------------- | ------------- |
|
||||||
|
| avr.cfg | |
|
||||||
|
| bento4.cfg | [Bento4](http://www.bento4.com/) |
|
||||||
|
| boost.cfg | [Boost](http://www.boost.org/)|
|
||||||
|
| bsd.cfg | [BSD](https://www.freebsd.org/) |
|
||||||
|
| cairo.cfg | [cairo](https://www.cairographics.org/) |
|
||||||
|
| cppcheck-lib.cfg | [Cppcheck](http://cppcheck.net/) | Used in selfcheck of the Cppcheck code base
|
||||||
|
| cppunit.cfg | [CppUnit](https://sourceforge.net/projects/cppunit/) |
|
||||||
|
| dpdk.cfg | |
|
||||||
|
| embedded_sql.cfg | |
|
||||||
|
| emscripten.cfg | |
|
||||||
|
| ginac.cfg | |
|
||||||
|
| gnu.cfg | [GNU](https://www.gnu.org/) |
|
||||||
|
| googletest.cfg | [GoogleTest](https://github.com/google/googletest) |
|
||||||
|
| gtk.cfg | [GTK](https://www.gtk.org/) |
|
||||||
|
| icu.cfg | |
|
||||||
|
| kde.cfg | [KDE](https://kde.org/) |
|
||||||
|
| libcerror.cfg | [libcerror](https://github.com/libyal/libcerror) |
|
||||||
|
| libcurl.cfg | [libcurl](https://curl.se/libcurl/) |
|
||||||
|
| libsigc++.cfg | [libsigc++](https://github.com/libsigcplusplus/libsigcplusplus) |
|
||||||
|
| lua.cfg | |
|
||||||
|
| mfc.cfg | [MFC](https://learn.microsoft.com/en-us/cpp/mfc/mfc-desktop-applications) |
|
||||||
|
| microsoft_atl.cfg | [ATL](https://learn.microsoft.com/en-us/cpp/atl/active-template-library-atl-concepts) |
|
||||||
|
| microsoft_sal.cfg | [SAL annotations](https://learn.microsoft.com/en-us/cpp/c-runtime-library/sal-annotations) |
|
||||||
|
| microsoft_unittest.cfg | [CppUnitTest](https://learn.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference) |
|
||||||
|
| motif.cfg | |
|
||||||
|
| nspr.cfg | |
|
||||||
|
| ntl.cfg | |
|
||||||
|
| opencv2.cfg | [OpenCV](https://opencv.org/) |
|
||||||
|
| opengl.cfg | [OpenGL](https://opengl.org/) |
|
||||||
|
| openmp.cfg | [OpenMP](https://www.openmp.org/) |
|
||||||
|
| openssl.cfg | [OpenSSL](https://www.openssl.org/) |
|
||||||
|
| pcre.cfg | [PCRE](https://pcre.org/) |
|
||||||
|
| posix.cfg | [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/) |
|
||||||
|
| python.cfg | |
|
||||||
|
| qt.cfg | [Qt](https://doc.qt.io/qt.html) |
|
||||||
|
| ruby.cfg | |
|
||||||
|
| sdl.cfg | |
|
||||||
|
| sfml.cfg | |
|
||||||
|
| sqlite3.cfg | [SQLite](https://www.sqlite.org/) |
|
||||||
|
| std.cfg | C/C++ standard library | Loaded by default
|
||||||
|
| tinyxml2.cfg | [TinyXML-2](https://github.com/leethomason/tinyxml2) |
|
||||||
|
| vcl.cfg | |
|
||||||
|
| windows.cfg | [Win32 API](https://learn.microsoft.com/en-us/windows/win32/) |
|
||||||
|
| wxsqlite3.cfg | |
|
||||||
|
| wxsvg.cfg | |
|
||||||
|
| wxwidgets.cfg | [wxWidgets](https://www.wxwidgets.org/) |
|
||||||
|
| zephyr.cfg | |
|
||||||
|
| zlib.cfg | [zlib](https://www.zlib.net) |
|
||||||
|
|
||||||
|
## Creating a custom .cfg file
|
||||||
|
|
||||||
You can create and use your own .cfg files for your projects. Use `--check-library` to get hints about what you should configure.
|
You can create and use your own .cfg files for your projects. Use `--check-library` to get hints about what you should configure.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Cppcheck manual
|
title: Cppcheck manual
|
||||||
subtitle: Version 2.12.99
|
subtitle: Version 2.13.99
|
||||||
author: Cppcheck team
|
author: Cppcheck team
|
||||||
lang: en
|
lang: en
|
||||||
documentclass: report
|
documentclass: report
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Cppcheck .cfg format
|
title: Cppcheck .cfg format
|
||||||
subtitle: Version 2.12.99
|
subtitle: Version 2.13.99
|
||||||
author: Cppcheck team
|
author: Cppcheck team
|
||||||
lang: en
|
lang: en
|
||||||
documentclass: report
|
documentclass: report
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Writing addons
|
title: Writing addons
|
||||||
subtitle: Version 2.12.99
|
subtitle: Version 2.13.99
|
||||||
author: Cppcheck team
|
author: Cppcheck team
|
||||||
lang: en
|
lang: en
|
||||||
documentclass: report
|
documentclass: report
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue