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:
|
||||
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:
|
||||
- build_gui: false
|
||||
- image: "ubuntu:23.10"
|
||||
|
@ -39,13 +39,6 @@ jobs:
|
|||
steps:
|
||||
- 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
|
||||
if: contains(matrix.image, 'ubuntu')
|
||||
run: |
|
||||
|
@ -62,22 +55,12 @@ jobs:
|
|||
# - it doesn't support centos
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
if: matrix.image != 'ubuntu:14.04' # no support for --set-config
|
||||
with:
|
||||
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
|
||||
- name: CMake build (no tests)
|
||||
if: matrix.image == 'centos:7' || matrix.image == 'ubuntu:16.04'
|
||||
if: matrix.image == 'ubuntu:16.04'
|
||||
run: |
|
||||
mkdir cmake.output
|
||||
cd cmake.output
|
||||
|
@ -85,7 +68,7 @@ jobs:
|
|||
cmake --build . -- -j$(nproc)
|
||||
|
||||
- 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: |
|
||||
mkdir cmake.output
|
||||
cd cmake.output
|
||||
|
@ -99,7 +82,7 @@ jobs:
|
|||
cmake --build cmake.output -- -j$(nproc)
|
||||
|
||||
- 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: |
|
||||
cmake --build cmake.output --target check -- -j$(nproc)
|
||||
|
||||
|
@ -107,7 +90,7 @@ jobs:
|
|||
|
||||
strategy:
|
||||
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
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
@ -118,13 +101,6 @@ jobs:
|
|||
steps:
|
||||
- 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
|
||||
if: contains(matrix.image, 'ubuntu')
|
||||
run: |
|
||||
|
@ -136,7 +112,6 @@ jobs:
|
|||
# - it doesn't support centos
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
if: matrix.image != 'ubuntu:14.04' # no support for --set-config
|
||||
with:
|
||||
key: ${{ github.workflow }}-${{ matrix.image }}
|
||||
|
||||
|
|
|
@ -446,8 +446,6 @@ jobs:
|
|||
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.c.dump
|
||||
../../cppcheck --dump naming_test.cpp
|
||||
python3 ../naming.py --var='[a-z].*' --function='[a-z].*' naming_test.cpp.dump
|
||||
../../cppcheck --dump namingng_test.c
|
||||
python3 ../namingng.py --configfile ../naming.json --verify namingng_test.c.dump
|
||||
|
||||
- name: Build democlient
|
||||
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!
|
||||
..\..\cppcheck --dump naming_test.cpp || 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
|
||||
|
||||
env:
|
||||
PREMIUM_VERSION: devdrop-20231105
|
||||
PREMIUM_VERSION: 23.12.0
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download cppcheckpremium
|
||||
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
|
||||
|
||||
- name: Generate a license file
|
||||
run: |
|
||||
echo cppcheck > cppcheck.lic
|
||||
echo 231231 >> cppcheck.lic
|
||||
echo 241231 >> cppcheck.lic
|
||||
echo 80000 >> cppcheck.lic
|
||||
echo 57e08c39523ab54d >> cppcheck.lic
|
||||
echo 53b72a908d7aeeee >> cppcheck.lic
|
||||
echo path:lib >> cppcheck.lic
|
||||
|
||||
- name: Check
|
||||
|
|
|
@ -63,7 +63,7 @@ jobs:
|
|||
# TODO: switch to Qt 6 after we enabled the Qt mappings again
|
||||
- name: Prepare CMake
|
||||
run: |
|
||||
cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -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
|
||||
run: |
|
||||
|
@ -140,7 +140,7 @@ jobs:
|
|||
|
||||
- name: Prepare CMake
|
||||
run: |
|
||||
cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -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:
|
||||
CC: clang-17
|
||||
CXX: clang++-17
|
||||
|
|
1
AUTHORS
1
AUTHORS
|
@ -221,6 +221,7 @@ Lukas Grützmacher
|
|||
Lukasz Czajczyk
|
||||
Łukasz Jankowski
|
||||
Luxon Jean-Pierre
|
||||
Maarten van der Schrieck
|
||||
Maksim Derbasov
|
||||
Malcolm Parsons
|
||||
Marc-Antoine Perennou
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
project(Cppcheck)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
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)
|
||||
use_cxx11()
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(cmake/ccache.cmake)
|
||||
include(cmake/compilerCheck.cmake)
|
||||
include(cmake/versions.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
|
||||
$(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
|
||||
|
||||
$(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.
|
||||
- misra_9.py
|
||||
Implementation of the MISRA 9.x rules used by `misra` addon.
|
||||
- naming.json
|
||||
- namingng.config.json
|
||||
Example configuration for `namingng` addon.
|
||||
- namingng.json
|
||||
Example JSON file that can be used using --addon=namingng.json, referring to namingng.py and namingng.config.json
|
||||
- ROS_naming.json
|
||||
Example configuration for the `namingng` addon enforcing the [ROS naming convention for C++ ](http://wiki.ros.org/CppStyleGuide#Files).
|
||||
- runaddon.py
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"RE_FILE": {".*[A-Z]": [true, "under_scored"]},
|
||||
"RE_FILE": [".*[A-Z]"],
|
||||
"RE_NAMESPACE": {".*[A-Z]": [true, "under_scored"],
|
||||
".*\\_$": [true, "under_scored"]},
|
||||
"RE_FUNCTIONNAME": {".*\\_": [true, "camelCase"],
|
||||
|
|
|
@ -1619,11 +1619,11 @@ def is_suppressed(location, message, errorId):
|
|||
return True
|
||||
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:
|
||||
msg = { 'file': location.file,
|
||||
'linenr': location.linenr,
|
||||
'column': location.column,
|
||||
'column': location.column if columnOverride is None else columnOverride,
|
||||
'severity': severity,
|
||||
'message': message,
|
||||
'addon': addon,
|
||||
|
|
|
@ -311,8 +311,7 @@ class InitializerParser:
|
|||
if self.ed and self.ed.isValue:
|
||||
if not isDesignated and len(self.rootStack) > 0 and self.rootStack[-1][1] == self.root:
|
||||
self.rootStack[-1][0].markStuctureViolation(self.token)
|
||||
|
||||
if isFirstElement and self.token.str == '0' and self.token.next.str == '}':
|
||||
if isFirstElement and self.token.isInt and self.token.getKnownIntValue() == 0 and self.token.next.str == '}':
|
||||
# Zero initializer causes recursive initialization
|
||||
self.root.initializeChildren()
|
||||
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_PRIVATE_MEMBER_VARIABLE": null,
|
||||
"RE_FUNCTIONNAME": ["[a-z0-9A-Z]*\\Z"],
|
||||
"include_guard": {
|
||||
"input": "path",
|
||||
"prefix": "",
|
||||
"suffix": "",
|
||||
"case": "upper",
|
||||
"max_linenr": 5,
|
||||
"RE_HEADERFILE": "[^/].*\\.h\\Z",
|
||||
"required": true
|
||||
},
|
||||
"var_prefixes": {"uint32_t": "ui32",
|
||||
"int*": "intp"},
|
||||
"function_prefixes": {"uint16_t": "ui16",
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"script":"namingng.py",
|
||||
"args":[
|
||||
"--configfile=namingng.config.json"
|
||||
]
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
# cppcheck addon for naming conventions
|
||||
# An enhanced version. Configuration is taken from a json file
|
||||
# It supports to check for type-based prefixes in function or variable names.
|
||||
# Aside from include guard naming, include guard presence can also be tested.
|
||||
#
|
||||
# Example usage (variable name must start with lowercase, function name must start with uppercase):
|
||||
# $ cppcheck --dump path-to-src/
|
||||
|
@ -11,9 +12,18 @@
|
|||
# JSON format:
|
||||
#
|
||||
# {
|
||||
# "RE_VARNAME": "[a-z]*[a-zA-Z0-9_]*\\Z",
|
||||
# "RE_VARNAME": ["[a-z]*[a-zA-Z0-9_]*\\Z"],
|
||||
# "RE_PRIVATE_MEMBER_VARIABLE": null,
|
||||
# "RE_FUNCTIONNAME": "[a-z0-9A-Z]*\\Z",
|
||||
# "RE_FUNCTIONNAME": ["[a-z0-9A-Z]*\\Z"],
|
||||
# "_comment": "comments can be added to the config with underscore-prefixed keys",
|
||||
# "include_guard": {
|
||||
# "input": "path",
|
||||
# "prefix": "GUARD_",
|
||||
# "case": "upper",
|
||||
# "max_linenr": 5,
|
||||
# "RE_HEADERFILE": "[^/].*\\.h\\Z",
|
||||
# "required": true
|
||||
# },
|
||||
# "var_prefixes": {"uint32_t": "ui32"},
|
||||
# "function_prefixes": {"uint16_t": "ui16",
|
||||
# "uint32_t": "ui32"}
|
||||
|
@ -24,230 +34,386 @@
|
|||
|
||||
import cppcheckdata
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import argparse
|
||||
import json
|
||||
|
||||
|
||||
# Auxiliary class
|
||||
class DataStruct:
|
||||
def __init__(self, file, linenr, string):
|
||||
def __init__(self, file, linenr, string, column=0):
|
||||
self.file = file
|
||||
self.linenr = linenr
|
||||
self.str = string
|
||||
self.column = column
|
||||
|
||||
def reportNamingError(location,message,errorId='namingConvention',severity='style',extra='',column=None):
|
||||
cppcheckdata.reportError(location,severity,message,'namingng',errorId,extra,columnOverride=column)
|
||||
|
||||
def reportError(filename, linenr, severity, msg):
|
||||
message = "[{filename}:{linenr}] ( {severity} ) naming.py: {msg}\n".format(
|
||||
filename=filename,
|
||||
linenr=linenr,
|
||||
severity=severity,
|
||||
msg=msg
|
||||
)
|
||||
sys.stderr.write(message)
|
||||
return message
|
||||
def configError(error,fatal=True):
|
||||
print('config error: %s'%error)
|
||||
if fatal:
|
||||
sys.exit(1)
|
||||
|
||||
def validateConfigREs(list_or_dict,json_key):
|
||||
have_error = False
|
||||
for item in list_or_dict:
|
||||
try:
|
||||
re.compile(item)
|
||||
except re.error as err:
|
||||
configError("item '%s' of '%s' is not a valid regular expression: %s"%(item,json_key,err),fatal=False)
|
||||
have_error = True
|
||||
continue
|
||||
if not isinstance(list_or_dict,dict):
|
||||
continue
|
||||
# item is actually a dict key; check value
|
||||
value = list_or_dict[item]
|
||||
if (not isinstance(value,list) or len(value) != 2
|
||||
or not isinstance(value[0],bool) or not isinstance(value[1],str)):
|
||||
configError("item '%s' of '%s' must be an array [bool,string]"%(item,json_key),fatal=False)
|
||||
have_error = True
|
||||
|
||||
return have_error
|
||||
|
||||
def loadConfig(configfile):
|
||||
with open(configfile) as fh:
|
||||
data = json.load(fh)
|
||||
return data
|
||||
if not os.path.exists(configfile):
|
||||
configError("cannot find config file '%s'"%configfile)
|
||||
|
||||
try:
|
||||
with open(configfile) as fh:
|
||||
data = json.load(fh)
|
||||
except json.JSONDecodeError as e:
|
||||
configError("error parsing config file as JSON at line %d: %s"%(e.lineno,e.msg))
|
||||
except Exception as e:
|
||||
configError("error opening config file '%s': %s"%(configfile,e))
|
||||
|
||||
if not isinstance(data, dict):
|
||||
configError('config file must contain a JSON object at the top level')
|
||||
|
||||
# All errors are emitted before bailing out, to make the unit test more
|
||||
# effective.
|
||||
have_error = False
|
||||
|
||||
# Put config items in a class, so that settings can be accessed using
|
||||
# config.feature
|
||||
class Config:
|
||||
pass
|
||||
config = Config()
|
||||
|
||||
mapping = {
|
||||
'file': ('RE_FILE', (list,)),
|
||||
'namespace': ('RE_NAMESPACE', (list,dict)),
|
||||
'include_guard': ('include_guard', (dict,)),
|
||||
'variable': ('RE_VARNAME', (list,dict)),
|
||||
'variable_prefixes': ('var_prefixes', (dict,), {}),
|
||||
'private_member': ('RE_PRIVATE_MEMBER_VARIABLE', (list,dict)),
|
||||
'public_member': ('RE_PUBLIC_MEMBER_VARIABLE', (list,dict)),
|
||||
'global_variable': ('RE_GLOBAL_VARNAME', (list,dict)),
|
||||
'function_name': ('RE_FUNCTIONNAME', (list,dict)),
|
||||
'function_prefixes': ('function_prefixes', (dict,), {}),
|
||||
'class_name': ('RE_CLASS_NAME', (list,dict)),
|
||||
'skip_one_char_variables': ('skip_one_char_variables', (bool,)),
|
||||
}
|
||||
|
||||
# parse defined keys and store as members of config object
|
||||
for key,opts in mapping.items():
|
||||
json_key = opts[0]
|
||||
req_type = opts[1]
|
||||
default = None if len(opts)<3 else opts[2]
|
||||
|
||||
value = data.pop(json_key,default)
|
||||
if value is not None and type(value) not in req_type:
|
||||
req_typename = ' or '.join([tp.__name__ for tp in req_type])
|
||||
got_typename = type(value).__name__
|
||||
configError('%s must be %s (not %s), or not set'%(json_key,req_typename,got_typename),fatal=False)
|
||||
have_error = True
|
||||
continue
|
||||
|
||||
# type list implies that this is either a list of REs or a dict with RE keys
|
||||
if list in req_type and value is not None:
|
||||
re_error = validateConfigREs(value,json_key)
|
||||
if re_error:
|
||||
have_error = True
|
||||
|
||||
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):
|
||||
res = re.match(expr, data.str)
|
||||
if res:
|
||||
errors.append(reportError(data.file, data.linenr, 'style', msg))
|
||||
def evalExpr(conf, exp, mockToken, msgType):
|
||||
report_as_error = False
|
||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention'
|
||||
|
||||
|
||||
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 conf[exp][0]:
|
||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
|
||||
checkTrueRegex(mockToken, exp, msg, errors)
|
||||
elif ~conf[exp][0]:
|
||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
|
||||
checkFalseRegex(mockToken, exp, msg, errors)
|
||||
else:
|
||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][0]
|
||||
checkFalseRegex(mockToken, exp, msg, errors)
|
||||
report_as_error = conf[exp][0]
|
||||
msg += ': ' + conf[exp][1]
|
||||
|
||||
res = re.match(exp,mockToken.str)
|
||||
if bool(res) == report_as_error:
|
||||
reportNamingError(mockToken,msg)
|
||||
|
||||
def check_include_guard_name(conf,directive):
|
||||
parts = directive.str.split()
|
||||
if len(parts) != 2:
|
||||
msg = 'syntax error'
|
||||
reportNamingError(directive,msg,'syntax')
|
||||
return None,None
|
||||
guard_name = parts[1]
|
||||
guard_column = 1+directive.str.find(guard_name)
|
||||
|
||||
filename = directive.file
|
||||
if conf.include_guard.get('input','path') == 'basename':
|
||||
filename = os.path.basename(filename)
|
||||
use_case = conf.include_guard.get('case','upper')
|
||||
if use_case == 'upper':
|
||||
filename = filename.upper()
|
||||
elif use_case == 'lower':
|
||||
filename = filename.lower()
|
||||
elif use_case == 'keep':
|
||||
pass # keep filename case as-is
|
||||
else:
|
||||
msg = msgType + ' ' + mockToken.str + ' violates naming convention'
|
||||
checkFalseRegex(mockToken, exp, msg, errors)
|
||||
print("invalid config value for 'case': '%s'"%use_case,file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
if not afile[-5:] == '.dump':
|
||||
continue
|
||||
print('Checking ' + afile + '...')
|
||||
if not args.cli:
|
||||
print('Checking ' + afile + '...')
|
||||
data = cppcheckdata.CppcheckData(afile)
|
||||
process_data(conf,data)
|
||||
|
||||
# Check File naming
|
||||
if "RE_FILE" in conf and conf["RE_FILE"]:
|
||||
mockToken = DataStruct(afile[:-5], "0", afile[afile.rfind('/') + 1:-5])
|
||||
msgType = 'File name'
|
||||
for exp in conf["RE_FILE"]:
|
||||
evalExpr(conf["RE_FILE"], exp, mockToken, msgType, errors)
|
||||
def check_file_naming(conf,data):
|
||||
for source_file in data.files:
|
||||
basename = os.path.basename(source_file)
|
||||
good = False
|
||||
for exp in conf.file:
|
||||
good |= bool(re.match(exp, source_file))
|
||||
good |= bool(re.match(exp, basename))
|
||||
if not good:
|
||||
mockToken = DataStruct(source_file, 0, basename)
|
||||
reportNamingError(mockToken, 'File name ' + basename + ' violates naming convention')
|
||||
|
||||
# Check Namespace naming
|
||||
if "RE_NAMESPACE" in conf and conf["RE_NAMESPACE"]:
|
||||
for tk in data.rawTokens:
|
||||
if tk.str == 'namespace':
|
||||
mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str)
|
||||
msgType = 'Namespace'
|
||||
for exp in conf["RE_NAMESPACE"]:
|
||||
evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors)
|
||||
def check_namespace_naming(conf,data):
|
||||
for tk in data.rawTokens:
|
||||
if tk.str != 'namespace':
|
||||
continue
|
||||
mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str, tk.next.column)
|
||||
for exp in conf.namespace:
|
||||
evalExpr(conf.namespace, exp, mockToken, 'Namespace')
|
||||
|
||||
for cfg in data.configurations:
|
||||
print('Checking %s, config %s...' % (afile, cfg.name))
|
||||
if "RE_VARNAME" in conf and conf["RE_VARNAME"]:
|
||||
for var in cfg.variables:
|
||||
if var.nameToken and var.access != 'Global' and var.access != 'Public' and var.access != 'Private':
|
||||
prev = var.nameToken.previous
|
||||
varType = prev.str
|
||||
while "*" in varType and len(varType.replace("*", "")) == 0:
|
||||
prev = prev.previous
|
||||
varType = prev.str + varType
|
||||
def check_variable_naming(conf,cfg):
|
||||
for var in cfg.variables:
|
||||
if not var.nameToken:
|
||||
continue
|
||||
if var.access in ('Global','Public','Private'):
|
||||
continue
|
||||
prev = var.nameToken.previous
|
||||
varType = prev.str
|
||||
while "*" in varType and len(varType.replace("*", "")) == 0:
|
||||
prev = prev.previous
|
||||
varType = prev.str + varType
|
||||
|
||||
if debugprint:
|
||||
print("Variable Name: " + str(var.nameToken.str))
|
||||
print("original Type Name: " + str(var.nameToken.valueType.originalTypeName))
|
||||
print("Type Name: " + var.nameToken.valueType.type)
|
||||
print("Sign: " + str(var.nameToken.valueType.sign))
|
||||
print("variable type: " + varType)
|
||||
print("\n")
|
||||
print("\t-- {} {}".format(varType, str(var.nameToken.str)))
|
||||
if args.debugprint:
|
||||
print("Variable Name: " + str(var.nameToken.str))
|
||||
print("original Type Name: " + str(var.nameToken.valueType.originalTypeName))
|
||||
print("Type Name: " + var.nameToken.valueType.type)
|
||||
print("Sign: " + str(var.nameToken.valueType.sign))
|
||||
print("variable type: " + varType)
|
||||
print("\n")
|
||||
print("\t-- {} {}".format(varType, str(var.nameToken.str)))
|
||||
|
||||
if conf["skip_one_char_variables"] and len(var.nameToken.str) == 1:
|
||||
continue
|
||||
if varType in conf["var_prefixes"]:
|
||||
if not var.nameToken.str.startswith(conf["var_prefixes"][varType]):
|
||||
errors.append(reportError(
|
||||
var.typeStartToken.file,
|
||||
var.typeStartToken.linenr,
|
||||
'style',
|
||||
'Variable ' +
|
||||
var.nameToken.str +
|
||||
' violates naming convention'))
|
||||
if conf.skip_one_char_variables and len(var.nameToken.str) == 1:
|
||||
continue
|
||||
if varType in conf.variable_prefixes:
|
||||
prefix = conf.variable_prefixes[varType]
|
||||
if not var.nameToken.str.startswith(prefix):
|
||||
reportNamingError(var.typeStartToken,
|
||||
'Variable ' +
|
||||
var.nameToken.str +
|
||||
' violates naming convention',
|
||||
column=var.nameToken.column)
|
||||
|
||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
||||
msgType = 'Variable'
|
||||
for exp in conf["RE_VARNAME"]:
|
||||
evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType, errors)
|
||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column)
|
||||
for exp in conf.variable:
|
||||
evalExpr(conf.variable, exp, mockToken, 'Variable')
|
||||
|
||||
# Check Private Variable naming
|
||||
if "RE_PRIVATE_MEMBER_VARIABLE" in conf and conf["RE_PRIVATE_MEMBER_VARIABLE"]:
|
||||
# TODO: Not converted yet
|
||||
for var in cfg.variables:
|
||||
if (var.access is None) or var.access != 'Private':
|
||||
continue
|
||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
||||
msgType = 'Private member variable'
|
||||
for exp in conf["RE_PRIVATE_MEMBER_VARIABLE"]:
|
||||
evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
|
||||
# Naming check for Global, Private and Public member variables
|
||||
def check_gpp_naming(conf_list,cfg,access,message):
|
||||
for var in cfg.variables:
|
||||
if var.access != access:
|
||||
continue
|
||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str, var.nameToken.column)
|
||||
for exp in conf_list:
|
||||
evalExpr(conf_list, exp, mockToken, message)
|
||||
|
||||
# Check Public Member Variable naming
|
||||
if "RE_PUBLIC_MEMBER_VARIABLE" in conf and conf["RE_PUBLIC_MEMBER_VARIABLE"]:
|
||||
for var in cfg.variables:
|
||||
if (var.access is None) or var.access != 'Public':
|
||||
continue
|
||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
||||
msgType = 'Public member variable'
|
||||
for exp in conf["RE_PUBLIC_MEMBER_VARIABLE"]:
|
||||
evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
|
||||
def check_function_naming(conf,cfg):
|
||||
for token in cfg.tokenlist:
|
||||
if not token.function:
|
||||
continue
|
||||
if token.function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
|
||||
continue
|
||||
retval = token.previous.str
|
||||
prev = token.previous
|
||||
while "*" in retval and len(retval.replace("*", "")) == 0:
|
||||
prev = prev.previous
|
||||
retval = prev.str + retval
|
||||
if args.debugprint:
|
||||
print("\t:: {} {}".format(retval, token.function.name))
|
||||
|
||||
# Check Global Variable naming
|
||||
if "RE_GLOBAL_VARNAME" in conf and conf["RE_GLOBAL_VARNAME"]:
|
||||
for var in cfg.variables:
|
||||
if (var.access is None) or var.access != 'Global':
|
||||
continue
|
||||
mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
|
||||
msgType = 'Public member variable'
|
||||
for exp in conf["RE_GLOBAL_VARNAME"]:
|
||||
evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType, errors)
|
||||
if retval and retval in conf.function_prefixes:
|
||||
if not token.function.name.startswith(conf.function_prefixes[retval]):
|
||||
reportNamingError(token, 'Function ' + token.function.name + ' violates naming convention', column=token.column)
|
||||
mockToken = DataStruct(token.file, token.linenr, token.function.name, token.column)
|
||||
msgType = 'Function'
|
||||
for exp in conf.function_name:
|
||||
evalExpr(conf.function_name, exp, mockToken, msgType)
|
||||
|
||||
# Check Functions naming
|
||||
if "RE_FUNCTIONNAME" in conf and conf["RE_FUNCTIONNAME"]:
|
||||
for token in cfg.tokenlist:
|
||||
if token.function:
|
||||
if token.function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
|
||||
continue
|
||||
retval = token.previous.str
|
||||
prev = token.previous
|
||||
while "*" in retval and len(retval.replace("*", "")) == 0:
|
||||
prev = prev.previous
|
||||
retval = prev.str + retval
|
||||
if debugprint:
|
||||
print("\t:: {} {}".format(retval, token.function.name))
|
||||
def check_class_naming(conf,cfg):
|
||||
for fnc in cfg.functions:
|
||||
if fnc.type not in ('Constructor','Destructor'):
|
||||
continue
|
||||
mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name, fnc.tokenDef.column)
|
||||
msgType = 'Class ' + fnc.type
|
||||
for exp in conf.class_name:
|
||||
evalExpr(conf.class_name, exp, mockToken, msgType)
|
||||
|
||||
if retval and retval in conf["function_prefixes"]:
|
||||
if not token.function.name.startswith(conf["function_prefixes"][retval]):
|
||||
errors.append(reportError(
|
||||
token.file, token.linenr, 'style', 'Function ' + token.function.name + ' violates naming convention'))
|
||||
mockToken = DataStruct(token.file, token.linenr, token.function.name)
|
||||
msgType = 'Function'
|
||||
for exp in conf["RE_FUNCTIONNAME"]:
|
||||
evalExpr(conf["RE_FUNCTIONNAME"], exp, mockToken, msgType, errors)
|
||||
def process_data(conf,data):
|
||||
if conf.file:
|
||||
check_file_naming(conf,data)
|
||||
|
||||
# Check Class naming
|
||||
if "RE_CLASS_NAME" in conf and conf["RE_CLASS_NAME"]:
|
||||
for fnc in cfg.functions:
|
||||
# Check if it is Constructor/Destructor
|
||||
if fnc.type == 'Constructor' or fnc.type == 'Destructor':
|
||||
mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name)
|
||||
msgType = 'Class ' + fnc.type
|
||||
for exp in conf["RE_CLASS_NAME"]:
|
||||
evalExpr(conf["RE_CLASS_NAME"], exp, mockToken, msgType, errors)
|
||||
return errors
|
||||
if conf.namespace:
|
||||
check_namespace_naming(conf,data)
|
||||
|
||||
unguarded_include_files = []
|
||||
if conf.include_guard and conf.include_guard.get('required',1):
|
||||
unguarded_include_files = [fn for fn in data.files if re.match(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__":
|
||||
parser = argparse.ArgumentParser(description='Naming verification')
|
||||
parser.add_argument('dumpfiles', type=str, nargs='+',
|
||||
help='A set of dumpfiles to process')
|
||||
parser = cppcheckdata.ArgumentParser()
|
||||
parser.add_argument("--debugprint", action="store_true", default=False,
|
||||
help="Add debug prints")
|
||||
parser.add_argument("--configfile", type=str, default="naming.json",
|
||||
parser.add_argument("--configfile", type=str, default="namingng.config.json",
|
||||
help="Naming check config file")
|
||||
parser.add_argument("--verify", action="store_true", default=False,
|
||||
help="verify this script. Must be executed in test folder !")
|
||||
|
||||
args = parser.parse_args()
|
||||
errors = process(args.dumpfiles, args.configfile, args.debugprint)
|
||||
|
||||
if args.verify:
|
||||
print(errors)
|
||||
if len(errors) < 6:
|
||||
print("Not enough errors found")
|
||||
sys.exit(1)
|
||||
target = [
|
||||
'[namingng_test.c:8] ( style ) naming.py: Variable badui32 violates naming convention\n',
|
||||
'[namingng_test.c:11] ( style ) naming.py: Variable a violates naming convention\n',
|
||||
'[namingng_test.c:29] ( style ) naming.py: Variable badui32 violates naming convention\n',
|
||||
'[namingng_test.c:20] ( style ) naming.py: Function ui16bad_underscore violates naming convention\n',
|
||||
'[namingng_test.c:25] ( style ) naming.py: Function u32Bad violates naming convention\n',
|
||||
'[namingng_test.c:37] ( style ) naming.py: Function Badui16 violates naming convention\n']
|
||||
diff = set(errors) - set(target)
|
||||
if len(diff):
|
||||
print("Not the right errors found {}".format(str(diff)))
|
||||
sys.exit(1)
|
||||
print("Verification done\n")
|
||||
sys.exit(0)
|
||||
|
||||
if len(errors):
|
||||
print('Found errors: {}'.format(len(errors)))
|
||||
sys.exit(1)
|
||||
process(args.dumpfile, args.configfile)
|
||||
|
||||
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 f[5] = { 0 };
|
||||
int f1[5] = { 0u }; // no-warning #11298
|
||||
int g[5][2] = { 0 };
|
||||
int h[2][2] = { { 0 } }; // 9.3
|
||||
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"/>
|
||||
<!-- TODO: Configure cairo_status_t as an enum when this is implemented in Cppcheck -->
|
||||
<podtype name="cairo_status_t"/>
|
||||
<define name="CAIRO_STATUS_READ_ERROR" value="10"/>
|
||||
<!-- ########## cairo Macros / Defines ########## -->
|
||||
<define name="CAIRO_HAS_MIME_SURFACE" value="1"/>
|
||||
<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 -->
|
||||
<!-- Now it is maintained and extended manually. -->
|
||||
<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_val_if_fail(expr, val)" value="do{if(!(expr)){return val;}}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_not_reached()" value="assert(NULL)"/>
|
||||
<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_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_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_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_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)"/>
|
||||
|
|
|
@ -4179,6 +4179,30 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
|
|||
<valid>0:</valid>
|
||||
</arg>
|
||||
</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 -->
|
||||
<!-- char *asctime_r(const struct tm *tm, char *buf); -->
|
||||
<function name="asctime_r">
|
||||
|
|
18
cfg/std.cfg
18
cfg/std.cfg
|
@ -737,6 +737,7 @@
|
|||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- https://en.cppreference.com/w/cpp/numeric/math/tgamma -->
|
||||
<!-- double tgamma(double x); -->
|
||||
<function name="tgamma,std::tgamma">
|
||||
<use-retval/>
|
||||
|
@ -746,8 +747,11 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1" direction="in">
|
||||
<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>
|
||||
</function>
|
||||
<!-- https://en.cppreference.com/w/cpp/numeric/math/tgamma -->
|
||||
<!-- float tgammaf(float x); -->
|
||||
<function name="tgammaf,std::tgammaf">
|
||||
<use-retval/>
|
||||
|
@ -757,8 +761,11 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1" direction="in">
|
||||
<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>
|
||||
</function>
|
||||
<!-- https://en.cppreference.com/w/cpp/numeric/math/tgamma -->
|
||||
<!-- long double tgammal(long double x); -->
|
||||
<function name="tgammal,std::tgammal">
|
||||
<use-retval/>
|
||||
|
@ -768,6 +775,8 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1" direction="in">
|
||||
<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>
|
||||
</function>
|
||||
<!-- double trunc(double x); -->
|
||||
|
@ -3035,6 +3044,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- https://cplusplus.com/reference/cmath/lgamma/ -->
|
||||
<!-- double lgamma(double x); -->
|
||||
<function name="lgamma,std::lgamma">
|
||||
<use-retval/>
|
||||
|
@ -3044,8 +3054,11 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<leak-ignore/>
|
||||
<arg nr="1" direction="in">
|
||||
<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>
|
||||
</function>
|
||||
<!-- https://cplusplus.com/reference/cmath/lgamma/ -->
|
||||
<!-- float lgammaf(float x); -->
|
||||
<function name="lgammaf,std::lgammaf">
|
||||
<use-retval/>
|
||||
|
@ -3055,8 +3068,11 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<leak-ignore/>
|
||||
<arg nr="1" direction="in">
|
||||
<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>
|
||||
</function>
|
||||
<!-- https://cplusplus.com/reference/cmath/lgamma/ -->
|
||||
<!-- long double lgammal(long double x); -->
|
||||
<function name="lgammal,std::lgammal">
|
||||
<use-retval/>
|
||||
|
@ -3066,6 +3082,8 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<leak-ignore/>
|
||||
<arg nr="1" direction="in">
|
||||
<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>
|
||||
</function>
|
||||
<!-- double rint(double x); -->
|
||||
|
|
|
@ -6,11 +6,11 @@ list(REMOVE_ITEM srcs ${mainfile})
|
|||
add_library(cli_objs OBJECT ${hdrs} ${srcs})
|
||||
target_include_directories(cli_objs PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
||||
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()
|
||||
target_include_directories(cli_objs SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||
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)
|
||||
target_precompile_headers(cli_objs PRIVATE precompiled.h)
|
||||
endif()
|
||||
|
@ -38,11 +38,11 @@ endif()
|
|||
add_executable(cppcheck ${cppcheck_SOURCES})
|
||||
target_include_directories(cppcheck PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
||||
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()
|
||||
target_include_directories(cppcheck SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||
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)
|
||||
target_link_libraries(cppcheck ${PCRE_LIBRARY})
|
||||
endif()
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib> // EXIT_FAILURE
|
||||
#include <cstring>
|
||||
|
@ -797,9 +798,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
|
|||
}
|
||||
|
||||
if (str == "c")
|
||||
mSettings.enforcedLang = Settings::Language::C;
|
||||
mSettings.enforcedLang = Standards::Language::C;
|
||||
else if (str == "c++")
|
||||
mSettings.enforcedLang = Settings::Language::CPP;
|
||||
mSettings.enforcedLang = Standards::Language::CPP;
|
||||
else {
|
||||
mLogger.printError("unknown language '" + str + "' enforced.");
|
||||
return Result::Fail;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib> // EXIT_SUCCESS and EXIT_FAILURE
|
||||
#include <ctime>
|
||||
|
@ -49,6 +50,7 @@
|
|||
#include <list>
|
||||
#include <set>
|
||||
#include <sstream> // IWYU pragma: keep
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -217,21 +219,29 @@ int CppCheckExecutor::check_wrapper(CppCheck& 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) {
|
||||
const auto& suppressions = settings.nomsg.getSuppressions();
|
||||
if (std::any_of(suppressions.begin(), suppressions.end(), [](const Suppressions::Suppression& s) {
|
||||
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& suppr = suppressions.getSuppressions();
|
||||
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 false;
|
||||
|
||||
bool err = false;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -277,7 +287,7 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) const
|
|||
cppcheck.analyseWholeProgram(settings.buildDir, mFiles, mFileSettings);
|
||||
|
||||
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)
|
||||
returnValue = settings.exitCode;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
class CppCheck;
|
||||
class Settings;
|
||||
class ErrorLogger;
|
||||
class Suppressions;
|
||||
|
||||
/**
|
||||
* This class works as an example of how CppCheck can be used in external
|
||||
|
@ -48,7 +49,7 @@ public:
|
|||
*/
|
||||
CppCheckExecutor() = default;
|
||||
CppCheckExecutor(const CppCheckExecutor &) = delete;
|
||||
void operator=(const CppCheckExecutor&) = delete;
|
||||
CppCheckExecutor& operator=(const CppCheckExecutor&) = delete;
|
||||
|
||||
/**
|
||||
* Starts the checking.
|
||||
|
@ -81,7 +82,7 @@ private:
|
|||
|
||||
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
|
||||
|
|
|
@ -109,7 +109,7 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context)
|
|||
pid_t killid;
|
||||
// TODO: separate these two defines
|
||||
#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);
|
||||
if (uc) {
|
||||
type = (int)uc->uc_mcontext.gregs[REG_ERR] & 2;
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
|
||||
#include "color.h"
|
||||
#include "errorlogger.h"
|
||||
#include "library.h"
|
||||
#include "settings.h"
|
||||
#include "suppressions.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <sstream> // IWYU pragma: keep
|
||||
#include <utility>
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
virtual ~Executor() = default;
|
||||
|
||||
Executor(const Executor &) = delete;
|
||||
void operator=(const Executor &) = delete;
|
||||
Executor& operator=(const Executor &) = delete;
|
||||
|
||||
virtual unsigned int check() = 0;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
/**
|
||||
*
|
||||
* @mainpage Cppcheck
|
||||
* @version 2.12.99
|
||||
* @version 2.13.99
|
||||
*
|
||||
* @section overview_sec Overview
|
||||
* 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
|
||||
{
|
||||
{
|
||||
const char t = static_cast<char>(type);
|
||||
const auto t = static_cast<char>(type);
|
||||
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);
|
||||
writeToPipeInternal(type, &len, l_size);
|
||||
|
|
|
@ -43,7 +43,7 @@ class ProcessExecutor : public Executor {
|
|||
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 ProcessExecutor &) = delete;
|
||||
void operator=(const ProcessExecutor &) = delete;
|
||||
ProcessExecutor& operator=(const ProcessExecutor &) = delete;
|
||||
|
||||
unsigned int check() override;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class SingleExecutor : public Executor
|
|||
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(const SingleExecutor &) = delete;
|
||||
void operator=(const SingleExecutor &) = delete;
|
||||
SingleExecutor& operator=(const SingleExecutor &) = delete;
|
||||
|
||||
unsigned int check() override;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class ThreadExecutor : public Executor {
|
|||
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 ThreadExecutor &) = delete;
|
||||
void operator=(const ThreadExecutor &) = delete;
|
||||
ThreadExecutor& operator=(const ThreadExecutor &) = delete;
|
||||
|
||||
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_VERSION VERSION_LESS 4.8)
|
||||
message(ERROR "GCC >= 4.8 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1)
|
||||
message(ERROR "GCC >= 5.1 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
||||
endif ()
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# TODO: verify this
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.9)
|
||||
message(ERROR "Clang >= 2.9 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
|
||||
message(ERROR "Clang >= 3.5 required - detected ${CMAKE_CXX_COMPILER_VERSION} not supported")
|
||||
endif ()
|
||||
elseif(MSVC)
|
||||
if (MSVC_VERSION VERSION_LESS 1800)
|
||||
message(ERROR "Visual Studio >= 2013 (1800) required - detected ${MSVC_VERSION} not supported")
|
||||
if (MSVC_VERSION VERSION_LESS 1900)
|
||||
message(ERROR "Visual Studio >= 2015 (19.0) required - detected ${MSVC_VERSION} not supported")
|
||||
endif ()
|
||||
endif()
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
if (MSVC)
|
||||
# add_compile_definitions() requires CMake 3.12
|
||||
|
||||
# Visual Studio only sets _DEBUG
|
||||
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)
|
||||
|
||||
|
|
|
@ -16,6 +16,14 @@ function(target_compile_options_safe TARGET FLAG)
|
|||
endif()
|
||||
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")
|
||||
add_compile_options(-Weverything)
|
||||
endif()
|
||||
|
@ -77,7 +85,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|||
|
||||
if (USE_LIBCXX)
|
||||
add_compile_options(-stdlib=libc++)
|
||||
add_link_options(-lc++)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++")
|
||||
endif()
|
||||
|
||||
# TODO: fix and enable these warnings - or move to suppression list below
|
||||
|
@ -125,6 +133,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|||
endif()
|
||||
|
||||
if (MSVC)
|
||||
# add_link_options() requires CMake 3.13
|
||||
|
||||
# General
|
||||
add_compile_options(/W4) # Warning Level
|
||||
add_compile_options(/Zi) # Debug Information Format - Program Database
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
macro(use_cxx11)
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif ()
|
||||
# some GitHub Action Windows runners randomly fail with a complaint that Qt6 requires a C++17 compiler
|
||||
if (MSVC AND USE_QT6)
|
||||
# CMAKE_CXX_STANDARD 17 was added in CMake 3.8
|
||||
set (CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to use")
|
||||
else ()
|
||||
# some GitHub Action windows runners randomly fail with a complaint that Qt6 requires a C++17 compiler
|
||||
if (MSVC)
|
||||
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 ()
|
||||
set (CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to use")
|
||||
endif()
|
||||
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_UNDEFINED "Clang dynamic analyzer: undefined behavior checker. " OFF)
|
||||
option(ANALYZE_DATAFLOW "Clang dynamic analyzer: general dynamic dataflow analysis." 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_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")
|
||||
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_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 "CMake Version = ${CMAKE_VERSION}")
|
||||
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_UNDEFINED = ${ANALYZE_UNDEFINED}" )
|
||||
message( STATUS "ANALYZE_DATAFLOW = ${ANALYZE_DATAFLOW}" )
|
||||
message( STATUS )
|
||||
message( STATUS "WARNINGS_ARE_ERRORS = ${WARNINGS_ARE_ERRORS}" )
|
||||
message( STATUS "EXTERNALS_AS_SYSTEM = ${EXTERNALS_AS_SYSTEM}" )
|
||||
message( STATUS )
|
||||
message( STATUS "USE_MATCHCOMPILER = ${USE_MATCHCOMPILER}" )
|
||||
message( STATUS "USE_MATCHCOMPILER_OPT = ${USE_MATCHCOMPILER_OPT}" )
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
# Version for libraries CPP
|
||||
# Version string must have 3 "parts". https://sourceforge.net/p/cppcheck/discussion/development/thread/e57efb2b62/
|
||||
SET(VERSION "2.12.99")
|
||||
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}")
|
||||
SET(SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
|
||||
# Postfix of so's:
|
||||
SET(DLLVERSION "")
|
||||
|
|
|
@ -37,11 +37,11 @@
|
|||
# - empty the releasenotes.txt in main branch
|
||||
#
|
||||
# Update version numbers in:
|
||||
# sed -i -r "s/version 2[.][0-9]+([.]99)*/version 2.9/" 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/MINOR [0-9]+/MINOR 9/" lib/version.h
|
||||
# sed -i -r "s/2[.][0-9]+([.]99)*/2.9/" win_installer/productInfo.wxi
|
||||
# sed -i -r "s/subtitle: Version 2\.[0-9]+/subtitle: Version 2.9/" man/*.md
|
||||
# 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.13.0|" cmake/versions.cmake # version must have 3 parts.
|
||||
# sed -i -r "s/CPPCHECK_MINOR_VERSION [0-9]+/CPPCHECK_MINOR_VERSION 13/" lib/version.h
|
||||
# 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.13/" man/*.md
|
||||
# Ensure that "-rc1" is added in productInfo.wxi and lib/version.h
|
||||
# Verify:
|
||||
# grep '\.99' */*.[ch]* && grep '[0-9][0-9] dev' */*.[ch]*
|
||||
|
@ -72,7 +72,7 @@
|
|||
# git tag 2.8 ; git push --tags
|
||||
# ./createrelease 2.8
|
||||
#
|
||||
# copy msi from release-windows
|
||||
# copy msi from release-windows, install and test cppcheck
|
||||
# copy manual from build-manual
|
||||
#
|
||||
# Update download link on index.php main page
|
||||
|
@ -96,13 +96,14 @@
|
|||
# ./build-cppcheck.sh
|
||||
#
|
||||
# run daca with new release
|
||||
# 1. edit tools/donate-cpu-server.py. Update OLD_VERSION and VERSION
|
||||
# 2. scp -i ../.ssh/osuosl_id_rsa tools/donate-cpu-server.py danielmarjamaki@cppcheck1.osuosl.org:/var/daca@home/
|
||||
# 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/
|
||||
#
|
||||
# Backup:
|
||||
# * trac: cd /var && nice tar -zcf /home/danielmarjamaki/trac.tar.gz trac-cppcheck
|
||||
# * git: git checkout -f && git checkout main && git pull && tar -zcf ~/cppchecksolutions/backups/2.12.0-git.tar.gz .git
|
||||
# * trac: cd /var && nice tar -cJf trac.tar.xz trac-cppcheck
|
||||
# * git: git checkout -f && git checkout main && git pull && tar -cJf git.tar.xz .git
|
||||
# * Changelog
|
||||
# * ci status: screenshot(s) showing that all tests pass for tagged commit
|
||||
|
||||
# Folder/tag to use
|
||||
folder=$1
|
||||
|
@ -132,8 +133,8 @@ rm $releasename.*
|
|||
cd ..
|
||||
|
||||
# Generate version.txt
|
||||
make -j4
|
||||
rm cppcheck.cfg
|
||||
make -j12
|
||||
rm -f cppcheck.cfg
|
||||
./cppcheck --version > upload/version.txt
|
||||
|
||||
cd ~/cppcheck/upload
|
||||
|
@ -149,7 +150,7 @@ cp -R ~/cppcheck/cfg .
|
|||
cp -R ~/cppcheck/addons .
|
||||
cp -R ~/cppcheck/platforms .
|
||||
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
|
||||
|
||||
git checkout main
|
||||
|
|
|
@ -38,7 +38,7 @@ CheckOptions:
|
|||
set_target_properties(cppcheck-gui PROPERTIES WIN32_EXECUTABLE ON)
|
||||
target_include_directories(cppcheck-gui PRIVATE ${PROJECT_SOURCE_DIR}/lib/)
|
||||
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()
|
||||
target_include_directories(cppcheck-gui SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
|
|
@ -112,7 +112,7 @@ of the GNU General Public License version 3</string>
|
|||
<item>
|
||||
<widget class="QLabel" name="mUsedLibs">
|
||||
<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>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <QChar>
|
||||
#include <QColor>
|
||||
#include <QCryptographicHash>
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QKeySequence>
|
||||
|
@ -37,7 +38,6 @@
|
|||
#include <QTextCursor>
|
||||
#include <QTextEdit>
|
||||
#include <QTextFormat>
|
||||
#include <QtCore>
|
||||
|
||||
class QTextDocument;
|
||||
|
||||
|
@ -287,11 +287,11 @@ CodeEditor::CodeEditor(QWidget *parent) :
|
|||
setStyleSheet(generateStyleString());
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QShortcut *copyText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_C),this);
|
||||
QShortcut *allText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_A),this);
|
||||
auto *copyText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_C),this);
|
||||
auto *allText = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_A),this);
|
||||
#else
|
||||
const QShortcut *copyText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C),this);
|
||||
const QShortcut *allText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A),this);
|
||||
const auto *copyText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C),this);
|
||||
const auto *allText = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A),this);
|
||||
#endif
|
||||
|
||||
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
||||
|
@ -448,15 +448,14 @@ void CodeEditor::lineNumberAreaPaintEvent(const QPaintEvent *event)
|
|||
QString CodeEditor::generateStyleString()
|
||||
{
|
||||
QString bgcolor = QString("background:rgb(%1,%2,%3);")
|
||||
.arg(mWidgetStyle->widgetBGColor.red())
|
||||
.arg(mWidgetStyle->widgetBGColor.green())
|
||||
.arg(mWidgetStyle->widgetBGColor.blue());
|
||||
.arg(mWidgetStyle->widgetBGColor.red(),
|
||||
mWidgetStyle->widgetBGColor.green(),
|
||||
mWidgetStyle->widgetBGColor.blue());
|
||||
QString fgcolor = QString("color:rgb(%1,%2,%3);")
|
||||
.arg(mWidgetStyle->widgetFGColor.red())
|
||||
.arg(mWidgetStyle->widgetFGColor.green())
|
||||
.arg(mWidgetStyle->widgetFGColor.blue());
|
||||
.arg(mWidgetStyle->widgetFGColor.red(),
|
||||
mWidgetStyle->widgetFGColor.green(),
|
||||
mWidgetStyle->widgetFGColor.blue());
|
||||
QString style = QString("%1 %2")
|
||||
.arg(bgcolor)
|
||||
.arg(fgcolor);
|
||||
.arg(bgcolor, fgcolor);
|
||||
return style;
|
||||
}
|
||||
|
|
|
@ -72,10 +72,10 @@ StyleEditDialog::StyleEditDialog(const CodeEditorStyle& newStyle,
|
|||
mStyleIncoming(newStyle),
|
||||
mStyleOutgoing(newStyle)
|
||||
{
|
||||
QVBoxLayout *vboxMain = new QVBoxLayout(this);
|
||||
QHBoxLayout *hboxEdit = new QHBoxLayout();
|
||||
auto *vboxMain = new QVBoxLayout(this);
|
||||
auto *hboxEdit = new QHBoxLayout();
|
||||
// Color/Weight controls
|
||||
QFormLayout *flEditControls = new QFormLayout();
|
||||
auto *flEditControls = new QFormLayout();
|
||||
mBtnWidgetColorFG = new SelectColorButton(this);
|
||||
flEditControls->addRow(QObject::tr("Editor Foreground Color"),
|
||||
mBtnWidgetColorFG);
|
||||
|
@ -141,7 +141,7 @@ StyleEditDialog::StyleEditDialog(const CodeEditorStyle& newStyle,
|
|||
vboxMain->addLayout(hboxEdit);
|
||||
|
||||
// Default Controls
|
||||
QHBoxLayout *hboxDefaultControls = new QHBoxLayout();
|
||||
auto *hboxDefaultControls = new QHBoxLayout();
|
||||
mBtnDefaultLight = new QPushButton(QObject::tr("Set to Default Light"),
|
||||
this);
|
||||
mBtnDefaultDark = new QPushButton(QObject::tr("Set to Default Dark"),
|
||||
|
@ -153,7 +153,7 @@ StyleEditDialog::StyleEditDialog(const CodeEditorStyle& newStyle,
|
|||
vboxMain->addLayout(hboxDefaultControls);
|
||||
vboxMain->addStretch(2);
|
||||
// dialog controls
|
||||
QDialogButtonBox *dBtnBox = new QDialogButtonBox(
|
||||
auto *dBtnBox = new QDialogButtonBox(
|
||||
QDialogButtonBox::Cancel |
|
||||
QDialogButtonBox::Ok |
|
||||
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
|
||||
// thus be sorted alphabetically over the descriptions.
|
||||
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(";;");
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QCoreApplication>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
@ -52,7 +53,6 @@
|
|||
#include <QStringList>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTextStream>
|
||||
#include <QtCore>
|
||||
|
||||
static void addHeaders(const QString& file1, QSet<QString> &allFiles) {
|
||||
if (allFiles.contains(file1))
|
||||
|
@ -170,7 +170,7 @@ void ComplianceReportDialog::save()
|
|||
} catch (InternalError &e) {
|
||||
QMessageBox msg(QMessageBox::Critical,
|
||||
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,
|
||||
this);
|
||||
msg.exec();
|
||||
|
|
|
@ -176,7 +176,7 @@ Parameters: -l(line) (file)</translation>
|
|||
<message>
|
||||
<location filename="compliancereportdialog.cpp" line="173"/>
|
||||
<source>Failed to import '%1' (%2), can not show files in compliance report</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>'%1' (%2)のインポートに失敗しました。コンプライアンスレポートに表示できません</translation>
|
||||
</message>
|
||||
<message>
|
||||
<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>
|
||||
<location filename="mainwindow.cpp" line="961"/>
|
||||
<source>Failed to load %1 - %2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>%1 - %2 の読み込みに失敗</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="1313"/>
|
||||
|
@ -1233,7 +1233,7 @@ Analysis is stopped.</source>
|
|||
<message>
|
||||
<location filename="mainwindow.cpp" line="1799"/>
|
||||
<source>Failed to import '%1' (%2), analysis is stopped</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>'%1' (%2) のインポートに失敗しました。解析は停止</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="2099"/>
|
||||
|
@ -2213,7 +2213,7 @@ Options:
|
|||
<message>
|
||||
<location filename="resultstree.cpp" line="347"/>
|
||||
<source>internal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>内部</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="resultstree.cpp" line="692"/>
|
||||
|
@ -2435,7 +2435,7 @@ To toggle what kind of errors are shown, open view menu.</source>
|
|||
<message>
|
||||
<location filename="resultsview.cpp" line="575"/>
|
||||
<source>when checking a file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>ファイルをチェックするとき</translation>
|
||||
</message>
|
||||
<message>
|
||||
<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'")
|
||||
.arg(xmlReader.lineNumber())
|
||||
.arg(attributeName)
|
||||
.arg(xmlReader.name().toString()).toStdString());
|
||||
.arg(attributeName, xmlReader.name().toString())
|
||||
.toStdString());
|
||||
}
|
||||
|
||||
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);
|
||||
QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line);
|
||||
line += QString("%1,%2,%3").arg(GuiSeverity::toString(error.severity)).arg(error.errorId).arg(error.summary);
|
||||
QString line = QString("%1,%2,").arg(file, error.errorPath.back().line);
|
||||
line += QString("%1,%2,%3").arg(GuiSeverity::toString(error.severity), error.errorId, error.summary);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
mTxtWriter << line << Qt::endl;
|
||||
#else
|
||||
|
|
|
@ -121,7 +121,7 @@ void LibraryDialog::openCfg()
|
|||
if (!errmsg.isNull()) {
|
||||
QMessageBox msg(QMessageBox::Critical,
|
||||
tr("Cppcheck"),
|
||||
tr("Failed to load %1. %2.").arg(selectedFile).arg(errmsg),
|
||||
tr("Failed to load %1. %2.").arg(selectedFile, errmsg),
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
msg.exec();
|
||||
|
@ -185,7 +185,7 @@ void LibraryDialog::saveCfgAs()
|
|||
|
||||
void LibraryDialog::addFunction()
|
||||
{
|
||||
LibraryAddFunctionDialog *d = new LibraryAddFunctionDialog;
|
||||
auto *d = new LibraryAddFunctionDialog;
|
||||
if (d->exec() == QDialog::Accepted && !d->functionName().isEmpty()) {
|
||||
|
||||
CppcheckLibraryData::Function f;
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <QtCore>
|
||||
|
||||
|
||||
static void ShowUsage();
|
||||
|
@ -59,7 +58,7 @@ int main(int argc, char *argv[])
|
|||
QCoreApplication::setOrganizationName("Cppcheck");
|
||||
QCoreApplication::setApplicationName("Cppcheck-GUI");
|
||||
|
||||
QSettings* settings = new QSettings("Cppcheck", "Cppcheck-GUI", &app);
|
||||
auto* settings = new QSettings("Cppcheck", "Cppcheck-GUI", &app);
|
||||
|
||||
// Set data dir..
|
||||
const QStringList args = QApplication::arguments();
|
||||
|
@ -71,7 +70,7 @@ int main(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
TranslationHandler* th = new TranslationHandler(&app);
|
||||
auto* th = new TranslationHandler(&app);
|
||||
th->setLanguage(settings->value(SETTINGS_LANGUAGE, th->suggestLanguage()).toString());
|
||||
|
||||
if (!CheckArgs(QApplication::arguments()))
|
||||
|
|
|
@ -247,7 +247,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
|
|||
|
||||
for (int i = 0; i < mPlatforms.getCount(); i++) {
|
||||
PlatformData platform = mPlatforms.mPlatforms[i];
|
||||
QAction *action = new QAction(this);
|
||||
auto *action = new QAction(this);
|
||||
platform.mActMainWindow = action;
|
||||
mPlatforms.mPlatforms[i] = platform;
|
||||
action->setText(platform.mTitle);
|
||||
|
@ -392,10 +392,10 @@ void MainWindow::loadSettings()
|
|||
mUI->mActionToolBarFilter->setChecked(showFilterToolbar);
|
||||
mUI->mToolBarFilter->setVisible(showFilterToolbar);
|
||||
|
||||
const Settings::Language enforcedLanguage = (Settings::Language)mSettings->value(SETTINGS_ENFORCED_LANGUAGE, 0).toInt();
|
||||
if (enforcedLanguage == Settings::CPP)
|
||||
const Standards::Language enforcedLanguage = (Standards::Language)mSettings->value(SETTINGS_ENFORCED_LANGUAGE, 0).toInt();
|
||||
if (enforcedLanguage == Standards::Language::CPP)
|
||||
mUI->mActionEnforceCpp->setChecked(true);
|
||||
else if (enforcedLanguage == Settings::C)
|
||||
else if (enforcedLanguage == Standards::Language::C)
|
||||
mUI->mActionEnforceC->setChecked(true);
|
||||
else
|
||||
mUI->mActionAutoDetectLanguage->setChecked(true);
|
||||
|
@ -469,11 +469,11 @@ void MainWindow::saveSettings() const
|
|||
mSettings->setValue(SETTINGS_TOOLBARS_FILTER_SHOW, mUI->mToolBarFilter->isVisible());
|
||||
|
||||
if (mUI->mActionEnforceCpp->isChecked())
|
||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Settings::CPP);
|
||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::CPP);
|
||||
else if (mUI->mActionEnforceC->isChecked())
|
||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Settings::C);
|
||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::C);
|
||||
else
|
||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Settings::None);
|
||||
mSettings->setValue(SETTINGS_ENFORCED_LANGUAGE, Standards::Language::None);
|
||||
|
||||
mApplications->saveSettings();
|
||||
|
||||
|
@ -861,7 +861,7 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename)
|
|||
const Library::Error error = loadLibrary(library, filename);
|
||||
if (error.errorcode != Library::ErrorCode::OK) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -899,7 +899,7 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename)
|
|||
}
|
||||
if (!error.reason.empty())
|
||||
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 true;
|
||||
|
@ -958,7 +958,7 @@ Settings MainWindow::getCppcheckSettings()
|
|||
{
|
||||
const QString cfgErr = QString::fromStdString(result.loadCppcheckCfg());
|
||||
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;
|
||||
result.addons.clear();
|
||||
|
@ -1021,7 +1021,7 @@ Settings MainWindow::getCppcheckSettings()
|
|||
result.platform.loadFromFile(applicationFilePath.toStdString().c_str(), platform.toStdString());
|
||||
} else {
|
||||
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)) {
|
||||
result.platform.set(p);
|
||||
break;
|
||||
|
@ -1091,7 +1091,7 @@ Settings MainWindow::getCppcheckSettings()
|
|||
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.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) {
|
||||
result.jobs = 1;
|
||||
|
@ -1468,21 +1468,21 @@ void MainWindow::about()
|
|||
msg.exec();
|
||||
}
|
||||
else {
|
||||
AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this);
|
||||
auto *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this);
|
||||
dlg->exec();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::showLicense()
|
||||
{
|
||||
FileViewDialog *dlg = new FileViewDialog(":COPYING", tr("License"), this);
|
||||
auto *dlg = new FileViewDialog(":COPYING", tr("License"), this);
|
||||
dlg->resize(570, 400);
|
||||
dlg->exec();
|
||||
}
|
||||
|
||||
void MainWindow::showAuthors()
|
||||
{
|
||||
FileViewDialog *dlg = new FileViewDialog(":AUTHORS", tr("Authors"), this);
|
||||
auto *dlg = new FileViewDialog(":AUTHORS", tr("Authors"), this);
|
||||
dlg->resize(350, 400);
|
||||
dlg->exec();
|
||||
}
|
||||
|
@ -1634,7 +1634,7 @@ void MainWindow::openHelpContents()
|
|||
|
||||
void MainWindow::openOnlineHelp()
|
||||
{
|
||||
HelpDialog *helpDialog = new HelpDialog;
|
||||
auto *helpDialog = new HelpDialog;
|
||||
helpDialog->showMaximized();
|
||||
}
|
||||
|
||||
|
@ -1787,7 +1787,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile, const bool check
|
|||
if (!errorMessage.isEmpty()) {
|
||||
QMessageBox msg(QMessageBox::Critical,
|
||||
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,
|
||||
this);
|
||||
msg.exec();
|
||||
|
@ -1796,7 +1796,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile, const bool check
|
|||
} catch (InternalError &e) {
|
||||
QMessageBox msg(QMessageBox::Critical,
|
||||
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,
|
||||
this);
|
||||
msg.exec();
|
||||
|
@ -1923,7 +1923,7 @@ void MainWindow::enableProjectOpenActions(bool enable)
|
|||
|
||||
void MainWindow::openRecentProject()
|
||||
{
|
||||
QAction *action = qobject_cast<QAction *>(sender());
|
||||
auto *action = qobject_cast<QAction *>(sender());
|
||||
if (!action)
|
||||
return;
|
||||
const QString project = action->data().toString();
|
||||
|
@ -2012,7 +2012,7 @@ void MainWindow::removeProjectMRU(const QString &project)
|
|||
|
||||
void MainWindow::selectPlatform()
|
||||
{
|
||||
QAction *action = qobject_cast<QAction *>(sender());
|
||||
auto *action = qobject_cast<QAction *>(sender());
|
||||
if (action) {
|
||||
const Platform::Type platform = (Platform::Type) action->data().toInt();
|
||||
mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform);
|
||||
|
@ -2100,7 +2100,7 @@ void MainWindow::replyFinished(QNetworkReply *reply) {
|
|||
}
|
||||
mUI->mButtonHideInformation->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);
|
||||
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 += "\n";
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
#include <QSize>
|
||||
#include <QSpinBox>
|
||||
#include <QVariant>
|
||||
#include <QtCore>
|
||||
|
||||
static constexpr char ADDON_MISRA[] = "misra";
|
||||
static constexpr char CODING_STANDARD_MISRA_C_2023[] = "misra-c-2023";
|
||||
|
@ -183,7 +182,7 @@ ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, bool premium, QWi
|
|||
libs.sort();
|
||||
mUI->mLibraries->clear();
|
||||
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->setCheckState(Qt::Unchecked); // AND initialize check state
|
||||
}
|
||||
|
@ -605,7 +604,7 @@ void ProjectFileDialog::setProjectConfigurations(const QStringList &configs)
|
|||
mUI->mListVsConfigs->clear();
|
||||
mUI->mListVsConfigs->setEnabled(!configs.isEmpty() && !mUI->mChkAllVsConfigs->isChecked());
|
||||
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->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
|
@ -622,7 +621,7 @@ void ProjectFileDialog::addIncludeDir(const QString &dir)
|
|||
return;
|
||||
|
||||
const QString newdir = QDir::toNativeSeparators(dir);
|
||||
QListWidgetItem *item = new QListWidgetItem(newdir);
|
||||
auto *item = new QListWidgetItem(newdir);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
mUI->mListIncludeDirs->addItem(item);
|
||||
}
|
||||
|
@ -633,7 +632,7 @@ void ProjectFileDialog::addCheckPath(const QString &path)
|
|||
return;
|
||||
|
||||
const QString newpath = QDir::toNativeSeparators(path);
|
||||
QListWidgetItem *item = new QListWidgetItem(newpath);
|
||||
auto *item = new QListWidgetItem(newpath);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
mUI->mListCheckPaths->addItem(item);
|
||||
}
|
||||
|
@ -644,7 +643,7 @@ void ProjectFileDialog::addExcludePath(const QString &path)
|
|||
return;
|
||||
|
||||
const QString newpath = QDir::toNativeSeparators(path);
|
||||
QListWidgetItem *item = new QListWidgetItem(newpath);
|
||||
auto *item = new QListWidgetItem(newpath);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
mUI->mListExcludedPaths->addItem(item);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ void ResultsTree::initialize(QSettings *settings, ApplicationList *list, ThreadH
|
|||
|
||||
QStandardItem *ResultsTree::createNormalItem(const QString &name)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem(name);
|
||||
auto *item = new QStandardItem(name);
|
||||
item->setData(name, Qt::ToolTipRole);
|
||||
item->setEditable(false);
|
||||
return item;
|
||||
|
@ -118,7 +118,7 @@ QStandardItem *ResultsTree::createNormalItem(const QString &name)
|
|||
|
||||
QStandardItem *ResultsTree::createCheckboxItem(bool checked)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem;
|
||||
auto *item = new QStandardItem;
|
||||
item->setCheckable(true);
|
||||
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
|
||||
item->setEnabled(false);
|
||||
|
@ -127,7 +127,7 @@ QStandardItem *ResultsTree::createCheckboxItem(bool checked)
|
|||
|
||||
QStandardItem *ResultsTree::createLineNumberItem(const QString &linenumber)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem();
|
||||
auto *item = new QStandardItem();
|
||||
item->setData(QVariant(linenumber.toInt()), Qt::DisplayRole);
|
||||
item->setToolTip(linenumber);
|
||||
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
|
||||
//member variables
|
||||
QSignalMapper *signalMapper = new QSignalMapper(this);
|
||||
auto *signalMapper = new QSignalMapper(this);
|
||||
|
||||
if (mContextItem && mApplications->getApplicationCount() > 0 && mContextItem->parent()) {
|
||||
//Create an action for the application
|
||||
|
@ -619,7 +619,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
if (defaultApplicationIndex < 0)
|
||||
defaultApplicationIndex = 0;
|
||||
const Application& app = mApplications->getApplication(defaultApplicationIndex);
|
||||
QAction *start = new QAction(app.getName(), &menu);
|
||||
auto *start = new QAction(app.getName(), &menu);
|
||||
if (multipleSelection)
|
||||
start->setDisabled(true);
|
||||
|
||||
|
@ -646,11 +646,11 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
}
|
||||
|
||||
//Create an action for the application
|
||||
QAction *recheckAction = new QAction(tr("Recheck"), &menu);
|
||||
QAction *copyAction = new QAction(tr("Copy"), &menu);
|
||||
QAction *hide = new QAction(tr("Hide"), &menu);
|
||||
QAction *hideallid = new QAction(tr("Hide all with id"), &menu);
|
||||
QAction *opencontainingfolder = new QAction(tr("Open containing folder"), &menu);
|
||||
auto *recheckAction = new QAction(tr("Recheck"), &menu);
|
||||
auto *copyAction = new QAction(tr("Copy"), &menu);
|
||||
auto *hide = new QAction(tr("Hide"), &menu);
|
||||
auto *hideallid = new QAction(tr("Hide all with id"), &menu);
|
||||
auto *opencontainingfolder = new QAction(tr("Open containing folder"), &menu);
|
||||
|
||||
if (multipleSelection) {
|
||||
hideallid->setDisabled(true);
|
||||
|
@ -668,7 +668,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
menu.addAction(hide);
|
||||
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();
|
||||
const QString messageId = data[ERRORID].toString();
|
||||
|
@ -691,7 +691,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
menu.addSeparator();
|
||||
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);
|
||||
connect(action, &QAction::triggered, [=]() {
|
||||
tagSelectedItems(QString());
|
||||
|
@ -699,7 +699,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
}
|
||||
|
||||
for (const QString& tagstr : currentProject->getTags()) {
|
||||
QAction *action = new QAction(tagstr, tagMenu);
|
||||
auto *action = new QAction(tagstr, tagMenu);
|
||||
tagMenu->addAction(action);
|
||||
connect(action, &QAction::triggered, [=]() {
|
||||
tagSelectedItems(tagstr);
|
||||
|
@ -816,7 +816,7 @@ void ResultsTree::startApplication(const QStandardItem *target, int application)
|
|||
}
|
||||
#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
|
||||
#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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (!item) {
|
||||
|
@ -463,7 +463,7 @@ void ResultsView::updateDetails(const QModelIndex &index)
|
|||
|
||||
const QString file0 = data["file0"].toString();
|
||||
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)
|
||||
formattedMsg.prepend("CWE: " + QString::number(data["cwe"].toInt()) + "\n");
|
||||
|
|
|
@ -140,7 +140,7 @@ void SettingsDialog::initTranslationsList()
|
|||
{
|
||||
const QString current = mTranslator->getCurrentLanguage();
|
||||
for (const TranslationInfo& translation : mTranslator->getTranslations()) {
|
||||
QListWidgetItem *item = new QListWidgetItem;
|
||||
auto *item = new QListWidgetItem;
|
||||
item->setText(translation.mName);
|
||||
item->setData(mLangCodeRole, QVariant(translation.mCode));
|
||||
mUI->mListLanguages->addItem(item);
|
||||
|
|
|
@ -182,9 +182,9 @@ void StatsDialog::pdfExport()
|
|||
"<font color=\"blue\"><h3>%9 : %10</h3></font>\n"
|
||||
"<font color=\"blue\"><h3>%11 : %12</h3></font>\n"
|
||||
"<font color=\"purple\"><h3>%13 : %14</h3></font>\n")
|
||||
.arg(tr("Statistics"))
|
||||
.arg(QDate::currentDate().toString("dd.MM.yyyy"))
|
||||
.arg(tr("Errors"))
|
||||
.arg(tr("Statistics"),
|
||||
QDate::currentDate().toString("dd.MM.yyyy"),
|
||||
tr("Errors"))
|
||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
||||
.arg(tr("Warnings"))
|
||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
||||
|
@ -246,17 +246,17 @@ void StatsDialog::copyToClipboard()
|
|||
"\t%8:\t%9\n"
|
||||
"\t%10:\t%11\n"
|
||||
)
|
||||
.arg(projSettings)
|
||||
.arg(project)
|
||||
.arg(mUI->mProject->text())
|
||||
.arg(paths)
|
||||
.arg(mUI->mPaths->text())
|
||||
.arg(incPaths)
|
||||
.arg(mUI->mIncludePaths->text())
|
||||
.arg(defines)
|
||||
.arg(mUI->mDefines->text())
|
||||
.arg(undefines)
|
||||
.arg(mUI->mUndefines->text());
|
||||
.arg(projSettings,
|
||||
project,
|
||||
mUI->mProject->text(),
|
||||
paths,
|
||||
mUI->mPaths->text(),
|
||||
incPaths,
|
||||
mUI->mIncludePaths->text(),
|
||||
defines)
|
||||
.arg(mUI->mDefines->text(),
|
||||
undefines,
|
||||
mUI->mUndefines->text());
|
||||
|
||||
const QString previous = QString(
|
||||
"%1\n"
|
||||
|
@ -264,13 +264,13 @@ void StatsDialog::copyToClipboard()
|
|||
"\t%4:\t%5\n"
|
||||
"\t%6:\t%7\n"
|
||||
)
|
||||
.arg(prevScan)
|
||||
.arg(selPath)
|
||||
.arg(mUI->mPath->text())
|
||||
.arg(numFiles)
|
||||
.arg(mUI->mNumberOfFilesScanned->text())
|
||||
.arg(duration)
|
||||
.arg(mUI->mScanDuration->text());
|
||||
.arg(prevScan,
|
||||
selPath,
|
||||
mUI->mPath->text(),
|
||||
numFiles,
|
||||
mUI->mNumberOfFilesScanned->text(),
|
||||
duration,
|
||||
mUI->mScanDuration->text());
|
||||
|
||||
const QString statistics = QString(
|
||||
"%1\n"
|
||||
|
@ -281,8 +281,8 @@ void StatsDialog::copyToClipboard()
|
|||
"\t%10:\t%11\n"
|
||||
"\t%12:\t%13\n"
|
||||
)
|
||||
.arg(stats)
|
||||
.arg(errors)
|
||||
.arg(stats,
|
||||
errors)
|
||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
||||
.arg(warnings)
|
||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
||||
|
@ -308,17 +308,17 @@ void StatsDialog::copyToClipboard()
|
|||
" <tr><th>%10:</th><td>%11</td></tr>\n"
|
||||
"</table>\n"
|
||||
)
|
||||
.arg(projSettings)
|
||||
.arg(project)
|
||||
.arg(mUI->mProject->text())
|
||||
.arg(paths)
|
||||
.arg(mUI->mPaths->text())
|
||||
.arg(incPaths)
|
||||
.arg(mUI->mIncludePaths->text())
|
||||
.arg(defines)
|
||||
.arg(mUI->mDefines->text())
|
||||
.arg(undefines)
|
||||
.arg(mUI->mUndefines->text());
|
||||
.arg(projSettings,
|
||||
project,
|
||||
mUI->mProject->text(),
|
||||
paths,
|
||||
mUI->mPaths->text(),
|
||||
incPaths,
|
||||
mUI->mIncludePaths->text(),
|
||||
defines)
|
||||
.arg(mUI->mDefines->text(),
|
||||
undefines,
|
||||
mUI->mUndefines->text());
|
||||
|
||||
const QString htmlPrevious = QString(
|
||||
"<h3>%1</h3>\n"
|
||||
|
@ -328,13 +328,13 @@ void StatsDialog::copyToClipboard()
|
|||
" <tr><th>%6:</th><td>%7</td></tr>\n"
|
||||
"</table>\n"
|
||||
)
|
||||
.arg(prevScan)
|
||||
.arg(selPath)
|
||||
.arg(mUI->mPath->text())
|
||||
.arg(numFiles)
|
||||
.arg(mUI->mNumberOfFilesScanned->text())
|
||||
.arg(duration)
|
||||
.arg(mUI->mScanDuration->text());
|
||||
.arg(prevScan,
|
||||
selPath,
|
||||
mUI->mPath->text(),
|
||||
numFiles,
|
||||
mUI->mNumberOfFilesScanned->text(),
|
||||
duration,
|
||||
mUI->mScanDuration->text());
|
||||
|
||||
const QString htmlStatistics = QString(
|
||||
"<h3>%1</h3>\n"
|
||||
|
@ -346,8 +346,8 @@ void StatsDialog::copyToClipboard()
|
|||
" <tr><th>%12:</th><td>%13</td></tr>\n"
|
||||
"</table>\n"
|
||||
)
|
||||
.arg(stats)
|
||||
.arg(errors)
|
||||
.arg(stats,
|
||||
errors)
|
||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors))
|
||||
.arg(warnings)
|
||||
.arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowWarnings))
|
||||
|
@ -362,7 +362,7 @@ void StatsDialog::copyToClipboard()
|
|||
|
||||
const QString htmlSummary = htmlSettings + htmlPrevious + htmlStatistics;
|
||||
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
auto *mimeData = new QMimeData();
|
||||
mimeData->setText(textSummary);
|
||||
mimeData->setHtml(htmlSummary);
|
||||
clipboard->setMimeData(mimeData);
|
||||
|
@ -384,14 +384,14 @@ void StatsDialog::setStatistics(const CheckStatistics *stats)
|
|||
#ifdef QT_CHARTS_LIB
|
||||
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 + "-warning"));
|
||||
chart->addSeries(numberOfReports(statsFile, tool + "-style"));
|
||||
chart->addSeries(numberOfReports(statsFile, tool + "-performance"));
|
||||
chart->addSeries(numberOfReports(statsFile, tool + "-portability"));
|
||||
|
||||
QDateTimeAxis *axisX = new QDateTimeAxis;
|
||||
auto *axisX = new QDateTimeAxis;
|
||||
axisX->setTitleText("Date");
|
||||
chart->addAxis(axisX, Qt::AlignBottom);
|
||||
|
||||
|
@ -399,7 +399,7 @@ QChartView *createChart(const QString &statsFile, const QString &tool)
|
|||
s->attachAxis(axisX);
|
||||
}
|
||||
|
||||
QValueAxis *axisY = new QValueAxis;
|
||||
auto *axisY = new QValueAxis;
|
||||
axisY->setLabelFormat("%i");
|
||||
axisY->setTitleText("Count");
|
||||
chart->addAxis(axisY, Qt::AlignLeft);
|
||||
|
@ -407,7 +407,7 @@ QChartView *createChart(const QString &statsFile, const QString &tool)
|
|||
qreal maxY = 0;
|
||||
for (QAbstractSeries *s : chart->series()) {
|
||||
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()) {
|
||||
if (p.y() > maxY)
|
||||
maxY = p.y();
|
||||
|
@ -419,14 +419,14 @@ QChartView *createChart(const QString &statsFile, const QString &tool)
|
|||
//chart->createDefaultAxes();
|
||||
chart->setTitle(tool);
|
||||
|
||||
QChartView *chartView = new QChartView(chart);
|
||||
auto *chartView = new QChartView(chart);
|
||||
chartView->setRenderHint(QPainter::Antialiasing);
|
||||
return chartView;
|
||||
}
|
||||
|
||||
QLineSeries *numberOfReports(const QString &fileName, const QString &severity)
|
||||
{
|
||||
QLineSeries *series = new QLineSeries();
|
||||
auto *series = new QLineSeries();
|
||||
series->setName(severity);
|
||||
QFile f(fileName);
|
||||
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
|
|
|
@ -10,7 +10,8 @@ add_executable(test-filelist
|
|||
${CMAKE_SOURCE_DIR}/lib/utils.cpp
|
||||
$<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_link_libraries(test-filelist ${QT_CORE_LIB} ${QT_TEST_LIB})
|
||||
|
||||
|
|
|
@ -408,8 +408,8 @@ def filter_bar(enabled):
|
|||
,'\n | '
|
||||
,''.join([filter_button(enabled, tool, 'toggleTool') for tool in ['cppcheck', 'clang-tidy']])
|
||||
,'\n | '
|
||||
,'\n <label class="severityHeader">File: <input type="text" oninput="filterFile(this.value)"/></label>'
|
||||
,'\n <label class="severityHeader">Filter: <input type="text" oninput="filterText(this.value)"/></label>'
|
||||
,'\n <label class="severityHeader">File: <input type="search" oninput="filterFile(this.value)"/></label>'
|
||||
,'\n <label class="severityHeader">Filter: <input type="search" oninput="filterText(this.value)"/></label>'
|
||||
,'\n </div>\n'])
|
||||
|
||||
def git_blame(errors, path, file, blame_options):
|
||||
|
|
|
@ -43,14 +43,14 @@ if (BUILD_CORE_DLL)
|
|||
else()
|
||||
add_library(cppcheck-core OBJECT ${srcs_lib} ${hdrs})
|
||||
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)
|
||||
target_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
||||
target_externals_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/tinyxml2/)
|
||||
else()
|
||||
target_include_directories(cppcheck-core SYSTEM PRIVATE ${tinyxml2_INCLUDE_DIRS})
|
||||
endif()
|
||||
target_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/picojson/)
|
||||
target_externals_include_directories(cppcheck-core PRIVATE ${PROJECT_SOURCE_DIR}/externals/simplecpp/)
|
||||
if (HAVE_RULES)
|
||||
target_include_directories(cppcheck-core SYSTEM PRIVATE ${PCRE_INCLUDE})
|
||||
endif()
|
||||
|
|
|
@ -52,42 +52,73 @@ static std::string parseAddonInfo(AddonInfo& addoninfo, const picojson::value &j
|
|||
return "Loading " + fileName + " failed. " + json_error;
|
||||
}
|
||||
if (!json.is<picojson::object>())
|
||||
return "Loading " + fileName + " failed. Bad json.";
|
||||
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>();
|
||||
}
|
||||
return "Loading " + fileName + " failed. JSON is not an object.";
|
||||
|
||||
if (obj.count("ctu")) {
|
||||
// ctu is specified in the config file
|
||||
if (!obj["ctu"].is<bool>())
|
||||
return "Loading " + fileName + " failed. ctu must be boolean.";
|
||||
addoninfo.ctu = obj["ctu"].get<bool>();
|
||||
} else {
|
||||
addoninfo.ctu = false;
|
||||
}
|
||||
|
||||
if (obj.count("python")) {
|
||||
// Python was defined in the config file
|
||||
if (obj["python"].is<picojson::array>()) {
|
||||
return "Loading " + fileName +" failed. python must not be an array.";
|
||||
// TODO: remove/complete default value handling for missing fields
|
||||
const picojson::object& obj = json.get<picojson::object>();
|
||||
{
|
||||
const auto it = obj.find("args");
|
||||
if (it != obj.cend()) {
|
||||
const auto& val = it->second;
|
||||
if (!val.is<picojson::array>())
|
||||
return "Loading " + fileName + " failed. 'args' must be an array.";
|
||||
for (const picojson::value &v : val.get<picojson::array>()) {
|
||||
if (!v.is<std::string>())
|
||||
return "Loading " + fileName + " failed. 'args' entry is not a string.";
|
||||
addoninfo.args += " " + v.get<std::string>();
|
||||
}
|
||||
}
|
||||
addoninfo.python = obj["python"].get<std::string>();
|
||||
} else {
|
||||
addoninfo.python = "";
|
||||
}
|
||||
|
||||
if (obj.count("executable")) {
|
||||
if (!obj["executable"].is<std::string>())
|
||||
return "Loading " + fileName + " failed. executable must be a string.";
|
||||
addoninfo.executable = getFullPath(obj["executable"].get<std::string>(), fileName);
|
||||
return "";
|
||||
{
|
||||
const auto it = obj.find("ctu");
|
||||
if (it != obj.cend()) {
|
||||
const auto& val = it->second;
|
||||
// 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) {
|
||||
|
|
|
@ -181,6 +181,8 @@ struct Analyzer {
|
|||
virtual bool stopOnCondition(const Token* condTok) const = 0;
|
||||
/// The condition that will be assumed during analysis
|
||||
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
|
||||
virtual ValuePtr<Analyzer> reanalyze(Token* tok, const std::string& msg = emptyString) const = 0;
|
||||
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 (findAstNode(val.tokvalue,
|
||||
[&](const Token* aliasTok) {
|
||||
return aliasTok->exprId() == childTok->exprId();
|
||||
return aliasTok != childTok && aliasTok->exprId() == childTok->exprId();
|
||||
})) {
|
||||
if (val.isInconclusive() && inconclusive != nullptr) {
|
||||
value = &val;
|
||||
|
@ -2651,8 +2651,11 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings,
|
|||
const Token * ptok = tok2;
|
||||
while (Token::Match(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 isChanged = isVariableChangedByFunctionCall(ptok, indirect, settings, &inconclusive);
|
||||
bool isChanged = isVariableChangedByFunctionCall(ptok, pindirect, settings, &inconclusive);
|
||||
isChanged |= inconclusive;
|
||||
if (isChanged)
|
||||
return true;
|
||||
|
@ -3257,6 +3260,8 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
|
|||
continue;
|
||||
if (arg->isReference())
|
||||
return ExprUsage::PassedByReference;
|
||||
if (arg->isPointer() && indirect == 1)
|
||||
return ExprUsage::PassedByReference;
|
||||
}
|
||||
if (!args.empty() && indirect == 0 && !addressOf)
|
||||
return ExprUsage::Used;
|
||||
|
@ -3301,6 +3306,8 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings,
|
|||
parent = parent->astParent();
|
||||
if (Token::Match(parent, "%assign%") && (astIsRHS(tok) || astIsLHS(parent->astOperand1())))
|
||||
return ExprUsage::NotUsed;
|
||||
if (Token::Match(parent, "++|--"))
|
||||
return ExprUsage::NotUsed;
|
||||
if (parent->isConstOp())
|
||||
return ExprUsage::NotUsed;
|
||||
if (parent->isCast())
|
||||
|
|
|
@ -948,7 +948,7 @@ bool CheckBufferOverrun::isCtuUnsafePointerArith(const Settings *settings, const
|
|||
/** @brief Parse current TU and extract file info */
|
||||
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->unsafePointerArith = CTU::getUnsafeUsage(tokenizer, settings, isCtuUnsafePointerArith);
|
||||
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 pointerArith("pointer-arith");
|
||||
|
||||
MyFileInfo *fileInfo = new MyFileInfo;
|
||||
auto *fileInfo = new MyFileInfo;
|
||||
for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
||||
if (e->Name() == arrayIndex)
|
||||
fileInfo->unsafeArrayIndex = CTU::loadUnsafeUsageListFromXml(e);
|
||||
|
|
|
@ -2633,6 +2633,7 @@ namespace { // avoid one-definition-rule violation
|
|||
|
||||
const Variable *var;
|
||||
const Token *tok;
|
||||
std::vector<const Variable*> initArgs;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2663,25 +2664,44 @@ void CheckClass::initializerListOrder()
|
|||
tok = tok->next();
|
||||
|
||||
// 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% (|{")) {
|
||||
const Variable *var = scope->getVariable(tok->str());
|
||||
if (var)
|
||||
vars.emplace_back(var, tok);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (Token::Match(tok->tokAt(2), "%name% =")) {
|
||||
var = scope->getVariable(tok->strAt(2));
|
||||
|
||||
if (var)
|
||||
vars.emplace_back(var, tok->tokAt(2));
|
||||
const Token* const end = tok->next()->link();
|
||||
for (; tok != end; tok = tok->next()) {
|
||||
if (const Variable* argVar = scope->getVariable(tok->str())) {
|
||||
if (scope != argVar->scope())
|
||||
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 = 1; j < vars.size(); j++) {
|
||||
for (int j = 0; 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
|
||||
if (vars[j].var->index() < vars[j - 1].var->index())
|
||||
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 };
|
||||
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",
|
||||
"$symbol:" + classname + "::" + varname +"\n"
|
||||
"Member variable '$symbol' is in the wrong place in the initializer list.\n"
|
||||
"Member variable '$symbol' is in the wrong place in the initializer list. "
|
||||
"$symbol:" + classname + "::" + varname + '\n' +
|
||||
msg + '\n' +
|
||||
msg + ' ' +
|
||||
"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 "
|
||||
"initialization errors.", CWE398, Certainty::inconclusive);
|
||||
}
|
||||
|
@ -2988,7 +3011,8 @@ static std::vector<DuplMemberFuncInfo> getDuplInheritedMemberFunctionsRecursive(
|
|||
if (classFuncIt.name() == parentClassFuncIt.name() &&
|
||||
(parentClassFuncIt.access != AccessControl::Private || !skipPrivate) &&
|
||||
!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);
|
||||
}
|
||||
}
|
||||
|
@ -3509,14 +3533,14 @@ Check::FileInfo *CheckClass::getFileInfo(const Tokenizer *tokenizer, const Setti
|
|||
if (classDefinitions.empty())
|
||||
return nullptr;
|
||||
|
||||
MyFileInfo *fileInfo = new MyFileInfo;
|
||||
auto *fileInfo = new MyFileInfo;
|
||||
fileInfo->classDefinitions.swap(classDefinitions);
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
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()) {
|
||||
if (std::strcmp(e->Name(), "class") != 0)
|
||||
continue;
|
||||
|
|
|
@ -199,7 +199,7 @@ private:
|
|||
void operatorEqToSelfError(const Token *tok);
|
||||
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 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 selfInitializationError(const Token* tok, const std::string& varname);
|
||||
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)
|
||||
{
|
||||
if (tok && (diag(tok) | diag(tok->astParent())))
|
||||
return;
|
||||
std::ostringstream expression;
|
||||
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
|
||||
bool result1, result2;
|
||||
if (isfloat) {
|
||||
const double testvalue = getvalue<double>(test, d1, d2);
|
||||
const auto testvalue = getvalue<double>(test, d1, d2);
|
||||
result1 = checkFloatRelation(op1, testvalue, d1);
|
||||
result2 = checkFloatRelation(op2, testvalue, d2);
|
||||
} 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);
|
||||
result2 = checkIntRelation(op2, testvalue, u2);
|
||||
} 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);
|
||||
result2 = checkIntRelation(op2, testvalue, i2);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "symboldatabase.h"
|
||||
#include "token.h"
|
||||
#include "tokenize.h"
|
||||
#include "tokenlist.h"
|
||||
#include "utils.h"
|
||||
#include "vfvalue.h"
|
||||
|
||||
|
@ -466,6 +467,9 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
const Token * closingParenthesis = tok->linkAt(1);
|
||||
for (const Token *innerTok = tok->tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->next()) {
|
||||
// TODO: replace with checkTokenInsideExpression()
|
||||
const Token* const openingPar = isFunctionCall(innerTok);
|
||||
if (!openingPar)
|
||||
checkTokenInsideExpression(innerTok, varInfo);
|
||||
|
||||
if (!isLocalVarNoAutoDealloc(innerTok, mTokenizer->isCPP()))
|
||||
continue;
|
||||
|
@ -502,7 +506,6 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
}
|
||||
|
||||
// check for function call
|
||||
const Token * const openingPar = isFunctionCall(innerTok);
|
||||
if (openingPar) {
|
||||
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(innerTok);
|
||||
// innerTok is a function name
|
||||
|
@ -805,14 +808,15 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
const Token * vtok = typeEndTok->tokAt(3);
|
||||
const VarInfo::AllocInfo allocation(af ? af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, ftok);
|
||||
changeAllocStatus(varInfo, allocation, vtok, vtok);
|
||||
}
|
||||
} else if (Token::Match(tok, "%var% ."))
|
||||
checkTokenInsideExpression(tok, varInfo);
|
||||
}
|
||||
ret(endToken, varInfo, 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..
|
||||
if (tok->varId() > 0) {
|
||||
|
@ -838,7 +842,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
|
|||
if (rhs->varId() == tok->varId()) {
|
||||
// simple assignment
|
||||
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
|
||||
const std::string &returnValue = mSettings->library.returnValue(rhs->astOperand1());
|
||||
if (startsWith(returnValue, "arg")) {
|
||||
|
@ -859,7 +863,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
|
|||
}
|
||||
|
||||
// check for function call
|
||||
const Token * const openingPar = isFunctionCall(tok);
|
||||
const Token * const openingPar = inFuncCall ? nullptr : isFunctionCall(tok);
|
||||
if (openingPar) {
|
||||
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(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)
|
||||
{
|
||||
// Ignore function call?
|
||||
if (mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)))
|
||||
return;
|
||||
const bool isLeakIgnore = mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName));
|
||||
if (mSettings->library.getReallocFuncInfo(tokName))
|
||||
return;
|
||||
|
||||
|
@ -990,6 +993,8 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
|
|||
varAlloc.allocTok = arg;
|
||||
}
|
||||
}
|
||||
else if (isLeakIgnore)
|
||||
checkTokenInsideExpression(arg, varInfo);
|
||||
else
|
||||
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);
|
||||
changeAllocStatus(varInfo, sp_allocation, vtok, vtok);
|
||||
} 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)
|
||||
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()) {
|
||||
if (tok2->str() == ";")
|
||||
break;
|
||||
if (!Token::Match(tok2, "return|(|{|,"))
|
||||
if (!Token::Match(tok2, "return|(|{|,|*"))
|
||||
continue;
|
||||
|
||||
const Token* tok3 = tok2->next();
|
||||
|
|
|
@ -135,7 +135,7 @@ private:
|
|||
* @param varInfo Variable info
|
||||
* @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 */
|
||||
void functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af);
|
||||
|
|
|
@ -86,7 +86,7 @@ private:
|
|||
public:
|
||||
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)
|
||||
: mTokenizer_(t), mErrorLogger_(e), mSettings_(s) {}
|
||||
|
|
|
@ -586,7 +586,7 @@ Check::FileInfo *CheckNullPointer::getFileInfo(const Tokenizer *tokenizer, const
|
|||
if (unsafeUsage.empty())
|
||||
return nullptr;
|
||||
|
||||
MyFileInfo *fileInfo = new MyFileInfo;
|
||||
auto *fileInfo = new MyFileInfo;
|
||||
fileInfo->unsafeUsage = unsafeUsage;
|
||||
return fileInfo;
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ Check::FileInfo * CheckNullPointer::loadFileInfoFromXml(const tinyxml2::XMLEleme
|
|||
if (unsafeUsage.empty())
|
||||
return nullptr;
|
||||
|
||||
MyFileInfo *fileInfo = new MyFileInfo;
|
||||
auto *fileInfo = new MyFileInfo;
|
||||
fileInfo->unsafeUsage = unsafeUsage;
|
||||
return fileInfo;
|
||||
}
|
||||
|
|
|
@ -995,16 +995,7 @@ void CheckOther::checkVariableScope()
|
|||
|
||||
// parse else if blocks..
|
||||
} else if (Token::simpleMatch(tok, "else { if (") && Token::simpleMatch(tok->linkAt(3), ") {")) {
|
||||
const Token *endif = tok->linkAt(3)->linkAt(1);
|
||||
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;
|
||||
}
|
||||
tok = tok->next();
|
||||
} else if (tok->varId() == var->declarationId() || tok->str() == "goto") {
|
||||
reduce = false;
|
||||
break;
|
||||
|
|
|
@ -1642,12 +1642,7 @@ void CheckUninitVar::valueFlowUninit()
|
|||
const bool isarray = tok->variable()->isArray();
|
||||
if (isarray && tok->variable()->isMember())
|
||||
continue; // Todo: this is a bailout
|
||||
const bool ispointer = astIsPointer(tok) && !isarray;
|
||||
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
||||
if (ispointer && v->indirect == 1 && !deref)
|
||||
continue;
|
||||
if (isarray && !deref)
|
||||
continue;
|
||||
uninitderef = deref && v->indirect == 0;
|
||||
const bool isleaf = isLeafDot(tok) || uninitderef;
|
||||
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())
|
||||
return nullptr;
|
||||
|
||||
MyFileInfo *fileInfo = new MyFileInfo;
|
||||
auto *fileInfo = new MyFileInfo;
|
||||
fileInfo->unsafeUsage = unsafeUsage;
|
||||
return fileInfo;
|
||||
}
|
||||
|
@ -1721,7 +1716,7 @@ Check::FileInfo * CheckUninitVar::loadFileInfoFromXml(const tinyxml2::XMLElement
|
|||
if (unsafeUsage.empty())
|
||||
return nullptr;
|
||||
|
||||
MyFileInfo *fileInfo = new MyFileInfo;
|
||||
auto *fileInfo = new MyFileInfo;
|
||||
fileInfo->unsafeUsage = unsafeUsage;
|
||||
return fileInfo;
|
||||
}
|
||||
|
|
|
@ -325,15 +325,15 @@ namespace clangimport {
|
|||
std::string nodeType;
|
||||
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 createTokens1(TokenList *tokenList) {
|
||||
void createTokens1(TokenList &tokenList) {
|
||||
//dumpAst();
|
||||
if (!tokenList->back())
|
||||
if (!tokenList.back())
|
||||
setLocations(tokenList, 0, 1, 1);
|
||||
else
|
||||
setLocations(tokenList, tokenList->back()->fileIndex(), tokenList->back()->linenr(), 1);
|
||||
setLocations(tokenList, tokenList.back()->fileIndex(), tokenList.back()->linenr(), 1);
|
||||
createTokens(tokenList);
|
||||
if (nodeType == VarDecl || nodeType == RecordDecl || nodeType == TypedefDecl)
|
||||
addtoken(tokenList, ";");
|
||||
|
@ -351,22 +351,22 @@ namespace clangimport {
|
|||
return children[c];
|
||||
}
|
||||
private:
|
||||
Token *createTokens(TokenList *tokenList);
|
||||
Token *addtoken(TokenList *tokenList, const std::string &str, bool valueType=true);
|
||||
const ::Type *addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope = nullptr);
|
||||
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, const std::vector<AstNodePtr> &children2, const Token *def);
|
||||
Token *createTokensCall(TokenList *tokenList);
|
||||
void createTokensFunctionDecl(TokenList *tokenList);
|
||||
void createTokensForCXXRecord(TokenList *tokenList);
|
||||
Token *createTokensVarDecl(TokenList *tokenList);
|
||||
Token *createTokens(TokenList &tokenList);
|
||||
Token *addtoken(TokenList &tokenList, const std::string &str, bool valueType=true);
|
||||
const ::Type *addTypeTokens(TokenList &tokenList, const std::string &str, const Scope *scope = nullptr);
|
||||
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, const std::vector<AstNodePtr> &children2, const Token *def);
|
||||
Token *createTokensCall(TokenList &tokenList);
|
||||
void createTokensFunctionDecl(TokenList &tokenList);
|
||||
void createTokensForCXXRecord(TokenList &tokenList);
|
||||
Token *createTokensVarDecl(TokenList &tokenList);
|
||||
std::string getSpelling() const;
|
||||
std::string getType(int index = 0) const;
|
||||
std::string getFullType(int index = 0) const;
|
||||
bool isDefinition() const;
|
||||
std::string getTemplateParameters() const;
|
||||
const Scope *getNestedInScope(TokenList *tokenList);
|
||||
const Scope *getNestedInScope(TokenList &tokenList);
|
||||
void setValueType(Token *tok);
|
||||
|
||||
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) {
|
||||
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 std::string::size_type sep1 = windowsPath ? ext.find(':', 4) : colon;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
tokenList->addtoken(str, mLine, mCol, mFile);
|
||||
tokenList->back()->scope(scope);
|
||||
tokenList.addtoken(str, mLine, mCol, mFile);
|
||||
tokenList.back()->scope(scope);
|
||||
if (valueType)
|
||||
setValueType(tokenList->back());
|
||||
return tokenList->back();
|
||||
setValueType(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) {
|
||||
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
|
||||
if (!scope) {
|
||||
scope = tokenList->back() ? tokenList->back()->scope() : nullptr;
|
||||
scope = tokenList.back() ? tokenList.back()->scope() : nullptr;
|
||||
if (!scope)
|
||||
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())
|
||||
continue;
|
||||
const ::Type *recordType = scope->check->findVariableType(scope, typeToken);
|
||||
|
@ -590,12 +590,12 @@ const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const s
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void clangimport::AstNode::addFullScopeNameTokens(TokenList *tokenList, const Scope *recordScope)
|
||||
void clangimport::AstNode::addFullScopeNameTokens(TokenList &tokenList, const Scope *recordScope)
|
||||
{
|
||||
if (!recordScope)
|
||||
return;
|
||||
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);
|
||||
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();
|
||||
if (tokenList->back()->str() == "}" && mData->mNotScope.find(tokenList->back()) == mData->mNotScope.end())
|
||||
return tokenList->back()->scope()->nestedIn;
|
||||
return tokenList->back()->scope();
|
||||
if (tokenList.back()->str() == "}" && mData->mNotScope.find(tokenList.back()) == mData->mNotScope.end())
|
||||
return tokenList.back()->scope()->nestedIn;
|
||||
return tokenList.back()->scope();
|
||||
}
|
||||
|
||||
void clangimport::AstNode::setValueType(Token *tok)
|
||||
|
@ -626,7 +626,7 @@ void clangimport::AstNode::setValueType(Token *tok)
|
|||
continue;
|
||||
|
||||
TokenList decl(nullptr);
|
||||
addTypeTokens(&decl, type, tok->scope());
|
||||
addTypeTokens(decl, type, tok->scope());
|
||||
if (!decl.front())
|
||||
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)};
|
||||
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;
|
||||
|
||||
Scope *nestedIn = const_cast<Scope *>(getNestedInScope(tokenList));
|
||||
auto *nestedIn = const_cast<Scope *>(getNestedInScope(tokenList));
|
||||
|
||||
symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nestedIn);
|
||||
Scope *scope = &symbolDatabase->scopeList.back();
|
||||
|
@ -682,7 +682,7 @@ Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType
|
|||
}
|
||||
}
|
||||
scope->bodyStart = addtoken(tokenList, "{");
|
||||
tokenList->back()->scope(scope);
|
||||
tokenList.back()->scope(scope);
|
||||
mData->scopeAccessControl[scope] = scope->defaultAccess();
|
||||
if (!children2.empty()) {
|
||||
for (const AstNodePtr &astNode: children2) {
|
||||
|
@ -700,7 +700,7 @@ Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType
|
|||
astNode->createTokens(tokenList);
|
||||
if (scopeType == Scope::ScopeType::eEnum)
|
||||
astNode->addtoken(tokenList, ",");
|
||||
else if (!Token::Match(tokenList->back(), "[;{}]"))
|
||||
else if (!Token::Match(tokenList.back(), "[;{}]"))
|
||||
astNode->addtoken(tokenList, ";");
|
||||
}
|
||||
}
|
||||
|
@ -710,7 +710,7 @@ Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType
|
|||
return scope;
|
||||
}
|
||||
|
||||
Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||
Token *clangimport::AstNode::createTokens(TokenList &tokenList)
|
||||
{
|
||||
if (nodeType == ArraySubscriptExpr) {
|
||||
Token *array = getChild(0)->createTokens(tokenList);
|
||||
|
@ -796,7 +796,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
if (nodeType == CompoundStmt) {
|
||||
for (const AstNodePtr& child: children) {
|
||||
child->createTokens(tokenList);
|
||||
if (!Token::Match(tokenList->back(), "[;{}]"))
|
||||
if (!Token::Match(tokenList.back(), "[;{}]"))
|
||||
child->addtoken(tokenList, ";");
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -818,14 +818,14 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
return getChild(0)->createTokens(tokenList);
|
||||
if (nodeType == CXXBoolLiteralExpr) {
|
||||
addtoken(tokenList, mExtTokens.back());
|
||||
tokenList->back()->setValueType(new ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0));
|
||||
return tokenList->back();
|
||||
tokenList.back()->setValueType(new ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0));
|
||||
return tokenList.back();
|
||||
}
|
||||
if (nodeType == CXXConstructExpr) {
|
||||
if (!children.empty())
|
||||
return getChild(0)->createTokens(tokenList);
|
||||
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
||||
Token *type = tokenList->back();
|
||||
Token *type = tokenList.back();
|
||||
Token *par1 = addtoken(tokenList, "(");
|
||||
Token *par2 = addtoken(tokenList, ")");
|
||||
par1->link(par2);
|
||||
|
@ -866,7 +866,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
}
|
||||
}
|
||||
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 *par2 = addtoken(tokenList, ")");
|
||||
|
||||
|
@ -961,7 +961,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
}
|
||||
if (nodeType == DoStmt) {
|
||||
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 *par1 = addtoken(tokenList, "(");
|
||||
Token *expr = children[1]->createTokens(tokenList);
|
||||
|
@ -974,7 +974,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
}
|
||||
if (nodeType == EnumConstantDecl) {
|
||||
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());
|
||||
Enumerator *e = &scope->enumeratorList.back();
|
||||
e->name = nameToken;
|
||||
|
@ -1088,7 +1088,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
createScope(tokenList, Scope::ScopeType::eIf, thenCode, iftok);
|
||||
if (elseCode) {
|
||||
elseCode->addtoken(tokenList, "else");
|
||||
createScope(tokenList, Scope::ScopeType::eElse, elseCode, tokenList->back());
|
||||
createScope(tokenList, Scope::ScopeType::eElse, elseCode, tokenList.back());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1099,11 +1099,11 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
return expr;
|
||||
}
|
||||
if (nodeType == InitListExpr) {
|
||||
const Scope *scope = tokenList->back()->scope();
|
||||
const Scope *scope = tokenList.back()->scope();
|
||||
Token *start = addtoken(tokenList, "{");
|
||||
start->scope(scope);
|
||||
for (const AstNodePtr& child: children) {
|
||||
if (tokenList->back()->str() != "{")
|
||||
if (tokenList.back()->str() != "{")
|
||||
addtoken(tokenList, ",");
|
||||
child->createTokens(tokenList);
|
||||
}
|
||||
|
@ -1261,7 +1261,7 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
|||
return addtoken(tokenList, "?" + nodeType + "?");
|
||||
}
|
||||
|
||||
Token * clangimport::AstNode::createTokensCall(TokenList *tokenList)
|
||||
Token * clangimport::AstNode::createTokensCall(TokenList &tokenList)
|
||||
{
|
||||
int firstParam;
|
||||
Token *f;
|
||||
|
@ -1302,7 +1302,7 @@ Token * clangimport::AstNode::createTokensCall(TokenList *tokenList)
|
|||
return par1;
|
||||
}
|
||||
|
||||
void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
||||
void clangimport::AstNode::createTokensFunctionDecl(TokenList &tokenList)
|
||||
{
|
||||
const bool prev = contains(mExtTokens, "prev");
|
||||
const bool hasBody = !children.empty() && children.back()->nodeType == CompoundStmt;
|
||||
|
@ -1317,16 +1317,16 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
|||
addtoken(tokenList, "static");
|
||||
if (isInline)
|
||||
addtoken(tokenList, "inline");
|
||||
const Token * const before = tokenList->back();
|
||||
const Token * const before = tokenList.back();
|
||||
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
||||
startToken = before ? before->next() : tokenList->front();
|
||||
startToken = before ? before->next() : tokenList.front();
|
||||
}
|
||||
|
||||
if (mExtTokens.size() > 4 && mExtTokens[1] == "parent")
|
||||
addFullScopeNameTokens(tokenList, mData->getScope(mExtTokens[2]));
|
||||
|
||||
Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
|
||||
Scope *nestedIn = const_cast<Scope *>(nameToken->scope());
|
||||
auto *nestedIn = const_cast<Scope *>(nameToken->scope());
|
||||
|
||||
if (prev) {
|
||||
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;
|
||||
}
|
||||
|
||||
Function * const function = const_cast<Function*>(nameToken->function());
|
||||
auto * const function = const_cast<Function*>(nameToken->function());
|
||||
|
||||
if (!prev) {
|
||||
auto accessControl = mData->scopeAccessControl.find(tokenList->back()->scope());
|
||||
auto accessControl = mData->scopeAccessControl.find(tokenList.back()->scope());
|
||||
if (accessControl != mData->scopeAccessControl.end())
|
||||
function->access = accessControl->second;
|
||||
}
|
||||
|
@ -1377,10 +1377,10 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
|||
AstNodePtr child = children[i];
|
||||
if (child->nodeType != ParmVarDecl)
|
||||
continue;
|
||||
if (tokenList->back() != par1)
|
||||
if (tokenList.back() != par1)
|
||||
addtoken(tokenList, ",");
|
||||
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();
|
||||
Token *vartok = nullptr;
|
||||
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");
|
||||
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;
|
||||
}
|
||||
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();
|
||||
if (contains(mExtTokens, "static"))
|
||||
|
@ -1479,14 +1479,14 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
|
|||
typeIndex--;
|
||||
const std::string type = mExtTokens[typeIndex];
|
||||
const std::string name = mExtTokens[typeIndex - 1];
|
||||
const Token *startToken = tokenList->back();
|
||||
const Token *startToken = tokenList.back();
|
||||
const ::Type *recordType = addTypeTokens(tokenList, type);
|
||||
if (!startToken)
|
||||
startToken = tokenList->front();
|
||||
startToken = tokenList.front();
|
||||
else if (startToken->str() != "static")
|
||||
startToken = startToken->next();
|
||||
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);
|
||||
mData->varDecl(addr, vartok1, &scope->varlist.back());
|
||||
if (mExtTokens.back() == "cinit" && !children.empty()) {
|
||||
|
@ -1510,9 +1510,9 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
|
|||
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 (")) {
|
||||
for (Token *typeToken = tok->tokAt(2); typeToken->str() != ")"; typeToken = typeToken->next()) {
|
||||
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) {
|
||||
if (!scope.definedType)
|
||||
|
@ -1542,7 +1542,7 @@ static void setValues(const Tokenizer *tokenizer, const SymbolDatabase *symbolDa
|
|||
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 (")) {
|
||||
ValueType vt = ValueType::parseDecl(tok->tokAt(2), *settings);
|
||||
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();
|
||||
SymbolDatabase *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer->getSymbolDatabase());
|
||||
tokenizer.createSymbolDatabase();
|
||||
auto *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer.getSymbolDatabase());
|
||||
symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nullptr);
|
||||
symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
|
||||
symbolDatabase->scopeList.back().check = symbolDatabase;
|
||||
|
||||
clangimport::Data data;
|
||||
data.mSettings = tokenizer->getSettings();
|
||||
data.mSettings = tokenizer.getSettings();
|
||||
data.mSymbolDatabase = symbolDatabase;
|
||||
std::string line;
|
||||
std::vector<AstNodePtr> tree;
|
||||
|
@ -1617,16 +1617,16 @@ void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
|||
tree[0]->createTokens1(tokenList);
|
||||
|
||||
// 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())
|
||||
throw InternalError(tok, "Token::link() is not set properly");
|
||||
}
|
||||
|
||||
if (tokenList->front())
|
||||
tokenList->front()->assignIndexes();
|
||||
if (tokenList.front())
|
||||
tokenList.front()->assignIndexes();
|
||||
symbolDatabase->clangSetVariables(data.getVariableList());
|
||||
symbolDatabase->createSymbolDatabaseExprIds();
|
||||
tokenList->clangSetOrigFiles();
|
||||
tokenList.clangSetOrigFiles();
|
||||
setTypes(tokenList);
|
||||
setValues(tokenizer, symbolDatabase);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
class Tokenizer;
|
||||
|
||||
namespace clangimport {
|
||||
void CPPCHECKLIB parseClangAstDump(Tokenizer *tokenizer, std::istream &f);
|
||||
void CPPCHECKLIB parseClangAstDump(Tokenizer &tokenizer, std::istream &f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
227
lib/cppcheck.cpp
227
lib/cppcheck.cpp
|
@ -188,13 +188,13 @@ static void createDumpFile(const Settings& settings,
|
|||
|
||||
std::string language;
|
||||
switch (settings.enforcedLang) {
|
||||
case Settings::Language::C:
|
||||
case Standards::Language::C:
|
||||
language = " language=\"c\"";
|
||||
break;
|
||||
case Settings::Language::CPP:
|
||||
case Standards::Language::CPP:
|
||||
language = " language=\"cpp\"";
|
||||
break;
|
||||
case Settings::Language::None:
|
||||
case Standards::Language::None:
|
||||
if (Path::isCPP(filename))
|
||||
language = " language=\"cpp\"";
|
||||
else if (Path::isC(filename))
|
||||
|
@ -423,120 +423,127 @@ static bool reportClangErrors(std::istream &is, const std::function<void(const E
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned int CppCheck::check(const std::string &path)
|
||||
unsigned int CppCheck::checkClang(const std::string &path)
|
||||
{
|
||||
if (mSettings.clang) {
|
||||
if (!mSettings.quiet)
|
||||
mErrorLogger.reportOut(std::string("Checking ") + path + " ...", Color::FgGreen);
|
||||
if (!mSettings.quiet)
|
||||
mErrorLogger.reportOut(std::string("Checking ") + path + " ...", Color::FgGreen);
|
||||
|
||||
const std::string lang = Path::isCPP(path) ? "-x c++" : "-x c";
|
||||
const std::string analyzerInfo = mSettings.buildDir.empty() ? std::string() : AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, path, emptyString);
|
||||
const std::string clangcmd = analyzerInfo + ".clang-cmd";
|
||||
const std::string clangStderr = analyzerInfo + ".clang-stderr";
|
||||
const std::string clangAst = analyzerInfo + ".clang-ast";
|
||||
std::string exe = mSettings.clangExecutable;
|
||||
// TODO: this ignores the configured language
|
||||
const std::string lang = Path::isCPP(path) ? "-x c++" : "-x c";
|
||||
const std::string analyzerInfo = mSettings.buildDir.empty() ? std::string() : AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, path, emptyString);
|
||||
const std::string clangcmd = analyzerInfo + ".clang-cmd";
|
||||
const std::string clangStderr = analyzerInfo + ".clang-stderr";
|
||||
const std::string clangAst = analyzerInfo + ".clang-ast";
|
||||
std::string exe = mSettings.clangExecutable;
|
||||
#ifdef _WIN32
|
||||
// append .exe if it is not a path
|
||||
if (Path::fromNativeSeparators(mSettings.clangExecutable).find('/') == std::string::npos) {
|
||||
exe += ".exe";
|
||||
}
|
||||
// append .exe if it is not a path
|
||||
if (Path::fromNativeSeparators(mSettings.clangExecutable).find('/') == std::string::npos) {
|
||||
exe += ".exe";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string flags(lang + " ");
|
||||
if (Path::isCPP(path) && !mSettings.standards.stdValue.empty())
|
||||
flags += "-std=" + mSettings.standards.stdValue + " ";
|
||||
std::string flags(lang + " ");
|
||||
// TODO: does not apply C standard
|
||||
if (Path::isCPP(path) && !mSettings.standards.stdValue.empty())
|
||||
flags += "-std=" + mSettings.standards.stdValue + " ";
|
||||
|
||||
for (const std::string &i: mSettings.includePaths)
|
||||
flags += "-I" + i + " ";
|
||||
for (const std::string &i: mSettings.includePaths)
|
||||
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 redirect2 = analyzerInfo.empty() ? std::string("2>&1") : ("2> " + clangStderr);
|
||||
if (!mSettings.buildDir.empty()) {
|
||||
std::ofstream fout(clangcmd);
|
||||
fout << exe << " " << args2 << " " << redirect2 << std::endl;
|
||||
} else if (mSettings.verbose && !mSettings.quiet) {
|
||||
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;
|
||||
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);
|
||||
if (!mSettings.buildDir.empty()) {
|
||||
std::ofstream fout(clangcmd);
|
||||
fout << exe << " " << args2 << " " << redirect2 << std::endl;
|
||||
} else if (mSettings.verbose && !mSettings.quiet) {
|
||||
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()) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -1347,8 +1354,8 @@ void CppCheck::executeRules(const std::string &tokenlist, const Tokenizer &token
|
|||
}
|
||||
break;
|
||||
}
|
||||
const unsigned int pos1 = (unsigned int)ovector[0];
|
||||
const unsigned int pos2 = (unsigned int)ovector[1];
|
||||
const auto pos1 = (unsigned int)ovector[0];
|
||||
const auto pos2 = (unsigned int)ovector[1];
|
||||
|
||||
// jump to the end of the match for the next pcre_exec
|
||||
pos = (int)pos2;
|
||||
|
@ -1751,7 +1758,7 @@ bool CppCheck::analyseWholeProgram()
|
|||
// Analyse the tokens
|
||||
CTU::FileInfo ctu;
|
||||
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) {
|
||||
ctu.functionCalls.insert(ctu.functionCalls.end(), fi2->functionCalls.cbegin(), fi2->functionCalls.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);
|
||||
#endif
|
||||
|
||||
unsigned int checkClang(const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Errors and warnings are directed here.
|
||||
*
|
||||
|
|
|
@ -309,7 +309,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer)
|
|||
{
|
||||
const SymbolDatabase * const symbolDatabase = tokenizer->getSymbolDatabase();
|
||||
|
||||
FileInfo *fileInfo = new FileInfo;
|
||||
auto *fileInfo = new FileInfo;
|
||||
|
||||
// Parse all functions in TU
|
||||
for (const Scope &scope : symbolDatabase->scopeList) {
|
||||
|
@ -513,7 +513,7 @@ static bool findPath(const std::string &callId,
|
|||
if (c->callArgNr != callArgNr)
|
||||
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 (!warning && functionCall->warning)
|
||||
continue;
|
||||
|
@ -537,7 +537,7 @@ static bool findPath(const std::string &callId,
|
|||
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)
|
||||
continue;
|
||||
|
||||
|
@ -570,7 +570,7 @@ std::list<ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(InvalidValueTy
|
|||
if (!path[index])
|
||||
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 (functionCallPtr)
|
||||
|
|
|
@ -31,14 +31,17 @@ struct CPPCHECKLIB FileSettings {
|
|||
std::string cfg;
|
||||
std::string filename;
|
||||
std::string defines;
|
||||
// TODO: handle differently
|
||||
std::string cppcheckDefines() const {
|
||||
return defines + (msc ? ";_MSC_VER=1900" : "") + (useMfc ? ";__AFXWIN_H__=1" : "");
|
||||
}
|
||||
std::set<std::string> undefs;
|
||||
std::list<std::string> includePaths;
|
||||
// only used by clang mode
|
||||
std::list<std::string> systemIncludePaths;
|
||||
std::string standard;
|
||||
Platform::Type platformType = Platform::Type::Unspecified;
|
||||
// TODO: get rid of these
|
||||
bool msc{};
|
||||
bool useMfc{};
|
||||
};
|
||||
|
|
|
@ -26,10 +26,12 @@
|
|||
#include "settings.h"
|
||||
#include "symboldatabase.h"
|
||||
#include "token.h"
|
||||
#include "utils.h"
|
||||
#include "valueptr.h"
|
||||
#include "vfvalue.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
@ -443,7 +445,7 @@ namespace {
|
|||
if (checkElse && isDoWhile &&
|
||||
(condTok->hasKnownIntValue() ||
|
||||
(!bodyAnalysis.isModified() && !condAnalysis.isModified() && condAnalysis.isRead()))) {
|
||||
if (updateRange(endBlock->link(), endBlock) == Progress::Break)
|
||||
if (updateScope(endBlock) == Progress::Break)
|
||||
return Break();
|
||||
return updateRecursive(condTok);
|
||||
}
|
||||
|
@ -519,8 +521,17 @@ namespace {
|
|||
return updateLoop(endToken, endBlock, condTok, initTok, stepTok, true);
|
||||
}
|
||||
|
||||
Progress updateScope(Token* endBlock) {
|
||||
return updateRange(endBlock->link(), endBlock);
|
||||
Progress updateScope(Token* endBlock, int depth = 20)
|
||||
{
|
||||
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) {
|
||||
|
@ -682,7 +693,7 @@ namespace {
|
|||
thenBranch.escape = isEscapeScope(endBlock, thenBranch.escapeUnknown);
|
||||
if (thenBranch.check) {
|
||||
thenBranch.active = true;
|
||||
if (updateRange(endCond->next(), endBlock, depth - 1) == Progress::Break)
|
||||
if (updateScope(endBlock, depth - 1) == Progress::Break)
|
||||
return Break();
|
||||
} else if (!elseBranch.check) {
|
||||
thenBranch.active = true;
|
||||
|
@ -694,7 +705,7 @@ namespace {
|
|||
elseBranch.escape = isEscapeScope(endBlock->linkAt(2), elseBranch.escapeUnknown);
|
||||
if (elseBranch.check) {
|
||||
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)
|
||||
return Break();
|
||||
} else if (!thenBranch.check) {
|
||||
|
@ -746,7 +757,7 @@ namespace {
|
|||
} else if (Token::simpleMatch(tok, "try {")) {
|
||||
Token* endBlock = tok->next()->link();
|
||||
ForwardTraversal tryTraversal = fork();
|
||||
tryTraversal.updateRange(tok->next(), endBlock, depth - 1);
|
||||
tryTraversal.updateScope(endBlock, depth - 1);
|
||||
bool bail = tryTraversal.actions.isModified();
|
||||
if (bail) {
|
||||
actions = tryTraversal.actions;
|
||||
|
@ -760,7 +771,7 @@ namespace {
|
|||
return Break();
|
||||
endBlock = endCatch->linkAt(1);
|
||||
ForwardTraversal ft = fork();
|
||||
ft.updateRange(endBlock->link(), endBlock, depth - 1);
|
||||
ft.updateScope(endBlock, depth - 1);
|
||||
bail |= ft.terminate != Analyzer::Terminate::None || ft.actions.isModified();
|
||||
}
|
||||
if (bail)
|
||||
|
@ -880,6 +891,8 @@ Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const V
|
|||
if (a->invalid())
|
||||
return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail};
|
||||
ForwardTraversal ft{a, settings};
|
||||
if (start)
|
||||
ft.analyzer->updateState(start);
|
||||
ft.updateRange(start, end);
|
||||
return Analyzer::Result{ ft.actions, ft.terminate };
|
||||
}
|
||||
|
|
|
@ -757,6 +757,7 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
|
|||
FileSettings fs;
|
||||
fs.filename = cfilename;
|
||||
fs.cfg = p.name;
|
||||
// TODO: detect actual MSC version
|
||||
fs.msc = true;
|
||||
fs.useMfc = useOfMfc;
|
||||
fs.defines = "_WIN32=1";
|
||||
|
|
|
@ -34,14 +34,13 @@
|
|||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
ExprIdToken::ExprIdToken(const Token* tok) : tok(tok), exprid(tok ? tok->exprId() : 0) {}
|
||||
|
||||
nonneg int ExprIdToken::getExpressionId() const {
|
||||
|
@ -1640,6 +1639,14 @@ namespace {
|
|||
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)
|
||||
{
|
||||
depth--;
|
||||
|
@ -1648,13 +1655,29 @@ namespace {
|
|||
}};
|
||||
if (depth < 0)
|
||||
return unknown();
|
||||
ValueFlow::Value v = executeImpl(expr);
|
||||
if (!v.isUninitValue())
|
||||
ValueFlow::Value v = unknown();
|
||||
if (updateValue(v, executeImpl(expr)))
|
||||
return v;
|
||||
if (!expr)
|
||||
return v;
|
||||
if (expr->exprId() > 0 && pm->hasValue(expr->exprId()))
|
||||
return pm->at(expr->exprId());
|
||||
if (expr->exprId() > 0 && pm->hasValue(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))
|
||||
return *value;
|
||||
return v;
|
||||
|
|
|
@ -182,12 +182,8 @@ public:
|
|||
bool dump{};
|
||||
std::string dumpFile;
|
||||
|
||||
enum Language {
|
||||
None, C, CPP
|
||||
};
|
||||
|
||||
/** @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)
|
||||
/** @brief Is --exception-handling given */
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
* This struct contains all possible standards that cppcheck recognize.
|
||||
*/
|
||||
struct Standards {
|
||||
enum Language { None, C, CPP };
|
||||
|
||||
/** C code standard */
|
||||
enum cstd_t { C89, C99, C11, CLatest = C11 } c = CLatest;
|
||||
|
||||
|
|
|
@ -43,11 +43,11 @@
|
|||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <sstream> // IWYU pragma: keep
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -1052,7 +1052,7 @@ void SymbolDatabase::createSymbolDatabaseSetScopePointers()
|
|||
|
||||
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() == "{") {
|
||||
bool isEndOfScope = false;
|
||||
for (Scope* innerScope: scope.nestedList) {
|
||||
|
@ -1702,7 +1702,7 @@ void SymbolDatabase::createSymbolDatabaseExprIds()
|
|||
std::unordered_map<std::string, nonneg int> unknownIds;
|
||||
// Assign IDs to incomplete vars which are part of an expression
|
||||
// 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())
|
||||
continue;
|
||||
if (!isExpression(tok->astParent()))
|
||||
|
@ -1725,7 +1725,7 @@ void SymbolDatabase::createSymbolDatabaseExprIds()
|
|||
// Assign IDs
|
||||
ExprIdMap exprIdMap;
|
||||
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) {
|
||||
tok->exprId(tok->varId());
|
||||
if (tok->astParent() && tok->astParent()->exprId() == 0)
|
||||
|
@ -1794,7 +1794,7 @@ void SymbolDatabase::setArrayDimensionsUsingValueFlow()
|
|||
continue;
|
||||
// check each array dimension
|
||||
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)
|
||||
continue;
|
||||
|
||||
|
@ -3383,7 +3383,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
|||
if (match) {
|
||||
auto range = scope1->functionMap.equal_range((*tok)->str());
|
||||
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->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
||||
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)
|
||||
{
|
||||
ValueType* valuetypePtr = new ValueType(valuetype);
|
||||
auto* valuetypePtr = new ValueType(valuetype);
|
||||
if (mSettings.debugnormal || mSettings.debugwarnings)
|
||||
valuetypePtr->setDebugPath(tok, loc);
|
||||
tok->setValueType(valuetypePtr);
|
||||
|
@ -6584,7 +6584,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
|
|||
setValueType(var1Tok, vt);
|
||||
if (var1Tok != parent->previous())
|
||||
setValueType(parent->previous(), vt);
|
||||
Variable *var = const_cast<Variable *>(parent->previous()->variable());
|
||||
auto *var = const_cast<Variable *>(parent->previous()->variable());
|
||||
if (var) {
|
||||
ValueType vt2_(*vt2);
|
||||
if (vt2_.pointer == 0 && autoTok->strAt(1) == "*")
|
||||
|
@ -6737,7 +6737,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
|
|||
varvt.constness |= 1;
|
||||
}
|
||||
setValueType(parent->previous(), varvt);
|
||||
Variable *var = const_cast<Variable *>(parent->previous()->variable());
|
||||
auto *var = const_cast<Variable *>(parent->previous()->variable());
|
||||
if (var) {
|
||||
var->setValueType(varvt);
|
||||
if (vt2->typeScope && vt2->typeScope->definedType) {
|
||||
|
@ -6803,7 +6803,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
|
|||
if (isconst)
|
||||
varvt.constness |= (1 << autovt.pointer);
|
||||
setValueType(parent->previous(), varvt);
|
||||
Variable * var = const_cast<Variable *>(parent->previous()->variable());
|
||||
auto * var = const_cast<Variable *>(parent->previous()->variable());
|
||||
if (var) {
|
||||
var->setValueType(varvt);
|
||||
if (templateArgType && templateArgType->classScope && templateArgType->classScope->definedType) {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
static Token *skipRequires(Token *tok)
|
||||
|
@ -1376,7 +1377,7 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
|||
}
|
||||
|
||||
if (found) {
|
||||
Token *end = const_cast<Token *>(aliasDeclaration.aliasEndToken());
|
||||
auto *end = const_cast<Token *>(aliasDeclaration.aliasEndToken());
|
||||
|
||||
// remove declaration tokens
|
||||
if (aliasDeclaration.token()->previous())
|
||||
|
@ -3227,7 +3228,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
|||
// process uninstantiated templates
|
||||
// TODO: remove the specialized check and handle all uninstantiated templates someday.
|
||||
if (!instantiated && specialized) {
|
||||
Token * tok2 = const_cast<Token *>(templateDeclaration.nameToken());
|
||||
auto * tok2 = const_cast<Token *>(templateDeclaration.nameToken());
|
||||
if (mErrorLogger && !mTokenList.getFiles().empty())
|
||||
mErrorLogger->reportProgress(mTokenList.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue());
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <set>
|
||||
#include <sstream> // IWYU pragma: keep
|
||||
#include <stack>
|
||||
#include <type_traits>
|
||||
#include <unordered_set>
|
||||
#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 *after = tok3;
|
||||
|
@ -3354,10 +3361,10 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration)
|
|||
if (mTimerResults) {
|
||||
Timer t("Tokenizer::simplifyTokens1::createAst", mSettings->showtime, mTimerResults);
|
||||
list.createAst();
|
||||
list.validateAst();
|
||||
list.validateAst(mSettings->debugnormal);
|
||||
} else {
|
||||
list.createAst();
|
||||
list.validateAst();
|
||||
list.validateAst(mSettings->debugnormal);
|
||||
}
|
||||
|
||||
if (mTimerResults) {
|
||||
|
@ -3915,7 +3922,7 @@ void Tokenizer::simplifyLabelsCaseDefault()
|
|||
int indentLevel = 0;
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
// Simplify labels in the executable scope..
|
||||
Token *start = const_cast<Token *>(startOfExecutableScope(tok));
|
||||
auto *start = const_cast<Token *>(startOfExecutableScope(tok));
|
||||
if (start) {
|
||||
tok = start;
|
||||
executablescope = true;
|
||||
|
|
|
@ -50,6 +50,9 @@ TokenList::TokenList(const Settings* settings) :
|
|||
mSettings(settings)
|
||||
{
|
||||
mTokensFrontBack.list = this;
|
||||
if (mSettings && (mSettings->enforcedLang != Standards::Language::None)) {
|
||||
mLang = mSettings->enforcedLang;
|
||||
}
|
||||
}
|
||||
|
||||
TokenList::~TokenList()
|
||||
|
@ -80,12 +83,12 @@ void TokenList::deallocateTokens()
|
|||
|
||||
void TokenList::determineCppC()
|
||||
{
|
||||
if (!mSettings) {
|
||||
mIsC = Path::isC(getSourceFilePath());
|
||||
mIsCpp = Path::isCPP(getSourceFilePath());
|
||||
} else {
|
||||
mIsC = mSettings->enforcedLang == Settings::Language::C || (mSettings->enforcedLang == Settings::Language::None && Path::isC(getSourceFilePath()));
|
||||
mIsCpp = mSettings->enforcedLang == Settings::Language::CPP || (mSettings->enforcedLang == Settings::Language::None && Path::isCPP(getSourceFilePath()));
|
||||
// only try to determine it if it wasn't enforced
|
||||
if (mLang == Standards::Language::None) {
|
||||
if (Path::isC(getSourceFilePath()))
|
||||
mLang = Standards::Language::C;
|
||||
else if (Path::isCPP(getSourceFilePath()))
|
||||
mLang = Standards::Language::CPP;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,8 +576,12 @@ static bool iscpp11init_impl(const Token * const tok)
|
|||
}
|
||||
|
||||
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;
|
||||
if (const Token* castTok = colonTok->linkAt(-1)) {
|
||||
if (Token::simpleMatch(castTok->astParent(), "case"))
|
||||
return true;
|
||||
}
|
||||
const Token* caseTok = colonTok->tokAt(-2);
|
||||
while (caseTok && Token::Match(caseTok->tokAt(-1), "::|%name%"))
|
||||
caseTok = caseTok->tokAt(-1);
|
||||
|
@ -1718,10 +1725,10 @@ namespace {
|
|||
};
|
||||
}
|
||||
|
||||
void TokenList::validateAst() const
|
||||
void TokenList::validateAst(bool print) const
|
||||
{
|
||||
OnException oe{[&] {
|
||||
if (mSettings && mSettings->debugnormal)
|
||||
if (print)
|
||||
mTokensFrontBack.front->printOut();
|
||||
}};
|
||||
// Check for some known issues in AST to avoid crash/hang later on
|
||||
|
@ -1850,7 +1857,7 @@ void TokenList::simplifyPlatformTypes()
|
|||
if (!mSettings)
|
||||
return;
|
||||
|
||||
const bool isCPP11 = mSettings->standards.cpp >= Standards::CPP11;
|
||||
const bool isCPP11 = isCPP() && (mSettings->standards.cpp >= Standards::CPP11);
|
||||
|
||||
enum { isLongLong, isLong, isInt } type;
|
||||
|
||||
|
@ -1992,7 +1999,7 @@ void TokenList::simplifyStdType()
|
|||
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 isSigned = false;
|
||||
bool isUnsigned = false;
|
||||
|
@ -2015,7 +2022,7 @@ void TokenList::simplifyStdType()
|
|||
else if (Token::Match(tok2, "float|double")) {
|
||||
isFloat = true;
|
||||
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
|
||||
else if (Token::Match(tok2, "char|int")) {
|
||||
if (!typeSpec)
|
||||
|
@ -2053,7 +2060,7 @@ void TokenList::simplifyStdType()
|
|||
|
||||
bool TokenList::isKeyword(const std::string &str) const
|
||||
{
|
||||
if (mIsCpp) {
|
||||
if (isCPP()) {
|
||||
// TODO: integrate into keywords?
|
||||
// types and literals are not handled as keywords
|
||||
static const std::unordered_set<std::string> cpp_types = {"bool", "false", "true"};
|
||||
|
|
|
@ -22,15 +22,16 @@
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "config.h"
|
||||
#include "standards.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Settings;
|
||||
class Token;
|
||||
class TokenList;
|
||||
class Settings;
|
||||
|
||||
namespace simplecpp {
|
||||
class TokenList;
|
||||
|
@ -61,12 +62,12 @@ public:
|
|||
|
||||
/** Is the code C. Used for bailouts */
|
||||
bool isC() const {
|
||||
return mIsC;
|
||||
return mLang == Standards::Language::C;
|
||||
}
|
||||
|
||||
/** Is the code CPP. Used for bailouts */
|
||||
bool isCPP() const {
|
||||
return mIsCpp;
|
||||
return mLang == Standards::Language::CPP;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,7 +172,7 @@ public:
|
|||
* Check abstract syntax tree.
|
||||
* Throws InternalError on failure
|
||||
*/
|
||||
void validateAst() const;
|
||||
void validateAst(bool print) const;
|
||||
|
||||
/**
|
||||
* Verify that the given token is an element of the tokenlist.
|
||||
|
@ -214,8 +215,7 @@ private:
|
|||
const Settings* const mSettings{};
|
||||
|
||||
/** File is known to be C/C++ code */
|
||||
bool mIsC{};
|
||||
bool mIsCpp{};
|
||||
Standards::Language mLang{Standards::Language::None};
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -2969,6 +2969,13 @@ struct ValueFlowAnalyzer : Analyzer {
|
|||
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*/)
|
||||
{
|
||||
assert(false && "Internal update unimplemented.");
|
||||
|
@ -5113,7 +5120,7 @@ static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symbo
|
|||
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;
|
||||
if (Token::Match(tok, "%var% . reset|clear (") && tok->next()->originalName().empty()) {
|
||||
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)
|
||||
{
|
||||
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, "="))
|
||||
continue;
|
||||
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)
|
||||
{
|
||||
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())
|
||||
continue;
|
||||
|
||||
|
@ -5575,7 +5582,7 @@ struct SymbolicInferModel : InferModel {
|
|||
static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings* settings)
|
||||
{
|
||||
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%"))
|
||||
continue;
|
||||
if (tok->hasKnownIntValue())
|
||||
|
@ -5923,7 +5930,7 @@ static void valueFlowAfterAssign(TokenList &tokenlist,
|
|||
if (skippedFunctions.count(scope))
|
||||
continue;
|
||||
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
|
||||
bool isInit = false;
|
||||
if (tok->str() != "=" && !(isInit = isVariableInit(tok)))
|
||||
|
@ -6056,7 +6063,7 @@ static void valueFlowAfterSwap(TokenList& tokenlist,
|
|||
const Settings* settings)
|
||||
{
|
||||
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 ("))
|
||||
continue;
|
||||
if (!Token::simpleMatch(tok->next()->astOperand2(), ","))
|
||||
|
@ -6231,7 +6238,7 @@ struct ConditionHandler {
|
|||
for (const Scope *scope : symboldatabase.functionScopes) {
|
||||
if (skippedFunctions.count(scope))
|
||||
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 ("))
|
||||
continue;
|
||||
if (Token::Match(tok, ":|;|,"))
|
||||
|
@ -6720,7 +6727,7 @@ struct ConditionHandler {
|
|||
return;
|
||||
if (r.action.isModified())
|
||||
return;
|
||||
Token* start = const_cast<Token*>(loopScope->bodyEnd);
|
||||
auto* start = const_cast<Token*>(loopScope->bodyEnd);
|
||||
if (Token::simpleMatch(start, "} while (")) {
|
||||
start = start->tokAt(2);
|
||||
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)
|
||||
continue;
|
||||
|
||||
Token* tok = const_cast<Token*>(scope.classDef);
|
||||
Token* const bodyStart = const_cast<Token*>(scope.bodyStart);
|
||||
auto* tok = const_cast<Token*>(scope.classDef);
|
||||
auto* const bodyStart = const_cast<Token*>(scope.bodyStart);
|
||||
|
||||
if (!Token::simpleMatch(tok->next()->astOperand2(), ";") ||
|
||||
!Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";"))
|
||||
|
@ -8772,7 +8779,7 @@ static void valueFlowContainerSize(TokenList& tokenlist,
|
|||
|
||||
// after assignment
|
||||
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% ;")) {
|
||||
Token* containerTok = tok->next();
|
||||
if (containerTok->exprId() == 0)
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
#define versionH
|
||||
|
||||
#define CPPCHECK_MAJOR_VERSION 2
|
||||
#define CPPCHECK_MINOR_VERSION 12
|
||||
#define CPPCHECK_DEVMINOR_VERSION 13
|
||||
#define CPPCHECK_FIX_VERSION 0
|
||||
#define CPPCHECK_MINOR_VERSION 13
|
||||
#define CPPCHECK_DEVMINOR_VERSION 14
|
||||
#define CPPCHECK_BUGFIX_VERSION 99
|
||||
|
||||
#define STRINGIFY(x) STRING(x)
|
||||
#define STRING(VER) #VER
|
||||
#if CPPCHECK_MINOR_VERSION == CPPCHECK_DEVMINOR_VERSION
|
||||
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR_VERSION) "." STRINGIFY(CPPCHECK_MINOR_VERSION) "." STRINGIFY(CPPCHECK_FIX_VERSION)
|
||||
#define CPPCHECK_VERSION CPPCHECK_MAJOR_VERSION,CPPCHECK_MINOR_VERSION,CPPCHECK_FIX_VERSION,0
|
||||
#if CPPCHECK_BUGFIX_VERSION < 99
|
||||
#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_BUGFIX_VERSION,0
|
||||
#else
|
||||
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR_VERSION) "." STRINGIFY(CPPCHECK_DEVMINOR_VERSION) " dev"
|
||||
#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-destructor-override")
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include <tinyxml2.h> // IWYU pragma: export
|
||||
|
||||
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:
|
||||
|
||||
bear make
|
||||
bear -- make
|
||||
|
||||
# Preprocessor Settings
|
||||
|
||||
|
@ -450,10 +450,10 @@ The format for an error suppression is one of:
|
|||
[error id]:[filename2]
|
||||
[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.
|
||||
It is recommended to use "/" as path separator on all operating systems. The filename must match the filename in the reported warning exactly.
|
||||
The filename may include the wildcard characters \* or ?, which matches any sequence of characters or any single character respectively.
|
||||
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.
|
||||
|
||||
## 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.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Cppcheck manual
|
||||
subtitle: Version 2.12.99
|
||||
subtitle: Version 2.13.99
|
||||
author: Cppcheck team
|
||||
lang: en
|
||||
documentclass: report
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Cppcheck .cfg format
|
||||
subtitle: Version 2.12.99
|
||||
subtitle: Version 2.13.99
|
||||
author: Cppcheck team
|
||||
lang: en
|
||||
documentclass: report
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Writing addons
|
||||
subtitle: Version 2.12.99
|
||||
subtitle: Version 2.13.99
|
||||
author: Cppcheck team
|
||||
lang: en
|
||||
documentclass: report
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue